Тестирование классификатора NLTK на конкретном файле

следующий код наивный Байес фильм обзор классификатор. Код генерирует список наиболее информативных функций.

Примечание:

2 ответов


во-первых, внимательно прочитайте эти ответы, они содержат части ответов, которые вам нужны, а также кратко объясняют, что делает классификатор и как он работает в NLTK:


тестирование классификатора на размеченных данных

чтобы ответить на ваш вопрос. Мы предполагаем, что ваш вопрос является продолжением этого вопроса: используя свой собственный корпус вместо рецензии корпус для классификации в nltk

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

на всякий случай, если объяснение кода неясно, вот пошаговое руководство:

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

две строки выше, чтобы прочитать каталог my_movie_reviews С такой структурой:

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

затем следующая строка извлекает документы с его pos/neg тег, который является частью структуры каталогов.

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

вот объяснение приведенной выше строки:

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

то же процесс должен применяться, когда вы читаете тестовые данные!!!

теперь к обработке функций:

следующие строки дополнительные 100 лучших функций для классификатора:

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

рядом с обработкой документов в формат классификации:

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

теперь, чтобы объяснить, что длинный список понимания для train_set и 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]

вам нужно обработать документы, как указано выше, для извлечения функций в тестовых документах тоже!!!

вот как вы можете прочитать тестовые данные:

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

затем продолжите описанные выше шаги обработки и просто сделайте это, чтобы получить метку для тестового документа, поскольку @yvespeirsman ответил:

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

если приведенный выше код и объяснение не имеют для вас смысла, то вы должны читать этот учебник, прежде чем продолжить: http://www.nltk.org/howto/classify.html


теперь предположим, что у вас нет аннотации на тестовых данных, т. е. test.txt не в структуре каталогов, как movie_review и просто текстовый файл:

\test_movie_reviews
    .txt
    .txt

тогда нет смысла читать его в категоризированный корпус, вы можете просто прочитать и пометить документы, т. е.:

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

но вы не можете оценить результаты без аннотации, так что вы не удается проверить тег, если if-else, и вам нужно токенизировать свой текст если вы не используете CategorizedPlaintextCorpusReader.

если вы просто хотите пометить текстовый файл 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)

еще раз, пожалуйста, не просто скопировать и вставить решение и попытаться понять, почему и как это работает.


вы можете протестировать один файл с помощью классификатора.классифицировать.)( Этот метод принимает в качестве входных данных словарь с объектами в качестве ключей и True или False в качестве их значений, в зависимости от того, происходит ли объект в документе или нет. Он выводит наиболее вероятную метку для файла, согласно классификатору. Затем вы можете сравнить эту метку с правильной меткой для файла, чтобы увидеть, правильна ли классификация.

в ваших учебных и тестовых наборах словари объектов всегда являются первым элементом в кортежах, метки являются вторым элементом в кортежах.

таким образом, вы можете классифицировать первый документ в тестовом наборе следующим образом:

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