Основная идея - учить нейросетевую модель восстанавливать "запиканные" в тесте словосочетания.
В отличие от классической MLM задачи, мы будем закрывать не одиночные слова, а синтаксически связанные группы слов. К примеру, маскируем целые именные группы (Noun Phrases, сокращенно NP), то есть существительное со всеми прилагательными и т.д.
Исходное предложение:
На чердаке голодная кошка ловит жирную мышку.
После маскирования одной из NP:
На чердаке NP ловит жирную мышку.
Нейросетка должна предложить варианты NP в оставшемся контексте. Не стоит забывать, валидных вариантов обычно много.
Датасет формируется автоматически из "сырых" текстов с помощью синтаксического анализатора. В качестве синтаксического парсера используется UDPipe с русской языковой моделью, обученной на SynTagRus. Эту модель можно скачать с сайта UDPipe.
Код для формирования датасета выложен в этом репозитории - см. prepare_training_dataset.py.
Исходные тексты я не выкладываю в репозиторий по соображениям размера, но Вы можете подставить путь к своим файлам.
Готовые датасеты также выложены в репозитории - см. содержимое папки data. Размер этих датасетов небольшой, поэтому для получения хороших результатов рекомендую сгенерировать свои датасеты.
Оценивая необходимый размер датасета, следует учитывать располагаемые вычислительные ресурсы: на датасете с 10 миллионами сэмплов (~1 Гб) модель ruGPT small файнтюнится около 4 часов на 1 эпоху.
Я проверял файнтюнинг для двух языковых моделей: ruGPT и ruT5. К сожалению, ruT5 обучается намного тяжелее, поэтому я последующие эксперименты делал с ruGPT, вариант small.
Файл дообученной модели слишком велик даже в случае использования small варианта GPT, поэтому для экспериментов Вам нужно обучить модель у себя.
Для запуска обучения rugpt можно воспользоваться скриптом train_gpt.sh.
Запустите console_query_gpt.py.
После загрузки моделей GPT и UDPipe появится приглашение :>
.
Введите предложение, например "на чердаке голодная кошка отчаянно ловит мышку".
Код выполняет синтаксический анализ введенного предложения, выделяет NP и несколько раз запускает GPT для каждой NP, печатая результаты в консоли.
К примеру, такая выдача
Input: на чердаке [np1] отчаянно ловит мышку
+-------------------------+---------------------------------------------------------+
| np1 | result |
+-------------------------+---------------------------------------------------------+
| маленький рыжий котенок | на чердаке маленький рыжий котенок отчаянно ловит мышку |
| маленькая девочка | на чердаке маленькая девочка отчаянно ловит мышку |
| маленький котенок | на чердаке маленький котенок отчаянно ловит мышку |
| наш кот | на чердаке наш кот отчаянно ловит мышку |
| маленький мальчик | на чердаке маленький мальчик отчаянно ловит мышку |
+-------------------------+---------------------------------------------------------+
означает, что на вход GPT подавалась затравка "на чердаке [np1] отчаянно ловит мышку", в которой подлежащее было замаскировано символами [np1]. В таблице выведены сгенерированные варианты для [np1] и результат их подстановки.