OnVsRestClassifier 给出 0 精度
OnVsRestClassifier gives 0 accuracy
我正在尝试解决多标签分类问题
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 Col2
asd dfgfg [1,2,3]
poioi oiopiop [4]
编辑
感谢@lejlot 的帮助。我想我已经掌握了窍门。这是我试过的
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
tdf = 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 sdf
predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())
print predicted
ty=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 Xt
print yt
print "One vs rest accuracy: %.3f" % clf.score(Xt,yt)
我还需要对测试集预测列进行二值化:)
实际问题是您处理文本的方式,您应该 extract some kind of features 并将其用作文本表示。例如,您可以使用 bag of words 表示,或 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
因此,class化几乎是不可能的,因为这无法捕捉到您文本的任何含义。
例如,您可以执行计数向量化(词袋)
from sklearn.feature_extraction.text import CountVectorizer
print 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
如果你只有三个 class,那么向量应该有 3 个元素,你的有 6 个所以检查你传递的是什么 "y",你的数据可能有一些错误
from sklearn.preprocessing import MultiLabelBinarizer
MultiLabelBinarizer().fit_transform([[1,2], [1], [3], [2]])
给予
array([[1, 1, 0],
[1, 0, 0],
[0, 0, 1],
[0, 1, 0]])
符合预期。
我最好的猜测是你的 "tags" 也是 字符串 因此你实际上调用了
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 class。三个真实的,2 "trivial" classes "[" 和 "]" 存在 always 并且几乎微不足道 class ","对于属于多个 class.
的每个对象都会出现
您应该先将标签转换为实际列表,例如通过
y = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in y]
我正在尝试解决多标签分类问题
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 Col2
asd dfgfg [1,2,3]
poioi oiopiop [4]
编辑
感谢@lejlot 的帮助。我想我已经掌握了窍门。这是我试过的
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import SGDClassifier
from sklearn.multiclass import OneVsRestClassifier
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression
tdf = 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 sdf
predicted = clf.predict(t.fit_transform(sdf["Content"]).toarray())
print predicted
ty=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 Xt
print yt
print "One vs rest accuracy: %.3f" % clf.score(Xt,yt)
我还需要对测试集预测列进行二值化:)
实际问题是您处理文本的方式,您应该 extract some kind of features 并将其用作文本表示。例如,您可以使用 bag of words 表示,或 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
因此,class化几乎是不可能的,因为这无法捕捉到您文本的任何含义。
例如,您可以执行计数向量化(词袋)
from sklearn.feature_extraction.text import CountVectorizer
print 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
如果你只有三个 class,那么向量应该有 3 个元素,你的有 6 个所以检查你传递的是什么 "y",你的数据可能有一些错误
from sklearn.preprocessing import MultiLabelBinarizer
MultiLabelBinarizer().fit_transform([[1,2], [1], [3], [2]])
给予
array([[1, 1, 0],
[1, 0, 0],
[0, 0, 1],
[0, 1, 0]])
符合预期。
我最好的猜测是你的 "tags" 也是 字符串 因此你实际上调用了
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 class。三个真实的,2 "trivial" classes "[" 和 "]" 存在 always 并且几乎微不足道 class ","对于属于多个 class.
的每个对象都会出现您应该先将标签转换为实际列表,例如通过
y = [map(int, list(_y.replace(',','').replace('[','').replace(']',''))) for _y in y]