̶с̶а̶м̶̶о̶изолента мёбиуса
2.44K subscribers
13 photos
2 videos
1 file
191 links
Костыли и технологии для обработки естественных языков. Обзоры статей и личный опыт. by @cointegrated
Download Telegram
#sotanlu
Ещё одна задача из SuperGLUE зовётся BoolQ: Exploring the Surprising Difficulty of Natural Yes/No Questions.

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

Авторы попробовали сделать transfer learning, дообучая на своём датасете модельки, натасканные на reading comprehension или natural language inference. Удивительно, но RC-подобные задачи типа SQuAD оказались не особо релевантными, а вот задачи на определение entailment - вполне. Моделька, предобученная только на MultiNLI, после файн-тюнинга дала точность 75.5%, тогда как BERT - 77%. А если уменьшить обучающую выборку для файн-тюнинга, то модель, предобученная на MultiNLI, справляется даже заметно лучше берта. Возможно, говорят авторы, это потому, что в MultiNLI есть примеры противоречий.

Для справки, люди справились с этой задачей на 89%, а бейзлайн "всегда говори да" дал точность 62%. T5 сейчас решает её на 91.5%, так что уже и эту задачу можно считать "хакнутой". Но из множества других задач SuperGLUE мне она как-то особенно симпатично - видимо, как раз в силу своей простоты и "натуральности".
#sotanlu послушал умных людей, почитал прошлогоднюю статью про mixout.
Это такая специальная регуляризация для файн-тюнинга моделей, когда в каждом батче некоторые случайно выбранные нейроны дообучаемой модели заменяются на старые. По аналогии с дропаутом, где они бы просто занулялись.
Авторы математически доказывают, что обе эти регуляризации, как и weight decay, примерно эквивалентны L2-штрафу за отдаление новых параметров от старых, и экспериментально показывают, что для файн-тюнинга BERT на GLUE mixout работает лучше аналогичного dropoutа. В принципе, очень понятно, почему так.
Простенький код для pytorch к статье прилагается)
#sotanlu ещё один датасет из SuperGLUE - ReCoRD, то бишь Reading Comprehension with Commonsense Reasoning Dataset
Этот датасет придумывался как сложная задача на понимание текстов. Решаемая боль была в том, что многие подобные задачи, типа SQuAD - довольно простые, и для их решения достаточно не очень сложных когнитивных навыков, типа детекции парафраз.

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

Тройки (текст, фраза, правильный ответ) были намайнены автоматически из новостных корпусов и отфильтрованы простыми правилами. То, что осталось, авторы пофильтровали моделькой типа Stochastic Answer Networks (текст и вопрос к нему энкодятся, вопрос с помощью атеншна подтягивается к тексту, и дальше для каждого токена текста предсказывается вероятность того, что на нем начинается или заканчивается верный ответ, и всё это с кучей дропаута). Оставили только треть троек, с которыми нейросетка не справилась, и из них отобрали ту половину, с которой справился хотя бы один адекватный тёркер. В результате осталось 100 тысяч обучающих троек, и 20 тысяч дополнительно провалидированных тестовых.

Авторы разметили часть заданий по тому, какой тип мышления нужен для получения ответа - в 3/4 случаев это "здравый смысл", который в свою очередь в основном сводится к работе с понятиями, пониманию причинно-следственных связей, и базовой психологии.

Люди корректно решили 91% задач, случайный выбор и простые языковые модели - 19%, а модель DocQA с ELMO-векторами (BERT'а тогда ещё не было), наилучшая из попробованных - 45%. После чего датасет рекомендовали как сложный. BERT впоследствии решил эту задачу на 72%, RoBERTa - на 84%, а T5 уже на 94%, обогнав кожаных мешков.

Чё, клёво.
Довольно прикольную модель для редактирования текстов, LaserTagger предложили зимой ребята из Гугла.
Чего хочется: быстро и дёшево и на маленьких выборках обучать модели для решения несложных seq2seq-задач.

В чём идея: во многих seq2seq задачках выход очень похож на вход: суммаризация (даже абстрактивная), разрезание и склейка предложений, исправление грамматических ошибок. А раз так, имеет смысл не генерировать выход с нуля, а получить его из входа путём вставок и удалений токенов. Решения можно принимать отдельно для каждого токена входа: оставлять его или удалять, вставлять ли перед ним текст, и если да, то какой. То есть архитектурно получается задачка, эквивалентная NER или POS-теггингу, для которых языковые модели хорошо файн-тюнятся даже на маленьких выборках. И хотя теоретически вставка может быть какой угодно, на практике словарём из 500 слов или коротких фраз можно покрыть 80-90% необходимых вставок.

То есть рецепт такой:
- берёшь seq2seq задачу
- строишь выравнивание input'а c output'ом, определяя необходимые вставки или удаления
- выкидываешь все редкие вставки, оставляя небольшой словарь
- при желании, можно ввести собственные операции редактирования, например, замену сущностей на подходящие местоимения
- файн-тюнишь BERT на по-токенное предсказание всех этих операций
- при желании, поверх BERT можно прилепить рекуррентный декодер, чтобы последующие правки явно зависели от предыдущих

В чём профит: в силу своей простоты по сравнению с полноценным seq2seq, такая моделька заводится даже на небольшой обучающей выборке (сотни и тысячи примеров), и, например, на 6К примерах для суммаризации уделывает бейзлайны с большим отрывом. А ещё, такая моделька, в отличие от seq2seq, не склонна выдумывать несуществующие слова или по многу раз повторять имеющиеся, и менее склонна галлюцинировать несуществующие факты. Ну и ещё такая моделька очень быстрая.

Мораль: большие и сложные модели - это хорошо, но маленькие и экономные модели - это ещё лучше. Ну и вообще, кажется, лень - это полезное для компьютерного лингвиста качество.
Рассказал на Диалоге про своё участие в дорожке по обогащению таксономии.
С одной стороны, стыдненько, что моё решение такое примитивное, по сравнению с некоторыми другими докладами.
С другой стороны, очень рад, что в эту тусовку вообще ворвался. К следующей конфе подготовлю что-нибудь уже действительно вкусное)
В последние два месяца я как-то выпал из айтишно-nlpшно-диалоговой жизни. Возвращаюсь.
Посмотрел воркшоп Витальца по разрабоке навыков Алисы с нуля на Node. Видос. Код.
Мне понравилось, насколько он чётко разложил всё по полочкам:
- работаем в докере, ничего не меняя на самой машине. Сначала ничего не деплоим, тестируемся через ngrok. Удобно.
- используются только две внешних зависимости, micro и nodemon - запуск и перезапуск http сервера
- выход на минимально работающий навык максимально быстро
- на втором этапе - обзор вау-эффектов
- вся разработка оооочень маленькими шагами
- по архитектуре: вся бизнес-логика в центре, оттуда вызываются функции для отдельных вью. Кажется, это довольно гибко.
- теория - в начале и в конце. Сложное посерединочке. Слушателям комфортно.
Ставлю Виталию большой лайк. Если/когда буду делать свой воркшоп по Алисе, обязательно возьму его на заметку.
Как посмотреть, кто забил все gpu на коммунтальном сервере и не использует: watch -c gpustat -cp --color
(предварительно pip install gpustat)
Недавно понадобился корпус plain text русского языка.
Мне хвалили Тайгу, но она по умолчанию лежит в conllu формате, т.е. с кучей синтаксической разметки. Я переупаковал архив, оставив только текст; можно пользоваться.
Сейчас, впрочем, это уже не так актуально, т.к. rusvectores выложили в открытый доступ НКРЯ, который раньше был закрытым. Впрочем, Тайга всё равно больше и прикольнее)
Одна из особенностей естественного языка, важная для разработки чатботов, это эллипсис, то есть пропуск слов, понятных из контекста. В частности, люди любят отвечать на вопросы "эхом": там, где ожидается ответ "да/нет", человек повторяет слово из вопроса. Например, так:

Бот: Нашла в каталоге торт "Маракуйя", добавить его в корзину?
Юзер: Добавь.

Очевидно, что тут интент пользователя - подтверждение. Забавно, что этот интент может выражаться какими угодно словами, но только если они соответствуют контексту.
Если вы разрабатываете нечто диалоговое, вам полезно заранее добавить такой интент или диалоговый акт. Конечно, разработчик может и сам правило написать. Но удобно, когда это сделано один раз и придумывать больше не надо)
Клёвая статья Reformulating Unsupervised Style Transfer as Paraphrase Generation (https://arxiv.org/abs/2010.05700)
Решаемая задача: научиться менять стиль предложения на заранее заданный, не меняя при этом его смысл.
Решение: обучить этому seq2seq-модель. В самой идее нет ничего нового, вопрос только, откуда брать пары предложений для обучения с одинаковым смыслом и нужным стилем.

Авторы предлагают идею, аналогичную back-translation в переводе:
0) Обучить seq2seq модель для перефразирования, не ориентируясь на стиль, но стараясь максимизировать разнообразие парафраз. Для этого датасеты найти не особо сложно.
1) Взять корпус А в нужном стиле, прогнать его через этот парафразер и получить корпус А', в котором фразы будут (предположительно) совпадать со фразами из А по смыслу, но не обязательно по стилю.
2) Обучить ещё одну seq2seq модель восстанавливать фразы из A по фразам из A', приводя их, таким образом, к нужному стилю.

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

А ещё они собрали большой датасет, на котором потенциально можно бенчмаркать свои собственные модельки для переноса стиля.
Если вы когда-нибудь захотите с нуля решить задачу тегирования текстов (типа NER), плюс-минус стандартный рецепт такой:
- Попробовать бейзлайн, основанный на словаре (для быстрого поиска большого количества подстрок в тексте удобно использовать pyahocorasick);
- Если словаря вам мало мало, разметить данные для ML можно в бесплатном labelstudio;
- Пофайнтюнить на этой разметке BERT или другой трансформер для вашего языка, примерно как в этом блокноте.
̶с̶а̶м̶̶о̶изолента мёбиуса
Клёвая статья Reformulating Unsupervised Style Transfer as Paraphrase Generation (https://arxiv.org/abs/2010.05700) Решаемая задача: научиться менять стиль предложения на заранее заданный, не меняя при этом его смысл. Решение: обучить этому seq2seq-модель.…
Прошлогодняя статья A Probabilistic Formulation of Unsupervised Text Style Transfer на ту же тему переноса стиля.

Здесь авторы решили строго вероятностно подойти к решению задачи переноса стиля между стилями, содержащимися в непараллельных корпусах A и B.
Для этого они обучают две языковые модели на A и B, и две seq2seq модели для перефразирования из A в B и обратно (точнее, это одна рекуррентная нейронка с дополнительным флажком для домена). Инновация в том, что авторы собирают из этих моделек конструкцию, честно описывающую совместное правдоподобие корпусов A и B и их "переводов" A' и B', и потом оптимизируют его честную же вариационную нижнюю границу.

В результате авторы получили крутые скоры на ряде задач переноса стиля, составив все свои модели из простых LSTMок. Правда, чуть позже их побила предыдущая описанная мною статья. И, кажется, причиной этого побития было использование предобученных трансформеров, в том числе явно обученных на задачу перефразирования. Всё-таки выучиться сохранять смысл, видя только коллекцию неразмеченных непарных текстов - дофига сложно, и не факт, что возможно вообще. И если уж есть возможность явно поучиться на хоть какой-то задаче перефразирования, стоит этим пользоваться.
Недавняя статья [DeBERTa: Decoding-enhanced BERT with Disentangled Attention](https://arxiv.org/abs/2006.03654) примечательна тем, что модель из нее сейчас сидит на верхушке лидерборда SuperGLUE, обогнав кожаных мешков на пол процентных пункта. Удалось это сделать за счёт пары небольших архитектурных изменений. Про классический BERT известно, что он не очень хорошо учитывает порядок слов. Чтобы справиться с этим, исследователи из Microsoft:

1) Добавили в атеншн веса для позиций токенов относительно друг друга. В ванильном берте позиция учитывается единожды, когда к эмбеддингу токена на самом первом слое добавляется эмбеддинг его абсолютной позиции, и дальше все self-attentions считаются примерно как softmax(Q*K). А в деберте атеншны считаются как softmax(Qc*Kc + Qc*Kp+QpKc), где матрицы с префиксами c учитывают активации на предыдущем слое, т.е. "контент" токена, а матрицы с префиксами p учитывают только позиции токенов относительно друг друга. Таким образом, модель гораздо охотнее выучивается смотреть на определенных соседей слова. И ещё, как бонус, мы получаем возможность обрабатывать неограниченно длинные тексты, т.к. эти самые относительные позиции считаются только по окну ограниченной ширины.

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

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

В итоге: мы получаем чуть более крутой BERT, чем раньше, и SuperGLUE, продержавшийся два года, уже тоже пора чем-то заменять.
#sotanlu
Если предобученные модели такие умные, почему им требуются обучающие примеры для такой простой задачи, как классификация текстов? Люди вот вполне могут размечать тексты без обучающих примеров, ориентируясь только на названия классов. В статье Text Classification Using Label Names Only: A Language Model Self-Training Approach (https://arxiv.org/abs/2010.07245) авторы придумали, как заставить BERT делать так же. Правда, им всё-таки нужен для подготовки модели большой неразмеченный корпус.

Итак, даны однословные названия классов, и хочется получить классификатор, различающий эти классы в тексте. Алгоритм:

1. Найдем данные названия классов в неразмеченном корпусе, и обычным BERTом предскажем для каждого вхождения топ 50 слов, которые могли бы стоять на их месте.
2. Почистим предсказанные слова, удалив стоп-слова и слова, часто встречающиеся в нескольких классах. Остальные будем считать "характерным словарем для данного класса".
3. Ещё раз пройдемся по всему корпусу, и разметим тексты следующим образом: если в тексте есть такое слово, что из топ 50 его замен минимум 20 входят в характерный словарь класса А, то весь текст относится к классу А. А само это словно заменим на маску, чтобы усложнить задачу
4. Обучим BERT-for-sequence-classification на текстах, которые удалось разметить таким образом.
5. Разметим полученным классификатором оставшиеся тексты, и дообучим классификатор на них тоже.

Оказалось, что на ряде задач классификации этот метод перформит сильно лучше остальных zero-shot бейзлайнов, и соответствует берту, обученному на примерно 50 размеченных примерах на класс.

В целом, идея кажется достаточно хитроумной и даже полезной, особенно для случая, если классов очень много, так что совокупно примеров нужно разметить дофига, но при этом классы достаточно простые, так что подход с ключевыми словами - справится. Напрягает только то, что с каждым новым классом такую модельку нужно будет обучать на всем корпусе заново, и в этом смысле подход явно недотягивает до человеческой гибкости.
Ребята во главе с @yuri_baburov наконец-то затащили русские модели в spacy!
https://nightly.spacy.io/models/ru
spacy - это, если что, примерно самая популярная питонячья либа для прикладного NLP. Там для кучи языков есть морфология, парсеры зависимостей, ner, и очень компактные векторные модели, да и в целом всё компактно и оптимизировано для продакшна. То есть это примерно как обновленная natasha, только ещё можно из коробки переключится на другой язык.
Попробовал русским GPT генерировать вопросы для рефлексии в @the_watchman_bot.
Среди них получилось довольно много нетривиальных. Вот 8 перлов, отобранные из 30 сгенерированных:

- Как Вы относитесь к тому, что ваши друзья должны быть лучшими из лучших?
- Какова ваша цель и за чем она стоит?
- На что способны ваши способности?
- Что для вас является лучшим подарком на Новый год?
- Что нужно сделать, чтобы перестать быть рабом своего тела и начать жить полноценной жизнью без всяких вредных привычек?
- Как давно Вы планируете начать новую жизнь?
- Как часто вы смотрите телевизор (особенно когда он выключен)?
- Что вы знаете о своей работе?
Включил пару своих алисьих навыков в "утреннее шоу", надо было быстренько сделать им нагрузочное тестирование, чтобы понять, с каким RPS их нормально прокачивать.
Нашёл тулзу molotov - питонячий load tester с очень низким порогов входа.
Тем, кто вообще нагрузочное тестирование своих веб-сервисов не проводит, крайне рекомендую)
Недавно я участвовал в последнем хакатоне Яндекса по разработке "городских" навыков Алисы, и позорно его слил. Но было интересно)
У хакатона были три фишки.
1) Тематика: его соорганизатор - правительство Великого Новгорода, и навыки должны быть посвящены этому городу.
2) Возможности: для участников хакатона открыли долгожданную фичу доступа к геолокации (до этого она была только у in-house навыков Яндекса).
3) Формат: хакатон растянули на месяц, в ходе которого сотрудники Яндекса пытались обучить народ правильной методологии разработки голосовых приложений.

Если всё такое вкусное, почему же я запорол этот хакатон?
- У меня тупо было мало времени: сначала я пытался успеть сделать статью к ACL, потом меня захватил водоворот других важных и срочных дел, и в итоге навык всё равно пилил в последнюю ночь.
- У меня не было хорошей идеи. Все мои успешные навыки делают по сути одну вещь, и делают её хорошо: собирают продукты для заказа доставки, ищут другие навыки, засекают время, предлагают отгадать автора цитаты. На этом хакатоне я попробовал сделать навык-экскурсовод, и это оказалось суперсложно, потому что экскурсовод должен хорошо мочь много вещей: ориентироваться на местности, обращать внимание на достопримечательности и интересные места, рассказывать связную историю. Это в принципе можно закодить, но нужно много часов кодинга, и ещё больше часов отладки. И нужен сильный контент: качественные тексты, качественные маршруты для навигации. Это тоже трудоёмко.
- Отсутствие нормальной команды. В одну меня звали сильные ребята, но мне был лень пересаживаться на их фреймворк разработки. В итоге я нашёл себе неопытного партнёра, и это оказалось полным провалом. Когда я погружён в проект достаточно сильно, в неопытного товарища можно отгружать отдельные таски, не требующие большой ответственности, а все ключевые решения принимать самому. Когда времени в обрез, и проектом занимаешься по остаточному принципу, это работает так себе: на коммуникацию уходит дефицитное время, которое я бы иначе потратил, чтобы сделать хоть что-нибудь. В следующий раз буду следить, чтобы в команде был кто-то решительный и инициативный, даже если я сам намереваюсь работать на отвали.
- Низкая мотивация. В качестве приза Яндекс предлагал свою колонку (которая в принципе у меня уже есть), а самостоятельно навык монетизировать не очень интересно: гостей Новгорода, являющихся пользователями Алисы и готовых платить за навык-экскурсовод вряд ли много. Возможно, для Москвы, которая сильно больше, такое разработать ещё стоит попробовать.

Работать с "географическим" навыком оказалось неожиданно сложно, ибо это требует многозадачности: нужно и выдерживать сюжет рассказа, и управлять перемещениями пользователя, и адекватно отвечать на все вопросы, возникающие в процессе - а их у туриста возникает очень много. Пока что я не понял, как это сделать правильно. Но, наверное, буду ещё пытаться, ибо это любопытно 🙃
Статья Beyond BLEU: Training Neural Machine Translation with Semantic Similarity - сентябрь 2019.

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

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

Кажется, что эта штука хорошо работает, потому что по смыслу это transfer learning: знания о семантике "перекачиваются" из модели сходства в переводчик или другую генерировалку текстов. А значит, особенно полезным такой подход должен быть, когда обучающих данных сравнительно мало. Собственно, в оригинальной статье так и было: в каждой языковой паре, на которой делали эксперименты, было 200-300 тысяч обучающих примеров, что для машинного перевода довольно скудно.

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

Одна из маленьких полезных тулзовин, доставшаяся мне с дорожки по детекции токсичных спанов в тексте.
Посмотрел видос митапа от сберовского Салюта по разработке их навыков - "смартапов" (https://youtu.be/Y6J3QR-Tq6I) . Видос на три часа, и даже на x2 довольно долго получается. В целом, рекомендую ещё их доки: https://salute.sber.ru/smartmarket/dev/.

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

Есть куча гибких настроек синтеза и распознавания речи, типа подсказок распознавателю, какие слова ожидать и сколько ждать.

Монетизация - через апи покупки товаров и услуг, для подключения нужно юрлицо или ИП. Встроенную в аппы рекламу обещают через полгода.

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

Салют предлагает несколько сервисов для исполнения сценарной логики: smartservices для действий с пользователем, NLU сервисы, и среда исполнения для аппов на графе.

Граф - это язык визуального создания сценариев state machine, типа как aimylogic. Есть классификаторы интентов. Можно смотреть логи.

Code - IDE в браузере на своём DSL со вставками JS. Можно интегрироваться с гитхабом и делать совместную разработку. Можно делать слот филлинг, есть куча именованных сущностей.

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

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

Сам я собираюсь в каком-то обозримом будущем попробовать разработать развлекательный смартап. Если хотите поучаствовать, пишите)

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