• Русский
  • Сэмплирование

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

    Очевидное правило — всегда брать самый вероятный токен — оказывается плохим (рисунок 9.3 показывает почему). Поэтому сэмплеры выбирают случайно, пропорционально вероятностям, а сами вероятности сначала подправляют.

    От логитов к вероятностям

    Softmax превращает логиты ziz_i в вероятности. Температура TT делит каждый логит перед softmax:

    pi=ezi/T∑jezj/Tp_i = \frac{e^{z_i / T}}{\sum_j e^{z_j / T}}
    • T=1T = 1 оставляет распределение модели как есть.
    • T<1T < 1 растягивает разрывы между логитами, и фаворит становится ещё вероятнее. При T→0T \to 0 получается жадное декодирование: всегда берётся самый вероятный токен.
    • T>1T > 1 сжимает разрывы, и маловероятные токены догоняют лидеров. При очень большой TT все токены почти равновероятны.

    Возьмём три оценки из главы 1 — 2, 1 и 0; softmax превращает их в 67%, 24% и 9%. При T=0,5T = 0{,}5 они становятся 4, 2 и 0, а вероятности — 87%, 12% и 2%. При T=2T = 2 они становятся 1; 0,5 и 0, а вероятности — 51%, 31% и 19%. Температура никогда не меняет порядок токенов — только то, насколько далеко друг от друга их шансы.

    Рисунок 9.1 · Температура меняет форму тех же логитов

    Моя любимая еда — ▍

    логит÷ Tтокенвероятность
    4,14,1·пицца39,3%
    3,63,6·суши23,8%
    3,23,2·паста16,0%
    2,62,6·шоколад8,8%
    2,32,3·тако6,5%
    1,51,5·любая2,9%
    0,90,9·мамин1,6%
    0,20,2·холодная0,8%
    −0,8−0,8·фиолетовый0,3%
    −1,6−1,6·вторник0,1%
    39%шанс «пицца»5,1реальных вариантов
    Логиты слева фиксированы: их модель посчитала для «Моя любимая еда —». Двигайте температуру и следите за вероятностями. Полоса сверху — всё распределение целиком. «Реальных вариантов» — это e в степени энтропии (среднего −ln p, взвешенного по вероятностям токенов; это мера неопределённости): примерно сколько токенов всерьёз участвуют в выборе.

    Отрезаем длинный хвост

    В настоящем словаре около 200 000 токенов. Даже если у каждого бессмысленного токена крошечная вероятность, вместе они складываются в заметную долю, и рано или поздно какой-нибудь из них выпадет. Один плохой токен может испортить всё, что идёт после, ведь модели придётся продолжать от собственной ошибки. Поэтому сэмплеры обрезают распределение перед выбором:

    • Top-k оставляет только kk самых вероятных токенов.
    • Top-p (nucleus-сэмплирование) оставляет наименьший набор лучших токенов, чьи вероятности в сумме дают не меньше pp. Когда модель уверена, набор крошечный; когда сомневается — растёт.
    • Min-p оставляет токены, чья вероятность не меньше pmin⁡p_{\min}, умноженного на вероятность лидера, так что порог подстраивается под уверенность модели.

    После отсечения выжившие перенормируются, чтобы снова давать в сумме 1, и один токен выбирается случайно — пропорционально своей вероятности.

    В лаборатории ниже при T=1T = 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 впускают всё больше, потому что уверенность модели расплывается.

    Рисунок 9.2 · Лаборатория сэмплирования
    токенвероятностьвыпало
    ·пицца39,3%0
    ·суши23,8%0
    ·паста16,0%0
    ·шоколад8,8%0
    ·тако6,5%0
    ·любая2,9%0
    ·мамин1,6%0
    ·холодная0,8%0
    ·фиолетовый0,3%0
    ·вторник0,1%0
    Последние выборки
    Можно выбрать 10 из 10 токенов
    Зачёркнутые токены больше нельзя выбрать. Нажмите «Выбрать 100 раз», чтобы сделать настоящие случайные выборки: на 100 бросках гистограмма шумная, но повторяет вероятности. Каждое нажатие использует новое зерно (seed) — начальное число генератора случайных чисел.

    Движки инференса (программы, которые запускают обученную модель для пользователей) обычно сначала применяют температуру, потом фильтры. Частые настройки по умолчанию — TT от 0,70{,}7 до 11 и top-p между 0,90{,}9 и 0,950{,}95, но каждый провайдер подбирает их по-своему.

    Что ручки делают с текстом

    Прогоним одно и то же начало через игрушечную языковую модель — таблицу того, какое слово обычно идёт за каким, — при четырёх температурах.

    Рисунок 9.3 · Одно начало, четыре температуры
    seed 4
    T = 0 (жадно)

    Жил-был кот, который любил спать на солнце и на солнце и на солнце и на солнце

    T = 0.7

    Жил-был пёс. Однажды кот и на солнце и на солнце. Однажды он пошёл на солнце

    T = 1.2

    Жил-был кот. Однажды кот, и на вторник и в лесу умел Потом он любил петь

    T = 2.5

    Жил-был кот налог луна. фиолетовый потом квант и потом зебра фиолетовый. вторник пошёл в лесу

    Жадное декодирование застревает в цикле («на солнце и на солнце и…») — классический провал. Умеренная температура читается естественно. Высокая пускает в текст длинный хвост, и получается словесная каша. Включите штраф за повтор — и жадный цикл разорвётся.

    Жадное декодирование — это не «самый точный» текст, а текст, который никогда не рискует, а языковые модели, которые никогда не рискуют, склонны повторяться. Немного случайности — вот что делает вывод похожим на живой язык.

    Структурированный вывод: сэмплирование по грамматике

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

    Хитрость происходит между логитами и выбором. Маленький парсер — программа, проверяющая текст по правилам формата (его грамматике), — следит, где мы находимся в грамматике (внутри строки, ждём ключ, ждём цифру…), и знает, какие токены могут законно идти дальше. Логит всех остальных токенов приравнивается к −∞-\infty, а поскольку e−∞=0e^{-\infty} = 0, softmax даёт им ровно нулевую вероятность. Среди допустимых токенов модель по-прежнему выбирает по своим предпочтениям.

    Рисунок 9.4 · Ограниченное декодирование: грамматика JSON маскирует логиты
    Вывод▍

    Грамматика ждёт начало объекта: подходит только «{»

    токенлогитс маскойвероятность
    Конечно3,1·45%
    Вот2,4·22%
    {2,0·15%
    ```json1,8·12%
    Хорошо1,0·6%
    1/19

    Исходные оценки модели. Её фаворит — Конечно, и он сломал бы JSON.

    Схема требует {'name': строка, 'age': целое}. На каждом шаге сначала видны исходные оценки модели, потом маска грамматики: зачёркнутые токены получают −∞ и падают до 0%. Посмотрите, как вето получают любимцы модели — «Конечно», Ada без кавычек и строка '36'.

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

    Маска гарантирует форму, а не правду

    Грамматика может заставить "age": 36 быть целым числом, но не правильным числом. Кроме того, маска может загнать модель в угол, куда она сама бы не пошла, поэтому схема, которая спорит с естественными формулировками модели, может снизить качество ответа.

    Ещё несколько инструментов

    • Штрафы за повтор и частоту понижают логиты уже встречавшихся токенов и мешают циклам вроде того, что выше. Они должны быть мягкими: какие-то повторы (предлоги, имена, код) правильны.
    • Зерно (seed). «Случайность» берётся из генератора псевдослучайных чисел. Зафиксируйте его зерно — и те же настройки воспроизведут тот же текст, что удобно для тестов. (На практике крошечные численные различия на GPU всё равно могут сдвигать вывод.)
    • Logprobs. Большинство API (интерфейсов, через которые программы отправляют запросы облачной модели) умеют возвращать логарифм вероятности каждого выбранного токена и нескольких лучших альтернатив. Это собственная уверенность модели: по ней удобно оценивать ответы, замечать догадки и делать классификаторы из чат-модели.
    • Лучевой поиск (beam search) ведёт несколько вариантов продолжения параллельно и выбирает тот, у которого лучшая общая вероятность. Он помогает в машинном переводе, но в свободном диалоге делает текст пресным, поэтому чат-модели им почти не пользуются.
    Температура 0 для фактов, повыше для идей

    Для извлечения данных, классификации или кода, где есть один правильный ответ, обычно лучше низкая температура (или жадное декодирование). Для мозгового штурма и художественного текста более высокая температура даёт больше разнообразия. Модель та же — меняется только сэмплер.

    Итоги

    • Модель выдаёт логиты; сэмплер превращает их в один выбранный токен.
    • Температура заостряет (T<1T < 1) или сглаживает (T>1T > 1) распределение, не меняя порядка.
    • Top-k, top-p и min-p отрезают ненадёжный хвост перед выбором.
    • Жадное декодирование склонно к циклам; немного случайности делает текст естественным.
    • Ограниченное декодирование маскирует недопустимые токены через −∞-\infty, поэтому структурированный вывод всегда разбирается парсером.

    Сэмплирование дёшево. Дорого — получить сами логиты, и следующая глава показывает, как движки инференса делают это быстро.