我试图建立一个多标签的核心文本分类器。正如所描述的这里,其思想是读取(大规模的)文本数据集,并将其部分地与分类器相匹配。此外,当您有描述这里的多标签实例时,想法是以一种单一的方式,将许多二进制分类器构建为数据集中的类数。
当将MultiLabelBinarizer和OneVsRestClassifier类与部分拟合结合起来时,我得到以下错误:
ValueError:包含多个元素的数组的真值是不明确的。使用a.any()或a.all()
守则如下:
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.preprocessing import MultiLabelBinarizer
from sklearn.multiclass import OneVsRestClassifier
categories = ['a', 'b', 'c']
X = ["This is a test", "This is another attempt", "And this is a test too!"]
Y = [['a', 'b'],['b'],['a','b']]
mlb = MultiLabelBinarizer(classes=categories)
vectorizer = HashingVectorizer(decode_error='ignore', n_features=2 ** 18, non_negative=True)
clf = OneVsRestClassifier(MultinomialNB(alpha=0.01))
X_train = vectorizer.fit_transform(X)
Y_train = mlb.fit_transform(Y)
clf.partial_fit(X_train, Y_train, classes=categories)
您可以想象,最后三行应用于每一个小型批处理,为了简单起见,我删除了其中的代码。
如果删除OneVsRestClassifier并仅使用MultinomialNB,则代码运行良好。
发布于 2017-02-16 21:58:09
您正在将y_train作为转换自以[1,1,0,0,1,0,1,1,1,0]的形式从MultiLabelBinarizer
转换而来,但将类别传递为['a','b','c']
,然后通过这一行代码传递:-
if np.setdiff1d(y, self.classes_):
raise ValueError(("Mini-batch contains {0} while classes " +
"must be subset of {1}").format(np.unique(y),
self.classes_))
这会导致一个布尔值数组,如False、True、. if
不能处理这样的数组,例如一个真值,从而导致错误。
首先,您应该以与Y_train
相同的数字格式传递类。现在,即使您这样做,OneVsRestClassifier的也会决定它的类型是"multiclass“而不是multilabel
,然后拒绝正确地转换这些类。在我看来,这是OneVsRestClassifer和/或LabelBinarizer中的一个bug。
请向scikit提交一个问题-学习关于partial_fit
的github,看看会发生什么。
显然,Update从目标向量(y)中决定“多标签”或“多类”是当前在scikit上正在进行的一个问题--学习是因为围绕它的所有复杂因素。
发布于 2017-02-16 15:34:57
所以,也许你会发现一个不同的答案,但我建议你不要使用OneVsRestClassifier,而应该使用建立在scikit-learn之上的scikit多重学习库,它提供了多标签分类器,这比简单的OneVsRest更先进。
您可以找到一个如何在教程中使用scikit-multilearn的示例。对多标签分类方法的回顾可以在Tsoumakas对刚果解放运动的介绍中找到.
但是,如果碰巧标签是相互共存的,我建议使用不同的分类器--例如,在输出空间使用快速贪婪的社区检测标记Powerset和标签空间分割--我解释了为什么这在我关于标签空间划分的论文中有效。
将代码转换为使用scikit-multilearn将使其看起来如下所示:
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import HashingVectorizer
from sklearn.preprocessing import MultiLabelBinarizer
from skmultilearn.ensemble import LabelSpacePartitioningClassifier
from skmultilearn.cluster import IGraphLabelCooccurenceClusterer
from skmultilearn.problem_transform import LabelPowerset
categories = ['a', 'b', 'c']
X = ["This is a test", "This is another attempt", "And this is a test too!"]
Y = [['a', 'b'],['b'],['a','b']]
mlb = MultiLabelBinarizer(classes=categories)
vectorizer = HashingVectorizer(decode_error='ignore', n_features=2 ** 18, non_negative=True)
X_train = vectorizer.fit_transform(X)
Y_train = mlb.fit_transform(Y)
# base single-label classifier
base_classifier = MultinomialNB(alpha=0.01)
# problem transformation from multi-label to single-label
transformation_classifier = LabelPowerset(base_classifier)
# clusterer dividing the label space using fast greedy modularity maximizing scheme
clusterer = IGraphLabelCooccurenceClusterer('fastgreedy', weighted=True, include_self_edges=True)
# ensemble
clf = LabelSpacePartitioningClassifier(transformation_classifier, clusterer)
clf.fit(X_train, Y_train)
https://stackoverflow.com/questions/42280439
复制