Всем привет!
Сегодня расскажу об одном из базовых машин лёрнинг алгоритмов — алгоритм спам фильтра. Сам алгоритм может быть реализован разными способами, поэтому сегодня рассмотрим основную идею. Более полную реализацию кода опишу в следующих статьях, поэтому подпишить на мой телеграм канал, чтобы быть в курсе новых статей. Все коды и ноутбуки доступны в моём гите (о jupyter notebooks и git я уже рассказывала).
Давай рассмотрим 3 коротких сообщения, о которых уже известно, является ли данное сообщение спамом:
e-mail текст | лейбл |
---|---|
это спам | спам |
привет привет, друг | не спам |
привет, Ксюня | не спам |
На основании данных знаний ты хочешь определить является ли сообщение ‘спам спам спам’ спамом.
Шаг 1: Векторизация
Первым делом, предложения понятные человеку необходимо перевести в форму удобную для создания алгоритма. Алгоритмами работы с текстом занимается направление информатики и искусственного интеллекта NLP. И это не то NLP, о котором ты подумал. NLP расшифровывается как Natural Language Processing, что-то вроде «обработка естественного языка». Так вот, при работе с текстовыми документами, их представляют в виде вектора признаков — числового описания особенностей данного текста.
Одним из простейших способов векторизации текста является Count Vectorizer. При его использовании результат бы выглядел следующим образом:
e-mail текст | вектор |
---|---|
это спам | [0 0 0 1 1] |
привет привет, друг | [1 0 2 0 0] |
привет, Ксюня | [0 1 1 0 0] |
Этот вектор описывает сколько раз то или иное слово встречается в документе. При этом положение каждого слова зафиксировано. Давай разбираться.
В терменах NLP ты работаешь с 3-мя документами (3 e-mail сообщения). Эти документы содержат всего 5 уникальных слов: «друг», «ксюня», «привет», «спам», «это». Поэтому каждое предложение будет описываться количеством каждого из этих слов в нём. Например, в 1-ом предложении слова «друг», «ксюня», «привет» встречаются 0 раз, а вот слова «это» и «спам» встречаются по 1-му разу.
Ну а теперь возвращаемся к фразе «спам спам спам». В терменах уже известных документов, вектор признаков для данный фразы будет выглядить [0 0 0 3 0].
Шаг 2: Классификация
Что имеем?
вектор | лейбл |
---|---|
[0 0 0 1 1] | спам |
[1 0 2 0 0] | не спам |
[0 1 1 0 0] | не спам |
[0 0 0 3 0] | ? |
Главная цель данного шага определить на какой вектор (или группу векторов) похож тот, который ты хочешь классифицировать.
Здесь можешь использовать любой известный тебе классификатор (например, knn алгоритм — метод ближайших соседей о котором я уже рассказывала). В нашем случае интуитивно понятно, что вектор [0 0 0 3 0] похож на [0 0 0 1 1] — только в этом векторе на 4-ом месте не нулевое значение. Поэтому данный ветор ты можешь классифицировать как спам.
Подтвердить наше предположение математически можно с помощью так называемой евклидовой метрики — расстояние между двумя точками в N-мерном пространстве. Евклидово расстояние между первым вектором и последним (тем, что хотим классифицировать):
√
(0-0)^2 +
= 2.24(0-0)^2 +
(0-0)^2 + (1-3)^2 + (1-0)^2
меньше, чем расстояние между вторым/третьим вектором и тем что хотим классифицировать:
√
(1-0)^2 +
= 3.74(0-0)^2 +
(2-0)^2 + (0-3)^2 + (0-0)^2
√
(0-0)^2 +
= 3.32(1-0)^2 +
(1-0)^2 + (0-3)^2 + (0-0)^2
Познакомься ближе со спам фильтром
Ноутбук с кодом доступен в гите.
import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.metrics.pairwise import euclidean_distances
# Create data
data = ['это спам',
'привет привет, друг',
'привет, Ксюня']
label = ['spam',
'ham',
'ham']
data_test = ['спам спам спам']
# Vectorize data
vectorizer = CountVectorizer()
vectorizer = vectorizer.fit(data)
data_train = vectorizer.transform(data)
data_train = data_train.todense()
data_test = vectorizer.transform(data_test)
data_test = data_test.todense()
# Calculate euclidean distance
ed_0 = euclidean_distances(data_test, data_train[0])
ed_1 = euclidean_distances(data_test, data_train[1])
ed_2 = euclidean_distances(data_test, data_train[2])
Привет, Машуля!😀 статья крутая, как и все предыдущие. Давай ещё, ты молодец, так держать!)
😘