̶с̶а̶м̶̶о̶изолента мёбиуса
2.28K subscribers
13 photos
2 videos
1 file
174 links
Костыли и технологии для обработки естественных языков. Обзоры статей и личный опыт. by @cointegrated
Download Telegram
Обещал выложить код с объяснениями к моему посту про модель T5, в которой я оставил только русский язык.

Дано: модель mT5 на 101 язык
Найти: её уменьшенную версию для русского
Решение:
1) Токенизировал токенайзером от mt5 русский корпус, подсчитал, какие токены часто использовались.
2) Залез в кишки токенайзера, удалил редко использованные токены. Запомнил соответствие между старыми и новыми номерами токенов.
3) Заменил матрицы входных и выходных эмбеддингов в нейронке, сократив их размер и передвинув строки этих матриц по соответствию из пункта 2.
4) Изменил размер словаря в конфиге модели, чтобы он совпадал с тем, что в нейронке.

Блогпост с более подробными объяснениями и кодом: https://cointegrated.medium.com/how-to-adapt-a-multilingual-t5-model-for-a-single-language-b9f94f3d9c90
Are Pre-trained Convolutions Better than Pre-trained Transformers? Такой вопрос поставили себе исследователи из Гугла, и ответили на него в лоб. Они предобучили T5-подобный трансформер и его аналоги, использующие вместо атеншна три чуть разных типа свёрток, на одном и том же текстовом датасете C4. И потом пофайнтюнили на несколько задач класификации (токсичность, сентимент, темы новостей и типы вопросов) и одной задаче семантического парсинга. И сравнили это с обучением тех же архитектур на конечной задаче с нуля. Оказалось, что на большинстве задач классификации CNN работают сопоставимо по качеству с трансформером, и так же выигрывают от предобучения. И даже на семантическом парсинге CNN отработала весьма прилично.

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

И всё-таки иметь готовый быстрый энкодер для длинных текстов было бы круто. Будем ждать, когда кто-нибудь выложит крутую предобученную свёрточную сетку для текстов в открытый доступ)
Поделюсь несколькими статьями про сжатие языковых моделей. Зачем их сжимать? Чтобы CPU и памяти кушали меньше, очевидно.

On the Effect of Dropping Layers of Pre-trained Transformer Models подходят к задаче просто: удаляют в трансформере половину слоёв (лучше всего - верхние) и файн-тюнят его на конечную задачу. Говорят, что для многих задач просадки в качестве нет, потому что трансформеры заведомо избыточны.

Well-Read Students Learn Better: On the Importance of Pre-training Compact Models - авторы статьи утверждают, что если маленькую языковую модель предобучить на MLM задаче, потом подистиллировать об большую модель, и потом дообучить на конечную задачу, то она будет работать лучше, чем если пропустить шаг предобучения или дистилляции. Что в целом логично: предобучение без дистилляции недостаточно информативно (модель-ученик может просто не осознать, чего от неё хотят), а дистилляция без предобучения дорогая (т.к. приходится много данных через тяжеловесную модель-учителя пропускать). Но не очевидно, почему бы не попробовать и предобучение, и дистилляцию одновременно, а не последовательно.

ALBERT: A Lite BERT for Self-supervised Learning of Language Representations - успешная попытка сократить число параметров BERT: уменьшили размер эмбеддингов токенов и объединили параметры всех трансформерных слоёв. В итоге получилось в 18 раз меньше параметров, чем в обычном берте, и ускорение обучения раза в два (впрочем, скорость инференса от этого не уменьшается). Ещё поменяли одну из двух подзадач предобучения BERT: вместо next sentence prediction (определять, идёт ли второе предложение после первого, или выбрано случайно) дают sentence order prediction (определять, какое из двух предложений идёт в тексте раньше другого). Эта более сложная задача вместе с большим вычислительным бюджетам на обучение привела к тому, что ALBERT какое-то время был SOTA на GLUE (и вскоре после этого GLUE закопали).

TinyBERT: Distilling BERT for Natural Language Understanding - успешная многослойная дистилляция BERT с 10-кратным ускорением, про неё я писал отдельно.

А вообще, если хочется узнать, как сжимают языковые модели, можно почитать обзоры, типа лаконичного поста All The Ways You Can Compress BERT или относительно свежей статьи Compression of Deep Learning Models for Text: A Survey. Из обзоров видно, что для GLUE-подобных задач ничего лучше дистилляции пока не придумали, и что дистилляцию можно применять в комплекте с квантизацией (например, LadaBERT комбинируют матричные разложения, прунинг отдельных весов и дистилляцию, и получают качество TinyBERT более дёшево).

Я сам тоже на днях попробовал таки сжать BERT для русского, получил rubert-tiny, и работает он, если честно, пока отстойно. Но он в 10 раз меньше и быстрее bert-base, и, может быть, таки пригодится для какой-нибудь задачки, где скорость сильно важнее качества.
The Winograd Schema Challenge - задача по разрешению кореференции в предложениях. По сути, надо понять, к какому слову относится местоимение.
Например: "Кубок не помещается в коричневый чемодан, потому что он слишком большой". Верно ли, что слово "он" относится к слову "чемодан"? Неверно.

Прикол WSD в том, что в тестовой выборке может содержаться похожее предложение: "Кубок не помещается в коричневый чемодан, потому что он слишком маленький". И вот в таком предложении "он" уже относится к "чемодану". И оказывается, что ML алгоритмы к такому повороту не очень готовы.

На русскоязычном лидерборде наилучшая моделька выдаёт точность 67% на таких предложениях - то есть столько же, сколько и рандомный бейзлайн. На английском SuperGLUE точность выше, но разрыв с человеческим перформансом (равным 100%) пока заметный.

Мне это кажется довольно удивительным. Задача разрешения кореференции для местоимений - супер важная, и кажется очень базовой. И до сих пор она решена весьма так себе.
#sotanlu
Хозяйке на заметку: если вам нужно относительно качественно перефразировать предложение, можно сделать это методом back-translation: перевести его русского на английский и назад на русский.
Чтобы не получить на выходе то же самое предложение, можно запретить модели-переводчику воспроизводить n-граммы (токенные), встречавшиеся в исходном предложении.
Кажется, получается дёшево и сердито.
import torch
from transformers import FSMTModel, FSMTTokenizer, FSMTForConditionalGeneration
tokenizer = FSMTTokenizer.from_pretrained("facebook/wmt19-en-ru")
model = FSMTForConditionalGeneration.from_pretrained("facebook/wmt19-en-ru")
inverse_tokenizer = FSMTTokenizer.from_pretrained("facebook/wmt19-ru-en")
inverse_model = FSMTForConditionalGeneration.from_pretrained("facebook/wmt19-ru-en")
model.cuda();
inverse_model.cuda();

def paraphrase(text, gram=4, num_beams=5, **kwargs):
""" Generate a paraphrase using back translation.
Parameter `gram` denotes size of token n-grams of the original sentence that cannot appear in the paraphrase.
"""
input_ids = inverse_tokenizer.encode(text, return_tensors="pt")
with torch.no_grad():
outputs = inverse_model.generate(input_ids.to(inverse_model.device), num_beams=num_beams, **kwargs)
other_lang = inverse_tokenizer.decode(outputs[0], skip_special_tokens=True)
# print(other_lang)
input_ids = input_ids[0, :-1].tolist()
bad_word_ids = [input_ids[i:(i+gram)] for i in range(len(input_ids)-gram)]
input_ids = tokenizer.encode(other_lang, return_tensors="pt")
with torch.no_grad():
outputs = model.generate(input_ids.to(model.device), num_beams=num_beams, bad_words_ids=bad_word_ids, **kwargs)
decoded = tokenizer.decode(outputs[0], skip_special_tokens=True)
return decoded

text = 'Женщина-дайвер исчезла в Черном море во время научных работ на побережье Анапы.'
print(paraphrase(text, gram=3, do_sample=False))
# Женщина-водолаз пропала в акватории Черного моря, когда выполняла исследовательские работы у берегов Анапы.
# Wall time: 699 ms
#sotanlu Ещё одна задача из SuperGLUE, RTE, (Recognizing Textual Entailment) - задача классификации, следует ли второе предложение из первого. Например, "Автор поста написал в комментарии, что прорвалась канализация." и "Автор поста написал про канализацию." - здесь второе предложение вытекает из первого.

Это - самая частая формулировка более общей задачи NLI (natural language inference). А ещё её можно рассматривать как обобщение задачи детекции парафраз, ибо если пара предложений друг друга перефразирует, то они взаимно друг из друга следуют. Ещё с помощью моделей RTE удобно оценивать качество суммаризации: саммари, если оно не врёт, должно следовать из исходного текста. А одна недавняя статья от FAIR вообще предлагает все задачи на классификацию предложений и их пар переформулировать в NLI, и утверждают, что это помогает на новые задачи дообучаться быстрее. В общем-то, и zero shot classification можно как NLI сформулировать, типа следует ли из фразы "Еда была очень вкусная, и сервис хороший" фраза "Отзыв положительный".

Для задачи RTE хорошо работает классическая архитектура для классификации пар: сконкатенировать два предложения с каким-то разделителем, прогнать через BERT-подобный энкодер, классифицировать по эмбеддингу CLS токена. На huggingface есть куча готовых моделей для NLI и zero-shot classification для английского, а вот для русского я с ходу не нашёл. Но тоже, наверное, должны быть)

Задача в стиле RTE входит и в RussianSuperGLUE, и скор на ней (87% у ансамбля, 73% у лучшей одиночной модели) пока что сильно ниже человеческого (92%). И даже на англоязычном лидерборде кожаные мешки пока что держат оборону, хоть разрыв с лучшей моделью уже и небольшой. Потому что, хоть на первый взгляд задача RTE и кажется простой и бесполезной, чтобы решить её хорошо, тексты нужно реально понимать.
Я в этом канале регулярно что-то пишу про свои pet projects, но мало пишу про основную работу в Сколтехе. Оправдываю это тем, что мы пока что мало публикуемся.
Но вот таки одну статью по моей теме (перенос стиля) опубликовали и на Диалоге представили. Там основной вклад Дарины (кстати, рекомендую ее канал @towards_nlp), но я тоже чутка поучаствовал.
Итак, Methods for Detoxification of Texts for the Russian Language, первый заход: https://arxiv.org/abs/2105.09052
Вчера СберДевайсы выпустили русскую версию модели CLIP (пост, веса).
CLIP - это пара энкодеров, которые переводят картинки и тексты в одно и то же векторное пространство. Довольно удобная штука для zero-shot классификации картинок и для поиска по ним.
А ещё в паре с картиночным GAN'ом из неё можно сделать генератор картинок по подписям, а в паре с годным генератором текстов - генератор подписей к картинкам.
В общем, полезная в хозяйстве штука, забирайте.
Помните, недавно я постил код для перефразирования предложений переводом на английский и обратно?
Так вот, оказалось, что этот бейзлайн пока что не может обойти ни одна нейросетка, специально обученная на задачу перефразирования.
Про то, как я собирал корпус парафраз, обучал модель и придумывал метрики для её оценки - читайте на Хабре.
Привет! Я сделал обзор существующих корпусов и моделей для генерации парафраз на русском языке.
А ещё сгенерировал свой корпус на миллион парафраз (он весьма неплох) и обучил свой парафразер на основе T5 (SOTA пока не получилась).
https://habr.com/ru/post/564916
Сегодня в 17:00 по Мск буду рассказывать на созвоне DeepPavlov про свой маленький русский BERT.
Вот ссылка на запись мероприятия.
Есть не до конца решённая задача: "сгенерировать предложение, похожее на заданное". Её можно решить с помощью авторегрессионной языковой модели, попросив её продолжить текст. Но можно сделать то же самое и с помощью MLM. Для этого надо просто несколько раз пропустить предложение через BERT, заменяя некоторые токены на [mask] и генерируя новое предложение из условного распределения, выданного моделью. Получается иногда бред, иногда удачно, примерно 50/50.

def replace_with_mlm(text, model, tokenizer, n_iter=5, temperature=0.5, max_span=2, change_size=True, mask=True, verbose=False):
enc = tokenizer(text)
n = len(enc.input_ids)

for i in range(n_iter):
if mask:
left = random.randint(1, n - 2)
right = random.randint(left + 1, min(left + max_span, n-1))
if change_size:
new_size = random.randint(1, max_span)
else:
new_size = right - left
enc.input_ids[left:right] = [tokenizer.mask_token_id] * new_size
with torch.no_grad():
out = model(torch.tensor(enc.input_ids).to(model.device).unsqueeze(0))
proba = torch.softmax(out.logits / temperature, -1)[0]
enc.input_ids[1:-1] = torch.multinomial(proba, 1)[1:-1, 0]
out_text = tokenizer.decode(enc.input_ids, skip_special_tokens=True)
if verbose:
print(out_text)
return out_text

Подставим сюда bert_ru_conversational_cased от DeepPavlov и какой-то текст, и посмотрим, как он мутирует:
replace_with_mlm('Путин утвердил новую Стратегию национальной безопасности России', model, tokenizer, verbose=True)
Национа Путин утвердил новую стратегию национальнои безопасности.
Владимирльный утвердил новую стратегию национально ориентированных.
Владимир Жириновский показал новую стратегию национально ориентированных.
Владимир Жириновский показал новую стратегию национального политики.
Владимир Жириновский показал нам российского национального политика.
По-моему, забавно.

Впрочем, иногда BERT скатывается в какой-то бред, типа такого
путин утвердил новую стратегию национальнои национальноной россии
путин утвердил новую стратегию национально - воскресной россии
путин утвердил новую партию для национально - воскресной россии
путин утвердил новую партию воскрес коммунистов - воскресной россии
путин утвердил новую партию воскресной - воскресной россии
путин утвердил новую партию воскресной - воскресной россии
путин утвердил новую партию воскресной воскресной россии
путин утвердил новую партию воскресной и воскресной россии
путин утвердил символы воскресной и воскресной россии
путин утвердил два - воскресной и воскресной россии
путин утвердил кресты - воскресной и воскресной россии
путин - - воскресной и воскресной россии
путин - - воскресной воскресной россии
путин - - воскресник воскресной россии
путин путин воскресник воскресной россии
путин путин воскресник воскрес!
путин путин путин воскрес!
путин путин путин!
путин путин путин путин!
путин путин путин путин!!
Видимо, это происходит потому, что хоть BERT был обучен заменять бредовые части предложения на нормальные, в обучении бредовых токенов было 15%, и если текст состоит из бреда наполовину или полностью, модель теряется.
Всем привет!
Те, кто уже общались со мной в этом канале или вне его, могут знать, что я, помимо работы в Сколтехе, занимаюсь образовательными, разработческими и исследовательскими пет-прожектами и халтурками. В последнее время количество этих проектов существенно превышает временны́е ресурсы одного человека, так что я ищу себе подмастерье.

Сделка простая: с меня – доступ к интересным и оплачиваемым проектам и менторство, с вас – наличие свободного времени и готовность вовремя выполнять поставленные задачи.
От вас я ожидаю навыков Python и базового NLP и интереса к NLP, чатботам и голосовым приложениям. По оплате базово предлагаю долю в выполненных проектах, и, если надо, могу закрепить наши отношения договором ГПХ.

Со всеми вопросами пишите в ЛС @cointegrated)
Раньше модели для понимания или генерации текстов составляли свой словарь из отдельно взятых слов. Это было похоже на то, как язык обычно изучают лингвисты и простые смертные, но приводило, с одной стороны, к раздуванию словарей, с другой - с неустранимой проблемой out-of-vocabulary слов.

В 2010-х стали популярными словари, собранные из отдельных слов, кусочков слов и букв, такие, как BPE (часто используется в GPT и моделях для перевода) и sentencepiece (используется, например, в BERT и T5). Это решило проблему и с раздуванием словаря, и с OOV-токенами. Но модели, использующие подобные словари, всё ещё сильно зависят от того, как такой словарь был собран, и при переходе на новый домен или другой язык большая часть собранного словаря оказывается бесполезна и лежит в модели мёртвым грузом.

Исследователи из Google решили пойти дальше и создали модель byT5: мультиязычный T5 (энкодер-декодер, обученный на MLM задаче), использующий в качестве словаря тупо байты. То есть всего 256 разных символов. Маленькость словаря компенсировали увеличенным энкодером. В результате получилась модель, которая применяется и обучается медленнее, чем mT5 (т.к. последовательности токенов стали длиннее: для русского в 6 раз, для английского - в 4), зато обходит её по качеству на генеративных задачах, мультиязычных задачах, и задачах с кучей шума.

Кажется, основная фишка таких моделей в том, что теперь дообучать модели на новых доменах и языках стало проще: не надо пересобирать словарь, надо просто сразу взять и запустить дообучение. В обозримом будущем хочу попробовать и для русского)
Напомню про недавнюю работа моего коллеги Коли про фильтрацию неуместных высказываний на русском языке.
Читайте описание простыми словами: https://www.skoltech.ru/2021/07/nejroseti-otfiltruyut-neumestnye-vyskazyvaniya-chat-botov
Скачивайте модель: https://huggingface.co/Skoltech/russian-inappropriate-messages
Привет всем матёрым NLPшникам!
Наша группа обработки естественного языка в Сколтехе ищет инженера-исследователя. Получается, моего прямого коллегу ☺️
Полное описание вакансии с требованиями и условиями есть на сайте. Если вкратце, нужно будет разрабатывать новые алгоритмы NLP, тщательно оценивать их, и писать про это научные статьи.
Темы могут быть самые разные (примеры статей есть опять-таки на сайте), например, в последнее время мы много занимаемся переносом стиля на текстах и оценкой его качества, активным обучением (применительно к классификации текстов и NER), и вопросно-ответными системами.
Придётся и писать код, и размечать данные, и описывать всё это связными текстами. Будет много свободы и довольно приличная зарплата. В общем, приходите к нам)
Вопросы можно задавать мне в личку.
У меня была серия постов про SuperGLUE (0 1 2 3 4 5 6 7 8), и её стоит завершить последним постом - про диагностические датасеты.
Их два. Первый содержит примеры задачи NLI (определения логической связи между парами предложений), размеченные по языковым явлениям, с которыми модель должна хорошо работать для решения задачи, в частности:
- Lexical Semantics: понимания смысла слов, как самих по себе, так и в контексте всего предложения
- Knowledge: модель должна знать и конкретные факты о мире, и то, что называется "здравым смыслом".
- Logic: умение применять к текстам логические операции (отрицание, "и", "или", "либо" и т.п.), понимание квантификаторов (все/некоторые) и т.п.
- Predicate-Argument Structure: понимание, как смысл фразы складывается из отдельных её частей, например, разрешение кореференции.
Никаких обучающих данных эта задача не содержит, только тестовые: предполагается, что модель будет учиться решать обычное NLI. Любопытно, что качество SOTA моделей на этой задаче довольно невысокое: Matthews correlation 69% на сегодняшний день против 76% у людей. Видимо, обучающие датасеты для NLI в среднем сильно проще, чем этот диагностический.

Второй диагностический датасет называется Winogender. Он содержит фразы типа "The technician told the customer that [he/she] could pay with cash.", и модель должна определить, к кому из двух лиц относится местоимение. Модель оценивается по двум характеристикам: точности угадывания, и, дополнительно, по точности в разрезе гендера. Все предложения гендерно-нейтральные, а потому модель, лишённая gender bias, должна выдавать одинаковые (и одинаково хорошие) ответы и для he, и для she. И в принципе, у большинства топовых моделей скор здесь достаточно высокий, за 90%. Но доля ошибок всё-таки на порядок больше, чем у людей.

В общем, с одной стороны, кажется, что SuperGLUE уже "решён": у трёх моделей уже средние скоры на задачах с обучающей выборкой выше, чем у людей. Но как только нужно обобщиться на диагностические задачи, их качество пошатывается. Так что от General NLU мы до сих пор далековато.
Возможно, вы знаете, что на Huggingface hub появилась возможность ставить лайки ❤️
Если вам нравятся мои модели, вы можете тоже полайкать, например, вот эти T5:
- rut5-base-multitask: первая и пока единственная русскоязычная модель T5, предобученная сразу на десяток разных полезных seq2seq задач
- rut5-base-paraphraser: русскоязычный парафразер, который довольно неплохо сохраняет смысл предложений, но может заметно изменить их форму
- rut5-small-chitchat: маленькая и не очень умная, но быстрая русскоязычная болталка
- rut5-small-normalizer: модель для восстановления связного предложения из мешка слов

А ещё можно полайкать берты:
- rubert-tiny: маленький и быстрый русско- и англоязычный BERT с неплохими представлениями предложений на CLS токене
- rubert-tiny-toxicity: русский классификатор токсичности и неполиткорректности
- rubert-tiny-sentiment-balanced: русский классификатор тональности
- LaBSE-en-ru: модель LaBSE, где я выкинул эмбеддинги всех языков, кроме ru и en; модель уменьшилась х4 без потери качества.
Посмотрел запись недавнего митапа Тинькофф по NLP.
В программе:
- Популярные рецепты создания болталки
- Задача классификации интентов, на которой tf-idf+логрег работает лучше, чем BERT
- Как Реплика пересаживалась с GPT-3 на собственную языковую модель.
В общем, рекомендую.
https://youtu.be/SwfzebRc1ZU
Статья Sentence-T5: Scalable Sentence Encoders from Pre-trained Text-to-Text Models
Оказывается, если просто усреднить эмбеддинги энкодера T5, на очень многих задачах NLU (в частности, STS) это оказывается лучше, чем эмбеддинги из BERT. А если ещё пофайнтюнить такую штуку на корпусе Stanford NLI, то качество получается сильно лучше, чем у ряда альтернативных sentence encoders. Как файнтюним: оптимизируем log loss софтмакса (температура 0.01), где позитивный пример - предложение с меткой entailment, а негативный пример - предложение с меткой contradiction и все другие предложения в батче. Ну и, естественно, чем больше размер модели T5, тем лучше оно работает.
Забавно, что на задачах STS лучше выходит, если не усреднять эмбеддинги энкодера, а взять первый эмбеддинг декодера - видимо, помогает дополнительный проход по всем атеншнам. И да, примечательно, что авторы все эксперименты проводили на бенчмарке SentEval, вообще не апеллируя к другим.

И да, надо бы для русского языка тоже попробовать сравнить эмбеддинги русских T5 и BERTов.