От чего зависит успех обучения большой языковой модели и какие данные для этого нужны
Вопрос обучения LLM с нуля (pre-training) не освещен в достаточной мере на русском языке. За один последний год в открытом доступе появились блестящие результаты исследований в этой области и обучение своей собственной LLM - не SFT-файнтюнинг уже предобученных весов - уже почти доступная для средней технической компании и, безусловно, заманчивая идея. Для старта обучения было бы достаточно, например, 64 x H200, то есть всего 8 нод с 8-карточной конфигурацией. Тем большим упущением выглядит отсутствие статьи с практическими шагами осуществления этой идеи.
Я решил по мере возможности заполнить этот пробел и не только собрал актуальные датасеты для pre-training в этой статье, но и сделал ее чуть более основательным пособием для обучения LLM на с нуля на большом корпусе данных, постаравшись внести ясность, в чем на самом деле состоит смысл данных при обучении.
Надеюсь, к концу статьи само обучение будет выглядеть менее магическим и роль данных в этом процессе станет более понятной.
Начнем с того, что более-менее известно каждому - все современные LLM обучены на гигантских объемах данных, триллионы токенов текста. Часто можно услышать мнение, что OpenAI обучают свои модели на данных "всего интернета", хотя это нельзя воспринимать буквально. Корпусы для обучения моделей статистически приближаются к описанию множества данных всего интернета, но не являются этим множеством в полном объеме. В этом утверждении кроется корень главной ошибки, которую многие делают, представляя себе обучение нейросети.
Я часто слышал: "хочу обучить модель, чтобы она запомнила вот этот список книг от начала до конца", "как обучить нейросеть полной документации по языку программирования X?".
Заблуждение №1
"Нейросеть запоминает текст из моего датасета" - целые предложения, страницы и так далее. Давайте сразу его разрушим, чтобы больше к этой ошибке не возвращаться.
Цель обучения языковой модели - не текст, а знания, представленные текстом.
Для сравнения, база данных является механизмом, и очень хорошим, для хранения текста в данной конкретной форме. При этом база данных ничего не знает о том, что в тексте говорится. Нейросеть, не имеющая ничего общего с базами данных, является "механизмом" изучения именно того, что означает текст, но практически бесполезна для хранения исходного текста в его полном объеме. Т.е. это машина для понимания данных, хранить которые следует в другом месте.
Объясняется это тем, что в процессе обучения LLM моделирует статистику нашего набора текстовых данных, и больше ничего. Это делали все языковые модели, начиная с простейшей биграммной, которая могла посчитать частоту всех биграмм (пар) токенов в наборе и на основании того, что биграмма "по" (предположим для простоты, что словарь модели - буквенный) встречается чаще, чем "пц", предсказать следующий токен "о" с большей вероятностью, чем "ц", если предыдущий токен - "п". Самая простая статистика. А трансформеры, несмотря на их сложность, концептуально эксплуатируют ту же N-gram идею, моделируя P(next_token | context).
Но есть важное различие.
Заблуждение №2
"Нейросеть запоминает таблицу вероятностей для каждого токена из словаря при всех контекстах из набора". N-граммные модели делали именно это до тех пор, пока N не становилось слишком большим (очень быстро, потому что таблица вероятностей при увеличении N растет экспоненциально).
Трансформер не может запомнить таблицу вероятностей, так как в его случае для вариантов сочетаний next_token | context не существует известного нам числа, через которое можно было бы выразить множество этих вариантов. Т.е. настоящего (истинного) вероятностного распределения данных нейросеть тоже не знает. То, чему она действительно обучается - это функция, приближенно моделирующая это распределение; аппроксимация. Точным это приближение, как следует из сказанного, быть не может.
Все, что нам остается, это сделать его удовлетворительным для нашей задачи - например, генерации текста на русском языке; на интересующем нас участке распределения - например, в области (домене) советов по здоровому питанию. И если нейросеть, обученная на наборе адекватных документов по здоровому питанию, не рекомендует с утра принимать натощак ложку стрихнина, то о некоторой степени аппроксимации мы можем говорить - остается множество итераций обучения и валидаций на соответствие тестовым данным.
Но мы слишком быстро коснулись понятий домена знаний и следования инструкциям. Сначала модели научиться бы генерировать что-то кроме "ааааа333333!%;" - то есть изучить синтаксические признаки, семантику языковых конструкций, их структуру и логику. И это тоже слишком большой шаг вперед от N-gram моделей, где признаков всего ничего и все они явные (explicit), основанные на чисто внешних особенностях текста:
предыдущие k токенов
их частоты
вероятности переходов к следующему токену от k предыдущих.
Однако уже по этому короткому списку вы можете заметить, что мы не программируем модель учить те или иные признаки, а другие - не учить. Модель приходит к ним сама от статистики, потому что 1. в данных эти признаки проявляются через распределение и 2. архитектура модели позволяет учить именно эти признаки.
Если модель биграммная, в ее функции аппроксимации P(xn∣xn−1) существует признак предыдущего токена, только одного, и признак частоты тех или иных биграмм. Если она 5-граммная, то архитектура "открывает" признак уже четырех предыдущих токенов, и это, в свою очередь, может выявить новые вероятностные признаки в данных, которые невозможно увидеть на уровне биграмм. Математически можно сказать, что признаки определяются функцией от трех переменных - архитектуры, данных и цели обучения, выраженной через функцию потерь, которая определяет, какие признаки существенны для правильной аппроксимации, а какие нет.
А нейросети пошли намного дальше! От явных признаков, которые в N-граммной модели представлены V^k-размерной матрицей, где V - размер словаря, они перешли к латентным признакам, которые являются абстракцией над явными и поэтому могут быть приведены к тензору меньшей размерности, чем V^k - ведь такая размерность, как уже было показано, при чуть большем контексте k уже слишком велика для наших вычислительных возможностей. Я имею в виду V x d-размерный embedding-вектор, который способен вместить d латентных признаков. При современных внушительных контекстах kVd - это все-таки очень много, но уже реально для обучения.
В общем, нейросеть - это такое математическое выражение, цель которого - выразить как можно больше полезных признаков из данных. Теперь, когда у нас есть некоторое представление о том, что вообще мы будем делать с данными, мы можем перейти к вопросу, что эти данные должны из себя представлять.
Прежде всего, данные должны быть статистически репрезентативными. Как следует из приведенного выше интуитивного объяснения основ representation learning - обучения признакам, чтобы модель научилась признакам, они должны быть выражены статистически в обучающем наборе. Но что это значит? Давайте посмотрим на эволюцию открытых датасетов.
CommonCrawl
Мы уже поняли, что устойчивого статистического моделирования нужных нам признаков ВСЕ данные модели видеть не нужно, как не нужно прочитать всю существующую в мире английскую литературу, чтобы научиться читать по-английски. Однако, если вы все-таки хотите "весь интернет" - почти - то вот он. 10 петабайт нефильтрованных веб-данных, собранных начиная с 2008 года. Использовать эти данные для обучения полностью практически невозможно, поэтому разработчики обычно выбирают из CommonCrawl подходящие для них сабсеты.
В плане покрытия CommonCrawl - однозначный победитель в нашем списке, а высокое покрытие - необходимое условие при обучении базовой foundation модели. Опять-таки, нельзя научить модель ответам на любой вопрос, чем шире область ее применения - тем больше неизбежных пробелов в изученном распределении данных, но чем оно разнообразнее и чем больше включает понятий - точек в векторном пространстве - тем проще модели будет правильно заполнить недостающие точки между ними, то есть - тем выше ее способность интерполировать.
Это очень важно для того, чтобы модель могла правильно выполнять совершенно новые для нее задачи, и не в последнюю очередь - для ее пригодности к ризонингу. Иначе как масштабированием - самой модели и датасета - пока эту проблему не решить.
Самое, пожалуй, известное и громкое проявление этого эффекта от обучения на данных масштаба CommonCrawl описано в статье о GPT-3 - "Language Models are Few-Shot Learners". Тогда разработчики просто опытным путем обнаружили, что способность модели интерполировать известные ей знания на новые примеры эволюционировала настолько, что она стала успешно выполнять инструкции по нескольким примерам из промпта - few-shot, и это стало предпосылкой для ChatGPT и всех генеративных языковых моделей, предназначенных для именно таких задач.
Однако мы помним и крупный недостаток GPT-3, ее подверженность галлюцинациям. Это связано с шумностью данных CommonCrawl, так как этот набор содержит огромное количество (до 50% в нефильтрованном виде) веб-страниц низкого качества. SEO-тексты, где полно "воды", спам и бесконечные дубликаты. Это все плохо сказывается на reasoning-способностях модели и способствует оверфиттингу на тех паттернах текста, у которых в датасете слишком много дубликатов. Поэтому данные из CommonCrawl всегда тщательно фильтруют, и так появился следующий кандидат в этом списке.
FineWeb
Есть замечательная опция - воспользоваться уже готовым, фильтрованным CommonCrawl, то есть FineWeb. Это 15 триллионов токенов достаточно чистых данных. Эффективность обучения на FineWeb гораздо выше, поэтому в большинстве случаев его стоит выбирать как дефолтный базовый датасет для обучения - кому хочется выбрасывать сотни GPU-часов на ветер, пока модель молотит терабайты SEO-мусора и вытаскивает из них редкие полезные признаки?
Т.е. существенно уменьшив объем данных и сэкономив на обучении, мы получим модель, более устойчивую к галлюцинациям и с более сильными способностями к ризонингу. Это замечательно. И все-таки фильтрация - зло, хотя и неизбежное. Редкие признаки, полнота знаний и непредвзятость модели страдают от этого.
Поэтому надо, что называется, оптимизировать распределение признаков - постараться добавить в набор столько разнообразия, сколько нужно. Например, сейчас пользуются спросом модели с хорошими навыками кодинга, математики и в целом научных знаний.
Поэтому актуальная идея - дополнить ваш дата-пайплайн наборами специально для кодинга, математики и тех доменов, в которых ваша модель должна быть сильна. А как понять, что вот такое количество и соотношение наборов и разных доменов хорошее, а такое - не очень? Здесь начинается время трудоемких экспериментов, когда вы обучаете несколько небольших моделей на нескольких вариантах данных, потом прогоняете их все по самым разным бенчмаркам. И так выявляется тот срез данных, который вам действительно нужен. Но все-таки было бы жаль, если бы мы на остановились на этом подходе - вручную, на глаз пытаться создать действительно хорошее распределение признаков. Есть пример более умного решения проблемы - конечно, с помощью ML - показавший очень хорошие результаты.
ClimbMix
Из сказанного выше уже понятно, что качество и состав данных часто важнее их объёма. Один из подходов, развивающих эту идею — фреймворк кластеризации данных CLIMB от NVIDIA. С его помощью создан набор ClimbMix, основанный на методе оптимизации смеси обучающих данных (data mixture optimization), направленный на максимизацию полезных статистических признаков в датасете.
Основная идея ClimbMix - не просто собрать много данных, а подобрать такое соотношение доменов, которое максимизирует обучение полезных представлений. Обычный pretraining датасет, включая два уже перечисленных, представляет собой смесь различных источников: web-тексты, код, научные статьи, книги, диалоги, форумы. Проблема в том, что разные источники обучают разные способности модели.
Можете представить в качестве интуитивного примера такую таблицу:
Тип данных Какие признаки формируются
Веб общая языковая статистика
Код строгая логика и синтаксис
Math reasoning паттерны
Книги длинный контекст
QA instruction following
Если распределение выбрано плохо, некоторые признаки переобучаются, другие почти не представлены - возникает неэффективное использование токенов. Это можно сформулировать так: неоптимальная смесь данных приводит к неоптимальному распределению признаков в representation space модели. Естественно, хорошо бы это representation space как-то проанализировать, поэтому первым делом метод преобразует тексты в embeddings с помощью небольшой модели. После этого данные кластеризуются по тематике, стилю, сложности, типу reasoning. То, что мы имеем в итоге - это набор семантических доменов, которые описывают карту пространства признаков для обучения. Далее обучается небольшая прокси-модель на разных смесях этих кластеров.
Например, микс A - 40% веб, 20% код, 20% книги, 20% академические тексты, микс B - процентное соотношение меняется, а книги, скажем, заменяем на QA. Затем для всех оцениваем validation loss, downstream performance, training efficiency. Читайте подробнее в статье - Nemotron-CLIMB: CLustering-based Iterative Data Mixture Bootstrapping for Language Model Pre-training. Таким образом находим, какой микс дает наилучший обучающий сигнал.
Преимущество подхода ClimbMix уже показало себя на практическом обучении моделей, так как оно следует из верного понимания разработчиками фундаментального принципа, который проходит через эту статью красной нитью - LLM обучаются не на данных, а на статистических вариациях внутри данных. Именно их в ClimbMix попытались автоматически сбалансировать и построить по-настроящему эффективный датасет - осталось обучить на нем модель и проверить, насколько у них получилось.
Надеюсь, эта статья помогает систематизировать отрывочные сведения о механике обучения нейросетей на текстовых данных и о скрытых особенностях этого процесса. Есть ощущение, что многое осталось недосказанным, и на случай, если у вас возникли вопросы и пожелания, я буду рад вашей обратной связи в моем телеграм-сообществе.













