2015-03-27 30 views
8

Poniższy kod uruchamia klasyfikator recenzji filmu naive Bayes . Kod generuje listę najbardziej przydatnych funkcji.Testowanie klasyfikatora NLTK na określonym pliku

Uwaga:**movie review** folder znajduje się w nltk.

from itertools import chain 
from nltk.corpus import stopwords 
from nltk.probability import FreqDist 
from nltk.classify import NaiveBayesClassifier 
from nltk.corpus import movie_reviews 
stop = stopwords.words('english') 

documents = [([w for w in movie_reviews.words(i) if w.lower() not in stop and w.lower() not in string.punctuation], i.split('/')[0]) for i in movie_reviews.fileids()] 


word_features = FreqDist(chain(*[i for i,j in documents])) 
word_features = word_features.keys()[:100] 

numtrain = int(len(documents) * 90/100) 
train_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents[:numtrain]] 
test_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents[numtrain:]] 

classifier = NaiveBayesClassifier.train(train_set) 
print nltk.classify.accuracy(classifier, test_set) 
classifier.show_most_informative_features(5) 

link of code z alvas

jak mogę Test klasyfikator na konkretnego pliku?

Proszę dać mi znać, jeśli moje pytanie jest niejednoznaczne lub błędne.

Odpowiedz

8

Najpierw przeczytaj te odpowiedzi ostrożnie, zawierają one elementy odpowiedzi potrzebne, a także pokrótce wyjaśnia, co robi klasyfikator i jak to działa w NLTK:


testowania klasyfikatora na adnotacjami danych

teraz, aby odpowiedzieć na to pytanie. Zakładamy, że pytanie jest kontynuacją tego pytania: Using my own corpus instead of movie_reviews corpus for Classification in NLTK

Jeśli tekst test jest skonstruowany w taki sam sposób jak movie_review corpus, można po prostu odczytać dane testowe jak w przypadku danych szkoleniowej:

wszelki wypadek wyjaśnienie kodu jest jasne, oto solucja:

traindir = '/home/alvas/my_movie_reviews' 
mr = CategorizedPlaintextCorpusReader(traindir, r'(?!\.).*\.txt', cat_pattern=r'(neg|pos)/.*', encoding='ascii') 

dwie linie powyżej czytać katalogu my_movie_reviews z takiej struktury:

\my_movie_reviews 
    \pos 
     123.txt 
     234.txt 
    \neg 
     456.txt 
     789.txt 
    README 

Następnie następna linia wyodrębnia dokumenty ze znacznikiem pos/neg, który jest częścią struktury katalogów.

documents = [([w for w in mr.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr.fileids()] 

Oto wyjaśnienie powyższej linii:

# This extracts the pos/neg tag 
labels = [i for i.split('/')[0]) for i in mr.fileids()] 
# Reads the words from the corpus through the CategorizedPlaintextCorpusReader object 
words = [w for w in mr.words(i)] 
# Removes the stopwords 
words = [w for w in mr.words(i) if w.lower() not in stop] 
# Removes the punctuation 
words = [w for w in mr.words(i) w not in string.punctuation] 
# Removes the stopwords and punctuations 
words = [w for w in mr.words(i) if w.lower() not in stop and w not in string.punctuation] 
# Removes the stopwords and punctuations and put them in a tuple with the pos/neg labels 
documents = [([w for w in mr.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr.fileids()] 

Proces samo powinno być stosowane podczas odczytu danych testowych !!!

Teraz na przetwarzanie cecha:

następujące linie dodatkowe 100 najlepszych funkcji dla klasyfikatora:

# Extract the words features and put them into FreqDist 
# object which records the no. of times each unique word occurs 
word_features = FreqDist(chain(*[i for i,j in documents])) 
# Cuts the FreqDist to the top 100 words in terms of their counts. 
word_features = word_features.keys()[:100] 

Następny do przetwarzania dokumentów do klasyfikowania-stanie formacie:

# Splits the training data into training size and testing size 
numtrain = int(len(documents) * 90/100) 
# Process the documents for training data 
train_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents[:numtrain]] 
# Process the documents for testing data 
test_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents[numtrain:]] 

Teraz wyjaśnij, że zrozumienie długiej listy dla train_set i `test_set:

# Take the first `numtrain` no. of documents 
# as training documents 
train_docs = documents[:numtrain] 
# Takes the rest of the documents as test documents. 
test_docs = documents[numtrain:] 
# These extract the feature sets for the classifier 
# please look at the full explanation on https://stackoverflow.com/questions/20827741/nltk-naivebayesclassifier-training-for-sentiment-analysis/ 
train_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in train_docs] 

Należy również przetworzyć dokumenty jak wyżej dla ekstrakcji obiektów w dokumentach testowych !!!

Więc oto jak można odczytać dane testowe:

stop = stopwords.words('english') 

# Reads the training data. 
traindir = '/home/alvas/my_movie_reviews' 
mr = CategorizedPlaintextCorpusReader(traindir, r'(?!\.).*\.txt', cat_pattern=r'(neg|pos)/.*', encoding='ascii') 

# Converts training data into tuples of [(words,label), ...] 
documents = [([w for w in mr.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr.fileids()] 

# Now do the same for the testing data. 
testdir = '/home/alvas/test_reviews' 
mr_test = CategorizedPlaintextCorpusReader(testdir, r'(?!\.).*\.txt', cat_pattern=r'(neg|pos)/.*', encoding='ascii') 
# Converts testing data into tuples of [(words,label), ...] 
test_documents = [([w for w in mr_test.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr_test.fileids()] 

następnie kontynuować z etapów procesu opisanych powyżej, i po prostu to zrobić, aby uzyskać etykietę dla dokumentu testowego jako @yvespeirsman odpowiedział:

#### FOR TRAINING DATA #### 
stop = stopwords.words('english') 

# Reads the training data. 
traindir = '/home/alvas/my_movie_reviews' 
mr = CategorizedPlaintextCorpusReader(traindir, r'(?!\.).*\.txt', cat_pattern=r'(neg|pos)/.*', encoding='ascii') 

# Converts training data into tuples of [(words,label), ...] 
documents = [([w for w in mr.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr.fileids()] 
# Extract training features. 
word_features = FreqDist(chain(*[i for i,j in documents])) 
word_features = word_features.keys()[:100] 
# Assuming that you're using full data set 
# since your test set is different. 
train_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents] 

#### TRAINS THE TAGGER #### 
# Train the tagger 
classifier = NaiveBayesClassifier.train(train_set) 

#### FOR TESTING DATA #### 
# Now do the same reading and processing for the testing data. 
testdir = '/home/alvas/test_reviews' 
mr_test = CategorizedPlaintextCorpusReader(testdir, r'(?!\.).*\.txt', cat_pattern=r'(neg|pos)/.*', encoding='ascii') 
# Converts testing data into tuples of [(words,label), ...] 
test_documents = [([w for w in mr_test.words(i) if w.lower() not in stop and w not in string.punctuation], i.split('/')[0]) for i in mr_test.fileids()] 
# Reads test data into features: 
test_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in test_documents] 

#### Evaluate the classifier #### 
for doc, gold_label in test_set: 
    tagged_label = classifier.classify(doc) 
    if tagged_label == gold_label: 
     print("Woohoo, correct") 
    else: 
     print("Boohoo, wrong") 

Jeżeli powyższy kod i wyjaśnienia nie ma sensu do Ciebie, to MUSI przeczytać ten poradnik przed kontynuowaniem: http://www.nltk.org/howto/classify.html


Teraz powiedzmy, że nie ma adnotacji w danych testowych, czyli Twój test.txt nie jest w strukturze katalogów niczym movie_review i tylko zwykły plik.txt:

\test_movie_reviews 
    \1.txt 
    \2.txt 

Wtedy nie ma sensu go czytać w skategoryzowany corpus, można po prostu czytać i oznaczanie dokumentów, a mianowicie:

for infile in os.listdir(`test_movie_reviews): 
    for line in open(infile, 'r'): 
     tagged_label = classifier.classify(doc) 

ALE nIE mOŻE ocenia wyniki bez adnotacji, więc nie można sprawdzić znacznika, jeśli if-else, a także trzeba tokenizować tekst, jeśli nie używasz CategorizedPlaintextCorpusReader.

Jeśli chcesz po prostu oznaczyć zwykłego tekstu plik test.txt:

import string 
from itertools import chain 
from nltk.corpus import stopwords 
from nltk.probability import FreqDist 
from nltk.classify import NaiveBayesClassifier 
from nltk.corpus import movie_reviews 
from nltk import word_tokenize 

stop = stopwords.words('english') 

# Extracts the documents. 
documents = [([w for w in movie_reviews.words(i) if w.lower() not in stop and w.lower() not in string.punctuation], i.split('/')[0]) for i in movie_reviews.fileids()] 
# Extract the features. 
word_features = FreqDist(chain(*[i for i,j in documents])) 
word_features = word_features.keys()[:100] 
# Converts documents to features. 
train_set = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents] 
# Train the classifier. 
classifier = NaiveBayesClassifier.train(train_set) 

# Tag the test file. 
with open('test.txt', 'r') as fin: 
    for test_sentence in fin: 
     # Tokenize the line. 
     doc = word_tokenize(test_sentence.lower()) 
     featurized_doc = {i:(i in doc) for i in word_features} 
     tagged_label = classifier.classify(featurized_doc) 
     print(tagged_label) 

Ponownie proszę nie wystarczy skopiować i wkleić rozwiązanie i spróbować zrozumieć, dlaczego i jak to działa.

+0

Dziękuję za pełne wyjaśnienie i staram się je zrozumieć. Ale często napotykam złe wyniki. Mam na myśli, że powinien to być 'pos', ale program pokazuje' neg'. I nie znam powodu. – ZaM

+1

Istnieje wiele powodów, a to nie jest idealny, może (i) dane są niewystarczające, (ii) funkcje nie są wystarczająco dobre, (iii) wybór klasyfikatora, itd. Czy ten kurs https://www.coursera.org/ course/ml po więcej informacji. A jeśli mogę mocno zachęcić do wzięcia udziału w http://lxmls.it.pt/2015/ – alvas

+0

jestem zdezorientowany. Najpierw otrzymuję plik z 'nltk/movie_reviews/neg/cv081.txt'. Potem decyduję się na ** przetestowanie ** pliku w twoim programie, który daje 'Woohoo, correct'or'wrong'. Wstawiłem plik '/home/neg/cv081.txt' do testowania, a następnie otrzymuję' Boohoo, wrong'as output! Następnie umieszczam plik w katalogu '/ home/pos/cv081.txt', a następnie otrzymuję komunikat" Woohoo, correct "jako wynik! Następnie testuję ten sam plik w programie 'print (tagged_label)', który daje mi wiele 'neg'ów. Oraz o programie 'print (tagged_label)'. Nie wiem dokładnie, jak to działa. Daje mi wiele 'neg' nawet dla' pos' pliku !!. Jak mogę ocenić te wyniki 'neg's i' pos's. – ZaM

4

Możesz przetestować na jednym pliku przy pomocy klasy classifier.classify(). Ta metoda przyjmuje jako słownik słownik z funkcjami jako kluczami oraz True lub False jako wartości, w zależności od tego, czy funkcja występuje w dokumencie, czy nie. Wydaje najbardziej prawdopodobną etykietę pliku, zgodnie z klasyfikatorem. Następnie możesz porównać tę etykietę z właściwą etykietą pliku, aby sprawdzić, czy klasyfikacja jest prawidłowa.

W zestawach treningowych i testowych słowniki cech są zawsze pierwszą pozycją w krotkach, a etykiety są drugą pozycją w krotkach.

sposób można sklasyfikować pierwszy dokument w teście ustawiony tak:

(my_document, my_label) = test_set[0] 
if classifier.classify(my_document) == my_label: 
    print "correct!" 
else: 
    print "incorrect!" 
+0

Czy możesz pokazać mi pełny przykład i ** jeśli ** możliwy jest twój przykład zgodnie z moim przykładem. Jestem nowy w Pythonie.Czy mógłbyś mi powiedzieć dlaczego piszesz '0' w' test_set [0] ' – ZaM

+2

Jest to kompletny przykład: jeśli wkleić kod natychmiast po kodzie w pytaniu, to będzie działać. '0' po prostu pobiera pierwszy dokument z twojego zestawu testowego (pierwsza pozycja na liście ma indeks 0). – yvespeirsman

+0

Dziękuję bardzo. Czy istnieje sposób na zapisanie 'name_of_file' zamiast' 0' w 'test_set [0]'? Nie wiem, "test_set" dokładnie wskazuje, do którego pliku mamy 2 folder 'pos | neg', a każdy folder ma swoje pliki. Pytam o to, ponieważ słowo "najbardziej pouczające" było "złe" (wynik mojego przykładu). Pierwszy plik zawiera ponad sto ** "złego" ** słowa. Ale program pokazuje "nieprawidłowy" na wyjściu. Gdzie jest mój błąd? – ZaM