NLTK,朴素贝叶斯:为啥有些特征没有?

Posted

技术标签:

【中文标题】NLTK,朴素贝叶斯:为啥有些特征没有?【英文标题】:NLTK, Naive Bayes: why are some features NONE?NLTK,朴素贝叶斯:为什么有些特征没有? 【发布时间】:2016-08-16 03:26:15 【问题描述】:

我正在尝试使用 NLTK 实现朴素贝叶斯。

当我打印出信息量最大的特征时,其中一些被指定为“NONE”。这是为什么呢?

我使用的是词袋模型:当我输出特征时,每个特征都被赋值为真。

NONE 从何而来?

我读到了

The feature value 'None' is reserved for unseen feature values;

这里:http://www.nltk.org/_modules/nltk/classify/naivebayes.html

这是什么意思?

from nltk.corpus.reader import CategorizedPlaintextCorpusReader
import nltk.classify.util
from nltk.classify import NaiveBayesClassifier
from nltk.corpus import movie_reviews
import nltk.data
from nltk.corpus import stopwords
import collections
from nltk.classify.util import accuracy
import itertools
from nltk.collocations import BigramCollocationFinder
from nltk.metrics import BigramAssocMeasures
import nltk.metrics

def bag_of_words(words):
    return dict([(word, True) for word in words])

def bag_of_words_not_in_set(words, badwords):
    return bag_of_words(set(words) - set(badwords))

def bag_of_words_without_stopwords(words):
    badwords = stopwords.words("german")
    return bag_of_words_not_in_set(words, badwords)

def label_feats_from_corpus(corp, feature_detector=bag_of_words_without_stopwords):
    label_feats = collections.defaultdict(list)
    for label in corp.categories():
        for fileid in corp.fileids(categories=[label]):
            feats = feature_detector(corp.words(fileids=[fileid]))
            label_feats[label].append(feats)
    return label_feats

def split_label_feats(lfeats, split=0.75):
    train_feats = []
    test_feats = []
    for label, feats in lfeats.items():
        cutoff = int(len(feats) * split)
        train_feats.extend([(feat, label) for feat in feats[:cutoff]])
        test_feats.extend([(feat, label) for feat in feats[cutoff:]])
    return train_feats, test_feats


reader = CategorizedPlaintextCorpusReader('D:/corpus/', r'.*\.txt', cat_pattern=r'(\w+)/*')

all_words = nltk.FreqDist(w.lower() for w in reader.words())

def bigram_word_feats(words, score_fn=BigramAssocMeasures.chi_sq, n=200):
    bigram_finder = BigramCollocationFinder.from_words(words)
    bigrams = bigram_finder.nbest(score_fn, n)
    return dict([(ngram, True) for ngram in itertools.chain(words, bigrams)])

bigrams = bigram_word_feats(reader.words());

lfeats = label_feats_from_corpus(reader)

train_feats, test_feats = split_label_feats(lfeats, split=0.75)
len(train_feats)
nb_classifier = NaiveBayesClassifier.train(train_feats)


print("------------------------")
acc = accuracy(nb_classifier, test_feats)
print(acc)
print("------------------------")
feats = nb_classifier.most_informative_features(n=25)
for feat in feats:
    print(feat) # some are NONE

print("------------------------")
nb_classifier.show_most_informative_features(n=25) # some are NONE

【问题讨论】:

【参考方案1】:

我认为NaiveBayesClassifier 类的完整文档字符串解释了:

如果分类器遇到具有以下特征的输入 从未见过任何标签,而不是分配一个 所有标签的概率为 0,它将忽略该特征。

特征值“None”是为看不见的特征值保留的; 您通常不应将“无”用作其中之一的特征值 您自己的功能。

如果您的数据包含从未与标签关联的特征,则该特征的值将为None。假设你训练了一个带有特征WX 的分类器,然后用特征WXZ 对某些东西进行分类。 None 的值将用于特征 Z,因为该特征在训练中从未见过。

进一步说明:

看到None 我并不感到惊讶,因为语言数据很少。在电影评论语料库中,会有一些词只出现在 1 或 2 个文档中。例如,演员的名字或标题中的单词可能只出现在 1 条评论中。

在分析之前从语料库中删除频繁(停止)和不频繁的单词是很常见的。对于他们的主题模型 Science,Blei and Lafferty (2007) 写道:“这个集合中的总词汇量是 375,144 个术语。我们修剪了出现少于 70 次的 356,195 个术语以及 296 个停止词。”

【讨论】:

感谢您的回复!我仍然不完全明白这是怎么发生的。假设我的语料库包含关于这个词。我使用了词袋模型,所以我给这个特征赋值“真”。 about这个词在我的语料库中,不在我的停用词列表中,当我输出特征时,我可以看到每个特征都被赋值为“true”。你能在我的代码中发现任何错误吗?我将 75% 的语料库用于训练,25% 用于测试。 “none”表示在我的测试部分中存在从未分配过标签的单词? 我在您的代码中看不到任何错误。是的,我的理解是None 表示在训练期间从未遇到带有标签的单词。我用一些额外的解释更新了我的答案。 嗯……还是有点奇怪。除了停用词列表,我不做任何修剪。你的意思是 NLTK 的 NB 分类器会自动进行这种修剪吗? 你得到None 因为你没有做任何修剪。如果您修剪词汇表,None 值的频率会下降; NB 分类器不会自动修剪。这是您在分析之前为了降低特征空间的维数而做的事情。 啊,现在我明白了。删除不常用的单词,否则会被分配为“无”,对吗? (对不起,我对此完全陌生)

以上是关于NLTK,朴素贝叶斯:为啥有些特征没有?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Python Pandas 从 NLTK 运行朴素贝叶斯?

NLTK 的朴素贝叶斯分类器是不是适合商业应用?

python nltk 朴素贝叶斯概率

SparkMLib分类算法之朴素贝叶斯分类

无法在朴素贝叶斯中训练模型

NLTK 朴素贝叶斯分类错误