Учебное пособие по применению теоремы Байеса для прогнозирования вероятности того, что 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, в которой объясняются несколько подходов к объединению результатов для нескольких слов.
Я надеюсь, что это дало вам некоторое понимание и практический опыт использования теоремы Байеса, даже если мы коснемся поверхности.