Использование силы НЛП с помощью нисходящего подхода

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

От RNN к трансформаторам

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

  • Развернутые RNN
  • Кодер-декодеры
  • Механизм внимания с RNN
  • Первая архитектура трансформатора

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

Затем умные люди взяли RNN и использовали их в машинном переводе. Это особенно сложная проблема, поскольку сопоставление слов одного языка с другим языком предполагает сопоставление последовательности произвольной длины с другой последовательностью произвольной длины. Архитектуры кодер-декодер были разработаны для этого типа задач. По мере поступления новых входных данных кодировщик обновляет состояние до окончательного ввода, при котором последнее скрытое состояние преобразуется в числовое представление. Декодер получает это представление и использует его для генерации выходной последовательности. Представьте, что декодер постепенно «упаковывает» каждый вход, пока каждый не будет аккуратно помещен в окончательное скрытое состояние. Затем декодер «распаковывает» одно выходное слово за раз.

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

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

Однако даже у этого была проблема: последовательные вычисления, требующие ввода входных данных по одному, предотвращают распараллеливание входной последовательности. Есть несколько причин, по которым это нежелательно, но одна из них заключается в том, что это медленно. Чтобы решить эту проблему, трансформер сделал еще один шаг к свободной модели внимания. Для этого были удалены повторяющиеся сетевые блоки и разрешено взаимодействовать со всеми состояниями на одном уровне сети. Это известно как само-внимание, и показано ниже. Оба блока имеют механизмы самоконтроля, позволяющие им просматривать все состояния и передавать их в обычный блок нейронной сети. Это намного быстрее, чем предыдущий механизм внимания (с точки зрения обучения), и является основой большей части современной практики НЛП.

Трансферное обучение в НЛП

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

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

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

Этот прорыв породил два преобразователя, которые объединили внимание к себе с переносным обучением: GPT и BERT. Оба добились передовых результатов во многих тестах НЛП.

Почему нужно обнимать лицо?

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

Демонстрация трансформеров

Трансформеры имеют многоуровневый API, который позволяет программисту взаимодействовать с библиотекой на различных уровнях абстракции. Самый абстрактный из этих слоев — pipeline, который делает все за нас, а именно преобразовывает необработанный текст в набор прогнозов из точно настроенной модели.

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

Классификация настроений

В HF Transformers мы создаем конвейер, вызывая функцию pipeline() и указав имя интересующей нас задачи. Здесь мы также предоставляем модель; не беспокойтесь об этом слишком сильно, потому что HF Transformers по умолчанию будет использовать разумную модель для поставленной вами задачи, если вы не передадите модель.

Теперь, когда у нас есть конвейер, давайте сгенерируем несколько прогнозов! Каждый конвейер принимает строку текста (или список строк) в качестве входных данных и возвращает список прогнозов. Каждое предсказание представляет собой словарь Python, поэтому мы можем использовать Pandas, чтобы отобразить их красиво в виде Data⁠Frame:

Это дает нам следующий прогноз настроений:

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

Распознавание именованных объектов

Классификация настроений была хорошим первым шагом, но было бы полезно выделить конкретные вещи, о которых говорила Софи. Другое название объектов в НЛП — именованные объекты. Процесс извлечения их из необработанного текста называется распознаванием именованных объектов. Опять же, все, что нам нужно сделать, это загрузить нашу задачу в функцию pipeline() и передать ей наше текстовое сообщение:

Мы видим, что конвейер обнаружил объекты, а также присвоил им категорию, например. PER для человека и т. д. Он также может использовать другие категории, такие как LOC для местоположения. Баллы представляют уверенность модели в предсказанных объектах.

Ответ на вопрос

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

Модель совершенно уверена, что Джек не смог посмотреть фильм Сумерки. Надеюсь, Джек тоже понял это.

Подведение итогов

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

Вы заметите, что мы начали передавать некоторые аргументы в эти конвейеры, чтобы немного больше контролировать вывод. Изучение Hugging Face — это опускание уровней абстракции до тех пор, пока мы не погрузимся в глубины кода.

Генерация текста

Допустим, Джек — ужасный парень, и он только что узнал о Hugging Face. Предположим, он хочет использовать трансформер для создания ответа на текст Софи, потому что ему лень делать это самому. (До последних нескольких лет генерация текста определенно требовала бы гораздо больше усилий, чем написание текста с извинениями. Весьма примечательно, что на генерацию текста в Hugging Face, вероятно, действительно уходит меньше времени, чем на ввод ответа.)

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

Заключение

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

  • Модели. В HF Hub размещено более 20 000 бесплатных моделей с предварительно обученными весами.
  • Токенизаторы. Каждый конвейер использует этап предварительной обработки, называемый токенизацией, который разбивает необработанный текст на общие токены, которые затем сопоставляются с числовыми представлениями для обучения. Поскольку этот шаг очень важен (наряду с подшагами, такими как нормализация ввода и преобразование вывода модели из токенов обратно в текст), HF предоставляет Tokenizers, чтобы сделать это за нас.
  • Наборы данных.большинство наборов данных НЛП огромны — слишком велики, чтобы поместиться в оперативной памяти ноутбука. HF предоставляет стандартный интерфейс для наборов данных, а также использует интеллектуальное кэширование и сопоставление памяти, чтобы избежать ограничений ОЗУ.

Для получения дополнительных ресурсов отличным местом для начала является Документация Hugging Face. Откройте блокнот, напишите свой собственный образец текста и воссоздайте созданные выше приложения НЛП. Удачи в вашем путешествии по НЛП!

Рекомендации

[1] Л. Танстолл, Л. Верра и Т. Вольф, Обработка естественного языка с помощью преобразователя (2022), O’Reilly Media.

[2] Дж. Ховард и С. Рудер, Точная настройка универсальной языковой модели для классификации текстов (2018), arxiv

[3] А. Васвани и др., Внимание — это все, что вам нужно (2017), Google Brain