33

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

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

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

我是否应该一次只训练 5 个类别的分类器,然后通过分类器运行所有 150k 文档以查看是否有匹配项?似乎这会起作用,除了会有很多误报,其中与任何类别都不真正匹配的文档会被分类器硬塞进去,只是因为它是可用的最佳匹配......有吗?一种为分类器提供“以上都不是”选项的方法,以防文档不适合任何类别?

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

4

3 回答 3

33

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

另一种解决方案是使用 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)。

于 2010-06-24T21:55:16.733 回答
11

您的文档有多大(字数)?150K 训练文档的内存消耗应该不是问题。

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

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

准确度是判断分类器性能的一个糟糕选择。您应该使用精确率与召回率、精确率召回盈亏平衡点 (prbp)、f1、auc 并且必须查看精确率与召回率曲线,其中召回率 (x) 根据您的置信度阈值与精度 (y) 绘制(无论文档是否属于某个类别)。通常您会为每个类别构建一个二元分类器(一个类别的正训练示例与不属于您当前类别的所有其他训练示例)。您必须为每个类别选择一个最佳置信度阈值。如果你想将每个类别的这些单一衡量标准组合成一个全局绩效衡量标准,你必须微观(总结所有真阳性,假阳性,

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

于 2010-06-24T20:45:05.283 回答
2

有没有办法为分类器设置“以上都不是”选项,以防文档不适合任何类别?

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

仍然感觉有点杂乱无章,使用完全不同的方法可能会更好——找到一个多维文档度量,将 300K 预标记文档定义为 150 个可合理分离的集群,然后只分配其他每个集群-未标记的文档到如此确定的适当集群。我不认为 N​​LTK 有任何直接可用的东西来支持这种事情,但是,嘿,NLTK 发展得如此之快,以至于我很可能错过了一些东西......;-)

于 2010-06-24T20:42:55.973 回答