Ответ 1
Да, учебное пособие по главе 6 нацелено на базовые знания для студентов и оттуда, студенты должны опираться на него, изучая то, что доступно в NLTK, а что нет. Так что давайте рассмотрим проблемы по одному.
Во-первых, способ получить "pos" / "neg" документы через каталог, скорее всего, будет правильным, так как корпус был организован таким образом.
from nltk.corpus import movie_reviews as mr
from collections import defaultdict
documents = defaultdict(list)
for i in mr.fileids():
documents[i.split('/')[0]].append(i)
print documents['pos'][:10] # first ten pos reviews.
print
print documents['neg'][:10] # first ten neg reviews.
[выход]:
['pos/cv000_29590.txt', 'pos/cv001_18431.txt', 'pos/cv002_15918.txt', 'pos/cv003_11664.txt', 'pos/cv004_11636.txt', 'pos/cv005_29443.txt', 'pos/cv006_15448.txt', 'pos/cv007_4968.txt', 'pos/cv008_29435.txt', 'pos/cv009_29592.txt']
['neg/cv000_29416.txt', 'neg/cv001_19502.txt', 'neg/cv002_17424.txt', 'neg/cv003_12683.txt', 'neg/cv004_12641.txt', 'neg/cv005_29357.txt', 'neg/cv006_17022.txt', 'neg/cv007_4992.txt', 'neg/cv008_29326.txt', 'neg/cv009_29417.txt']
В качестве альтернативы мне нравится список кортежей, где первым является элемент список слов в .txt файле, а второй - категория. И при этом также удаляются стоп-слова и пунктуации:
from nltk.corpus import movie_reviews as mr
import string
from nltk.corpus import stopwords
stop = stopwords.words('english')
documents = [([w for w in mr.words(i) if w.lower() not in stop and w.lower() not in string.punctuation], i.split('/')[0]) for i in mr.fileids()]
Следующая ошибка в FreqDist(for w in movie_reviews.words() ...)
. В коде нет ничего плохого, просто вы должны попытаться использовать пространство имен (см. http://en.wikipedia.org/wiki/Namespace#Use_in_common_languages). Следующий код:
from nltk.corpus import movie_reviews as mr
from nltk.probability import FreqDist
from nltk.corpus import stopwords
import string
stop = stopwords.words('english')
all_words = FreqDist(w.lower() for w in mr.words() if w.lower() not in stop and w.lower() not in string.punctuation)
print all_words
[выходы]:
<FreqDist: 'film': 9517, 'one': 5852, 'movie': 5771, 'like': 3690, 'even': 2565, 'good': 2411, 'time': 2411, 'story': 2169, 'would': 2109, 'much': 2049, ...>
Так как приведенный выше код правильно печатает FreqDist
, ошибка кажется, что у вас нет файлов в каталоге nltk_data/
.
Тот факт, что у вас есть fic/11.txt
, говорит о том, что вы используете более старую версию корпусов NLTK или NLTK. Обычно fileids
в movie_reviews
начинается либо с pos
/neg
, либо с косой чертой, затем с именем файла и, наконец, .txt
, например. pos/cv001_18431.txt
.
Итак, я думаю, может быть, вы должны повторно загрузить файлы с помощью:
$ python
>>> import nltk
>>> nltk.download()
Затем убедитесь, что корпус просмотра фильма правильно загружен на вкладке "Корпорация":
Возвращаясь к коду, прокручивая все слова в корпусе просмотра фильма, кажется излишним, если у вас уже есть все слова, отфильтрованные в ваших документах, поэтому я предпочел бы сделать это, чтобы извлечь все возможности:
word_features = FreqDist(chain(*[i for i,j in documents]))
word_features = word_features.keys()[:100]
featuresets = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents]
Далее, разделение поезда/теста по функциям в порядке, но я считаю, что лучше использовать документы, поэтому вместо этого:
featuresets = [({i:(i in tokens) for i in word_features}, tag) for tokens,tag in documents]
train_set, test_set = featuresets[100:], featuresets[: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:]]
Затем загрузите данные в классификатор и вуаля! Итак, здесь код без комментариев и пошагового руководства:
import string
from itertools import chain
from nltk.corpus import movie_reviews as mr
from nltk.corpus import stopwords
from nltk.probability import FreqDist
from nltk.classify import NaiveBayesClassifier as nbc
import nltk
stop = stopwords.words('english')
documents = [([w for w in mr.words(i) if w.lower() not in stop and w.lower() not in string.punctuation], i.split('/')[0]) for i in mr.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 = nbc.train(train_set)
print nltk.classify.accuracy(classifier, test_set)
classifier.show_most_informative_features(5)
[выход]:
0.655
Most Informative Features
bad = True neg : pos = 2.0 : 1.0
script = True neg : pos = 1.5 : 1.0
world = True pos : neg = 1.5 : 1.0
nothing = True neg : pos = 1.5 : 1.0
bad = False pos : neg = 1.5 : 1.0