朴素贝叶斯的 nltk 词干和停用词
Posted
技术标签:
【中文标题】朴素贝叶斯的 nltk 词干和停用词【英文标题】:nltk stemming and stop words for naive bayes 【发布时间】:2017-04-30 08:06:12 【问题描述】:我希望了解为什么使用词干和停用词会导致我的朴素贝叶斯分类器的结果更差。
我有两个文件,正面评价和负面评价,它们都有大约 200 行但字数很多,每行可能有 5000 个字。
我有以下代码创建一个词袋,然后我创建了两个用于训练和测试的特征集,然后我针对 nltk 分类器运行它
word_features = list(all_words.keys())[:15000]
testing_set = featuresets[10000:]
training_set = featuresets[:10000]
nbclassifier = nltk.NaiveBayesClassifier.train(training_set)
print((nltk.classify.accuracy(nbclassifier, testing_set))*100)
nbclassifier.show_most_informative_features(30)
这会产生大约 45000 个单词,准确度为 85%。
我已经研究过在我的训练数据中添加词干提取 (PorterStemmer) 和删除停用词,但是当我再次运行分类器时,我现在在我的分类器中得到 205 个词和 0% 的准确度,并且在测试脚本生成的其他分类器时错误
Traceback (most recent call last):
File "foo.py", line 108, in <module>
print((nltk.classify.accuracy(MNB_classifier, testing_set))*100)
File "/Library/Python/2.7/site-packages/nltk/classify/util.py", line 87, in accuracy
results = classifier.classify_many([fs for (fs, l) in gold])
File "/Library/Python/2.7/site-packages/nltk/classify/scikitlearn.py", line 83, in classify_many
X = self._vectorizer.transform(featuresets)
File "/Library/Python/2.7/site-packages/sklearn/feature_extraction/dict_vectorizer.py", line 293, in transform
return self._transform(X, fitting=False)
File "/Library/Python/2.7/site-packages/sklearn/feature_extraction/dict_vectorizer.py", line 184, in _transform
raise ValueError("Sample sequence X is empty.")
ValueError: Sample sequence X is empty.
我不明白为什么添加词干和/或删除停用词会破坏分类器?
【问题讨论】:
这听起来像是一个相当大的差异,很难判断是否存在错误或它是否正常工作。但总的来说,词干和停用词删除并不能保证(甚至往往暗示)更好的性能。 删除停用词和词尾会让您从 45000 个词减少到 205 个词?没门。检查过滤后的文本数据,找出您的过滤出了什么问题。 【参考方案1】:添加词干或删除停用词可能不会导致您的问题。我认为由于您阅读文件的方式,您的代码中存在进一步的问题。当我在 YouTube 上关注 sentdex's tutorial 时,我遇到了同样的错误。我被困了一个小时,但我终于明白了。如果你按照他的代码,你会得到这个:
short_pos = open("short_reviews/positive.txt", "r").read()
short_neg = open("short_reviews/negative.txt", "r").read()
documents = []
for r in short_pos.split('\n'):
documents.append( (r, 'pos' ))
for r in short_neg.split('\n'):
documents.append( (r, 'neg' ))
all_words = []
short_pos_words = word_tokenize(short_pos)
short_neg_words = word_tokenize(short_neg)
for w in short_pos_words:
all_words.append(w.lower())
for w in short_neg_words:
all_words.append(w.lower())
all_words = nltk.FreqDist(all_words)
word_features = list(all_words.keys())[:5000]
我一直遇到这个错误:
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x97 in position 6056: invalid start byte
。
您收到此错误是因为 files provided 中没有 UTF-8 字符。通过将代码更改为以下代码,我能够绕过错误:
fname = 'short_reviews/positive.txt'
with open(fname, 'r', encoding='utf-16') as f:
for line in f:
pos_lines.append(line)
不幸的是,然后我开始收到此错误:
UnicodeError: UTF-16 stream does not start with BOM
我忘记了怎么做,但我也让这个错误消失了。然后我开始收到与您原来的问题相同的错误:
ValueError: Sample sequence X is empty.
当我打印featuresets
的长度时,我看到它只有2。
print("Feature sets list length : ", len(featuresets))
在这个网站上挖掘之后,我发现了这两个问题:
-
Delete every non utf-8 symbols froms string
'str' object has no attribute 'decode' in Python3
第一个并没有真正帮助,但第二个解决了我的问题(注意:我使用的是python-3)。
我不是一对一的班轮,但这对我有用:
pos_lines = [line.rstrip('\n') for line in open('short_reviews/positive.txt', 'r', encoding='ISO-8859-1')]
如果您想查看完整的解决方案,我将在本周晚些时候更新 my github repo 并提供 nlp 教程的完整代码。我意识到这个答案可能来得太晚了 2 年,但希望它有所帮助。
【讨论】:
以上是关于朴素贝叶斯的 nltk 词干和停用词的主要内容,如果未能解决你的问题,请参考以下文章