N元语法与朴素贝叶斯分类器

10

我是Python的新手,需要帮助! 我正在使用Python NLTK文本分类练习。 这是我正在练习的代码示例: http://www.laurentluce.com/posts/twitter-sentiment-analysis-using-python-and-nltk/

我尝试过这个。

from nltk import bigrams
from nltk.probability import ELEProbDist, FreqDist
from nltk import NaiveBayesClassifier
from collections import defaultdict

train_samples = {}

with file ('positive.txt', 'rt') as f:
   for line in f.readlines():
       train_samples[line]='pos'

with file ('negative.txt', 'rt') as d:
   for line in d.readlines():
       train_samples[line]='neg'

f=open("test.txt", "r")
test_samples=f.readlines()

def bigramReturner(text):
    tweetString = text.lower()
    bigramFeatureVector = {}
    for item in bigrams(tweetString.split()):
        bigramFeatureVector.append(' '.join(item))
    return bigramFeatureVector

def get_labeled_features(samples):
    word_freqs = {}
    for text, label in train_samples.items():
        tokens = text.split()
        for token in tokens:
            if token not in word_freqs:
                word_freqs[token] = {'pos': 0, 'neg': 0}
            word_freqs[token][label] += 1
    return word_freqs


def get_label_probdist(labeled_features):
    label_fd = FreqDist()
    for item,counts in labeled_features.items():
        for label in ['neg','pos']:
            if counts[label] > 0:
                label_fd.inc(label)
    label_probdist = ELEProbDist(label_fd)
    return label_probdist


def get_feature_probdist(labeled_features):
    feature_freqdist = defaultdict(FreqDist)
    feature_values = defaultdict(set)
    num_samples = len(train_samples) / 2
    for token, counts in labeled_features.items():
        for label in ['neg','pos']:
            feature_freqdist[label, token].inc(True, count=counts[label])
            feature_freqdist[label, token].inc(None, num_samples - counts[label])
            feature_values[token].add(None)
            feature_values[token].add(True)
    for item in feature_freqdist.items():
        print item[0],item[1]
    feature_probdist = {}
    for ((label, fname), freqdist) in feature_freqdist.items():
        probdist = ELEProbDist(freqdist, bins=len(feature_values[fname]))
        feature_probdist[label,fname] = probdist
    return feature_probdist



labeled_features = get_labeled_features(train_samples)

label_probdist = get_label_probdist(labeled_features)

feature_probdist = get_feature_probdist(labeled_features)

classifier = NaiveBayesClassifier(label_probdist, feature_probdist)

for sample in test_samples:
    print "%s | %s" % (sample, classifier.classify(bigramReturner(sample)))

但是为什么会出现这个错误?

    Traceback (most recent call last):
  File "C:\python\naive_test.py", line 76, in <module>
    print "%s | %s" % (sample, classifier.classify(bigramReturner(sample)))
  File "C:\python\naive_test.py", line 23, in bigramReturner
    bigramFeatureVector.append(' '.join(item))
AttributeError: 'dict' object has no attribute 'append'

为什么你不使用 Weka,是因为这是你的作业吗? - Grijesh Chauhan
这段代码是用于双字母组合的。 - Grijesh Chauhan
1个回答

16

一个二元特征向量遵循与一个一元特征向量完全相同的原则。因此,就像您提到的教程一样,您将不得不检查是否存在任何文档中使用了二元特征。

至于如何提取二元特征以及提取它们的代码,我已经在下面写好了。您可以简单地采用它们来更改教程中的变量“tweets”。

import nltk
text = "Hi, I want to get the bigram list of this string"
for item in nltk.bigrams (text.split()): print ' '.join(item)

你可以将它们附加到“tweets”列表中,而不是打印它们,然后就可以了!希望这足够有帮助。否则,请告诉我您是否仍有问题。

请注意,在情感分析等应用程序中,一些研究人员倾向于对单词进行标记化并去除标点符号,而另一些则不这样做。从经验上看,我知道如果您不删除标点符号,Naive贝叶斯算法准确率几乎相同,但SVM的准确率会降低。您可能需要尝试一下这些操作并决定在您的数据集上哪种操作更有效。

编辑1:

有一本名为“Python自然语言处理”的书,我可以推荐给你。它包含一些双词组的示例和练习。但是,我认为您甚至可以不用它来解决这个问题。选择使用双词组作为特征的主要思想是我们想知道单词A在我们的语料库中紧随单词B出现的概率。因此,例如,在以下句子中:

"我开着一辆卡车"

单个词特征将是这4个单词,而双词特征将是:

["我开", "开着", "着一辆", "一辆卡车"]

现在,您想使用这3个作为您的特征。因此,以下代码函数将字符串的所有双词组放入名为bigramFeatureVector的列表中。

def bigramReturner (tweetString):
  tweetString = tweetString.lower()
  tweetString = removePunctuation (tweetString)
  bigramFeatureVector = []
  for item in nltk.bigrams(tweetString.split()):
      bigramFeatureVector.append(' '.join(item))
  return bigramFeatureVector
请注意,您需要编写自己的removePunctuation函数。上述函数的输出是二元组特征向量。您将按照在提到的教程中处理单元特征向量的方式来处理它。

啊啊啊,不懂如何在Python中使用bigrams...有没有教程? - Aikin
我已经编辑了我的问题,你能帮我解决我遇到的错误吗? 我使用了你的代码。 - Aikin
在我的代码中,你可以看到我定义了一个列表,像这样:(bigramFeatureVector = [])。然而,由于某种原因,你把它改成了(bigramFeatureVector = {}),这是一个字典。命令“append”不能用于字典! - user823743
翻译:打字时出错了,但仍然出现错误回溯(Traceback): 在“C:\python\naive_test.py”的第74行,打印“%s | %s” % (sample, classifier.classify(bigramReturner(sample)))。 在“C:\python\lib\site-packages\nltk\classify\naivebayes.py”的第88行,分类器无法执行,返回self.prob_classify(featureset).max()。 在“C:\python\lib\site-packages\nltk\classify\naivebayes.py”的第94行,featureset = featureset.copy(),但是'list'对象没有'copy'属性。 - Aikin
我是编程新手,你能告诉我我的代码是否正确吗?我真的很感激你的帮助。也许我的理解有误((( - Aikin
@Aikin 使用 featureset[:] 替代 featureset.copy() - Poik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接