2015-03-27 23 views
8

Đoạn mã sau chạy Bộ phân loại đánh giá phim Naive Bayes. Mã tạo danh sách các tính năng thông tin nhất.Kiểm tra bộ phân loại NLTK trên tệp cụ thể

Lưu ý:**movie review** thư mục nằm trong 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 từ alvas

thế nào tôi có thể kiểm tra phân loại trên tập tin cụ thể?

Vui lòng cho tôi biết nếu câu hỏi của tôi không rõ ràng hoặc sai.

Trả lời

8

Thứ nhất, đọc những câu trả lời một cách cẩn thận, chúng chứa các bộ phận của câu trả lời bạn cần và cũng một thời gian ngắn giải thích những gì phân loại làm và cách thức hoạt động trong NLTK:


Kiểm tra phân loại trên dữ liệu chú thích

Bây giờ để trả lời câu hỏi của bạn. Chúng tôi giả định rằng câu hỏi của bạn là theo dõi câu hỏi này: Using my own corpus instead of movie_reviews corpus for Classification in NLTK

Nếu văn bản thử nghiệm của bạn được cấu trúc giống như số liệu movie_review, bạn có thể đọc dữ liệu thử nghiệm như bạn muốn cho dữ liệu đào tạo:

Chỉ trong trường hợp lời giải thích của mã này là không rõ ràng, đây là một hướng:

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

hai dòng trên là để đọc một thư mục my_movie_reviews với một cấu trúc như vậy:

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

Sau đó, dòng tiếp theo trích xuất tài liệu với thẻ pos/neg của nó là một phần của cấu trúc thư mục.

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()] 

Dưới đây là lời giải thích cho các dòng trên:

# 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()] 

Quá trình CÙNG nên được áp dụng khi bạn đọc các dữ liệu thử nghiệm !!!

Bây giờ để xử lý tính năng:

Những dòng này thêm top 100 tính năng cho các phân loại:

# 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] 

Next để xử lý các tài liệu vào classify-thể định dạng:

# 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:]] 

Bây giờ, hãy giải thích rằng việc hiểu danh sách dài cho train_set và `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] 

Bạn cũng cần xử lý các tài liệu như trên để trích xuất tính năng trong tài liệu thử nghiệm !!!

Vì vậy, dưới đây là cách bạn có thể đọc dữ liệu thử nghiệm:

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()] 

Sau đó, tiếp tục với các bước xử lý mô tả ở trên, và chỉ cần làm điều này để có được những nhãn cho tài liệu kiểm tra như @yvespeirsman trả lời:

#### 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") 

Nếu mã và giải thích ở trên làm cho không có ý nghĩa với bạn, sau đó bạn pHẢI đọc hướng dẫn này trước khi tiếp tục: http://www.nltk.org/howto/classify.html

012.

Bây giờ chúng ta hãy nói rằng bạn không có chú thích trong dữ liệu thử nghiệm của bạn, tức là test.txt của bạn không có trong cấu trúc thư mục như movie_review và chỉ là một textfile đồng bằng:

\test_movie_reviews 
    \1.txt 
    \2.txt 

Sau đó không có điểm trong việc đọc nó thành một corpus phân loại, bạn chỉ có thể làm đọc và tag các văn bản, ví dụ:

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

NHƯNG bạn kHÔNG tHỂ đánh giá kết quả mà không cần chú thích, vì vậy bạn không thể kiểm tra thẻ nếu if-else, cũng bạn cần phải mã hóa văn bản nếu bạn không sử dụng CategorPlaintextCorpusReader.

Nếu bạn chỉ muốn gắn thẻ một tệp văn bản thuần 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) 

Một lần nữa, xin đừng chỉ cần sao chép và dán các giải pháp và cố gắng tìm hiểu lý do tại sao và làm thế nào nó hoạt động.

+0

Cảm ơn bạn đã giải thích đầy đủ và tôi cố gắng hiểu chúng. Nhưng tôi thường gặp phải kết quả sai. Tôi có nghĩa là nó nên được 'pos' nhưng chương trình hiển thị' neg'. Và tôi không biết lý do. – ZaM

+1

Có nhiều lý do và nó không hoàn hảo, có thể (i) dữ liệu không đủ, (ii) các tính năng không đủ tốt, (iii) lựa chọn phân loại, v.v. Thực hiện khóa học này https://www.coursera.org/ khóa học/ml để biết thêm thông tin. Và nếu bạn có thể mạnh mẽ khuyến khích bạn tham dự http://lxmls.it.pt/2015/ – alvas

+0

Tôi đang bối rối. Đầu tiên tôi lấy một tập tin từ 'nltk/movie_reviews/neg/cv081.txt'. Sau đó, tôi quyết định ** thử nghiệm ** tệp của chương trình cung cấp cho 'Woohoo, correct'or'wrong'. Tôi đặt tập tin trong '/home/neg/cv081.txt' để thử nghiệm sau đó tôi nhận được' Boohoo, sai'as đầu ra! Sau đó, tôi đặt các tập tin trong '/ home/pos/cv081.txt' sau đó tôi nhận được' Woohoo, correct' là đầu ra! Sau đó, tôi kiểm tra cùng một tệp trên chương trình 'print (tagged_label)' nó cho tôi nhiều 'neg'. Và về chương trình mà 'print (tagged_label)'. Tôi không biết chính xác nó hoạt động ra sao. Nó cho tôi nhiều 'neg' ngay cả đối với tập tin' pos' !!. Làm thế nào tôi có thể đánh giá các đầu ra 'neg' và 'pos'. – ZaM

4

Bạn có thể thử nghiệm trên một tệp có classifier.classify(). Phương thức này lấy làm đầu vào của nó một từ điển với các tính năng như các khóa của nó, và True hoặc False là các giá trị của chúng, tùy thuộc vào việc tính năng có xuất hiện trong tài liệu hay không. Nó xuất ra nhãn có thể xảy ra nhất cho tệp, theo trình phân loại. Sau đó, bạn có thể so sánh nhãn này với nhãn chính xác cho tệp để xem liệu phân loại có chính xác hay không.

Trong bộ đào tạo và kiểm tra của bạn, từ điển tính năng luôn là mục đầu tiên trong bộ dữ liệu, nhãn là mục thứ hai trong bộ dữ liệu.

Vì vậy, bạn có thể phân loại các tài liệu đầu tiên trong các thử nghiệm thiết lập như sau:

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

Bạn có thể vui lòng chỉ cho tôi một ví dụ hoàn chỉnh và ** if ** ví dụ của bạn có thể được làm theo ví dụ của tôi được đề cập hay không. Tôi rất mới trong Python.Bạn có thể cho tôi biết tại sao bạn viết '0' trong' test_set [0] ' – ZaM

+2

Đây là ví dụ hoàn chỉnh: nếu bạn dán mã ngay sau mã của bạn trong câu hỏi, nó sẽ hoạt động. '0' chỉ đơn giản là lấy tài liệu đầu tiên trong tập kiểm tra của bạn (mục đầu tiên trong danh sách có chỉ số 0). – yvespeirsman

+0

Cảm ơn bạn rất nhiều. Có cách nào để viết 'name_of_file' thay vì' 0' trong 'test_set [0]'? Tôi không biết, 'test_set' chính xác chỉ ra tệp nào vì chúng ta có 2 thư mục' pos | neg' và mọi thư mục đều có tệp của nó. Tôi hỏi điều này vì từ 'thông tin nhất' là' xấu' (kết quả của ví dụ tôi đang đề cập đến). Tệp đầu tiên có hơn 1 trăm từ ** "xấu" **. Nhưng chương trình hiển thị 'không chính xác' ở đầu ra. Sai lầm của tôi đâu rồi? – ZaM

Các vấn đề liên quan