Обработка естественного языка для меня одна из самых увлекательных областей науки о данных. Тот факт, что машина может понимать содержание текста с определенной точностью, просто завораживает, а иногда и пугает.

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

Но как это работает на практике? В этом посте представлены концепции, лежащие в основе обработки естественного языка, и основное внимание уделяется пакету nltk для использования в Python.

Примечание: для выполнения приведенных ниже примеров вам потребуется установить nltk библиотеку. Если у вас его нет, просто запустите pip install nltk в своей оболочке и nltk.download() в записной книжке перед запуском.

Какой бы текст или предложение ни передавалось в машину, сначала его нужно упростить, и это можно сделать с помощью токенизации и лемматизации. Эти сложные слова означают что-то очень простое: токенизация означает, что мы разбиваем текст на токены, отдельные или сгруппированные слова в зависимости от случая. Лемматизация означает, что мы преобразуем некоторые слова в их корневые слова, т.е. слова множественного числа становятся единственными, спрягаемые глаголы становятся базовыми глаголами и так далее. Между этими манипуляциями мы также очищаем текст от всех слов, не несущих реальной информации, так называемых стоп-слов.

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

При разметке текста важно выбрать диаграмму соответственно. Это число, которое указывает, сколько слов мы хотим в каждом токене, и в большинстве случаев (как в примере выше) это число равно 1. Но если вы проводите анализ настроений на веб-сайте бизнес-обзоров, возможно, ваши тексты могут содержать такие утверждения, как «не доволен» или «не нравится», и вы не хотите, чтобы эти слова компенсировали друг друга, чтобы передать негативное мнение, стоящее за обзором. В подобных случаях вы можете подумать об увеличении ngram и посмотреть, как это повлияет на ваш анализ.

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

В приведенном ниже коде я использовал RegexpTokenizer, токенизатор регулярных выражений. Для тех, кто не знаком с регулярным выражением, в теории формального языка это последовательность символов, которая определяет шаблон, и в зависимости от аргумента, который вы передаете в функции RegexpTokenizer, он разделит текст в соответствии с этим аргументом. В выражении регулярного выражения \w+ буквально означает сгруппировать все символы слова длиной больше или равной единице, отбрасывая пустые пробелы (и, следовательно, размечая отдельные слова) и все символы, не являющиеся словами, то есть знаки препинания.

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

tokens = ['Rome', 'was', 'founded', 'in', '753BC', 'by', 'its', 'first', 'king', 'Romulus']

Неплохо для начала, наши жетоны состоят из отдельных слов, а знаки препинания исчезли! Теперь нам нужно удалить стоп-слова из токенов: к счастью, список стоп-слов включен в nltk для многих разных языков. Но, конечно, в зависимости от конкретного случая вам может потребоваться настроить этот список слов. Например, статья the включена в такой список по умолчанию, но если вы анализируете базу данных фильмов или музыки, вы можете оставить ее, потому что в этом случае она действительно имеет значение (весело факт: Справка и Справка! - это два разных фильма!).

Список новых токенов:

clean_tokens = ['Rome', 'founded', '753BC', 'first', 'king', 'Romulus']

Мы перешли с 10 слов на 6, и теперь, наконец, пришло время лемматизировать! До сих пор я тестировал два объекта с той же целью: WordNetLemmatizer и PorterStemmer, и последний определенно более жесток, чем первый, как показано в примерах ниже.

Результат последнего понимания списка:

['Rome', 'founded', '753BC', 'first', 'king', 'Romulus']

Ничего не изменилось! Это потому, что WordNetLemmatizer действует только на слова во множественном числе и некоторые другие вещи, и в этом конкретном случае ни одно слово не было фактически лемматизировано. С другой стороны, PorterStemmer преобразует множественное число и производные слова, сопряженные глаголы и переводит все термины в нижний регистр, как показано ниже:

Результат понимания списка:

['rome', 'found', '753bc', 'first', 'king', 'romulu']

В этом случае больше нет слов в верхнем регистре, и это нормально для нас, потому что нет смысла различать одни и те же слова только потому, что одно написано в нижнем регистре, а другое нет, они имеют одинаковое значение! Глагол основан был изменен на найден, и даже Ромул потерял последнюю букву своего имени, вероятно, потому что PorterStemmer думал, что это слово во множественном числе.

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

Существует много-много различных методов для сбора и систематизации слов из текста перед их моделированием, и это лишь небольшая часть доступных вариантов. Вся эта очистка необходима перед подачей текста в модель машинного обучения, чтобы максимально упростить ее. Когда вы анализируете большое количество слов в прогнозных моделях, после выполнения вышеуказанных шагов вы, скорее всего, будете полагаться на sklearn методы, такие как CountVectorizer, TfidfVectorizer или HashingVectorizer, для преобразования необработанного текста в матрицу количества токенов в обучите свою прогностическую модель.