Так ли хороша GPT(*) для оценки P(текст)?

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



  1. Берем SV-затравку для предложения с синтаксисом SVO, например "Кошки любят есть".

  2. Перебираем разные аккузативы существительных в качества прямого дополнения O, то есть "Кошки любят есть диваны" и т.д.

  3. Оцениваем  достоверность с помощью loss'а языковой модели GPT.

  4. Ранжируем в порядке от лучшего к худшему и смотрим первую десятку.


Результат меня мягко говоря неприятно удивил, и я даже проверил работу нескольких вариантов GPT, включая базовую многоязычную GPT2. Результат для многоязычной GPT2 еще можно оправдать тем, что русских текстов она при обучении видела очень немного. Но вот попадание в топ ruGPT грейпфрутов объяснить я не берусь.


Число в первом столбце - это "перплексия", поэтому чем оно меньше, тем более вероятно предложение. Код доступен по ссылке, оценка предложения реализована функцией в строке 16.


Collapse )

PS: листинг скоринга предложений в ruGPT small с фрагментами для рыбы, сметаны и т.д. Тут лучше видно, что интуитивные ожидания совершенно не коррелируют с оценкой GPT.


Collapse )

Masked NP Language Modeling

Идея эксперимента с MNPLM была следующая.
Что, если учить генеративную нейросетку восстанавливать не просто какое-то слово в контексте предложения, а цельное словосочетание?

К примеру, в предложении "Голодная кошка ловит серую мышку" будем запикивать именную группу прямого дополнения и просить сетку по строке "Голодная кошка ловит [NP]" догадаться, какие варианты подстановок [NP] допустимы. Главная мысль - так как целое словосочетание лучше описывает объективную сущность, то модель сформирует более качественное представление о мире.

Возможное практические применение модели - аугментация текстовых датасетов, а именно их рандомизация (несинонимичные замены).

Весь код, датасеты и небольшая техническая справка выложены в репозитории https://github.com/Koziev/masked_np_language_model.

Под катом - некоторые результаты, полученные после обучения rugpt-small на 10 миллионах сэмплов.
Collapse )

DIY Красная Бурда или ИА Панорама

Проверяю на работе генеративную модельку после тренировки на новостях, и вот такое в выдаче:


В Вологодской области с начала года на дорогах зарегистрировано более 1 тысячи новых случаев заражения коронавирусом.

В Вологде на реке Волховском, близ села Синеозерье, в среду произошло серьезное ДТП с участием лосей и волка.

Вологодских водятелей предупредили о брачном периоде лосей.

В областном центре в четверг, 5 февраля, на льду озера Кумур в Вологодской области на лед спустили несколько десятков лосей.



А вот что моделька сделала с бессмертными строчками из Евгения Онегина:


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

Вторая попытка сделать генератор иллюстраций для генератора стихов

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

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

1) Поиск изображения через Google Search API с помощью пакета Google-Images-Search. Процедура подключения к API пошагово описана на страничке проекта, хотя это не спасло от крайне запутанного фирменного UX. В общем, на получение API key и project cx у меня ушло около часа. Этот API позволяет программно искать картинки по текстовому запросу, причем прямо на русском языке.

2) Стилизация найденного изображения с помощью neural style transfer. Я взял готовую реализацию из примеров Keras, доработал некоторые мелочи.

Получившийся код доступен в репозитории проекта. Предполагается, что при его запуске через опции комстроки задаются api key, project cx и текст запроса, например - какое-то существительное из сгенерированного стиха или заголовок. Для текста:


--- Сны и реальность ---

Муравьи, осы, букашки
И пчёлы, как мухи, вьются,
И, как от счастья, бегают мурашки
И хочется в сказке проснуться



берем существительное "муравей" и генератор выдает такую иллюстрацию:
Collapse )


Абстрактно, но  все-таки релевантно заданному ключу, в отличие от результатов DALLE. Вот пример выдачи DALLE, я выбрал реально самую релевантную картинку:

Collapse )

Впрочем, и новый генератор пока не дотягивает до цели - иметь полностью автоматический пайплайн для генерации иллюстраций к генерируемым текстам :(

Генерация "примет" и "умных советов"

Забавы ради собрал небольшой датасет с приметами и причим фольклором, и обучил на нем ruGPT, чтобы модель для заданной темы выдавала релевантную "примету".

Увы, качество генерации получилось не ахти, хотя cherry-picking'ом можно найти забавные вещи.

Например, приметы касательно программирования:

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

Collapse )

Про деньги:

"Деньги, взятые в долг, не возвращай, иначе будешь должен еще больше."


Collapse )
Шедевр дедукции:

"не надо думать что ты самый умный в мире если ты не самый умный в мире"


И еще всякое:

Collapse )

Автоматическая генерация четверостиший с помощью GPT и T5 - часть 5

Генерация названия для стиха

После того, как всё четверостишье сгенерировано и скомпоновано (см. первую, вторую, третью, четвертую части), остается сгенерировать его название.

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

Бродила в Лесу огневая волчица, | Зарёй поджигая прозрачный подлесок, | И так надрывались безумные птицы, | Что звёзды посыпались в тучи, как в тесто. # Бессонница
У кого-то под ногами | Ворох памяти, забот. | Память топчут сапогами | И городят огород. # Мудрён Дурак


Диез отделяет тело стиха от "образцового" названия (выделено болдом).

В режиме генерации мы подаем на вход ruGPT текст стиха в качестве prompt'а, а модель генерирует вариант названия. Например:


--- Трудоголик ---

На работу опоздать не сложно,
Но увольнение по желанию.
Работодатель должен понимать,
Что это - добровольное страдание.

--- Выходной день ---

На работу опоздать не сложно,
Но увольнение по желанию.
И на работу опоздать на час можно
По собственному расписанию


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

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

Автоматическая генерация четверостиший с помощью GPT и T5 - часть 4

Дополнение последних слов до полных строк с помощью модели T5

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

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

Но я решил попробовать использовать супер-пупер новую модель ruT5, которая менее известна в сравнении с ruGPT, но архитектурно очень интересна. В ней сочетается BERT-подобный двунаправленный энкодер и GPT-подобный однонаправленный декодер. Некоторые технические подробности можно найти тут или в статье коллег из Сбера.

Среди прочего (а прочего много) T5 тренируется так, чтобы выполнять denoising - заполнять удаленные фрагменты текста. Как раз то, что нам надо! Мы считаем, что последние две строки четверостишья содержат такие лакуны:

На ветках малины почки
В бутонах висят.
<extra_id_0> строчки
<extra_id_1> взгляд

Выдача T5 для такого входа будет содержать вариант подстановки для <extra_id_0> и для <extra_id_1>. Нам остается только извлечь эти фрагменты и подставить их.

Разумеется, надо предварительно дообучить ruT5 на корпусе стихов.

(заключительная часть)

Автоматическая генерация четверостиший с помощью GPT и T5 - часть 3

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

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

Первая проверка выполняется с помощью акцентуатора. Он предсказывает позицию ударения в произвольных словах, используя как словарь для частотных слов, так и ML-модель для всяких oov.

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

Также используются некоторые эвристики. Например, для глагола в качестве рифмы предпочтаем существительное, чтобы не скатываться в банальщину "спать - играть". Часть речи определяется с помощью морфоанализатора ruword2tags.

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

Collapse )
(продолжение следует...)

Автоматическая генерация четверостиший с помощью GPT и T5 - часть 2

Генерация первых строк с помощью GPT

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


--- Берёзка ---

На небе, как прежде, ясный день,
Прохладный ветерок, как живая вода,
В саду, на скамейке, как в колыбели,
Стоит красавица берёза.


Хотя время от времени GPT-шка выдает что-то почти срифмованное:


--- Прохладный ветерок ---

Прохладный ветерок,
За окошком гроза,
С крыши падает листок,
На землю, как слеза.



В общем, было решено не пытаться заставть GPT2 модель выдавать весь стих, а пойти другим путем. А GPT-2 пусть генерирует первые две строки стиха на заданную тему. Вот это получается у этой модели вполне пристойно.

Как это сделано?

Корпус стихов подвергается синтаксическому парсингу. Каждая строка прогоняется через UDPipe, из нее выделяются именные группы (Noun Phrases). Далее формируется обучающий датасет, в котором каждая выделенная именная группа выступает в роли затравки (prompt), а текст стиха - ожидаемое продолжение:


белая береза # белая береза под моим окном | принакрылась снегом, словно серебром

Один исходный стих порождает несколько подобных записей с разными именными группами.

Далее, файнтюним ruGPT на этом датасете и получаем модель, которая для заданной темы (в виде словосочетания с существительным в главной роли) выдает четверостишье. Это четверостишье с пометкой "VERS-LIBRE" можно увидеть в выдаче генератора в докер-образе.

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


(продолжение следует...)

Автоматическая генерация четверостиший с помощью GPT и T5

Далее я постараюсь максимально просто и пошагово описать, как с помощью нейросетевых генеративных моделей GPT и T5 генерировать рифмованные короткие тексты уровня "Я поэт, зовусь я Цветик. От меня вам всем приветик", хотя временами и с претензией на глубину, пафос и душевный надрыв:


--- Весна идёт, весна идёт ---

На ветках малины почки
В бутонах висят.
В них рифмы, слова, слова, строчки
И, конечно, твой взгляд



Collapse )
Краткое представление о предлагаемом подходе может дать вот такая схема:
Collapse )
Репозиторий с кодом для инференса доступен тут. Собственно код генератора здесь.
Докер-образ с генератором и всеми моделями можно скачать тут.
Далее буду описывать каждый этап отдельно.
Collapse )