2

我正在使用 Python 中的 NLTK 构建垃圾邮件过滤器。我现在检查单词的出现并使用 NaiveBayesClassifier 产生 0.98 的准确度和 0.92 的垃圾邮件和非垃圾邮件的 F 度量:0.98。但是,当检查我的程序错误的文档时,我注意到很多被归类为非垃圾邮件的垃圾邮件都是非常短的消息。

所以我想把文档的长度作为 NaiveBayesClassifier 的一个特征。问题是它现在只处理二进制值。除了例如说:长度<100 = true / false之外,还有其他方法吗?

(ps 我已经构建了类似于http://nltk.googlecode.com/svn/trunk/doc/book/ch06.html示例的垃圾邮件检测器)

4

2 回答 2

3

有 MultiNomial NaiveBayes 算法可以处理范围值,但未在 NLTK 中实现。对于 NLTK NaiveBayesClassifier,您可以尝试将几个不同的长度阈值作为二进制特征。我还建议尝试使用 Maxent 分类器来查看它如何处理较小的文本。

于 2011-03-10T15:24:49.870 回答
3

NLTK 的朴素贝叶斯实现没有这样做,但您可以将 NaiveBayesClassifier 的预测与文档长度的分布结合起来。NLTK 的 prob_classify 方法将为您提供给定文档中单词的类的条件概率分布,即 P(cl|doc)。你想要的是 P(cl|doc,len) - 给定文档中的单词及其长度的类的概率。如果我们再做一些独立性假设,我们会得到:

P(cl|doc,len) = (P(doc,len|cl) * P(cl)) / P(doc,len)
              = (P(doc|cl) * P(len|cl) * P(cl)) / (P(doc) * P(len))
              = (P(doc|cl) * P(cl)) / P(doc) * P(len|cl) / P(len)
              = P(cl|doc) * P(len|cl) / P(len)

您已经从 prob_classify 中得到了第一项,所以剩下要做的就是估计 P(len|cl) 和 P(len)。

在对文档长度建模时,您可以随心所欲,但要开始,您可以假设文档长度的日志是正态分布的。如果您知道每个类和整体中日志文档长度的平均值和标准差,那么很容易计算 P(len|cl) 和 P(len)。

这是估计 P(len) 的一种方法:

from nltk.corpus import movie_reviews
from math import sqrt,log
import scipy

loglens = [log(len(movie_reviews.words(f))) for f in movie_reviews.fileids()]
sd = sqrt(scipy.var(loglens)) 
mu = scipy.mean(loglens)

p = scipy.stats.norm(mu,sd)

要记住的唯一棘手的事情是,这是对数长度而不是长度的分布,并且它是连续分布。因此,长度为 L 的文档的概率为:

p.cdf(log(L+1)) - p.cdf(log(L))

可以使用每个类中文档的对数长度以相同的方式估计条件长度分布。这应该为您提供 P(cl|doc,len) 所需的内容。

于 2011-03-12T22:49:35.660 回答