2014-05-23 18 views
9

Jestem nowicjuszem w Pythonie i Stackoverflow (proszę bądź łagodny) i staram się nauczyć, jak przeprowadzić analizę sentymentów. Używam kombinacji kodu znalazłem w tutorialu i tutaj: Python - AttributeError: 'list' object has no attribute Jednak wciąż otrzymujęPrzetwarzanie tekstu w języku Python: AttributeError: obiekt 'list' nie ma atrybutu 'niższego'

Traceback (most recent call last): 
    File "C:/Python27/training", line 111, in <module> 
    processedTestTweet = processTweet(row) 
    File "C:/Python27/training", line 19, in processTweet 
    tweet = tweet.lower() 
AttributeError: 'list' object has no attribute 'lower'` 

To jest mój kod:

import csv 
#import regex 
import re 
import pprint 
import nltk.classify 


#start replaceTwoOrMore 
def replaceTwoOrMore(s): 
    #look for 2 or more repetitions of character 
    pattern = re.compile(r"(.)\1{1,}", re.DOTALL) 
    return pattern.sub(r"\1\1", s) 

# process the tweets 
def processTweet(tweet): 
    #Convert to lower case 
    tweet = tweet.lower() 
    #Convert www.* or https?://* to URL 
    tweet = re.sub('((www\.[\s]+)|(https?://[^\s]+))','URL',tweet) 
    #Convert @username to AT_USER 
    tweet = re.sub('@[^\s]+','AT_USER',tweet) 
    #Remove additional white spaces 
    tweet = re.sub('[\s]+', ' ', tweet) 
    #Replace #word with word 
    tweet = re.sub(r'#([^\s]+)', r'\1', tweet) 
    #trim 
    tweet = tweet.strip('\'"') 
    return tweet 

#start getStopWordList 
def getStopWordList(stopWordListFileName): 
    #read the stopwords file and build a list 
    stopWords = [] 
    stopWords.append('AT_USER') 
    stopWords.append('URL') 

    fp = open(stopWordListFileName, 'r') 
    line = fp.readline() 
    while line: 
     word = line.strip() 
     stopWords.append(word) 
     line = fp.readline() 
    fp.close() 
    return stopWords 

def getFeatureVector(tweet, stopWords): 
    featureVector = [] 
    words = tweet.split() 
    for w in words: 
     #replace two or more with two occurrences 
     w = replaceTwoOrMore(w) 
     #strip punctuation 
     w = w.strip('\'"?,.') 
     #check if it consists of only words 
     val = re.search(r"^[a-zA-Z][a-zA-Z0-9]*[a-zA-Z]+[a-zA-Z0-9]*$", w) 
     #ignore if it is a stopWord 
     if(w in stopWords or val is None): 
      continue 
     else: 
      featureVector.append(w.lower()) 
    return featureVector 

def extract_features(tweet): 
    tweet_words = set(tweet) 
    features = {} 
    for word in featureList: 
     features['contains(%s)' % word] = (word in tweet_words) 
    return features 


#Read the tweets one by one and process it 
inpTweets = csv.reader(open('C:/GsTraining.csv', 'rb'), 
         delimiter=',', 
         quotechar='|') 
stopWords = getStopWordList('C:/stop.txt') 
count = 0; 
featureList = [] 
tweets = [] 

for row in inpTweets: 
    sentiment = row[0] 
    tweet = row[1] 
    processedTweet = processTweet(tweet) 
    featureVector = getFeatureVector(processedTweet, stopWords) 
    featureList.extend(featureVector) 
    tweets.append((featureVector, sentiment)) 

# Remove featureList duplicates 
featureList = list(set(featureList)) 

# Generate the training set 
training_set = nltk.classify.util.apply_features(extract_features, tweets) 

# Train the Naive Bayes classifier 
NBClassifier = nltk.NaiveBayesClassifier.train(training_set) 

# Test the classifier 
with open('C:/CleanedNewGSMain.txt', 'r') as csvinput: 
    with open('GSnewmain.csv', 'w') as csvoutput: 
    writer = csv.writer(csvoutput, lineterminator='\n') 
    reader = csv.reader(csvinput) 

    all=[] 
    row = next(reader) 

    for row in reader: 
     processedTestTweet = processTweet(row) 
     sentiment = NBClassifier.classify(
      extract_features(getFeatureVector(processedTestTweet, stopWords))) 
     row.append(sentiment) 
     processTweet(row[1]) 

    writer.writerows(all) 

Wszelkie pomoc byłaby znacznie doceniane.

Odpowiedz

8

Wynik z czytnika csv to lista, lower działa tylko na łańcuchach. Przypuszczalnie jest to lista ciągów znaków, więc są dwie opcje. Możesz zadzwonić pod numer lower w każdym elemencie lub zmienić listę w ciąg znaków, a następnie zadzwonić pod numer lower.

# the first approach 
[item.lower() for item in tweet] 

# the second approach 
' '.join(tweet).lower() 

Ale bardziej rozsądnie (trudno powiedzieć bez większej ilości informacji) faktycznie chcesz tylko jeden element z listy. Coś wzdłuż linii:

for row in reader: 
    processedTestTweet = processTweet(row[0]) # Again, can't know if this is actually correct without seeing the file 

Ponadto, domyślając się, że nie używasz czytnika csv zupełnie jak myślisz, że jesteś, bo teraz jesteś szkolenia naiwny klasyfikator bayesowski na jednym przykład za każdym razem, a następnie przewidując jeden przykład, na którym został przeszkolony. Może wyjaśnisz, co próbujesz zrobić?

+0

Dziękuję za szybką reakcję. Próbuję: mam mały zestaw szkoleniowy .csv z 1000 pozytywnych i 1000 negatywnych wypowiedzi. Szkolenie wydaje się działać tak, jak testowałem to po prostu twardym kodowaniu w instrukcji testowej, np. ' to wspaniale!'. Mam jednak plik z około 10000 tweetami i postami na Facebooku i chcę to otworzyć w tym programie i przetestować jego sentyment za pomocą Naive Bayes. Nie sądzę, żebym używał poprawnie czytnika csv, ale nie mogę tego jeszcze naszkicować .. – user3670554