В современном мире LLM, также известных как "чудо техники", сложилась забавная ситуация: формально LLAMA, Mistral и другие open source проекты не поддерживают ничего, кроме английского языка, но это не совсем так. Они поддерживают другие языки, даже с неплохим качеством, но есть нюанс — плотность токенизации довольно низкая-> в следствии чего модели не будут эффективно работать на языках заметно отличных от английского.
![](https://habrastorage.org/getpro/habr/upload_files/7d8/e45/22c/7d8e4522c5c7566f220d5f19a17a8410.png)
LLama1 датамикс, у Mistral он неизвестен, но скорее всего что то похожее и в разы бОльшое.
у нас есть русский в CommonCrawl(входит в топ10 языков интернета) + Wiki + немного в Github. Тоже самое касается китайского, корейского и прочих.
А по итогу метрики на бенчмарках очень хорошие, во многом за счет того что бОльшая часть бенчей подразумевает Accuracy -те выбор наиболее вероятного ответа, те модель вполне точно выбирает верный ответ. Пример для mmlu и ламм ниже.
![](https://habrastorage.org/getpro/habr/upload_files/50e/fa7/574/50efa757461548257fcc95243733143c.png)
Saiga
Огромный респект Илье Гусеву за создании сайги – единственной русской инструктивной модели статья.
И тут начинается самое интересное - Saiga была доучена на русские инструкции и до сих пор является базовой моделью(для быстрого старта - так точно) для большинства задач на русском языке.
Но с ней есть одна проблема - токенизация!
Если коротко: токенайзер это штука которая бьет str в циферки [0, max_tokenizer], учиться как дерево остатков те учиться пихать макс символов в токен, а BBpe токенайзеры(все начиная с gpt2 примерно~ ) умеют еще и байты переваривать. Читать больше (вы можете сунуть картинку в byte like виде в модель)
Для нас важно что у русских(сбер, яндекс) моделей на каждые три символа приходится 1 токен, а у Llama/Mistral/Gpt4(в меньшей степени) на ~ КАЖДЫЙ символ приходится токен.
Выглядит токенизация русского примерно так:
![](https://habrastorage.org/getpro/habr/upload_files/53c/d65/2e4/53cd652e47ae6ef55e7a38af34360d56.png)
По русски: у вас контекст влезет в три раза меньше от того что написано в описании модели. Те вместо 4096*3 символов влезет примерно 5000 символов. Если вы строите RAG based систему то понятно какие проблемы это влечет.
Всегда найдется азиат который сделает это быстрее тебя (с), длинный обзор предидущих работ и бессовестный PR крутых ребят из МГУ.
China llama
![](https://habrastorage.org/getpro/habr/upload_files/ba0/0c0/ddd/ba00c0ddd673762a3473e37a106bcf96.png)
Идея следующая: авторы расширяют токенайзер
![](https://habrastorage.org/getpro/habr/upload_files/f4c/6ed/057/f4c6ed0574023c8435f3cd67348cefca.png)
и учат LORA в начале на general domain датасете(википедия, новости и прочее) а затем доучивают на chinese alpaca(синта из GPT4)
![](https://habrastorage.org/getpro/habr/upload_files/d35/52d/988/d3552d98803cb74eaf5e4d696bec2d98.png)
По метрикам после такого обучения правда есть проблемы, они просаживаются причем ощутимо.
![](https://habrastorage.org/getpro/habr/upload_files/313/0a6/e73/3130a6e73187ff87b0a632936d805455.png)
Impact of Tokenization on LLaMa Russian Adaptation
Идея такая:
Учим русский токенайзер с нуля.
Заново инициализируем LmHead и embeddings нужного размера инитя их старыми.
Учим новые слои на 9B токенов(43GB) и получаем модель которая конкурента с оригинальной лламой.
![](https://habrastorage.org/getpro/habr/upload_files/c98/8ec/4f1/c988ec4f159ce2086aa3061f36e2b8a7.png)
Вообще существуют европийские адаптации, ранние адаптации gpt2 на русский(не нашел ссылки) и куча всякого от корейских-китайских лаб, но если рассматривать все - статьи не хватит. ну и большая часть этих подходов похожи и суть сводиться к: расширим токенайзер, прольем много токенов, а дальше будет что будет.
Подводка закончилась, началось описание того что мы сделали.
Расширение токенайзера
Мы обучили SentencePiece токенайзер 50к на RULM, оставили только русские токены
![](https://habrastorage.org/getpro/habr/upload_files/e4a/6d4/806/e4a6d4806fb54163e1558fbd141a6177.png)
Из данного графика можно сделать вывод, что эффективность процесса токенизации улучшается с увеличением размера словаря. В качестве примера можно рассмотреть ruGPT, где эффективность токенизации достигает значения около 0.27 по оси Y, что соответствует в среднем 2-3 токенам на слово. Расширение словаря токенизатора приводит к улучшению этого показателя примерно на 30% (1.3-кратное увеличение), что делает процесс токенизации более эффективным.
Для T5 графа в целом не страшна неэффективность токенизации(я не понял сейчас почему так плохо и вовремя не заметил, а когда к статье строил картинку было поздно потому что статья задерживалась на 4 недели. Возможно потом сделаю), за счет relative position embeddings можно пихать столько сколько в карту влезет токенов.
Как учить LLM если ты gpu poor?
Здесь и далее я ввожу термин gpu poor - он означает обучение в рамках одной ноды, не более месяца. При большом желании можно воспроизвести для вашего языка при вложении цены хорошего компьютера(<10k usd на все)
У нас было 4v100 32gb, те каждая карта меньше чем нужно - 7B кушает 54gb на обучение модели целиком. Спойлер: по итогу я снимал h100.
Проблемы:
v100 не умеют bf16
Что делать:
Это sxm карты,
выставляем сервер на улицу на табуретку, чтобы не перегреть, ставим питание 600watt и разгоняемся, полная сетевая связанность через NV => раскидываем модель по кусочкам на карту и учим с FSDP tensor paralelFlash attention отсюда для h100
Включаем grad checkpointing, благо в hf все впилено
Используем Adamw чтобы считать по всем слоям градиент стабильно и не подбирать параметры за 10 ранов несмотря на то что он кушает больше памяти.
В среде NLPшников ходит легенда основанная на этом твите о том что если размер токенайзера делиться на 32 или 64, то блочное умножение работает быстрее и в целом
![](https://habrastorage.org/getpro/habr/upload_files/546/133/982/546133982a6079017a45e68c7ad0523d.png)
Возможно с torch compile работало бы быстрее, но времени и желания я не нашел.
Если у вас есть - пишите кастомные Fused Kernels в стиле и будет вам счастье.
Возможно оно работает с определенного числа карт, возможно стоит трекать MFU чего я не делал, но на сингл ноде и в рамках игрушечных трейнов в целом можно очень сильно забивать на FUSED kernels, эффективные дата лоадеры и прочие радости. Чекните через torch.profiler карта не сильно стоит и ставьте учиться, либо пользуйтесь готовыми репозиториями.
Данные
Я учился на следующем миксе для 7b модели и 3b:
Habr(топ 100к лайкнутых) отсюда
Переведенный FLAN(для T5 модели, для 7b не хватило карт) отсюда
Инструктивная версия 7B модели полностью основана на Saiga Mistral
Flan t5 - VikhrT5-3b
Для претрена современных T5 like моделей используют не MLM( Какой <MASK> здесь токен), а Span corruption
![](https://habrastorage.org/getpro/habr/upload_files/64a/72b/5e1/64a72b5e107faace90e22b4e72fd0af4.png)
Идея собственно в том что уча модель на разные задачи мы можем потом решать всякие Fill in the middle, или заставлять T5 быть классик LMtask моделью(S denoising).
Я использовал кодовую базу отсюда https://github.com/google-research/t5x, а затем JAX модель конвертится в torch без проблем.
dataset | VikhrT5-3b | FRED-T5-XL(1.7b) | FLAN-t5-xl(3b) |
ru_mmlu | 0.32 | 0.252 | 0.28(лол2) |
xwinograd_ru | 0.71(lol) | 0.57 | 0.52 |
xnli_ru | 0.4280 | 0.34 | 0.33 |
Mistral 7b и что там надуло? в смысле обгоняет русские модели…
В чем сложность? Модели имеют свойство тупеть после обучения в лоб, те метрики у модели которая видела русские токены метрики будут ХУЖЕ чем у модели которая русских токенов НЕ видела.
Я обнаружил это в https://huggingface.co/AlexWortega/rugpt-neo-1.3b
Хотя тут и процедура была другая - я менял токенайзер целиком и учил целиком модель с новыми эмбедигами, но сути не меняло. Модель падала и падала трагично.
Собственно идея как решить проблму пришла идея из RL: давайте смешивать loss модели которую учим с оригинальной, тем самым будем не давать модели уходить очень далеко.
(В оригинале используется KL штраф), я же использую SLERP для интерполяции лоссов
![](https://habrastorage.org/getpro/habr/upload_files/7ef/8a8/232/7ef8a8232b64a5ddf7fe3f8fd3b39c4f.png)
Mistral metric:
dataset | Vikhr-7b-0.1 (5-shot) | Mistral-7B-v0.1 (5-shot) | GigaChat(7b) (5shot) |
mmlu_ru | 0.60 | 0.66 | 0.581 |
xwinograd_ru | 0.7243 | 0.68 | 0.7127 |
xnli_ru | 0.3780 | 0.3991 |
Качать тут
Авторы:
Александр
Карина - https://t.me/nadlskom
Денис @den4ikresearch за помощь с подбором гиперпараметров т5
Михаил Тихомиров за early adoption чекпоинты и найденный неверный чекпоинт
Илья Гусев, в этой статье не участвовал, но сделал много всего ранее для русскоязычного опенсурса, без него не было бы этой работы.
Почитать после статьи если какие то термины были не понятные: