在这个问题上,过去2-3周我一直在绞尽脑汁。 我有一个多标签(而不是多类)问题,每个样本都可以属于几个标签。
我有大约450万个文本文档作为训练数据,大约有100万个作为测试数据。标签大约35K。
我正在使用 scikit-learn 。对于特征提取,我之前使用的TfidfVectorizer根本没有扩展,现在我使用的是HashVectorizer,考虑到我拥有的文档数量,它更好但不具备可扩展性。
vect = HashingVectorizer(strip_accents='ascii', analyzer='word', stop_words='english', n_features=(2 ** 10))
SKlearn提供OneVsRestClassifier,我可以在其中提供任何估算器。对于多标签,我发现了LinearSVC& SGDClassifier只能正常工作。根据我的基准,SGD在内存和外形方面都优于LinearSVC。时间。所以,我有类似的东西
clf = OneVsRestClassifier(SGDClassifier(loss='log', penalty='l2', n_jobs=-1), n_jobs=-1)
但是这有一些严重的问题:
答案 0 :(得分:8)
OneVsRestClassifier
实现的算法非常简单:当有 K 类时,它只适合 K 二进制分类器。您可以在自己的代码中执行此操作,而不是依赖OneVsRestClassifier
。您也可以在大多数 K 核心上并行执行此操作:只需运行 K 进程。如果您的计算机中有多个类而不是处理器,则可以使用GNU parallel等工具安排培训。HashingVectorizer
有潜在的优化,但我(其中一个散列代码的作者)还没有完成它。至于功能的数量,它取决于问题,但对于大规模文本分类2 ^ 10 = 1024似乎非常小。我会尝试2 ^ 18 - 2 ^ 22左右的东西。如果训练具有L1惩罚的模型,则可以在训练模型上调用sparsify
以将其权重矩阵转换为更节省空间的格式。
答案 1 :(得分:7)
我会手工制作多标签部分。无论如何,OneVsRestClassifier将它们视为独立问题。您可以创建n_labels许多分类器,然后在它们上调用partial_fit。如果你只想要哈希一次(我建议),你不能使用管道。 不确定加速哈希矢量化器。你得问@Larsmans和@ogrisel;)
在OneVsRestClassifier上使用partial_fit
将是一个很好的补充,实际上我没有看到它的特殊问题。您也可以尝试自己实现并发送PR。
答案 2 :(得分:1)
我对可伸缩性的论证是,您应该使用更高级的问题转换方法集合,而不是使用OneVsRest,它只是最简单的最简单的基线。在我的paper中,我提供了一种方案,用于将标签空间划分为子空间,并使用Label Powerset将子问题转换为多类单标签分类。要尝试此操作,只需使用以下代码,该代码使用基于scikit-learn构建的多标签库 - scikit-multilearn:
from skmultilearn.ensemble import LabelSpacePartitioningClassifier
from skmultilearn.cluster import IGraphLabelCooccurenceClusterer
from skmultilearn.problem_transform import LabelPowerset
from sklearn.linear_model import SGDClassifier
# base multi-class classifier SGD
base_classifier = SGDClassifier(loss='log', penalty='l2', n_jobs=-1)
# problem transformation from multi-label to single-label multi-class
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)
prediction = clf.predict(x_test)
答案 3 :(得分:0)
The partial_fit()
method was recently added to sklearn
so hopefully it should be available in the upcoming release (it's in the master branch already).
The size of your problem makes it attractive to tackling it with neural networks. Have a look at magpie, it should give much better results than linear classifiers.