Данный проект является одновременно развитием и ответвлением проекта Pinder.
В комментариях к первой статье (да и сам думал об этом тоже) мне предлагали вариант для распознавания смыслов на GPT.
Почитал немного про использование GPT, круто это всё конечно, вот прямо спорткар, Ferrari какой-нибудь в мире NLP. В общем Ferrari это круто, но я люблю велосипеды, поэтому было принято решение запилить пусть что-нибудь простое, но своё.
Так появился проект NeBender (Neural Bender).
Изучение NLP и эксперименты с примерами
Чтобы хотя бы немного понимать как это всё работает, я пошёл по классическому подходу — прочитать умную книжку. В качестве умной книжки попалась «Обработка естественного языка в действии» (Хобсон, Ханнес, Коул).
На постепенное продвижение (с периодическим бросанием на месяцы) по теории и примерам до нужной для моей задачи 10-й главы ушло больше года.
В 10-й главе рассказывается как создать модель чат-бота Sequence-To-Sequence на основе архитектуры кодировщик-декодировщик (encoder-decoder). Также упоминается использование механизма внимания для создания модели трансформера, но примеров не приводится (на момент написания книги в Keras не было реализации данного механизма).
Так ладно, для моей задачи в приципе подходит — есть вопросы и реплики, обращённые к Бендеру, и есть его ответы. Для начала пойдёт, а дальше уже можно будет пробовать улучшения.
Сделаю здесь небольшое отступление и немного попинаю авторов книги и программное окружение Питона для ML.
До 10-й главы большинство примеров у меня работали практически без проблем, иногда конечно надо было что-то подпилить, доустановить. Но вот как раз в самой нужной главе с этим обнаружились проблемы. Примеры как есть либо работают криво, либо вообще не работают (на GitHub книги в разделе issues авторам шлют приветы — https://github.com/totalgood/nlpia/issues).
Ну да ладно, с матами, хождением по старым коммитам кое-что работало, и самое главное в книге для меня было уяснить принципы работы.
Ещё на примерах из 10-й главы проявилась ожидаемая проблема с моим железом. В качестве рабочей машинки у меня MacBook Pro 15 2013 года без дискретной видеокарты, и обучение моделей из примеров с посимвольной токенизацией занимало у меня огромное количество времени (примерно 16 часов). В следствие чего я перешёл на токенизацию по словам (на моём текущем датасете NeBender’а к примеру одна эпоха на посимвольной токенизации занимает чуть более 4-х минут, а по словам — примерно полторы минуты).
В качестве основы для примера взял вот этот notebook - https://colab.research.google.com/drive/1FKhOYhOz8d6BKLVVwL1YMlmoFQ2ML1DS
Датасет
Переходим к самой трудоёмкой и нудной части разработки.
В начале я вообще боялся, что придётся забирать тексты из субтитров или хуже того выслушивать всё. Но как оказалось нашлись хорошие люди, которые выложили расшифровки сценариев на вики - https://futurama.fandom.com/wiki/Category:Episodes
Конечно в этом случае я полагаюсь на то, что данные тексты корректны без проверки (на мой взгляд по памяти вроде всё неплохо).
Это изрядно упростило работу, но всё равно её осталось очень много.
Во-первых, к сожалению пока я отбросил фразы (они закомментированы в датасете), которые Бендер говорит на какие-то события или «просто так», оставив только те где Бендер реагирует на фразы других персонажей. Возможно в будущем соберу отдельно эти фразы, чтобы Бендер мог просто их случайно говорить (ну или вдруг прикручу камеру, чтобы ему что-то показывать) и инициировать диалог.
Также далеко не во всех случаях Бендер отвечает прям на предыдущую фразу, это может быть и ответ на фразы несколько строками выше, и на «сумму» нескольких строк, что исключает автоматизацию этого скриптом и требует ручной работы. В таких случаях я также оставлял кроме пары вопрос-ответ для обучения ещё и закомментированный оригинал, чтобы если кто захочет мог это переработать на своё усмотрение.
На текущий момент скомпилировал 4 первых «классических» сезона, надеюсь потихоньку доделать остальные позже.
Интерконнект с Pinder’ом, распознаванием и синтезом речи
Исходя из тяжести компонентов получающейся системы (распознавание на открытом словаре и нейронка для NLP) было понятно, что Pinder на Raspberry Pi Zero первой версии уже это всё не потянет, но я всё равно сделал попытку создать для PocketSphinx ограниченную языковую модель на основе вопросов из датасета (есть закомментированные строки в notebook если кто-то желает попробовать) – получилось 4699 тысяч слов (я пробовал когда работал над 3-м сезоном, сейчас их ещё больше). Эксперимент как и ожидалось провалился, всё это работало жутко медленно.
Ещё как вариант попробовал развернуть на компе сервер Kaldi, и по сети распознавать с Pinder’а, но из-за качества записи распознавание также выдалось не очень хорошим.
Поэтому я в итоге для этого проекта пока ушёл на схему при которой весь процессинг идёт на компьютере (моя NLP нейросеть) и в облаках(MS Azure STT и TTS). Возможно вызов облачных функций также было бы вызывать из Pinder’а и только вызывать инференс NLP на ноутбуке, но к сожалению Azure STT SDK не работает на ARM-архитектуре на текущей момент, а ради одного TTS оставлять часть логики на колонке я посчитал неразумным.
В общем такая колхозная схема работы: на компе запускается распознавание с микрофона -> передаётся распознанный текст в Seq2Seq модель NLP -> ответ передаётся на синтез -> синтезированный файл по NFS подкладывается на Pinder -> скрипт на Pinder’е проигрывает файл и анимирует «зубы». В отсутствии Pinder’а можно просто играть файл с компьютера.
Результат работы:
Исходники - https://github.com/sindar/NeBender
Будущее
Примерные пункты, которые хочется сделать:
Дополнить датасет остальными сезонами (на текущий момент 4 сезона это только 72 серии из 140).
Попробовать более продвинутые модели (BERT?).
Купить нормальную видеокарту для десктопа (ну или может новый ноут с мощным GPU), чтобы более продвинутые модели было приятнее пробовать.
Попробовать что-то типа Nvidia Jetson, возможно вполне потянет на себе без использования десктопа/серверов.
Сделать как вариант «морду» для софта, чтобы можно было без Pinder’а запускать на компе, а там были бы анимации какие-нибудь.
Хотелось бы модель на русском языке, но этот пункт к сожалению наименее реальный из всех — основы для датасета нет, и обработка русского гораздо сложнее (но здесь надо попробовать имеющиеся библиотеки, может не всё так страшно).
Спасибо, что прочитали статью, а Бендер как обычно говорит «Bite my shiny metal ass»! :)
Jury_78
Локально, например Vosk (Kaldi) неплохо работает на TV BOX - процессор Intel Baytrail Z3735F
Zen_Kong Автор
Да, Vosk неплох, конкретно у меня в сетапе проблема в том, что я использую плату ReSpeaker2, которая внутри корпуса сейчас, и качество записи такое, что Kaldi на выходе весьма ошибочные предложения выдаёт. А на компе мне уже просто проще было запустить пока вариант от MS Azure, так как и синтез от него использую, но в будущем обязательно попробую от облаков отвязаться.