我基本上拥有same question as this guy ..朴素贝叶斯分类器的example in the NLTK book只考虑一个单词是否作为特征出现在文档中...它不会将单词的频率视为要看的功能(“词袋”)。
One of the answers似乎暗示使用内置的NLTK分类器无法做到这一点。是这样的吗?如何用NLTK进行频率/词袋NB分类?
答案 0 :(得分:31)
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上进行训练。
答案 1 :(得分:7)
NLTK贝叶斯分类器中的功能是“名义上的”,而不是数字。这意味着它们可以采用有限数量的离散值(标签),但不能将它们视为频率。
因此,对于贝叶斯分类器,您不能直接使用单词频率作为功能 - 您可以使用每个文本中50个更频繁的单词作为您的功能集,但这是相当的不同的东西
但也许NLTK中还有其他依赖于频率的分类器。我不知道,但你看了吗?我说这值得一试。
答案 2 :(得分:3)
如果你的句子多次有相同的单词,它会多次添加probs。如果该单词在同一课程中多次出现,则您的训练数据应反映在单词计数中。
为了提高准确性,请将所有bi-gram,tri-gram等计算为单独的功能。
有助于手动编写自己的分类器,以便您准确了解正在发生的事情以及您需要做些什么才能提高准确性。如果你使用预先打包的解决方案并且它不能很好地工作,你就无法做到这一点。