Использование длины документа в наивном байесовском классификаторе NLTK Python

Я создаю спам-фильтр, используя NLTK в Python. Теперь я проверяю наличие слов и использую классификатор NaiveBayesClassifier, в результате чего точность составляет 0,98, а показатель F для спама — 0,92, а для не-спама — 0,98. Однако при проверке документов, в которых обнаружены ошибки моей программы, я заметил, что многие спам-сообщения, которые классифицируются как не-спам, представляют собой очень короткие сообщения.

Итак, я хочу указать длину документа как функцию для NaiveBayesClassifier. Проблема в том, что теперь он обрабатывает только двоичные значения. Есть ли другой способ сделать это, кроме как, например, сказать: length‹100 = true/false?

(ps я создал детектор спама, аналогичный http://nltk.googlecode.com/svn/trunk/doc/book/ch06.html пример)


person Javaaaa    schedule 09.03.2011    source источник


Ответы (2)


Реализация Naive Bayes в NLTK этого не делает, но вы можете комбинировать прогнозы NaiveBayesClassifier с распределением по длине документа. Метод prob_classify NLTK даст вам условное распределение вероятностей по классам с учетом слов в документе, т. е. P(cl|doc). Что вам нужно, так это P(cl|doc,len) - вероятность класса с учетом слов в документе и его длины. Если мы сделаем еще несколько предположений о независимости, мы получим:

P(cl|doc,len) = (P(doc,len|cl) * P(cl)) / P(doc,len)
              = (P(doc|cl) * P(len|cl) * P(cl)) / (P(doc) * P(len))
              = (P(doc|cl) * P(cl)) / P(doc) * P(len|cl) / P(len)
              = P(cl|doc) * P(len|cl) / P(len)

Вы уже получили первый член из prob_classify, поэтому все, что осталось сделать, это оценить P(len|cl) и P(len).

Вы можете сколько угодно фантазировать, когда дело доходит до моделирования длин документов, но для начала вы можете просто предположить, что журналы длин документов обычно распределяются. Если вы знаете среднее значение и стандартное отклонение длины документа журнала в каждом классе и в целом, то легко вычислить P(len|cl) и P(len).

Вот один из способов оценки P(len):

from nltk.corpus import movie_reviews
from math import sqrt,log
import scipy

loglens = [log(len(movie_reviews.words(f))) for f in movie_reviews.fileids()]
sd = sqrt(scipy.var(loglens)) 
mu = scipy.mean(loglens)

p = scipy.stats.norm(mu,sd)

Единственная сложная вещь, которую нужно помнить, это то, что это распределение по длинам журналов, а не по длинам, и что это непрерывное распределение. Итак, вероятность документа длины L будет:

p.cdf(log(L+1)) - p.cdf(log(L))

Условные распределения длин можно оценить таким же образом, используя логарифмические длины документов в каждом классе. Это должно дать вам то, что вам нужно для P(cl|doc,len).

person rmalouf    schedule 12.03.2011

Существуют алгоритмы MultiNomial NaiveBayes, которые могут обрабатывать значения диапазона, но не реализованы в NLTK. Для NLTK NaiveBayesClassifier вы можете попробовать использовать пару разных порогов длины в качестве бинарных функций. Я бы также посоветовал попробовать Maxent Classifier, чтобы увидеть, как он обрабатывает меньший текст.

person Jacob    schedule 10.03.2011