OnVsRestClassifier 准确率为0

我正在尝试解决一个多标签分类问题,如下所示:

        from sklearn.preprocessing import MultiLabelBinarizer         traindf = pickle.load("traindata.pkl","rb"))        X = traindf['Col1']        X=MultiLabelBinarizer().fit_transform(X)        y = traindf['Col2']        y= MultiLabelBinarizer().fit_transform(y)        Xtrain, Xvalidate, ytrain, yvalidate = train_test_split(X, y, test_size=.5)        from sklearn.linear_model import LogisticRegression        clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(Xtrain,ytrain)        print "One vs rest accuracy: %.3f"  % clf.score(Xvalidate,yvalidate)

通过这种方式,我总是得到0的准确率。请指出我是否做错了什么。我对多标签分类还是新手。以下是我的数据看起来的样子:

Col1                  Col2asd dfgfg             [1,2,3]poioi oiopiop         [4]

编辑

感谢您的帮助 @lejlot。我觉得我开始掌握了。这是我尝试过的:

import pandas as pdimport numpy as npfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.linear_model import SGDClassifier from sklearn.multiclass import OneVsRestClassifierfrom sklearn.preprocessing import MultiLabelBinarizerfrom sklearn.pipeline import Pipelinefrom sklearn.linear_model import LogisticRegressiontdf = pd.read_csv("mul.csv", index_col="DocID",error_bad_lines=False)print tdf

所以我的输入数据看起来像这样:

DocID   Content           Tags    1       abc abc abc       [1]2       asd asd asd       [2]3       abc abc asd     [1,2]4       asd asd abc     [1,2]5       asd abc qwe   [1,2,3]6       qwe qwe qwe       [3]7       qwe qwe abc     [1,3]8       qwe qwe asd     [2,3]

这些只是我创建的一些测试数据。然后我做了以下操作:

text_clf = Pipeline([                     ('vect', TfidfVectorizer()),                     ('clf', SGDClassifier(loss='hinge', penalty='l2',                                            alpha=1e-3, n_iter=5, random_state=42)), ])t=TfidfVectorizer()X=t.fit_transform(tdf["Content"]).toarray()print X

这会给我:

[[ 1.          0.          0.        ] [ 0.          1.          0.        ] [ 0.89442719  0.4472136   0.        ] [ 0.4472136   0.89442719  0.        ] [ 0.55247146  0.55247146  0.62413987] [ 0.          0.          1.        ] [ 0.40471905  0.          0.91444108] [ 0.          0.40471905  0.91444108]]

然后

y=tdf['Tags']y=MultiLabelBinarizer().fit_transform(y)print y

这会给我:

[[0 1 0 0 1 1] [0 0 1 0 1 1] [1 1 1 0 1 1] [1 1 1 0 1 1] [1 1 1 1 1 1] [0 0 0 1 1 1] [1 1 0 1 1 1] [1 0 1 1 1 1]]

在这里我想知道为什么有6列?不应该是只有3列吗?无论如何,我还创建了一个测试数据文件:

sdf=pd.read_csv("multest.csv", index_col="DocID",error_bad_lines=False)print sdf

所以这看起来像这样:

DocID  Content        PredTags             34     abc abc qwe    [1,3]35     asd abc asd    [1,2]36     abc abc abc      [1]

我有PredTags列来检查准确率。所以最后我进行拟合和预测如下:

clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(X,y)predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())print predicted

这会给我:

[[1 1 1 1 1 1] [1 1 1 0 1 1] [1 1 1 0 1 1]]

现在,我如何知道预测的是哪些标签?我如何根据我的PredTags列检查准确率?

更新

非常感谢 @lejlot 🙂 我还设法得到了如下准确率:

sdf=pd.read_csv("multest.csv", index_col="DocID",error_bad_lines=False)print sdfpredicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())print predictedty=sdf["PredTags"]ty = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in ty]yt=MultiLabelBinarizer().fit_transform(ty)Xt=t.fit_transform(sdf["Content"]).toarray()print Xtprint ytprint "One vs rest accuracy: %.3f"  % clf.score(Xt,yt)

我只需要将测试集的预测列也进行二值化处理 🙂


回答:

实际问题在于你处理文本的方式,你应该提取某种特征并将其用作文本表示。例如,你可以使用词袋表示法,或tfidf,或任何更复杂的方法。

那么现在发生了什么?你对字符串列表调用了MultiLabelBinarizer,因此,scikit-learn创建了列表中所有可迭代对象的集合…导致了字母集合的表示。例如

from sklearn.preprocessing import MultiLabelBinarizer X = ['abc cde', 'cde', 'fff']print MultiLabelBinarizer().fit_transform(X)

会给你

array([[1, 1, 1, 1, 1, 1, 0],       [0, 0, 0, 1, 1, 1, 0],       [0, 0, 0, 0, 0, 0, 1]])        |  |  |  |  |  |  |        v  v  v  v  v  v  v        a  b  _  c  d  e  f

因此分类几乎是不可能的,因为这并没有捕捉到你的文本的任何意义。

你可以进行例如计数向量化(词袋)

from sklearn.feature_extraction.text import CountVectorizerprint CountVectorizer().fit_transform(X).toarray()

会给你

      [[1  1  0]       [0  1  0]       [0  0  1]]        |  |  |        v  |  v       abc | fff           v          cde

更新

最后,为了使用标签而不是它们的二值化进行预测,你需要存储你的二值化器,因此

labels = MultiLabelBinarizer()y = labels.fit_transform(y)

然后

clf = OneVsRestClassifier(LogisticRegression(penalty='l2', C=0.01)).fit(X,y)predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())print labels.inverse_transform(predicted)

更新2

如果你只有三个类别,那么向量应该有3个元素,你的有6个,所以检查你传递的”y”是什么,你的数据中可能有一些错误

from sklearn.preprocessing import MultiLabelBinarizerMultiLabelBinarizer().fit_transform([[1,2], [1], [3], [2]])

会给你

array([[1, 1, 0],       [1, 0, 0],       [0, 0, 1],       [0, 1, 0]])

如预期的那样。

我最好的猜测是你的”标签”也是字符串,因此你实际上调用的是

MultiLabelBinarizer().fit_transform(["[1,2]", "[1]", "[3]", "[2]"])

这会导致

array([[1, 1, 1, 0, 1, 1],       [0, 1, 0, 0, 1, 1],       [0, 0, 0, 1, 1, 1],       [0, 0, 1, 0, 1, 1]])        |  |  |  |  |  |         v  v  v  v  v  v          ,  1  2  3  [  ] 

这些是你的6个类别。三个真正的类别,2个“琐碎”的类别“[”和“]”,它们总是存在,还有一个几乎琐碎的类别“,”,它出现在每个属于多个类别的对象中。

你应该首先将你的标签转换为实际的列表,例如通过

y = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in y]

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注