我基本上有same question as this guy ..朴素贝叶斯分类器的example in the NLTK book只考虑一个单词是否出现在文档中作为一个特征......它不考虑单词的频率作为要素的特征(“bag-of-话”)。
One of the answers似乎暗示使用内置的NLTK分类器无法做到这一点。是这样的吗?如何用NLTK进行频率/词袋NB分类?
scikit-learn有an implementation of multinomial naive Bayes,这是在这种情况下幼稚贝叶斯的正确变种。但是,支持向量机(SVM)可能会更好地工作。
正如肯在评论中指出的那样,NLTK有a nice wrapper for scikit-learn classifiers。从文档修改,这是一个有点复杂的TF-IDF加权,根据chi2统计选择1000个最佳特征,然后将其传递给多项式朴素贝叶斯分类器。 (我敢打赌这有点笨拙,因为我对NLTK或scikit-learn都不是很熟悉。)
import numpy as np
from nltk.probability import FreqDist
from nltk.classify import SklearnClassifier
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline
pipeline = Pipeline([('tfidf', TfidfTransformer()),
('chi2', SelectKBest(chi2, k=1000)),
('nb', MultinomialNB())])
classif = SklearnClassifier(pipeline)
from nltk.corpus import movie_reviews
pos = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('pos')]
neg = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('neg')]
add_label = lambda lst, lab: [(x, lab) for x in lst]
classif.train(add_label(pos[:100], 'pos') + add_label(neg[:100], 'neg'))
l_pos = np.array(classif.classify_many(pos[100:]))
l_neg = np.array(classif.classify_many(neg[100:]))
print "Confusion matrix:\n%d\t%d\n%d\t%d" % (
(l_pos == 'pos').sum(), (l_pos == 'neg').sum(),
(l_neg == 'pos').sum(), (l_neg == 'neg').sum())
这打印给我:
Confusion matrix:
524 376
202 698
不完美,但体面,考虑到它不是一个超级简单的问题,它只在100/100训练。
NLTK贝叶斯分类器中的功能是“名义上的”,而不是数字。这意味着它们可以采用有限数量的离散值(标签),但不能将它们视为频率。
因此,使用贝叶斯分类器,您不能直接使用词频作为一个功能 - 您可以使用每个文本中50个更频繁的单词作为您的功能集,但这是完全不同的事情
但也许NLTK中还有其他分类器依赖于频率。我不知道,但你看了吗?我想说值得一试。
如果你的句子多次有相同的单词,它会多次添加probs。如果单词在同一个班级中多次出现,您的训练数据应反映在单词计数中。
为了提高准确性,请将所有二元组,三元组等计算为单独的功能。
它有助于手动编写您自己的分类器,以便您准确了解正在发生的事情以及您需要做些什么来提高准确性。如果您使用预先打包的解决方案并且它不能很好地工作,那么您无能为力。