我有大约4400万个训练样本,分布在约6200个类别中。训练后,模型大小约为450MB。
在测试时,使用5个并行映射器(每个映射器都分配了足够的RAM),分类速度大约为每秒4个项目,这实在是太慢了。
如何加速呢?我想到的一种方法是减少词汇库,但我担心会损失准确性。我将maxDFPercent设置为80。
我还想到另一种方法,即通过聚类算法运行项目,并在保持每个类别内的项目限制在一个聚类内的前提下,经验性地最大化聚类的数量。这样,我可以为每个聚类构建单独的模型,从而(可能)减少训练和测试时间。
还有其他想法吗?
编辑 :
根据下面的一些回答,我开始考虑通过运行聚类算法进行某种形式的下采样,识别出彼此“高度”接近的项目组,然后从这些“高度”接近的组中取几个样本的并集,以及其他不太紧密接近的样本。
我也开始考虑使用某种形式的数据归一化技术,这些技术在使用n-gram时涉及到编辑距离(http://lucene.apache.org/core/4_1_0/suggest/org/apache/lucene/search/spell/NGramDistance.html)
我还考虑使用hadoop流API来利用Python中列出的某些机器学习库,参见这里 http://pydata.org/downloads/ 和这里 http://scikit-learn.org/stable/modules/svm.html#svm (我认为这些使用了下面一个回答中提到的liblinear
)
回答:
“但我担心会损失准确性”你真的尝试过使用更少的特征或更少的文档吗?你可能不会像你担心的那样损失那么多准确性。这里可能有几件事在起作用:
- 如此大量的文档不太可能来自同一时间段。随着时间的推移,流的内容不可避免地会发生漂移,指示一个类别的词可能会变成指示另一个类别的词。某种程度上,将今年的数据添加到去年训练的分类器中只会让它感到困惑。如果你用更少的数据进行训练,可能会获得更好的性能。
- 正如@Anony-Mousse已经说过的,大多数特征都没有帮助。你可能需要在训练分类器之前进行某种形式的特征选择。这也将加速训练。我过去在使用互信息时取得了不错的效果。
我之前为类似规模的数据集训练过分类器,发现系统在只有200k特征的情况下表现最佳,并且使用超过10%的数据进行训练并不会提高准确性。
附注:你能告诉我们更多关于你的问题和数据集的信息吗?
问题更新后的编辑:聚类是选择代表性文档的好方法,但它会花费很长时间。你还需要定期重新运行它,因为会有新的数据进来。
我不认为编辑距离是可行的方法。典型的算法在输入字符串长度上的复杂度是二次的,你可能需要为语料库中的每一对词运行。这需要很长时间!
我再次建议你尝试随机抽样。你说你担心准确性,但你在使用朴素贝叶斯。如果你想要金钱可以买到的最好的模型,你会选择非线性SVM,你可能活不到它完成训练的那一天。人们求助于已知有问题的分类器(朴素贝叶斯被称为“朴素”是有原因的),因为它们比替代方案快得多,但性能通常只会稍微差一点。让我给你举个我经验中的例子:
- RBF SVM- 85% F1分数 – 训练时间约一个月
- 线性SVM- 83% F1分数 – 训练时间约一天
- 朴素贝叶斯- 82% F1分数 – 训练时间约一天
你在文献中也会发现同样的情况:论文。出于好奇,你得到了什么样的准确性?