在过去的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)
但是它存在一些严重问题:
- OneVsRest没有partial_fit方法,这使得它无法进行 out-of-core 学习。有其他的替代方法吗?
- HashingVectorizer/Tfidf 都只能在单核上运行,并且没有 n_jobs 参数。哈希文档需要太长时间。有其他的方案/建议吗?另外,n_features 的值是否正确?
- 我测试了100万个文档。哈希需要15分钟,当进行 clf.fit(X, y) 时,会收到 MemoryError 错误,因为 OvR 内部使用 LabelBinarizer 并尝试分配一个(y x 类别数)维度的矩阵,这几乎不可能分配。该怎么办?
- 还有其他可靠且可扩展的多标签算法库吗?我知道 genism 和 mahout,但它们都没有针对多标签情况的任何内容?
HashVectorizer
是完全可扩展的:如果你投入两倍的计算资源,你将以两倍的速度处理数据(你可以通过分区数据并运行处理来并行使用它的无状态和有限内存使用)。这就是可扩展性的确切定义。我同意HashVectorizer
可能可以更优化,以在相同的计算资源上更快地工作,但这与可扩展性问题无关。 - ogrisel