Анализ настроений, наивная байесовская точность - PullRequest
0 голосов
/ 28 октября 2018

Я пытаюсь сформировать наивный байесовский классификатор для классификации настроений твитов.Я вставляю весь свой код здесь, потому что я знаю, что получу ад, если не сделаю.Таким образом, я в основном использую корпуса NLTK в качестве обучающих данных, а затем некоторые твиты, которые я выбрал в качестве тестовых данных.Я предварительно обрабатываю их и делаю мешок с извлечением слов.Классификатор обучен без проблем, и когда я делаю следующее

print(classifier.classify(bag_of_words('This is magnificent')))  

, он корректно выводит 'pos'.

Теперь моя проблема заключается в том, как рассчитать точность, используя точность ntlk.util.Я делаю

print(nltk.classify.accuracy(classifier, proc_set))

и получаю следующую ошибку:

  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-   packages/nltk/classify/util.py", line 87, in accuracy
  results = classifier.classify_many([fs for (fs, l) in gold])
  AttributeError: 'NaiveBayesClassifier' object has no attribute 'classify_many'

Я также попробовал это

test_set_final=[]
for tweet in proc_test:
test_set_final.append((bag_of_words(tweet),   classifier.classify(bag_of_words(tweet))))

print(nltk.classify.accuracy(classifier, test_set_final))

, и я получаю такую ​​же ошибку

print(nltk.classify.accuracy(classifier, test_set_final))
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/nltk/classify/util.py", line 87, in accuracy
results = classifier.classify_many([fs for (fs, l) in gold])
AttributeError: 'NaiveBayesClassifier' object has no attribute 'classify_many'

Я на 100% упускаю что-то чрезвычайно очевидное для машиностроителей. Я думаю, что прошло уже 3 дня, и я постепенно схожу с ума, поэтому любая помощь будет оценена.

Код ->

import nltk
import ast
import string
import re
import csv
import textblob
import pandas as pd
import numpy as np
import itertools
from textblob import TextBlob
from textblob import Word
from textblob.classifiers import NaiveBayesClassifier
from nltk.corpus import twitter_samples
from nltk.corpus import stopwords
from nltk.corpus import wordnet as wd
from nltk.tokenize import word_tokenize
from sklearn.feature_extraction.text import CountVectorizer
from random import shuffle
from nltk.classify.util import accuracy
from autocorrect import spell

stopwords = stopwords.words('english')
lemmatizer = nltk.WordNetLemmatizer().lemmatize
punct=['"','$','%','&','\',''','(',')','+',',','-     ','.','/',':',';','<','=','>','@','[','\',','^','_','`','{','|','}','~']

emoticons_happy = set([
':)', ';)', ':o)', ':]', ':3', ':c)', ':>', '=]', '8)', '=)', ':}',
':^)', ':-D', ':D', ': D','8-D', '8D', 'x-D', 'xD', 'X-D', 'XD', '=-D', '=D',
'=-3', '=3', ':-))', ':-)', ":'-)", ":')", ':*', ':^*', '>:P', ':-P', ':P', 'X-P',
'x-p', 'xp', 'XP', ':-p', ':p', '=p', ':-b', ':b', '>:)', '>;)', '>:-)',
'<3',':*', ':p'
])

emoticons_sad = set([
':L', ':-/', '>:/', ':S', '>:[', ':@', ':-(', ':[', ':-||', '=L', ':<',
':-[', ':-<', '=\\', '=/', '>:(', ':-(', '>.<', ":'-(", ":'(", ':\\', ':-c',
':c', ':{', '>:\\', ';('
])
emoticons = emoticons_happy.union(emoticons_sad)


def pre_process(tweet):

    tweet = re.sub(r'https?:\/\/.*[\r\n]*', '', tweet)

    tweet = re.sub(r'#', '', tweet)

    tweet=''.join([i for i in tweet if not i.isdigit()])

    tweet=re.sub(r'([.,/#!$%^&*;:{}=_`~-])([.,/#!$%^&*;:{}=_`~-]+)\1+', r'\1',tweet)

    tweet = re.sub(r'@[A-Za-z0-9]+', '', tweet)

    tweet=''.join([i for i in tweet if i not in emoticons])

    tweet=''.join([i for i in tweet if i not in punct])

    tweet=' '.join([i for i in tweet.split() if i not in stopwords])

    tweet=tweet.lower()

    tweet=lemmatize(tweet)

    return tweet

def get_wordnet_pos(treebank_tag):
    if treebank_tag.startswith('J'):
        return wd.ADJ
    elif treebank_tag.startswith('V'):
        return wd.VERB
    elif treebank_tag.startswith('N'):
        return wd.NOUN
    elif treebank_tag.startswith('R'):
        return wd.ADV
    else:
        return wd.NOUN

def lemmatize(tt):
    pos = nltk.pos_tag(nltk.word_tokenize(tt))
    lemm = [lemmatizer(sw[0], get_wordnet_pos(sw[1])) for sw in pos]
    sentence= ' '.join([i for i in lemm])

    return sentence


test_tweets=[]
file=open('scraped_tweets.csv', 'r')
reader = csv.reader(file)
for line in reader:
    line=line[1]
    test_tweets.append(line)

pos_tweets = twitter_samples.strings('positive_tweets.json')
neg_tweets = twitter_samples.strings('negative_tweets.json')



proc_train_pos=[]
for tweet in pos_tweets:
    proc_train_pos.append(pre_process(tweet))
proc_train_neg=[]
for tweet in neg_tweets:
    proc_train_neg.append(pre_process(tweet))
proc_test=[]
for tweet in test_tweets:
    proc_test.append(pre_process(tweet))


def bag_of_words(tweet):
    words_dictionary = dict([word, True] for word in tweet.split())    
    return words_dictionary

pos_tweets_set = []
for tweet in proc_train_pos:
    pos_tweets_set.append((bag_of_words(tweet), 'pos'))    

neg_tweets_set = []
for tweet in proc_train_neg:
    neg_tweets_set.append((bag_of_words(tweet), 'neg'))

shuffle(pos_tweets_set)
shuffle(neg_tweets_set)
train_set = pos_tweets_set+neg_tweets_set

classifier = NaiveBayesClassifier(train_set)
print('Training is done')

#print(classifier.classify(bag_of_words('This is magnificent'))) #output 'pos'

print(nltk.classify.accuracy(classifier, proc_set))

Ответы [ 2 ]

0 голосов
/ 28 октября 2018

Три быстрых идеи (без повторного запуска всего вашего кода, поскольку у меня нет ваших данных):

1) Я не вижу proc_set в вашем коде выше. Я скучаю по нему, или это ошибка?

2) Я вижу синтаксис classifier.accuracy(proc_set), поэтому я попробую это просто потому, что это легко. Это, кажется, делает фактическую классификацию и точность за один шаг.

3) Если это не сработает: classifier.classify(proc_set) работает? Если это так, у вас есть возможность самостоятельно рассчитать точность, что довольно просто.

0 голосов
/ 28 октября 2018

Ну, как говорится в сообщении об ошибке, у классификатора, который вы пытаетесь использовать (NaiveBayesClassifier), нет метода classify_many, который требуется для функции nltk.classify.util.accuracy.

(Ссылка: https://www.nltk.org/_modules/nltk/classify/naivebayes.html)

Теперь это похоже на ошибку NLTK, но вы можете легко получить свой ответ самостоятельно:

from sklearn.metrics import accuracy_score

y_predicted = [classifier.classify(x) for x in proc_set]

accuracy = accuracy_score(y_true, y_predicted)

Где y_true - это значения настроений, соответствующие proc_set входам (хотя я не вижу, чтобы вы на самом деле создавали их в приведенном выше коде).

Надеюсь, это поможет.

EDIT:

Или без использования функции точности sklearn, но с чистым Python:

hits = [yp == yt for yp, yt in zip(y_predicted, y_true)]

accuracy = sum(hits)/len(hits)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...