За последние полгода я несколько раз писал о тонкой настройке (fine tuning). Fine tuning — очень соблазнительная технология, обещающая закрыть проблемы в функциях GPT-4, будучи при этом быстрее и дешевле. Однако как бы часто не обсуждали fine tuning, я нашёл на удивление мало контента о том, который бы помог мне понять, насколько эффективен fine tuning и насколько сложно встраивать новые возможности в языковые модели.

Поэтому я решил взять всё в свои руки, сдуть пыль с моих навыков ML и разобраться самостоятельно.

Выбор задачи

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

Выбор карты в драфте Magic
Выбор карты в драфте Magic

Объясню для тех, кто не в теме: Magic: The Gathering — это стратегическая коллекционная карточная игра, в которой игроки при помощи колод карт, обозначающих существ или заклинания, сражаются со своими противниками. Один из способов игры в Magic (и мой самый любимый) — это драфт, при котором игроки собирают свои колоды, по очереди выбирая отдельные карты из пула случайных карт.

Драфт прекрасно соответствует моим критериям:

  • Рассуждения: выбор карты из случайно собранного набора — это довольно серьёзная проверка навыков, требующая целостного понимания контекста (например, уже выбранных ранее карт и карт, имеющихся в текущем наборе)

  • Вне распределения: новые карты Magic выпускают примерно 4-6 раз в год, и самые новые карты отсутствуют в корпусе обучения моделей LLM.

Ещё один важный аспект: данные. Существует потрясающий сервис 17lands, хранящий огромный объём исторических данных — игроки используют сервис трекинга 17lands для отслеживания данных драфтов из цифрового клиента Magic. При помощи этих данных можно извлечь «эталонные данные», изучив результаты драфта лучших игроков в сервисе (отсортированных по коэффициенту побед). Данные довольно нечёткие (многие замечательные игроки в Magic постоянно спорят о правильном выборе), но это достаточно хороший сигнал, чтобы протестировать способность LLM обучаться новым задачам.

Если вам любопытны подробности о данных, то вот пример того, как выглядят данные 17lands после преобразования в промт для LLM.

Результаты + вывод

Давайте сразу перейдём к результатам, а затем углубимся в выводы и размышления:

Качество моделей с тонкой настройкой. Голубые графики: стандартные модели. Зелёные: модели с тонкой настройкой с OpenAI. Сиреневые: опенсорсные модели с тонкой настройкой. Фиолетовый: автор статьи
Качество моделей с тонкой настройкой. Голубые графики: стандартные модели. Зелёные: модели с тонкой настройкой с OpenAI. Сиреневые: опенсорсные модели с тонкой настройкой. Фиолетовый: автор статьи

Мысли:

  • Модель параметров 7B с тонкой настройкой уверенно побеждает GPT-4 и приближается в точности выполнения этой задачи к уровню человека (или, по крайней мере, к уровню автора статьи).

  • Похоже, GPT-3.5 с тонкой настройкой показала бы себя ещё лучше, однако тонкая настройка GPT-3.5 очень дорога! (примерно в сто раз дороже, чем тонкая настройка Mistral на bare metal + дополнительная стоимость каждого инференса). Прогон тонкой настройки GPT-3.5, эквивалентный моему самому крупному прогону Mistral-7b, стоил бы примерно $500; дорогой получился бы эксперимент.

  • Тонкая настройка по-прежнему остаётся чем-то похожей на искусство — я надеялся, что это будет ближе к разработке, чем к науке, но приходится выполнять множество экспериментов. В частности, промт-инжиниринг с долгим циклом обратной связи тонкой настройки — это мучение. Подробнее об этом ниже.

  • Даже маленькие опенсорные модели огромны по стандартам пяти лет назад. Одно дело — считать «7 миллиардов параметров», и совсем другое —засунуть 7 миллиардов параметров и всю связанную с ними математику в GPU.

  • Я провёл интересный эксперимент: выполнил тонкую настройку модели на одном множестве карт, а затем оценил её точность на множестве карт, которое она не видела ранееПохоже, модель обобщила концепцию драфта, а не просто запомнила, какие карты были хорошими.

Журнал полевых наблюдений: методики и уроки

Данные

Создание текстового датасета: датасет драфтов 17lands — это огромный файл CSV, в котором описаны последовательности выбора драфтов пользователей приблизительно в таком формате:

  • Карты, имеющиеся в текущем наборе

  • Карты, которые драфтер выбрал ранее

  • Карта, которую драфтер выбрал из этого набора

Чтобы сделать эти данные подходящими для тонкой настройки языковой модели, их необходимо преобразовать в текст; в конечном итоге я воспользовался форматом assistant, популяризованным OpenAI:

{
  "messages": [
    {
      "role": "system",
      "content": "You are DraftGPT, a Magic the Gathering Hall of Famer and helpful AI assistant that helps players choose what card to pick during a draft. You are a master of the current draft set, and know every card well.\n\nWhen asked for a draft pick, respond with the card's name first."
    },
    {
      "role": "user",
      "content": "In our Magic the Gathering draft, we're on pack 2 pick 13. These are the contents of our pool so far:\n-------------------------\nEvolving Wilds --  (common)\nRat Out -- {B} (common)\nNot Dead After All -- {B} (common)\nHopeless Nightmare -- {B} (common)\nBarrow Naughty -- {1}{B} (common)\nUnassuming Sage -- {1}{W} (common)\nThe Witch's Vanity -- {1}{B} (uncommon)\nSpell Stutter -- {1}{U} (common)\nMintstrosity -- {1}{B} (common)\nWater Wings -- {1}{U} (common)\nBarrow Naughty -- {1}{B} (common)\nGadwick's First Duel -- {1}{U} (uncommon)\nBitter Chill -- {1}{U} (uncommon)\nThe Princess Takes Flight -- {2}{W} (uncommon)\nStockpiling Celebrant -- {2}{W} (common)\nVoracious Vermin -- {2}{B} (common)\nDevouring Sugarmaw // Have for Dinner -- {2}{B}{B} // {1}{W} (rare)\nMisleading Motes -- {3}{U} (common)\nJohann's Stopgap -- {3}{U} (common)\nBesotted Knight // Betroth the Beast -- {3}{W} // {W} (common)\nThreadbind Clique // Rip the Seams -- {3}{U} // {2}{W} (uncommon)\nTwining Twins // Swift Spiral -- {2}{U}{U} // {1}{W} (rare)\nEriette's Whisper -- {3}{B} (common)\nFarsight Ritual -- {2}{U}{U} (rare)\nTwisted Sewer-Witch -- {3}{B}{B} (uncommon)\nInto the Fae Court -- {3}{U}{U} (common)\n-------------------------\n\nTo keep track of what colors are open, you've counted how many cards of each color identity you've seen in the last 5 packs. Here is the breakdown:\nW: 11\nB: 6\nG: 4\nRW: 1\nR: 2\n\nThese are the contents of the pack:\n-------------------------\nCut In -- {3}{R}\nSorcery (common)\nCut In deals 4 damage to target creature.\nCreate a Young Hero Role token attached to up to one target creature you control. (If you control another Role on it, put that one into the graveyard. Enchanted creature has \"Whenever this creature attacks, if its toughness is 3 or less, put a +1/+1 counter on it.\")\n-------------------------\nSkewer Slinger -- {1}{R}\nCreature — Dwarf Knight (common)\nReach\nWhenever Skewer Slinger blocks or becomes blocked by a creature, Skewer Slinger deals 1 damage to that creature.\n1/3\n-------------------------\n\nWhat card would you pick from this pack?"
    },
    {
      "role": "assistant",
      "content": "Cut In"
    }
  ]
}

Это сразу демонстрирует самый сложный аспект тонкой настройки: форматирование данных для получения нужного результата — трудная и по своей сути экспериментальная задача.

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

Чтобы проиллюстрировать это на примере задачи драфта Magic, я протестировал следующее:

  • Примерно пять форматов промтов, в частности, различающиеся уровнем отображаемых подробностей о каждой карте;

  • Добавление дополнительного контекста о последних нескольких выбранных картах драфта, чтобы создать «память»;

  • Включение строк обучения «общей информации о картах», при котором модель просят запомнить подробности о новых картах.

Я потратил примерно сорок часов на эксперименты, но всё равно не могу с уверенностью сказать, что ответил на вопросы о том, какой формат «лучше» для этой задачи. Ещё требуется много экспериментов.

Выполнение тонкой настройки

Поиск GPU: об этом и говорить не стоит, но это отстой! В большинстве мест их доступность не очень велика. В конечном итоге я арендовал GPU с почасовой оплатой на Runpod (RTX 4090 с 24 ГБ VRAM) примерно за $0,7 в час.

Скрипт тонкой настройки: это не первый мой опыт в машинном обучении, поэтому инстинктивно я решил написать собственный скрипт обучения с трансформерами HuggingFace + PEFT. Учитывая напряжённую ситуацию с GPU, хорошим выбором показался QLoRA.

Оказалось, что написание собственного скрипта — плохая идея! Существует целая куча мелких оптимизаций и опций, от достаточно простых до требующих читать исследовательские статьи. Ничего неподъёмного, но самостоятельно бы пришлось разбираться долго.

В конечном итоге я воспользовался axolotl, который реализует множество таких оптимизаций и который гораздо проще (и быстрее) в работе. Его документация вполне хороша, и я считаю, что это хорошая начальная точка для людей, осваивающих тонкую настройку LLM.

Примечание о моделях: LLM огромны! В последний раз, когда я обучал модели регулярно (в 2019 году) в Bert было примерно 110 миллионов параметров; сегодня даже «маленькие» LLM в семьдесят раз больше. Такие объёмные модели неповоротливы по своей природе. Веса размером 16 ГБ сильно усложняют их хранение; память GPU — дефицитный ресурс даже при использовании методик наподобие QLora. Неудивительно, что на лучших исследователей такой большой спрос; в наибольших масштабах это очень сложная работа.

Оценка

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

Некоторые критерии языковых моделей сложно сформулировать: задачу «выбери нужную карту» достаточно легко сформулировать для драфтов Magic, но есть и более нечёткие задачи, которым бы я хотел научить готовую модель:

  • Когда она выбирает разные варианты, они должны быть допустимыми;

  • Было бы здорово, если бы модель могла разумно объяснить, «почему» она выбрала конкретный вариант.

Каждую из этих задач сформулировать гораздо сложнее, и в конечном итоге я проверял их «глазами», разобрав кучу примеров, но это было медленно. Как бы то ни было, GPT-4 лучше справляется с выбором менее «странных» вариантов и лучше оправдывает свой выбор, чем модели меньшего размера с тонкой настройкой.

Основные выводы

Мои два самых важных вывода из этого эксперимента:

  • Тонкая настройка на новых данных может быть примечательно эффективной, с лёгкостью превосходя контекстное обучение GPT-4 и по точности, и по затратам.

  • Для «правильной» реализации тонкой настройки требуется процесс экспериментов, и это само по себе становится отдельным набором навыков (который сложнее освоить, чем научиться промт-инжинирингу).

А, да, и про Magic

Как же боты справляются с ролью драфтеров? Довольно неплохо!

Я подключил модель выбора драфтов к генерируемым Magic Arena логам, написал небольшое Electron-приложение и провёл несколько драфтов с «Magic Copilot»:

Некоторые особенности:

  • Выбор генерируется моделью с тонкой настройкой, но комментарий сгенерирован GPT-4. Чаще всего это работает нормально, но время от времени GPT-4 не соглашается с тонкой настройкой и противоречит ей;

  • Я подключил к симулируемому драфту восемь ИИ драфта (то есть все боты проводили драфт друг против друга). При передаче набора противнику у них возникало странное поведение — необычная тенденция к драфту одноцветных колод. Если в качестве противника выступает человек, то они обычно сходятся к гораздо более нормальным колодам.

В целом, могу предположить, что это, вероятно, один из самых мощных и человекоподобных ИИ драфта на сегодня. По сравнению с ботами из функции быстрого драфта Magic Arena, они гораздо больше походят на высококачественного живого драфтера, чем на бота с эвристиками.

Wizards of the Coast — если вам нужен чрезвычайно точный и довольно дорогой в эксплуатации ИИ драфта, то напишите мне. Я с радостью отправлю вам LLM!

Комментарии (1)


  1. killyself
    07.12.2023 06:57
    +1

    Интересно было бы провести некоторое "Групповое сравнение" - группа людей явно покажет себя намного выше в навыке выбора. Как с этим сравнима модель? Могут ли модели работая вместе улучшить общий результат колоды? А также - может ли модель дать советы по игре по набранной ей же колоде, таким образом формируя ИИ-тренера?