Изучение глубокого обучения с помощью преобразователей для упрощения текста

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

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

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

Эта статья будет первой из трех. В этом я расскажу о реализации преобразователя с использованием библиотеки Hugging Face. Второй будет о подготовке набора данных и т. Д. А третий - о самодельном трансформаторе. Вместе они являются частью более крупного проекта. Просмотрите соответствующее репозиторий GitHub, чтобы получить обзор.

А теперь приступим!

Нет необходимости изобретать велосипед, если есть Обнимающее лицо 🤗. Для всех, кто не знаком с Hugging Face: это одна из самых известных и наиболее часто используемых библиотек для использования трансформеров в НЛП. Я не буду вдаваться в подробности, но настоятельно рекомендую ознакомиться с их материалами.
Использование последовательных моделей Hugging Face не только избавило от многих хлопот - написание преобразователя с нуля - но и открыло новые огромные возможности. Horizon, используя свои предварительно обученные кодировщики и декодеры.

Модель кодировщика-декодера, также известная как модель последовательность-последовательность.

Итак, все начинается примерно так:

Мы создаем EncoderDecoderModel, инициализируя кодировщик и декодер с помощью свободно доступных контрольных точек BERT (bert-base-uncased). Какая комбинация параметров кодера и декодера является наилучшей, зависит от варианта использования. Я начал с использования весов BERT в качестве параметров кодировщика и декодера и закончил тем, что использовал RoBERTa из-за более обширного корпуса, на котором он был обучен. Пробовать и анализировать все возможные комбинации - задача непростая. Так что мы можем быть счастливы, что Саша Роте, Шаши Нараян и Алиаксей Северин сделали это за нас в своей прекрасной бумаге.

Выполнение приведенного выше кода даст нам несколько сообщений:

Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertModel: ['cls.predictions.decoder.weight', 'cls.seq_relationship.weight', 'cls.predictions.transform.dense.bias', 'cls.seq_relationship.bias', 'cls.predictions.transform.LayerNorm.bias', 'cls.predictions.transform.LayerNorm.weight', 'cls.predictions.bias', 'cls.predictions.transform.dense.weight']
- This IS expected if you are initializing BertModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing BertModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model).
Some weights of the model checkpoint at bert-base-uncased were not used when initializing BertLMHeadModel: ['cls.seq_relationship.bias', 'cls.seq_relationship.weight']
- This IS expected if you are initializing BertLMHeadModel from the checkpoint of a model trained on another task or with another architecture (e.g. initializing a BertForSequenceClassification model from a BertForPreTraining model).
- This IS NOT expected if you are initializing BertLMHeadModel from the checkpoint of a model that you expect to be exactly identical (initializing a BertForSequenceClassification model from a BertForSequenceClassification model). Some weights of BertLMHeadModel were not initialized from the model checkpoint at bert-base-uncased and are newly initialized: ['bert.encoder.layer.7.crossattention.output.dense.bias', 'bert.encoder.layer.9.crossattention.self.query.bias'...]
You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.

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

Сейчас у нас уже есть модель кодировщика-декодера, которая обеспечивает ту же функциональность, что и другие модели этого типа, такие как BART, ProphetNet или T5. Единственная разница в том, что наша модель использует предварительно обученные веса BERT.

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

Интересные параметры, которые нужно настроить, - это параметры во втором блоке.
С помощью length_penalty мы подталкиваем модель так, что упрощенный текст автоматически становится короче исходного текста. Параметр num_beams немного сложнее объяснить. Таким образом, речь идет о том, сколько слов продолжения следует учитывать в последовательности для расчета вероятности. Пожалуйста, ознакомьтесь с этим отличным постом о блоке, чтобы получить подробную картину поиска Beam.

Модель

Это оно! Наша модель seq2seq с горячим запуском теперь готова для точной настройки. Следующим шагом является настройка всех необходимых обучающих аргументов. Полный список можно найти в документации. Я расскажу только о некоторых из них.

pred_with_generate должен быть одним из них, при установке его на «истинные» показатели, такие как METEOR или ROUGE, будут вычисляться во время обучения. О метриках поговорим чуть позже. Важно знать, что потеря и оценка-потеря как метрики не так значимы для упрощения текста, как в других приложениях глубокого обучения.
Для ускорения обучения и уменьшения использования памяти графическим процессором мы разрешаем fp16 использовать 16-битную точность вместо 32-битной. Надеемся, что эта настройка не вызовет исчезновения градиента, что опасно при работе с трансформаторами.
gradient_accumulation_steps действует в том же направлении. Он определяет, сколько шагов обновлений накапливается перед выполнением обратного пути. При использовании больших моделей на одном графическом процессоре это одна из возможностей не работать мгновенно при нехватке памяти графического процессора.

Seq2SeqTrainer, который получает аргументы обучения в качестве параметров, также ожидает функцию compute_metrics.

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

После извлечения label_ids и прогнозов из объекта prediction мы их декодируем. Строка одиннадцатая гарантирует, что мы правильно заменили токен панели. После этого мы вычисляем метрики METEOR и ROUGE и возвращаем их в виде словаря.

Теперь все готово, и мы можем приступить к тренировке. В зависимости от набора данных это может занять некоторое время. Мой последний подход с набором данных 1,3 млн строк занял 60 часов. Так что давайте подождем и съедим печенье 🍪.

Оценка

Наконец, мы можем использовать нашу модель для упрощения текста.

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

Давайте быстро пройдемся по коду. К счастью, снова используется Hugging Face:

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

Затем мы токенизируем input_text, чтобы он был готов для обработки модели. Мы задаем ему max_length 60 - остальное будет дополнено или обрезано - в зависимости от длины.

С помощью training_model.generate мы генерируем упрощенный текст. Здесь мы можем поиграть с такими параметрами, как temperature или num_beams, чтобы улучшить результат.

Следующий

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