将文档分类
machine-learning
nlp
nltk
python
9
0

我在Postgres数据库中存储了大约30万个文档,这些文档用主题类别标记(总共约150个类别)。我还有另外15万个尚未分类的文档。我正在尝试找到以编程方式对它们进行分类的最佳方法。

我一直在探索NLTK及其朴素贝叶斯分类器。似乎是一个很好的起点(如果您可以为此任务提出更好的分类算法,我将不胜枚举)。

我的问题是我没有足够的RAM来一次对所有150个类别/ 300k文档进行NaiveBayesClassifier训练(对使用8GB的5个类别进行训练)。此外,随着我对更多类别进行训练,分类器的准确性似乎有所下降(2个类别的准确性为90%,5个类别的准确性为81%,10个类别的准确性为61%)。

我是否应该一次对5个类别的分类器进行训练,然后通过分类器运行所有15万个文档以查看是否存在匹配项?看起来这将是可行的,除了会出现很多误报,因为与分类完全不符的文档会被分类器误入歧途,因为这是可用的最佳匹配项。一种方法,使分类器具有“以上皆非”选项,以防文档不适合任何类别?

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

参考资料:
Stack Overflow
收藏
评论
共 3 个回答
高赞 时间 活跃

您的文件有多大(字数)? 150K trainingdocs的内存消耗不成问题。

朴素贝叶斯(Naive Bayes)是一个不错的选择,尤其是当您有许多类别且仅提供少量训练示例或非常嘈杂的训练数据时。但是总的来说,线性支持向量机的性能要好得多。

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

准确性是判断分类器性能的不佳选择。您应该宁愿使用Precision vs Recall,Precision Recall盈亏平衡点(prbp),f1,auc,还必须查看Precision vs Recall曲线,其中根据您的置信度阈值将Recall(x)相对于precision(y)绘制(文档是否属于类别)。通常,您将为每个类别构建一个二元分类器(一个类别的积极训练示例与不属于您当前类别的所有其他训练示例)。您必须为每个类别选择最佳置信度阈值。如果要将每个类别的单个指标合并为整体绩效指标,则必须微观(汇总所有真实肯定,错误肯定,错误否定和真实否定并计算合并分数)或宏(汇总每个类别的计算得分,然后将所有类别的得分平均)。

我们拥有数千万个文档,数百万个培训示例和数千个类别(多标签)的语料库。由于我们面临着严重的培训时间问题(每天新文档的数量,每天更新或删除的文档数量都很高),因此我们使用liblinear的修改版。但是对于较小的问题,使用围绕liblinear的python包装之一( liblinear2scipyscikit-learn )应该可以正常工作。

收藏
评论

如果文档不适合任何类别,是否可以为分类器提供“以上皆非”选项?

您可以通过每次都对“以上都不存在”的伪类别进行训练来简单地获得这种效果。如果您最多可以训练5个类别(尽管我不确定为什么它会占用大量RAM),请从其实际的2K文档中分别训练4个实际类别,并在其2K文档中“以上都不是”从其他所有146个类别中随机抽取(如果要使用“分层抽样”方法,则每个类别大约13-14个,可能更合理)。

仍然有点犹豫,您可能会采用完全不同的方法来更好-找到一个多维文档度量,将300,000个预先标记的文档定义为150个合理可分离的集群,然后仅分配彼此-未加标签的文档到由此确定的适当群集。我不认为NLTK可以直接提供任何东西来支持这种事情,但是,嘿,NLTK的发展如此之快,以至于我很可能错过了某些东西... ;-)

收藏
评论

您应该首先将文档转换为TF-log(1 + IDF)矢量 :词频是稀疏的,因此您应该使用python dict,将term作为键并计数为值,然后除以总数即可得到全局频率。

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

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

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

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

收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题