bgc*_*ode 23 python nlp machine-learning nltk naivebayes
我基本上和这个家伙有同样的问题 .NNive Bayes分类器的NLTK书中的例子只考虑一个单词是否作为一个特征在文档中出现..它不考虑单词的频率作为特征看看("词袋").
其中一个答案似乎表明,使用内置的NLTK分类器无法做到这一点.是这样的吗?如何用NLTK进行频率/词袋NB分类?
Dou*_*gal 31
scikit-learn有一个多项式朴素贝叶斯的实现,这是在这种情况下朴素贝叶斯的正确变体.但是,支持向量机(SVM)可能会更好地工作.
正如Ken在评论中指出的那样,NLTK有一个很好的scikit-learn分类器包装器.从文档修改,这是一个有点复杂的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())
Run Code Online (Sandbox Code Playgroud)
这打印给我:
Confusion matrix:
524 376
202 698
Run Code Online (Sandbox Code Playgroud)
不完美,但体面,考虑到它不是一个超级简单的问题,它只在100/100训练.
NLTK贝叶斯分类器中的功能是"名义上的",而不是数字.这意味着它们可以采用有限数量的离散值(标签),但不能将它们视为频率.
因此,使用贝叶斯分类器,您不能直接使用词频作为一个功能 - 您可以使用每个文本中50个更频繁的单词作为您的功能集,但这是完全不同的事情
但也许NLTK中还有其他分类器依赖于频率.我不知道,但你看了吗?我想说值得一试.