【发布时间】:2013-09-12 03:50:57
【问题描述】:
在过去的 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 方法,因此无法进行核外学习。有没有其他选择?
- HashingVectorizer/Tfidf 都在单核上工作并且没有任何 n_jobs 参数。散列文档花费了太多时间。任何替代方案/建议? n_features 的值也正确吗?
- 我测试了 100 万份文档。散列需要 15 分钟,当涉及到 clf.fit(X, y) 时,我收到一个 MemoryError,因为 OvR 内部使用 LabelBinarizer 并且它试图分配一个几乎不可能分配的维度矩阵(y x 类)。我该怎么办?
- 还有其他具有可靠且可扩展的多标签算法的库吗?我知道 genism 和 mahout,但他们都没有任何多标签情况?
【问题讨论】:
-
当你说“HashVectorizer 更好但不是那么可扩展”时只是一个评论:
HashVectorizer是完全可扩展的:如果你投入两倍的计算资源,你将更快地处理数据(你可以分区由于无状态和有限的内存使用,数据并并行运行处理)。这是可扩展性的确切定义。我同意HashVectorizer可能会更优化,以便在相同的计算资源上更快地工作,但这与可伸缩性问题无关。 -
感谢您的澄清。我确实同意 HV 确实优于 Tfidf,但我不确定数据分区部分。现在我做了一个小的 POC 来对数据进行分区并分别在各个部分上运行 HV,然后再组合结果。我最初的意思是算法部分的工作是一项了不起的成就,但它仍然可以像您建议的分区和并行运行一样变得更具可扩展性。 (完成后我会提交一个PR,让HV也有n_jobs参数)
-
不幸的是,在 scikit-learn 中使用的 joblib 的当前实现中,我们使用多处理,因此必须复制输入数据才能发送到子进程。因此,这样的 n_jobs 参数会增加大量开销,并且可能根本没有好处。如果您确实拥有大型数据集,最好处理许多处理数据访问(磁盘、数据库、网络......)本身的并行核外循环,以避免任何内存复制。然而,这样的样板代码可能永远不会包含在 scikit-learn 中,因为它过于项目特定/框架化。
标签: machine-learning classification scikit-learn document-classification text-classification