Описание Проекта

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

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

Источник данных

Источником всех стихотворений, которые мы будем использовать для точной настройки предварительно обученной модели, является Полное собрание поэтических произведений Эдгара Аллана По, собрание стихов и эссе, написанных По. HTML-версия этого сборника стихов доступна в открытом доступе через Project Gutenberg. Текст и названия стихотворений были извлечены из сборника с помощью BeautifulSoup. Код, который я использовал для очистки стихов, можно найти в репозитории GitHub для этого проекта.

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

Текст стихотворения был скопирован и разбит на строфы, содержащие несколько строк. Каждая строфа текста будет служить отдельной текстовой последовательностью при вводе в модель для обучения. Очищенные данные строфы сохраняются в CSV, который мы загрузим для обучения модели:

ГПТ-2 и трансформаторы

Генеративный предварительно подготовленный преобразователь 2 (GPT-2) - это языковая модель на основе преобразователя, разработанная OpenAI. Модель вызвала ажиотаж после первоначального решения ее создателей не выпускать полностью обученную модель из-за опасений ее возможного неправильного использования. Меньшие версии модели были выпущены в январе 2019 года, а полная модель была выпущена к концу 2019 года.

Текст, используемый для обучения модели, был получен путем очистки исходящих URL-адресов, размещенных на Reddit, с минимальным значением кармы 3. Для обучения GPT-2 использовалось более 8 миллионов веб-сайтов, а полная модель («очень большая») включает более 1,5 миллиардов параметров. . Меньшие версии модели содержат 762 миллиона («большие»), 345 миллионов («средние») и 117 миллионов («маленькие») параметров.

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

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

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

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

Также следует отметить, что постоянно разрабатываются более мощные языковые модели, и OpenAI объявил о разработке GPT-3 в 2020 году. В настоящее время GPT-3 лицензирован для Microsoft и не доступен для публичного использования.

Конструкция модели

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

Константа MAX_LEN относится к максимально допустимой длине каждого образца текста, предоставленного модели для обучения. Образцы текста, содержащие меньше токенов, чем это значение, будут дополнены до этой длины, а образцы, превышающие это значение, будут усечены. Выбор этого значения имеет решающее значение, поскольку некоторые предварительно обученные текстовые модели (включая GPT-2) могут обрабатывать текстовые последовательности только до определенной длины.

Токенизация

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

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

Давайте загрузим токенизатор GPT-2, который мы будем использовать, и добавим несколько специальных токенов. Эти токены будут использоваться для обозначения начала (‹BOS›) и конца (‹EOS›) каждой последовательности текста (в данном случае каждой строфы стихотворения). Создается дополнительный маркер заполнения (‹PAD›), чтобы все записи могли быть дополнены до одинаковой длины для обучения модели. Обратите внимание, что мы загружаем токенизатор, используя небольшую версию предварительно обученной модели GPT-2 из-за ограничений памяти.

Наборы данных

Чтобы обучить нашу модель, нам нужно будет загрузить все данные строфы нашего стихотворения в настраиваемый объект набора данных, который наследуется от класса набора данных PyTorch. Набор данных примет список строф стихотворений в качестве входных данных и применит токенизатор GPT-2 к каждой из них. Он автоматически вставляет специальные токены начала и конца последовательности в начало и конец каждой строфы. Кроме того, он будет дополнять или усекать каждую строфу на основе значения MAX_LEN, которое было определено ранее. Наконец, он определит входные идентификаторы и маски внимания для каждой строфы стихотворения. Теперь ко всем этим данным можно легко получить доступ через объект Dataset.

Разделение на обучение / проверку

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

Случайные семена

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

Dataloaders

Каждый из наших наборов данных (обучение и проверка) необходимо будет разделить на отдельные пакеты для обучения. Это легко сделать путем создания экземпляров объектов с помощью класса DataLoader PyTorch. Каждый объект DataLoader принимает набор данных в качестве входных данных и отбирает его в отдельные пакеты на основе определенного пользователем размера пакета.

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

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

Модельное обучение

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

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

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

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

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

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

Теперь, когда у нас есть все наши гиперпараметры, мы готовы загрузить предварительно обученную модель GPT-2 и начать ее точную настройку, используя данные для обучения строфы стихотворения. Во-первых, нам нужно загрузить конфигурацию модели с помощью класса GPT2Config, предоставленного в библиотеке преобразователей Hugging Face. Чтобы настроить конфигурацию модели, нам нужно указать общий размер словаря нашего корпуса текста, как определено нашим токенизатором, а также максимальную длину последовательности каждой текстовой последовательности на основе значения MAX_LEN, определенного ранее. Наконец, мы должны обязательно загрузить данные конфигурации из предварительно обученной модели GPT-2.

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

Теперь давайте обучим нашу модель!

Создать стихотворные строфы

Теперь, когда модель обучена, давайте воспользуемся ею, чтобы сгенерировать несколько «оригинальных» строф Поэ помеха.

Вот пример некоторых строф стихотворения, созданных моделью:

Довольно хорошо, но не идеально. Тем не менее, стиль По определенно можно обнаружить во многих сгенерированных строках, а также в общих форматах строф, которые были сгенерированы. Имейте в виду, что мы используем самую маленькую доступную версию GPT-2, которая имеет менее десятой части параметров, доступных в полноразмерной (XL) версии. Кроме того, эта модель была разработана просто, чтобы продемонстрировать возможности GPT-2 для создания нового текста. Есть еще много возможностей для улучшения и оптимизации, которые можно использовать для создания еще более убедительных стихов Поэ.

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

Обязательно посмотрите код этого проекта в его репозитории GitHub. Также не забудьте дать этой статье несколько аплодисментов, если вы нашли ее интересной или полезной!