首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将文档分类为多个类别

将文档分类为多个类别
EN

Stack Overflow用户
提问于 2010-06-25 03:56:42
回答 3查看 13.9K关注 0票数 33

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

我一直在探索NLTK及其朴素的贝叶斯分类器。这似乎是一个很好的起点(如果你能为这项任务提出一个更好的分类算法,我洗耳恭听)。

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

我应该一次只训练5个类别的分类器,然后通过分类器运行所有15万个文档,看看是否有匹配的文档?这似乎是可行的,只是会有很多误报,那些与任何类别都不匹配的文档会被分类器硬塞进去,因为它是可用的最佳匹配……有没有办法让分类器有一个“以上都不是”的选项,以防文档不适合任何类别?

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-06-25 05:55:17

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

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

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

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

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

票数 33
EN

Stack Overflow用户

发布于 2010-06-25 04:45:05

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

朴素贝叶斯是一个很好的选择,特别是当你有许多类别,只有几个训练样本或非常嘈杂的训练数据时。但总的来说,线性支持向量机的性能确实要好得多。

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

准确性是判断分类器性能的一个很差的选择。你应该使用精确度vs召回率,精确度召回率盈亏平衡点(prbp),f1,auc,并且必须查看精确度vs召回率曲线,其中召回率(x)与精确度(y)基于您的置信度阈值(文档是否属于某个类别)绘制。通常,您将为每个类别构建一个二元分类器(一个类别的正训练样本与不属于当前类别的所有其他训练样本相比)。你必须为每个类别选择一个最优的置信度阈值。如果您想要将每个类别的这些单个度量组合为一个全局性能度量,您必须使用微观(将所有真阳性、假阳性、假阴性和真阴性相加,并计算组合分数)或宏观(计算每个类别的分数,然后将所有类别的分数平均)平均值。

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

票数 11
EN

Stack Overflow用户

发布于 2010-06-25 04:42:56

有没有办法在文档不属于任何类别的情况下,为分类器提供“不属于上述任何一项”的选项?

你可以通过每次训练一个“以上都不是”的伪类来达到这个效果。如果你可以训练的最大值是5个类别(尽管我不知道为什么它会消耗这么多的RAM),那么训练4个实际的类别,每个类别实际有2K个文档,还有一个“上面没有”的类别,它的2K文档是从所有其他146个类别中随机抽取的(如果你想要“分层抽样”的方法,可能会更合理,每个类别大约13-14个)。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3113428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档