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

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

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

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

3. Извлечение функций. После предварительной обработки вам необходимо преобразовать текстовые данные в числовую форму, которую могут понять алгоритмы машинного обучения. Этот процесс известен как извлечение признаков. Обычно используются такие методы, как Bag of Words, TF-IDF (частота терминов, обратная частоте документа) и вложения слов (например, Word2Vec и GloVe).

4. Построение модели. Теперь, когда ваши данные готовы, пришло время построить модель. Существует широкий спектр моделей, которые вы можете использовать, от традиционных алгоритмов машинного обучения, таких как наивные алгоритмы Байеса и машины опорных векторов, до более сложных моделей глубокого обучения, таких как рекуррентные нейронные сети (RNN) и преобразователи. Выбор модели часто зависит от вашей конкретной задачи, размера и характера вашего набора данных, а также имеющихся в вашем распоряжении вычислительных ресурсов.

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

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

Теперь давайте воспользуемся реальным примером, создав анализатор настроений.

Сначала мы получим наш набор данных.

"I absolutely loved this movie! It was so touching
  and beautifully made. A true masterpiece. 😍"
"This book is a complete waste of time.
  I don't recommend it to anyone."
"The phone's battery life is stellar.
  It's the best phone I've used in a while."
"The new software update is terrible!
  It slowed down my computer significantly."
"I really enjoy the food at this restaurant.
  The staff are very friendly as well."

Затем мы превратим предложения в списки только с соответствующими словами.

[
  ["absolutely", "loved", "movie", "touching",
    "beautifully", "made", "true", "masterpiece"],
  ["book", "complete", "waste", "time", "recommend", "anyone"],
  ["phone", "battery", "life", "stellar", "best", "phone", "used", "while"],
  ["new", "software", "update", "terrible",
    "slowed", "computer", "significantly"],
  ["really", "enjoy", "food", "restaurant", "staff", "friendly"]
]

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

[  
  [1, 2, 3, 4, 5, 6, 7, 8],
  [9, 10, 11, 12, 13, 14],
  [15, 16, 17, 18, 19, 15, 20, 21],
  [22, 23, 24, 25, 26, 27, 28],
  [29, 30, 31, 32, 33, 34]
]

В этом наборе данных всего 34 уникальных слова, но использование наборов данных с 10 000 уникальных слов не редкость для задач малого и среднего размера.

Теперь мы собираемся построить модель с помощью TensorFlow.

const model = tf.sequential();

model.add(tf.layers.embedding({inputDim: 10000, outputDim: 16}));
model.add(tf.layers.globalAveragePooling1d());
model.add(tf.layers.dense({units: 16, activation: 'relu'}));
model.add(tf.layers.dense({units: 1, activation: 'sigmoid'}));

const optimizer = tf.train.adam();
model.compile({optimizer: optimizer, loss: 'binaryCrossentropy', metrics: ['accuracy']});

Слой Embedding используется для преобразования дискретных слов (или других элементов) в непрерывные векторы. Он принимает параметр inputDim, который представляет собой размер словаря, и параметр outputDim, который представляет собой размер плотного вектора (в данном случае 16) для представления каждого слова. Dim означает измерения, и цель этого шага — преобразовать набор из 10 000 слов в векторы, содержащие 16 измерений. Измерения используются для отслеживания математического расстояния между словами в пространстве измерений. Слова, расположенные близко друг к другу, похожи, но их размеры обычно не соответствуют характеристикам, понятным людям. 16 измерений — это довольно мало, но они подойдут для бинарной оценки, такой как анализ настроений. Более стандартные размеры размеров варьируются от 50 до 300.
Конечная цель слоя Embedding — преобразовать необработанные входные текстовые данные в форму, с которой могут работать нейронные сети, что является необходимым шагом при работе с текстовыми данными.

Слой пула:
GlobalAveragePooling1D преобразует 2D-данные в 1D-данные путем усреднения векторов объектов. Два измерения — это размер слова или последовательность слов в каждом входе и измерение встраивания, которое мы сделали на предыдущем шаге. Это упрощает модель за счет уменьшения ее размерности.

Плотный слой с ReLU:
Этот слой является полностью связанным слоем, то есть все нейроны в предыдущем слое соединяются с нейронами в этом слое. Он имеет 16 единиц и использует функцию активации ReLU, которая нормализует данные, чтобы набор данных становился только таким большим или таким маленьким. В противном случае вы столкнетесь с проблемой «исчезающего градиента» во время тренировки.

Плотный слой с функцией активации сигмоида:
Это выходной слой, и он также полностью подключен. Он имеет только 1 единицу, потому что это проблема бинарной классификации (положительное настроение или отрицательное настроение). Сигмовидная функция активации отображает выходные данные между 0 и 1, что делает ее подходящей для двоичной классификации.

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

Затем мы собираемся обучить модель на нашем наборе данных:

async function trainModel(model, trainData, trainLabels, testData, testLabels) {
  const history = await model.fit(trainData, trainLabels, {
    epochs: 30,
    validationData: [testData, testLabels],
    verbose: 2
  });
  return history;
}

trainModel(model, trainData, trainLabels, testData, testLabels)
  .then(history => console.log(history))
  .catch(error => console.error(error));

model.fit: это метод, при котором происходит фактическое обучение модели. Модель учится сопоставлять входные данные (trainData) с выходными данными (trainLabels).

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

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

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

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

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