我正在尝试构建一个多标签的外部文本分类器。如下所述,这个想法是在批处理中读取(大规模)文本数据集,并将它们部分拟合到分类器中。此外,当您使用此处所述的多标签实例时,这个想法是以单vs-all方式构建许多二进制分类器作为数据集中的类数。
组合sklearn的多层次列赛和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)
您可以想象最后三行应用于每个MiniBatch,为了简单起见,我已将其删除的代码。
如果您删除OneVSrestClassifier并仅使用多元素nb,则代码运行正常。
您正在传递y_train,因为它以[[1,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的内部label_binarizer_
也会决定它是类型的"多类"而不是multilabel
,然后将拒绝正确地转换类。我认为这是OnevsrestClassifer和/或LabelBinarizer中的错误。
请提交有关partial_fit
的Scikit-Learn Github的问题,看看会发生什么。
更新显然,由于周围的所有并发症,从目标向量(y)决定"多标记"或"多类"是一个正在进行的问题。
- https://github.com/scikit-learn/scikit-learn/issues/7665
- https://github.com/scikit-learn/scikit-learn/issues/5959
- https://github.com/scikit-learn/scikit-learn/issues/7931
- https://github.com/scikit-learn/scikit-learn/issues/8098
- https://github.com/scikit-learn/scikit-learn/issues/7628
- https://github.com/scikit-learn/scikit-learn/pull/2626
所以您可能期望的答案可能要不同,但是我建议您不要使用OnevSrestClassifier来使用Scikit-MultiLearn库,该库构建在Scikit-Learn上,它提供了多标签分类器,它比简单的Onevsrest更具艺术品的状态。
您可以在教程中找到如何使用Scikit-MultiLearn的示例。可以在Tsoumakas的MLC简介中找到对多标签分类方法的综述。
。但是,如果碰巧您的标签彼此同时存在,我建议使用其他分类器,例如使用标签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)