Учебное пособие по применению теоремы Байеса для прогнозирования вероятности того, что SMS-сообщение является спамом.

Это руководство состоит из двух частей:
1. Получение теоремы Байеса из условной вероятности
2. Прогнозирование того, является ли SMS-сообщение спамом.

Часть 1: Вывод теоремы Байеса из условной вероятности

Условная возможность

Я рассмотрел условную вероятность более подробно здесь.

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

P(A|B) = P(A ∩ B) / P(B) - вероятность появления A в случаях, когда мы знаемB. Он рассчитывается как вероятность того, что выпадут и A, и B, деленная на вероятность того, что выпадет B.

Но что, если бы мы хотели найти обратное, вероятность B в случаях, когда встречается A?

Иногда для этого отлично подходит условная вероятность. Но иногда проще воспользоваться теоремой Байеса.

Теорема Байеса

Википедия говорит:

В теории вероятностей и статистике теорема Байеса (альтернативно закон Байеса или правило Байеса) описывает вероятность события , Основываясь на предварительном знании условий, которые могут быть связаны с событием.

Вывод теоремы Байеса

Мы начинаем с формулы для условной вероятности, которую можно записать либо «А, учитывая Б», либо «В, учитывая А».

Обратите внимание, что интуитивно P(A∩B) и P(B∩A) одинаковы (см. Ниже). Это означает, что мы можем использовать их как взаимозаменяемые. Имейте это в виду на будущее.

Начнем с первой формулы P(A|B)= P(A∩B) / P(B).

Умножьте обе стороны на P(B). Это аннулирует знаменатель P(B) справа, и мы останемся ниже.

Теперь мы можем увидеть (легче, если поменять местами левую и правую стороны), что P(A∩B)= P(A|B) * P(B). Мы вставим это обратно во вторую исходную формулу (оригинал ниже).

Чтобы получить эту формулу (измененную ниже).

Это теорема Байеса.

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

Часть 2. Как определить, является ли SMS-сообщение спамом

Байесовский вывод имеет долгую историю обнаружения спама. Здесь мы познакомимся с основами с некоторыми реальными данными.

В нашем случае probability an SMS is spam, given some word равно probability of the word, given it is in a spam SMS, умноженному на probability of spam, и все разделено на probability of the word.

Загрузите набор данных из Kaggle и изучите его во фрейме данных.

import pandas as pd
df = pd.read_csv('sms-spam.csv', encoding='ISO-8859-1')
df.head(3)

Столбцы в исходном CSV-файле не имеют смысла. Поэтому мы переместим полезную информацию в 2 новых столбца, один из которых является логическим, указывающим, является ли SMS спамом.

К вашему сведению, «ветчина» означает «не спам».

import numpy as np
df['sms'] = df['v2']
df['spam'] = np.where(df['v1'] == 'spam', 1, 0)
df.head(3)

Теперь отбросьте старые столбцы.

df = df[['sms','spam']]
df.head()

Намного лучше.

Проверить количество записей.

len(df)
#=> 5572

Это много. Давайте поработаем с выборкой из 25% исходных данных.

sample_df = df.sample(frac=0.25)
len(sample_df)
#=> 1393

Так-то лучше.

Теперь разделите данные на 2 отдельных фрейма данных, один для спама, а другой для радиолюбителей.

spam_df = sample_df.loc[df['spam'] == 1]
ham_df = sample_df.loc[df['spam'] == 0]
print(len(spam_df))
print(len(ham_df))
#=> 180
#=> 1213

Мы воспользуемся векторизатором TFIDF от sklearn, чтобы просмотреть некоторые слова, важные в спам-сообщениях, и выбрать одно из них, которое будет вставлено в нашу формулу.

from sklearn.feature_extraction.text import TfidfVectorizer
vectorizer_spam = TfidfVectorizer(stop_words='english', max_features=30)
vectorizer_spam.fit(spam_df['sms'])
vectorizer_spam.vocabulary_

Нам нужно выбрать слово для использования в нашей формуле, поэтому я собираюсь выбрать слово «победа», хотя было бы интересно попробовать это и для других слов.

Теперь нам нужно вычислить различные части нашей формулы.

P(W|S) = вероятность присутствия слова «победа» в спам-сообщении
P(S) = вероятность появления спам-сообщения в целом
P(W) = вероятность появления слова «победа» в сообщении в целом

Установи наше слово.

word = 'win'

Рассчитайте P(W|S).

word = 'win'
spam_count = 0
spam_with_word_count = 0
for idx,row in spam_df.iterrows():
    spam_count += 1
    
    if word in row.sms:
        spam_with_word_count += 1
probability_of_word_given_spam = spam_count / spam_with_word_count
print(probability_of_word_given_spam)
#=> 10.0

Рассчитайте P(S).

probability_of_spam = len(spam_df) / (len(sample_df))
print(probability_of_spam)
#=> 0.12921751615218952

Рассчитайте P(W).

sms_count = 0
word_in_sms_count = 0
for idx,row in sample_df.iterrows():
    sms_count += 1
    
    if word in row.sms:
        word_in_sms_count += 1
probability_of_word = word_in_sms_count / sms_count
print(probability_of_word)
#=> 0.022254127781765973

Теперь собираем все вместе.

(probability_of_word_given_spam * probability_of_spam) / probability_of_word
#=> 58.064516129032256

Бум. Это говорит нам о том, что если в SMS-сообщении содержится слово «выиграть», вероятность того, что это сообщение является спамом, составляет 58%.

Заключение и дальнейшие шаги

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

Мы также можем включить другие функции, такие как комбинации слов, длина сообщения, пунктуация и т. Д.

Это превратило бы этот пост в действительно длинный.

Если вам интересно, здесь есть статья в формате PDF, в которой объясняются несколько подходов к объединению результатов для нескольких слов.

Я надеюсь, что это дало вам некоторое понимание и практический опыт использования теоремы Байеса, даже если мы коснемся поверхности.