"Начиная"

TensorFlow и трансформаторы

Как использовать передовые модели трансформеров для НЛП в TF2

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

Несмотря на это, в основных фреймворках TensorFlow или PyTorch нет встроенных реализаций моделей преобразователей. Чтобы использовать их, вам нужно либо подать заявку на соискание соответствующей докторской степени. программы, и мы увидимся через три года - или вы pip install transformers.

Хотя это немного упрощает процесс - на самом деле невероятно легко начать работу с некоторыми из самых передовых моделей (вспомните BERT и GPT-2).

При использовании библиотеки трансформаторов Huggingface у нас есть возможность реализовать ее через TensorFlow или PyTorch. В этой статье мы расскажем обо всем, что вам нужно знать, чтобы начать работу с TensorFlow.

What is HuggingFace?
  - Finding Models
  - Visualing Attention
TensorFlow
  1. Pre-Processing
  2. Tokenizer and Model
  3. Encoding Inputs
  4. Full Model Architecture
  5. Metrics, Loss, and Optimizer
  6. Training
Results

Если вы предпочитаете видео, я также рассмотрел весь процесс сборки здесь:

Что такое HuggingFace?

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

Чтобы загрузить и начать работать с некоторыми из крупнейших моделей, включая (но не ограничиваясь ими) - BERT, RoBERTa, GPT, GPT-2, XLNet, а также DistilBERT и DistilGPT-2 от HuggingFace, требуется не более трех строк. кода, который выглядит так:

from transformers import TFAutoModel, AutoTokenizer
model = TFAutoModel.from_pretrained("<model-name>")
tokenizer = AutoTokenizer.from_pretrained("<model-name>")

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

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

Поиск моделей

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

Мы можем фильтровать модели с помощью раскрывающегося списка Теги. Мы можем выполнять поиск на основе фреймворка, на котором они построены, например PyTorch / TensorFlow - это вариант использования, такой как классификация, QnA и т. Д.

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

Модель bert-base-cased соответствует нашему варианту использования, и мы будем реализовывать эту модель (позже), используя инструкции, представленные на странице модели.

Визуализация внимания

В качестве краткого, но интересного примечания: HuggingFace вместе с IBM Research и Harvard NLP создали невероятно увлекательный инструмент для визуализации внимания в нескольких моделях трансформаторов с помощью exBERT lite.

TensorFlow

Поддержка TensorFlow в библиотеке трансформеров появилась позже, чем для PyTorch, а это означает, что большинство статей, которые вы читаете по этой теме, покажут вам, как интегрировать HuggingFace и PyTorch, но не TensorFlow.

Конечно, шаги немного другие, но на высоком уровне процесс тот же:

  1. Предварительно обработать данные
  2. Инициализируйте токенизатор и модель HuggingFace
  3. Кодировать входные данные для получения входных идентификаторов и масок внимания
  4. Создайте полную архитектуру модели (интегрируя модель HuggingFace)
  5. Оптимизатор настройки, показатели и потери
  6. Обучение

Мы рассмотрим каждый из этих шагов, но в первую очередь сосредоточимся на шагах 2–4.

1. Предварительная обработка

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

Мы можем использовать набор данных обзора фильмов IMDB, который дает нам оценки настроений от 0 (ужасно) до 4 (потрясающе).

Вы можете получить набор данных здесь - или через Kaggle API:

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

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

2. Токенизатор и модель

Мы будем использовать библиотеку трансформеров HuggingFace для создания наших моделей трансформеров. Доступная нам модель трансформатора меньшего размера - это DistilBERT - уменьшенная версия BERT с ~ 40% параметров при сохранении ~ 95% точности.

DistilBERT - хороший вариант для тех, кто работает с меньшими вычислительными ресурсами. Просто замените bert-base-cased на distilbert-base-cased ниже. Мы инициализируем токенизатор BERT и моделируем так:

Это действительно так просто!

3. Кодирование входов

У нас есть готовые входные данные и токенизатор, поэтому теперь мы можем закодировать наши входные данные в два массива - (1) входные идентификаторы и (2) маску внимания.

Входные идентификаторы - это просто набор целых чисел, которые представляют слово, «привет» может быть 0, «мир» может быть 1. Но BERT использует предопределенный набор сопоставлений - поэтому мы загрузили наш tokenizer с помощью метода .from_pretrained.

BERT использует несколько специальных токенов. Эти:

Когда у нас есть наши последовательности, мы можем закодировать их с помощьюtokenizer.encode_plus:

Где SEQ_LEN=50, выходные данные входных идентификаторов будут выглядеть следующим образом:

Далее идет маска внимания. Эта маска представляет собой просто массив из 0 и 1, где каждая 1 представляет допустимый идентификатор слова / ввода, а 0 представляет заполнение. Метод encode_plus выводит как входные идентификаторы, так и тензоры маски внимания внутри словаря:

Слои внимания BERT используют эту маску и применяют операции внимания к встраиванию слова, которое соответствует 1, игнорируя те, которые совпадают с 0.

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

4. Полная модельная архитектура

У нас есть закодированные входные идентификаторы и маски внимания, а также инициализированная модель BERT - теперь нам нужно добавить дополнительные слои, необходимые для ввода входных идентификаторов и массивов масок внимания, а также слои, необходимые для классификации выходных данных BERT по оценкам настроений.

Для каждой модели трансформатора на основе BERT нам нужны два входных слоя, которые соответствуют длине нашей последовательности. Мы закодировали наши входные данные длиной 50 токенов, поэтому мы используем здесь входную форму (50,):

И наши входные идентификаторы, и массивы масок внимания содержат только целые числа, поэтому мы указываем dtype='int32'. Что еще более важно, имена слоев должны соответствовать парам ключ-значение во входных данных, для которых у нас есть два варианта:

(1) We keep input and output arrays as seperate variables
model.fit({"input_ids": input_ids, "attention_mask": mask},
          labels=labels)

(2) We place them into a tf.data.Dataset object beforehand
model.fit(dataset)

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

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

Здесь мы извлекаем выходные данные из distilbert и используем слой MaxPooling для преобразования тензора из 3D в 2D - в качестве альтернативы, используйте 3D-сеть (например, сверточные или рекуррентные нейронные сети), а затем MaxPooling.

Когда мы сложим все это вместе, мы получим следующее:

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

В сводке нашей модели показаны два входных слоя, BERT и наши окончательные уровни классификации. У нас есть в общей сложности более 108 миллионов параметров, из которых только 100 тысяч можно обучить, потому что мы заморозили параметры BERT.

5. Метрики, потери и оптимизатор

Здесь мы возвращаемся к стандартному процессу сборки TensorFlow.

Во-первых, мы используем оптимизатор, который все знаем и любим. Затем мы используем перекрестную запись категорий и категориальную точность для наших потерь и единой метрики. Поскольку у нас есть горячая кодировка наших выходных данных, мы используем Categorical.

В качестве альтернативы мы можем избежать быстрого кодирования наших выходных данных и использовать losses.SparseCategoricalCrossentropy(from_logits=True) с metrics.SparseCategoricalAccuracy('accuracy').

Наконец, мы компилируем нашу модель методом .compile - теперь мы готовы начать обучение!

Примечание. Если вы также обучаете слои BERT, попробуйте оптимизатор Adam с уменьшением веса, который может помочь уменьшить переобучение и улучшить обобщение [1]. Я бы порекомендовал эту статью, чтобы понять почему.

import tensorflow_addons as tfa  # Adam with weight decay
optimizer = tfa.optimizers.AdamW(0.005, learning_rate=0.01)

6. Обучение

Мы тренируемся как обычно, используя метод fit. Если не используется объект tf.data.Dataset, мы должны явно указать наши множественные входные данные, используя словарь. Все это требует:

С большинством графических процессоров обучение займет много времени - удачи тем из вас, кто использует только центральный процессор!

Если вам не хватает ЦП, попробуйте Google Colab - это бесплатный облачный сервис для ноутбуков, предоставляемый Google. Colab включает в себя графический процессор в стандартной комплектации - хотя и не особо мощный (но бесплатно).

Вот полная версия кода:

Полученные результаты

После нескольких часов обучения на моем жалком 940MX мы получаем точность проверки 94,9% - с большим количеством эпох обучения модель, похоже, легко улучшится и в этом:

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

В качестве альтернативы (хотя я обнаружил, что это вредно) мы даже можем использовать предварительно объединенные выходные тензоры BERT, заменив last_hidden_state на pooler_output - но это в другой раз.

Надеюсь, вам понравилась эта статья об интеграции библиотеки трансформаторов TF2 и HuggingFace. Если вы хотите большего, я размещаю уроки программирования / машинного обучения на YouTube здесь!

Если у вас есть вопросы, дайте мне знать через Twitter или в комментариях ниже.

Спасибо за прочтение!

использованная литература

[1] И. Лощилов, Ф. Хаттер, Несвязанная регуляризация спада веса (2019), ICLR.

🤖 НЛП с курсом трансформеров

* Все изображения принадлежат автору, если не указано иное