"Начиная"

Как превратить текст в функции

Подробное руководство по использованию НЛП для машинного обучения

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

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

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

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

Как обычно, я не просто объясню, как это сделать, но и представлю три наиболее часто используемых метода моделирования: модель мешка слов, модель на основе алгоритма TF-IDF и модели Word2Vec. Приступим к обсуждению.

Функции?

Для тех из вас, кто не привык к этому слову, позвольте мне немного отвлечься. Функция - это имя, присвоенное выбранным или обработанным данным, которые подготовлены для использования в качестве входных данных для алгоритмов (обычно алгоритмов машинного обучения). Характеристики могут быть такими, как цена дома, значение RGB пикселя или, в нашем случае, представление слова.

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

Итак, в конечном итоге наша цель - получить необработанные данные (текст) и превратить их в функции (то, с чем могут работать компьютерные алгоритмы).

Векторизация текста

Методы, используемые для преобразования текста в функции, можно назвать методами «векторизации текста», поскольку все они преследуют одну цель: преобразование текста в векторы (или массивы, если вы хотите попроще; или тензоры, если вы хотите более сложный), которые затем могут быть переданы в модели машинного обучения классическим способом.

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

Я хочу превратить свой текст в данные.

Проще говоря, векторы - это списки с n позициями. Один естественный способ подумать о том, как превратить текст в векторы, - это создать упорядоченный список всех слов как таковых:

Однако что произойдет, если у вас будут более короткие или более крупные записи? А также, как ваш алгоритм машинного обучения (который по сути представляет собой серию матричных и векторных вычислений) может сравнивать два слова - эти придуманные человечеством символы, имеющие особое значение?

Поскольку вы умен, вы уже подумали: позвольте мне сделать словарь или какую-нибудь подобную структуру (в общем, словарную карту) и использовать указатели слов вместо слов!

Вы на правильном пути, но давайте рассмотрим некоторые из проблем: действительно ли слово «мой» важнее, чем «хочу»? Именно об этом «говорят» ваши данные для алгоритма машинного обучения. Алгоритмы машинного обучения не заботятся о том, является ли число индексом, а только о том, что это значение, которое нужно вычислить (конечно, у вас может быть категориальная функция, но мы увидим это ниже).

«Нормализовать, нормализовать, нормализовать !!!», - можно подумать. Однако помните: это не ценности! Это индексы.

Если вы достаточно долго играете в Data Science и Machine Learning, вы, вероятно, думаете о одном решении: используйте «One Hot Encoding».

Одно горячее кодирование - это процесс кодирования категориальных функций, при котором каждое возможное значение для этой функции сопоставляется с новым «столбцом», и, если он присутствует, для этого столбца устанавливается значение 1, 0 в противном случае.

Давайте рассмотрим это, используя ранее упомянутую словарную «карту» и предложенную фразу (в данном случае словарный запас совпадает со словами фразы). Получаем вот что:

Теперь, если мы захотим закодировать: «Мне нужны мои данные», мы получим:

Отлично, мы нашли способ кодировать наши данные в режиме машинного обучения! Но есть много проблем, которые нужно решить: давайте рассмотрим первую - частоты слов - вот где пригодятся модели Bag of Words!

Модель мешка слов (BoW)

Одно горячее кодирование обрабатывает значения только как «присутствующие» и «отсутствующие». Это не подходит для текста. Во многих текстовых приложениях частота слов играет важную роль. Рассмотрим два следующих абзаца:

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

Сегодня я гулял со своей собакой и нашел в парке 100 долларов. Мне грустно думать, что эти деньги могут быть деньгами на обед какой-нибудь бедной пожилой леди.

Первый - это первый абзац статьи в Википедии о собаках, а второй - это псевдоблог, который я сделал с целью демонстрации этой проблемы. Вопрос: какую веб-страницу вы бы порекомендовали пользователю, который выполняет поиск в гипотетической системе по слову «собака»?

Одно горячее кодирование даст одно и то же значение для слова "собака" в обеих записях, так что это нехорошо.

Входит в модель "Мешок слов"!

В этой модели предлагается вместо вектора логических значений использовать вектор частот слов. В приведенном выше примере столбец для слова «собака» получит значение «4» в первом тексте и только «1» во втором тексте. Теперь нормализовать значения можно, но не обязательно (только для более быстрой обработки).

Эта модель получила название «Сумка», потому что в ней не соблюдается слово «порядок» (как и у нашей мамы в 90-х всегда в беспорядке).

Но прежде чем говорить о недостатках модели Bag of Words, давайте посмотрим, как реализовать ее с помощью Python и Numpy.

Это очень просто, но давайте рассмотрим это шаг за шагом. Я решил сделать его классом, чтобы я мог создать несколько экземпляров BoW в модели. Это конструктор класса:

По сути, у нас есть набор всех слов и пара диктовок для хранения индексов слов.

Затем мы подготавливаем наш мешок слов, подгоняя его (добавляя все документы сразу, чтобы он мог «узнать», какие слова мы можем использовать).

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

Это пример использования и вывода:

Теперь, когда мы увидели, как это делается, мы можем поговорить о проблемах в модели:

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

Второй. Обычно он очень многомерный. Если в вашем корпусе хотя бы раз учитываются только 90% наиболее распространенных английских слов, согласно Oxford English Corpus, это приведет к вектору не менее 7000 измерений (большинство из которых будет иметь нули, но много габаритов, тем не менее)!

Но BoW прост и может дать быстрые результаты для простых задач. Если вы не знаете, с чего начать при создании решения НЛП, попробуйте простое: выберите модель BoW. Он работает как хороший инструмент оценки исходных условий.

Отметим, что есть один вариант, который полезен в случаях больших данных, особенно в ситуациях, когда вам нужно сравнивать тексты в базе символов (без учета семантики). В этом методе используется текстовая черепица (черепица). В этом случае вместо того, чтобы разбивать предложения на слова, разбивайте их на каждые k символов или на каждом стоп-слове. Подробнее читайте здесь:



Модель TF-IDF

Это на самом деле не модель, а, скорее, усовершенствование в вычислении «уместности» слова над документом. Для простоты я назову это моделью.

В модели TF-IDF вместо того, чтобы хранить частоту слов, мы сохраняем результат алгоритма tf-idf над входными данными. TF означает Частота термина, а IDF означает Частота обратного документа.

Короче говоря, TF-IDF вычисляет вес слова в конкретном документе с учетом общего распределения слов. Способ представления результатов такой же, как и у Bag of Words: разреженный вектор (0 для слов, которые не появляются, в противном случае некоторые плавают).

Модели TF-IDF могут давать лучшие результаты при использовании, например, в задачах анализа настроений, по сравнению с мешками слов.

Давайте разделим этот алгоритм на две части для лучшего понимания: вычисление глобальной обратной частоты документов, а затем вычисление индивидуальной оценки TF-IDF.

Частота обратного документа

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

Существует множество различных способов вычисления как TF, так и IDF (например, посмотрите алгоритм Страница Википедии). Я решил использовать IDF с логическим масштабированием, который вычисляется по следующей формуле:

Где:

  • D = общее количество документов
  • freq = количество документов, в которых встречается термин.

Для начала мы определяем вспомогательный метод:

1) Простой способ превратить предложение в диктовку слов и частот (можно использовать коллекции Python «Counter» для лучшей производительности, но я буду использовать старый способ диктовки для простоты):

Затем мы инициализируем класс IDF аналогично классу BoW:

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

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

Частота вычисления термина

Короче говоря, мы получаем оценку TF-IDF для предложения по:

  1. Подсчет частоты употребления терминов в предложении.
  2. Умножение частоты термина для каждого термина на обратную частоту документа.

Вот код (обратите внимание, что я добавил несколько условных операторов и частных методов для учета пакетного преобразования):

На этом наш featurizer TF-IDF готов!

Теперь для каждого предложения мы получаем массив размером со весь словарь с учетом соответствия каждого слова этому предложению (0, если оно отсутствует).

Вот пример вывода:

Или чуть более «читабельным»:

{‘of’: 0.0, ‘list’: 0.0, ‘sentence’: 0.08664339756999316, ‘a’: 0.07192051811294521, ‘second’: 0.0, ‘sentences’: 0.0, ‘in’: 0.0, ‘complexity’: 0.0, ‘is’: 0.08664339756999316, ‘this’: 0.08664339756999316, ‘word’: 0.08664339756999316, ‘for’: 0.0}

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

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



Некоторые дискуссии о BoW и TF-IDF:

Как мы видели, методы BoW и TF-IDF создают вектор размером со весь словарь для одного предложения. Это не учитывает порядок слов или их положение, что делает эти методы плохими для приложений, чувствительных к непрерывности (большинство приложений НЛП).

Одним из возможных обходных путей было бы использовать массив BoW / TFIDF для каждого слова, складывать их и передавать как функции, как на следующем изображении (на примере входного слоя искусственной нейронной сети):

Для приведенного выше изображения у вас будет разреженная матрица размером 10000 * 4 для одного предложения из 4 слов (даже используя бит для каждого логического значения, вы получите около 1 КБ на слово на предложение! Представьте себе большой корпус?). Время вычислений и хранилище, используемые для обучения простой модели анализа настроений, сделали бы ее слишком дорогой или невыполнимой (на самом деле, несколько лет назад текст был почти не затронутой темой, когда речь шла о машинном обучении из-за этих ограничений, связанных с отсутствием достаточно памяти и вычислительной мощности).

Однако такой подход позволяет сохранить последовательность слов. Что, если бы мы могли уменьшить размерность этого вектора?

Входит во вложения слов!

Вложения слов

Я не буду углубляться в объяснение вложения слов, поскольку существует несколько методов их вычисления, и большинство из них включает глубокие нейронные сети, которые сами требуют времени для объяснения (и это не является целью данной статьи).

Но я не воздержусь, чтобы дать вам самую важную и самую важную информацию об этом.

Сформулируем это так:

Вложения слов - это векторное представление слов, изученных в ходе контекстного обучения. Это не оценка за каждое слово, это больше похоже на «координаты» слова.

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

Одним из наиболее известных методов создания вложений Word является Word2Vec, на основе которого был создан этот метод. Сам Word2Vec может быть вычислен с использованием двух различных методов, но детали здесь не так важны.

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

  • Word2vec (Google) - 2 техники: непрерывный пакет слов (CBoW) и скип-грамм;
  • Global Vectors или GloVe (Стэнфорд);
  • fastText (Facebook) - интересный факт: учитывает слова вне словарного запаса.

Если вы хотите узнать больше, я предлагаю этот замечательный курс DeepLearning.AI, представленный на Coursera: https://www.coursera.org/learn/probabilistic-models-in-nlp

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

Поскольку слова представлены координатами, они сравниваются (для сравнения сходства). И если размер правильно уменьшен с помощью таких методов, как Анализ главных компонентов - PCA, слова могут быть нанесены на график, и на графике обычно отображаются слова с похожими значениями ближе друг к другу, как показано на следующем изображении. из IBM Research Blog:

Координаты обычно задаются в большом количестве измерений, обычно от 8 до 1024. Таким образом, вместо стопки из 10000 массивов измерений, заполненных нулями, у нас есть стопка из 8-1024 массивов измерений, которые не являются разреженными (они плотно заполнены поплавками). Это лучше для компьютеров.

Вот еще один интересный пример из статьи Дэвида Розадо в Journal Plos One:

При рассмотрении того, как люди используют Embeddings, важно отметить, что слово Embeddings может быть сгенерировано двумя различными способами:

  1. Обучаясь вместе с текущим процессом (например, задача анализа настроений) и фиксируя отношения между словами в соответствии с этой конкретной задачей. Вот что происходит, когда вы определяете слой Embeddings с помощью таких библиотек, как Keras, Pytorch или Trax. Эти слои сопоставляют индексы слов со значением встраивания.
  2. Пройдя предварительную подготовку на огромном корпусе, чтобы фиксировать наиболее распространенные отношения в языке. Эти предварительно обученные вложения затем можно загрузить в модель, чтобы ускорить процесс обучения или добиться лучших результатов. Здесь на помощь приходят fastText, Word2vec или GloVe. Библиотеки, такие как spaCy, предлагают вам такой вид встраивания.

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

Просто чтобы добавить немного больше по теме, можно также сделать Feature Engineering при преобразовании текста в функции. Другими словами, специалист по данным может применять свои собственные правила (обычно посредством предварительной обработки), чтобы определить, что следует извлечь перед преобразованием текста в числовые массивы.

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

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

Конечно, для каждого алгоритма и задачи требуются особые манипуляции с вводимым текстом. Например, модели Seq2Seq обычно имеют фиксированную последовательность.

длина. Чтобы обеспечить эту длину, используется заполнение или сжатие. Но в конце концов, отступы и слова преобразуются в вложения.

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

Кроме того, всегда проверяйте, что нового в коде в моем репозитории. Не стесняйтесь повторно использовать и вносить свой вклад в код в соответствии с текущим Лицензированием. И вы можете связаться со мной через Linkedin, если вам нужна помощь, просто проверьте мой профиль! Увидимся в следующей статье.