Объединение индивидуальных вероятностей в фильтрацию спама в наивном байесовском спаме

В настоящее время я пытаюсь создать спам-фильтр, анализируя собранный мною корпус.

Я использую запись wikipedia http://en.wikipedia.org/wiki/Bayesian_spam_filtering для разработки моего классификационного кода.

Я реализовал код для вычисления вероятности того, что сообщение является спамом, учитывая, что оно содержит конкретное слово, реализуя следующую формулу из вики:

pr(S|W) = (pr(W|S)*pr(S))/(pr(W|S)*pr(S) + pr(W|H)*pr(H))

Мой PHP-код:

public function pSpaminess($word)
{
    $ps = $this->pContentIsSpam();
    $ph = $this->pContentIsHam();
    $pws = $this->pWordInSpam($word);
    $pwh = $this->pWordInHam($word);
    $psw = ($pws * $ps) / ($pws * $ps + $pwh * $ph);
    return $psw;
}

В соответствии с разделом "Объединять отдельные вероятности" я реализовал код для объединения вероятностей всех уникальных слов в тестовом сообщении для определения спама.

Из формулы wiki:

p=(p1*pn)/((p1*pn)+(1-p)(1-pn))

Мой PHP-код:

public function predict($content)
{
    $words = $this->tokenize($content);
    $pProducts = 1;
    $pSums = 1;
    foreach($words as $word)
    {
        $p = $this->pSpaminess($word);
        echo "$word: $p\n";
        $pProducts *= $p;
        $pSums *= (1 - $p);
    }
    return $pProducts / ($pProducts + $pSums);
}

В тестовой строке "Это совсем не плохо". Выдается следующий вывод:

C:\projects\bayes>php test.php
this: 0.19907407407407
isn't: 0.23
very: 0.2
bad: 0.2906976744186
at: 0.17427385892116
all: 0.16098484848485
probability message is spam: float(0.00030795502523944)

Вот мой вопрос: Правильно ли я реализую комбинирование индивидуальных вероятностей? Предполагая, что я генерирую допустимые индивидуальные вероятности слов, правильный метод комбинации?

Моя забота - это действительно небольшая результирующая вероятность вычисления. Я тестировал его на более крупном тестовом сообщении и в итоге получал вероятность в научной нотации с более чем 10 местами нулей. Я ожидал ценностей в 10-м или 100-м местах.

Я надеюсь, что проблема кроется в моей реализации PHP - но когда я исследую функцию комбинации из wikipedia, дивиденд формулы является продуктом фракций. Я не вижу, как комбинация множественных вероятностей окажется еще более вероятной .1%.

Если это так, то чем длиннее сообщение, тем меньше будет счет вероятности, как я могу скомпенсировать квоту спама правильно предсказать спам/ветку для небольших и больших тестовых случаев?


Дополнительная информация

Мой корпус на самом деле представляет собой около 40 тыс. комментариев reddit. Я фактически применяю свой "спам-фильтр" к этим комментариям. Я оцениваю индивидуальный комментарий как спам/хам, основанный на количестве голосов, поданных на голосование: если голосует меньше голосов, это считается Хэм, иначе Спам.

Теперь, из-за типа корпуса, оказывается, что на самом деле есть несколько слов, которые используются в спаме больше, чем в ветчине. То есть, вот десятка лучших слов, которые появляются в спаме чаще, чем ветчина.

+-----------+------------+-----------+
| word      | spam_count | ham_count |
+-----------+------------+-----------+
| krugman   |         30 |        27 |
| fetus     |       12.5 |       7.5 |
| boehner   |         12 |        10 |
| hatred    |       11.5 |       5.5 |
| scum      |         11 |        10 |
| reserve   |         11 |        10 |
| incapable |        8.5 |       6.5 |
| socalled  |        8.5 |       5.5 |
| jones     |        8.5 |       7.5 |
| orgasms   |        8.5 |       7.5 |
+-----------+------------+-----------+

Напротив, большинство слов используется в большом количестве в ветчине больше, чем ветчина. Возьмем, к примеру, мой 10 лучших слов с наибольшим количеством спама.

+------+------------+-----------+
| word | spam_count | ham_count |
+------+------------+-----------+
| the  |       4884 |     17982 |
| to   |     4006.5 |   14658.5 |
| a    |     3770.5 |   14057.5 |
| of   |     3250.5 |   12102.5 |
| and  |       3130 |     11709 |
| is   |     3102.5 |   11032.5 |
| i    |     2987.5 |   10565.5 |
| that |     2953.5 |   10725.5 |
| it   |       2633 |      9639 |
| in   |     2593.5 |    9780.5 |
+------+------------+-----------+

Как вы можете видеть, частота использования спама значительно меньше, чем использование ветчины. В моем корпусе из 40 тыс. Комментариев 2100 комментариев считаются спамом.

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

Фраза

Cops are losers in general. That why they're cops.

Анализ:

C:\projects\bayes>php test.php
cops: 0.15833333333333
are: 0.2218958611482
losers: 0.44444444444444
in: 0.20959269435914
general: 0.19565217391304
that's: 0.22080730418068
why: 0.24539170506912
they're: 0.19264544456641
float(6.0865969793861E-5)

В соответствии с этим существует крайне низкая вероятность того, что это спам. Однако, если бы я теперь проанализировал комментарий ветчины:

Фраза

Bill and TED excellent venture?

Анализ

C:\projects\bayes>php test.php
bill: 0.19534050179211
and: 0.21093065570456
ted's: 1
excellent: 0.16091954022989
venture: 0.30434782608696
float(1)

Хорошо, это интересно. Я делаю эти примеры, когда я составляю это обновление, так что это первый раз, когда я видел результат для этого конкретного теста. Я думаю, что мое предсказание перевернуто. Фактически он выбрал вероятность "Хама" вместо "Спама". Это заслуживает подтверждения.

Новый тест на известную ветчину.

Фраза

Complain about $174,000 salary being too little for self.  Complain about $50,000 a year too much for teachers.
Scumbag congressman.

Анализ

C:\projects\bayes>php test.php
complain: 0.19736842105263
about: 0.21896031561847
174: 0.044117647058824
000: 0.19665809768638
salary: 0.20786516853933
being: 0.22011494252874
too: 0.21003236245955
little: 0.21134020618557
for: 0.20980452359022
self: 0.21052631578947
50: 0.19245283018868
a: 0.21149315683195
year: 0.21035386631717
much: 0.20139771283355
teachers: 0.21969696969697
scumbag: 0.22727272727273
congressman: 0.27678571428571
float(3.9604152477223E-11)

К сожалению нет. Оказывается, это был случайный результат. Я начинаю задаваться вопросом, возможно, что комментарии не могут быть так легко подсчитаны. Возможно, характер плохого комментария слишком сильно отличается от характера спам-сообщения.

Возможно, может быть, что фильтрация спама работает только тогда, когда у вас есть определенный класс слов спам-сообщений?


Окончательное обновление

Как указывалось в ответах, странные результаты были обусловлены характером корпуса. Использование комманды комментариев, где нет четкого определения спам-байесовской классификации, не выполняется. Поскольку возможно (и, вероятно,), что любой комментарий может получать как рейтинги спама, так и ветчины различными пользователями, невозможно создать жесткую классификацию для комментариев спама.

В конечном счете, я хотел создать классификатор комментариев, который мог бы определить, будет ли сообщение комментария украшать карму на основе байесовской классификации, настроенной на комментарий. Я могу по-прежнему расследовать настройку классификатора на отправку спам-сообщений электронной почты и посмотреть, может ли такой классификатор угадать ответ кармы для систем комментариев. Но на данный момент ответ на этот вопрос. Спасибо всем за ваш вклад.

Ответы

Ответ 1

Разновидность с помощью только калькулятора, кажется, одобренная фраза, не связанная с спамом. В этом случае у вас есть $pProducts пара порядков величин меньше $pSums.

Попробуйте запустить какой-либо настоящий спам из папки спама, где вы встретите вероятностей, таких как 0,8. И угадайте, почему спамеры когда-нибудь пытаются отправить часть газеты в скрытую рамку вместе с сообщением:)

Ответ 2

Если ваш фильтр не смещен (Pr (S) = Pr (H) = 0,5), то: "Также желательно, чтобы узнанный набор сообщений соответствовал 50% -ной гипотезе о перераспределении между спамом и ветчиной, т.е. наборы данных спама и ветчины имеют одинаковый размер".

Это означает, что вы должны научить свой байесовский фильтр аналогичному количеству сообщений о спаме и ветчине. Скажите 1000 спам-сообщений и 1000 сообщений ветчины.

Я бы предположил (не проверял), что если ваш фильтр является предвзятым, набор обучения должен соответствовать гипотезе о том, что любое сообщение является спамом.

Ответ 3

По идее компенсации длины сообщений вы можете оценить для каждого набора вероятности того, что слово сообщения является конкретным словом, а затем использовать распределение пуассонов для оценки вероятности сообщения из N слов, содержащих это конкретное слово.