Создание собственного детектора спама

Создание собственного детектора спама. Описание данных

Здравствуйте и вновь добро пожаловать на занятия по теме «Обработка данных: обработка естественных языков на языке Python».

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

При рассмотрении этого примера вы должны уяснить две важные вещи:

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

В этом примере мы воспользуемся библиотекой scikit-learn.

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

Итак, столбцы с 1 по 48 – это то, что мы рассматриваем в качестве входных данных, а именно мера упоминаемости слова. Она рассчитывается как количество случаев появления слова в документе, делённое на общее количество слов в документе и затем умноженное на 100.

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

Таким образом, в нашей термин-документ матрице элементы данных идут вдоль столбцов, а документы (в нашем случае электронные письма) – вдоль строк.

Создание собственного детектора спама. Код

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

Итак, создадим пустой файл и воспользуемся наивным байесовским классификатором из библиотеки scikit-learn. Если вы заглянете в документацию, то обнаружите, что с технической точки зрения используемый классификатор MultinomialNB предназначен для работы с целым количеством признаков, но он может работать и с другими типами, такими как TF-IDF, являющимися другой методикой NLP.

Кроме библиотеки Sklearn, импортируем также библиотеку Pandas, чтобы загрузить данные, и – в данном случае – библиотеку Numpy.

from sklearn.naive_bayes import MultinomialNB

import pandas as pd

import numpy as np

Загрузим наши данные, уже находящиеся в папке с NLP в репозитарии Github и преобразуем их в матрицу. Далее перемешаем данные, чтобы случайным образом разделить их на учебный и проверочный наборы, причём каждый раз они должны быть разными.

data = pd.read_csv(‘spambase.data’).as_matrix()

np.random.shuffle(data)

Как мы знаем, наши входные данные составляют первые 48 столбцов – это наше X, а исходящая переменная – в последнем столбце – это наше Y.

X = data[:, :-48]

Y = data[:, -1]

Поскольку наши данные перемешаны, в действительности нет никакого значения, в каком порядке будут определяться наши учебные и проверочные наборы, но для определённости установим, что последние 100 строк будут проверочным набором, а все остальные – учебным.

Xtrain = X[:-100,]

Ytrain = Y[:-100,]

Xtest = X[-100:,]

Ytest = Y[-100:,]

Теперь используем наивный байесовский классификатор из библиотеки scikit-learn.

model = MultinomialNB()

model.fit(Xtrain, Ytrain)

print ‘’Classification rate for NB:’’, model.score(Xtest, Ytest)

Запустим программу. Модель получилась весьма удачной – точность составила 87%. Повторный запуск даёт 88% точности.

Любопытная вещь – вы можете использовать любую модель из библиотеки scikit-learn, поскольку все они имеют одинаковый интерфейс. Предположим, к примеру, что мы захотели воспользоваться классификатором AdaBoost, являющийся ансамблевым методом машинного обучения. Импортируем из его из библиотеки scikit-learn и делаем то же, что и раньше.

from sklearn.ensemble import AdaBoostClassifier

model = AdaBoostClassifier()

model.fit(Xtrain, Ytrain)

print ‘’Classification rate for AdaBoost:’’, model.score(Xtest, Ytest)

Запустим программу. Как ни странно, классификатор AdaBoost показал худший результат. При втором прогоне программы получилось куда лучше. В целом же он выдает точность, примерно равную наивному байесовскому.

Если этот пример кода оказался для вас чересчур сложным или вам понадобилась дополнительная помощь, не стесняйтесь писать мне в Твиттер. Вы можете также посетить мой сайт lazyprogrammer.me, где размещены тонны бесплатных руководств, которые я регулярно выкладываю, а также бесплатный шестинедельный обзорный курс по машинному обучению, на который вы можете подписаться. Кстати, так получилось, что последнее написанное мною руководство как раз посвящено NLP. К тому же там я выкладываю дисконтные коды для моих существующих и будущих курсов. Чтобы получить их, вы можете подписаться на рассылку или, при желании, посетить мою страницу в Facebook. Я только недавно её завел, поэтому пожалуйста, заходите и составьте мне там компанию.

Другие типы признаков

В предыдущем примере мы разобрали один из способов создания термин-документ матрицы, основанный на доле слов в документе. Как вы впоследствии убедитесь, в NLP есть разные способы подсчёта слов в зависимости от того, что мы хотим от наших данных. К примеру, мы могли бы поступить проще, применяя так называемый «мешок слов» путём использования строк для подсчёта упоминаний каждого слова или их доли в документе.

Или мы могли бы сделать ещё проще и использовать лишь двоичные признаки – к примеру, присваивая значение 1, если слово встречается в документе, и 0 – если оно отсутствует.

Существуют и другой популярный показатель структуры документа, именуемая TF-IDF. Это сокращения от терминов «частота слова» (term frequency, TF) и «обратная частота документа» (inverse document frequency, IDF). По сути он учитывает тот факт, что если мы возьмём слова вроде «и», «или», «в», то они, вероятнее всего, будут встречаться очень часто в любом конкретном рассматриваемом документе, тогда как хотелось бы, чтобы они поменьше влияли на результат. Обратная частота документа определяется как величина, обратная количеству появлений данного слова в наших документах. В этом курсе мы не будем вычислять TF-IDF.

Как ни странно, но библиотека NLTK не включает в себя инструменты для работы с TF-IDF, но, к счастью, их включает библиотека Sci-kit learn. Если вы хотите посмотреть, как scikit-learn learn справляется с TF-IDF, то можете перейти по адресу.

Понравилась статья? Поделить с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: