将文档分类为类别

eri*_*kcw 32 python nlp machine-learning nltk naivebayes

我在Postgres数据库中存储了大约300k文档,这些文档标记有主题类别(总共有大约150个类别).我有另外150k文件还没有类别.我正在努力寻找以编程方式对它们进行分类的最佳方法.

我一直在探索NLTK及其朴素贝叶斯分类器.似乎是一个很好的起点(如果你可以建议一个更好的分类算法来完成这项任务,我会全力以赴).

我的问题是我没有足够的RAM来同时训练所有150个categoies/300k文件上的NaiveBayesClassifier(5个类别的培训使用8GB).此外,随着我​​在更多类别上的训练,分类器的准确性似乎下降(2个类别的准确度为90%,5%为61%,10个为61%).

我是否应该一次训练5个类别的分类器,并通过分类器运行所有150k文件以查看是否有匹配?看起来这样可行,除了会有很多误报,其中没有真正匹配任何类别的文档因为它是可用的最佳匹配而被分类器打开了...是否存在如果文档不适合任何类别,为分类器提供"无上述"选项的方法是什么?

这是我的测试类http://gist.github.com/451880

ogr*_*sel 32

您应该首先将文档转换为TF-log(1 + IDF)向量:术语频率稀疏,因此您应该使用python dict,其中term作为键并计为值,然后除以总计数以获得全局频率.

另一种解决方案是使用abs(hash(term))作为正整数键.然后你使用scipy.sparse向量比python dict更方便,更有效地执行线性代数运算.

还通过平均属于同一类别的所有标记文档的频率来构建150个频率向量.然后,对于要标记的新文档,您可以计算 文档向量和每个类别向量之间的余弦相似度,并选择最相似的类别作为文档的标签.

如果这还不够好,那么你应该尝试使用L1惩罚来训练逻辑回归模型,scikit-learn的这个例子中所解释的(这是由@ephes解释的liblinear的包装器).用于训练逻辑回归模型的向量应该是先前引入的TD-log(1 + IDF)向量,以获得良好的性能(精确度和召回率).scikit learn lib提供了一个sklearn.metrics模块,其中包含用于计算给定模型和给定数据集的分数的例程.

对于较大的数据集:你应该尝试vowpal wabbit,它可能是地球上最快的兔子,用于大规模文档分类问题(但不容易使用python包装器AFAIK).

  • Vowpal wabbit很快.但是我们仍然使用批量训练而不是在线学习算法,因为liblinear(适当优化)只需要几分钟就能完成数百万个文档(我们对特征向量进行了mmaped(共享),以便新的训练或分类过程不需要解析文件,但只循环在主内存上),它表现得更好(我现在没有数字......). (2认同)
  • 同意,当数据流无限且不再适合内存时,例如当来自流行的网络邮件提供商的"报告垃圾邮件"按钮时,vowpal wabbit非常有趣:) (2认同)
  • 此外...质心分类并不比朴素贝叶斯好多少.本文http://www2009.org/proceedings/pdf/p201.pdf是错误的.我们告诉他们,他们使用测试数据进行培训(由于一个错误),但讨论无处可去......线性SVM仍然是最先进的. (2认同)

eph*_*hes 11

你的文件有多大(单词数量)?150k trainingdocs的内存消耗应该不是问题.

朴素贝叶斯是一个很好的选择,特别是当你有很多类别,只有一些训练样例或非常嘈杂的训练数据.但总的来说,线性支持向量机确实表现得更好.

您的问题是多类(文档仅属于一个类别)或多标记(文档属于一个或多个类别)?

准确性是判断分类器性能的不良选择.您应该使用精确与召回,精确召回盈亏平衡点(prbp),f1,auc并且必须查看精确与召回曲线,其中召回(x)根据您的置信度阈值对精度(y)绘制(文件是否属于某一类别).通常,您将为每个类别构建一个二元分类器(一个类别的正面训练示例与不属于您当前类别的所有其他训练示例).您必须为每个类别选择最佳置信度阈值.如果你想将每个类别的单一措施组合成一个全球绩效指标,你必须微观(总结所有真正的积极因素,误报,

我们拥有数千万份文档,数百万个培训示例和数千个类别(多标签).由于我们面临严重的培训时间问题(每天新增,更新或删除的文档数量非常高),我们使用了liblinear的修改版本.但是对于使用liblinear(liblinear2scipyscikit-learn)周围的python包装器之一的小问题应该可以正常工作.