Реализация классификатора Bag-of-Words Naive-Bayes в НЛТК

У меня в принципе есть тот же вопрос, что и у этого парня.. The пример в книге NLTK для наивного классификатора Байеса рассматривается только то, встречается ли слово в документе как объект.. он не рассматривает частоту слов как функцию, на которую нужно смотреть ("мешок слов").

один из ответов Кажется, это не может быть сделано со встроенными классификаторами NLTK. Это так? Как я могу сделать частоту / мешок слов NB классификация с NLTK?

3 ответов


scikit-learn и реализация мультиномиальных наивных Байес, что является правильным вариантом наивного Байеса в этой ситуации. Однако машина вектора поддержки (SVM), вероятно, будет работать лучше.

Как отметил Кен в комментариях, NLTK имеет хорошая обертка для классификаторов scikit-learn. Модифицированный из документов, вот несколько сложный, который делает взвешивание TF-IDF, выбирает 1000 лучших функций на основе chi2 статистика, а затем передает это в мультиномиальный наивный классификатор Байеса. (Держу пари, это несколько неуклюже, так как я не очень хорошо знаком ни с NLTK, ни с scikit-learn.)

import numpy as np
from nltk.probability import FreqDist
from nltk.classify import SklearnClassifier
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_selection import SelectKBest, chi2
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline

pipeline = Pipeline([('tfidf', TfidfTransformer()),
                     ('chi2', SelectKBest(chi2, k=1000)),
                     ('nb', MultinomialNB())])
classif = SklearnClassifier(pipeline)

from nltk.corpus import movie_reviews
pos = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('pos')]
neg = [FreqDist(movie_reviews.words(i)) for i in movie_reviews.fileids('neg')]
add_label = lambda lst, lab: [(x, lab) for x in lst]
classif.train(add_label(pos[:100], 'pos') + add_label(neg[:100], 'neg'))

l_pos = np.array(classif.classify_many(pos[100:]))
l_neg = np.array(classif.classify_many(neg[100:]))
print "Confusion matrix:\n%d\t%d\n%d\t%d" % (
          (l_pos == 'pos').sum(), (l_pos == 'neg').sum(),
          (l_neg == 'pos').sum(), (l_neg == 'neg').sum())

это напечатано для меня:

Confusion matrix:
524     376
202     698

не идеально, но прилично, учитывая, что это не очень простая проблема, и она обучается только на 100/100.


функции в классификаторе nltk bayes являются "номинальными", а не числовыми. Это означает, что они могут принимать конечное число дискретных значений (меток), но их нельзя рассматривать как частоты.

таким образом, с классификатором Байеса вы не можете напрямую используйте частоту слов в качестве функции-вы можете сделать что-то вроде использования 50 более частых слов из каждого текста в качестве набора функций, но это совсем другое

но, возможно, есть и другие классификаторы в НЛТК, которые зависят от частоты. Я не знаю, но вы смотрели? Я бы сказал, это стоит проверить.


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

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

для добавленной точности, подсчитайте все Би-граммы, три-граммы, ЕТК как отдельные особенности.

это помогает вручную написать свои собственные классификаторы, так что вы точно понимаете, что происходит и что вам нужно сделать, чтобы imporve точность. Если вы используете предварительно упакованное решение и оно работает недостаточно хорошо, вы мало что можете с этим поделать.