Недавно я закончил Специализацию глубокого обучения на Coursera от Deeplearning.ai, но чувствовал, что мог бы узнать больше. Не из-за того, что некоторые инструкторы или материалы курса провалились, а потому, что я никогда не рискнул варить материал, вместо этого решив пройти курс как можно быстрее.

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

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

Анализ тональности — это задача классификации различных фрагментов текста по категориям. Конкретным случаем, используемым в курсе, является классификация твитов как положительных или отрицательных. Например, твит с надписью «Мне очень нравится изучать НЛП» будет помечен как положительный, а твит с надписью «Я действительно не люблю дождливые дни» — как отрицательный.

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

Первым шагом в построении модели, как и в большинстве задач машинного обучения, является предварительная обработка данных таким образом, чтобы сделать текст прямым и читаемым нашим алгоритмом. Что я имею в виду под простым и читаемым? Ну, во-первых, твиты, которые мы будем передавать нашей модели, написаны не для обработки алгоритмом машинного обучения, поэтому существует множество переменных, таких как прописные и строчные буквы, знаки препинания и стоп-слова (a, и, the) которые мало влияют на смысл твита. Поэтому, прежде чем мы передадим твиты в нашу модель, мы должны позаботиться об этих проблемах. Во-вторых, мы встретим слова с одним корнем, такие как давать, давать, дает. Каждое из этих слов должно иметь очень похожее значение, поэтому мы хотим, чтобы наша модель учитывала это. Для этого мы используем технику, называемую стемминг, при которой суффикс слова удаляется, оставляя, в данном случае, корень дай, который можно передать в нашу модель. Существует множество различных алгоритмов, которые можно использовать для стемминга, вот очень полный список алгоритмов и их преимуществ.

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

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

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

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

Хотя это уравнение выглядит сложным, на самом деле оно очень интуитивно понятно. Стоимость является средней, поэтому мы делим результат на m, который представляет собой общее количество образцов. Тогда в скобках у нас есть суммирование. Левая часть суммы показывает, насколько правильно мы оценили, был ли твит положительным. Например, если y равно 1 (обозначает положительный твит), а h близко к 1 (это означает, что x с точками w близок к 0 и, следовательно, очень похож), то левая часть суммирования будет близка к 1 и справа будет 0. Минимизируя эту функцию во время обучения, мы снижаем стоимость прогнозов.

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

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

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

Обновление:

Я смог закодировать пример этого, вот ссылка на github: https://github.com/DavidBrynnHouse/NLP-Logistic-Regression. Обратите внимание, что это не закончено в настройке.