Сэмплирование
Обучение позади: теперь модель даёт высокую вероятность правдоподобным следующим токенам. Пользоваться ею — значит запускать её снова и снова, добавляя по одному токену за раз (глава 1). В конце каждого прямого прохода модель выдаёт по одному числу на каждую запись словаря — логит. Токен она при этом не выбирает. Выбор делает отдельный небольшой кусок кода — сэмплер, и его настройки (стратегия декодирования) меняют характер текста сильнее, чем обычно ожидают. Одна и та же модель может быть скучной, изобретательной или бессвязной в зависимости от пары ручек.
Очевидное правило — всегда брать самый вероятный токен — оказывается плохим (рисунок 9.3 показывает почему). Поэтому сэмплеры выбирают случайно, пропорционально вероятностям, а сами вероятности сначала подправляют.
От логитов к вероятностям
Softmax превращает логиты в вероятности. Температура делит каждый логит перед softmax:
- оставляет распределение модели как есть.
- растягивает разрывы между логитами, и фаворит становится ещё вероятнее. При получается жадное декодирование: всегда берётся самый вероятный токен.
- сжимает разрывы, и маловероятные токены догоняют лидеров. При очень большой все токены почти равновероятны.
Возьмём три оценки из главы 1 — 2, 1 и 0; softmax превращает их в 67%, 24% и 9%. При они становятся 4, 2 и 0, а вероятности — 87%, 12% и 2%. При они становятся 1; 0,5 и 0, а вероятности — 51%, 31% и 19%. Температура никогда не меняет порядок токенов — только то, насколько далеко друг от друга их шансы.
Моя любимая еда — ▍
Отрезаем длинный хвост
В настоящем словаре около 200 000 токенов. Даже если у каждого бессмысленного токена крошечная вероятность, вместе они складываются в заметную долю, и рано или поздно какой-нибудь из них выпадет. Один плохой токен может испортить всё, что идёт после, ведь модели придётся продолжать от собственной ошибки. Поэтому сэмплеры обрезают распределение перед выбором:
- Top-k оставляет только самых вероятных токенов.
- Top-p (nucleus-сэмплирование) оставляет наименьший набор лучших токенов, чьи вероятности в сумме дают не меньше . Когда модель уверена, набор крошечный; когда сомневается — растёт.
- Min-p оставляет токены, чья вероятность не меньше , умноженного на вероятность лидера, так что порог подстраивается под уверенность модели.
После отсечения выжившие перенормируются, чтобы снова давать в сумме 1, и один токен выбирается случайно — пропорционально своей вероятности.
В лаборатории ниже при у пяти лучших токенов 39%, 24%, 16%, 9% и 6,5%. Top-k = 3 оставляет пиццу, суши и пасту. Top-p = 0,9 оставляет пять: первые четыре дают в сумме лишь 88%, поэтому добавляется тако, и сумма доходит до 94%. Min-p = 0,1 отбрасывает всё, что ниже 3,9% (десятой доли от 39% у пиццы), — тоже остаётся пять. Теперь поднимите температуру: top-k по-прежнему оставляет три токена, а top-p и min-p впускают всё больше, потому что уверенность модели расплывается.
Движки инференса (программы, которые запускают обученную модель для пользователей) обычно сначала применяют температуру, потом фильтры. Частые настройки по умолчанию — от до и top-p между и , но каждый провайдер подбирает их по-своему.
Что ручки делают с текстом
Прогоним одно и то же начало через игрушечную языковую модель — таблицу того, какое слово обычно идёт за каким, — при четырёх температурах.
Жил-был кот, который любил спать на солнце и на солнце и на солнце и на солнце
Жил-был пёс. Однажды кот и на солнце и на солнце. Однажды он пошёл на солнце
Жил-был кот. Однажды кот, и на вторник и в лесу умел Потом он любил петь
Жил-был кот налог луна. фиолетовый потом квант и потом зебра фиолетовый. вторник пошёл в лесу
Жадное декодирование — это не «самый точный» текст, а текст, который никогда не рискует, а языковые модели, которые никогда не рискуют, склонны повторяться. Немного случайности — вот что делает вывод похожим на живой язык.
Структурированный вывод: сэмплирование по грамматике
Программам, которые вызывают модель, часто нужен ответ в жёстком формате: JSON (распространённый текстовый формат данных) по схеме, то есть со списком обязательных полей и их типов, вызов функции, одна метка из списка. Вежливая просьба в промпте срабатывает в большинстве случаев. Ограниченное декодирование (constrained decoding) заставляет её срабатывать всегда.
Хитрость происходит между логитами и выбором. Маленький парсер — программа, проверяющая текст по правилам формата (его грамматике), — следит, где мы находимся в грамматике (внутри строки, ждём ключ, ждём цифру…), и знает, какие токены могут законно идти дальше. Логит всех остальных токенов приравнивается к , а поскольку , softmax даёт им ровно нулевую вероятность. Среди допустимых токенов модель по-прежнему выбирает по своим предпочтениям.
▍Грамматика ждёт начало объекта: подходит только «{»
Исходные оценки модели. Её фаворит — Конечно, и он сломал бы JSON.
Настоящие движки заранее компилируют JSON-схему или грамматику в конечный автомат (заранее построенную таблицу допустимых токенов для каждого состояния) над словарём токенизатора, так что маска на каждом шаге стоит микросекунды. Тот же механизм стоит за «JSON-режимом», вызовами инструментов и выводом по регулярному выражению (языку шаблонов для текста) в большинстве систем, обслуживающих модели для множества пользователей.
Грамматика может заставить "age": 36 быть целым числом, но не правильным числом. Кроме того, маска может загнать модель в угол, куда она сама бы не пошла, поэтому схема, которая спорит с естественными формулировками модели, может снизить качество ответа.
Ещё несколько инструментов
- Штрафы за повтор и частоту понижают логиты уже встречавшихся токенов и мешают циклам вроде того, что выше. Они должны быть мягкими: какие-то повторы (предлоги, имена, код) правильны.
- Зерно (seed). «Случайность» берётся из генератора псевдослучайных чисел. Зафиксируйте его зерно — и те же настройки воспроизведут тот же текст, что удобно для тестов. (На практике крошечные численные различия на GPU всё равно могут сдвигать вывод.)
- Logprobs. Большинство API (интерфейсов, через которые программы отправляют запросы облачной модели) умеют возвращать логарифм вероятности каждого выбранного токена и нескольких лучших альтернатив. Это собственная уверенность модели: по ней удобно оценивать ответы, замечать догадки и делать классификаторы из чат-модели.
- Лучевой поиск (beam search) ведёт несколько вариантов продолжения параллельно и выбирает тот, у которого лучшая общая вероятность. Он помогает в машинном переводе, но в свободном диалоге делает текст пресным, поэтому чат-модели им почти не пользуются.
Для извлечения данных, классификации или кода, где есть один правильный ответ, обычно лучше низкая температура (или жадное декодирование). Для мозгового штурма и художественного текста более высокая температура даёт больше разнообразия. Модель та же — меняется только сэмплер.
Итоги
- Модель выдаёт логиты; сэмплер превращает их в один выбранный токен.
- Температура заостряет () или сглаживает () распределение, не меняя порядка.
- Top-k, top-p и min-p отрезают ненадёжный хвост перед выбором.
- Жадное декодирование склонно к циклам; немного случайности делает текст естественным.
- Ограниченное декодирование маскирует недопустимые токены через , поэтому структурированный вывод всегда разбирается парсером.
Сэмплирование дёшево. Дорого — получить сами логиты, и следующая глава показывает, как движки инференса делают это быстро.