Токенизация и BPE
Модель не видит ни букв, ни слов — она видит номера токенов. Как текст превращается в эти номера, решает токенизатор, и от него зависят цена запроса, эффективная длина контекста и даже способность модели посчитать буквы в слове «strawberry».
Интуиция
Нейросеть ест числа, поэтому текст надо порезать на единицы из конечного словаря и заменить их индексами. Два наивных варианта плохи с разных сторон:
- Посимвольно — словарь крошечный, зато последовательности раздуваются в разы: каждый символ почти не несёт смысла, а вычисления и внимание дорожают с длиной.
- Пословно — словарь бесконечен: словоформы, опечатки, «блокчейн-стартапы» и новые имена. Всё, чего нет в словаре, превращается в бесполезный токен UNK — проблема OOV (out-of-vocabulary).
Золотая середина — подслова (subwords): частые слова остаются целыми токенами, редкие собираются из кусков. Самый популярный способ построить такой словарь — BPE (byte pair encoding), алгоритм, пришедший из сжатия данных 1994 года.
Как работает BPE
Обучение токенизатора — жадный цикл из трёх строк:
# старт: разбить корпус на символы
while len(vocab) < target_size:
pair = самая_частая_пара_соседних_токенов(корпус)
слить pair в новый токен, дописать мердж в список
Итоговый словарь = стартовый алфавит + все выученные слияния (мерджи, merges). Размер словаря — гиперпараметр: у современных LLM обычно 50–200 тысяч токенов. Новое слово токенизируется детерминированно: разбиваем на символы и применяем мерджи в том порядке, в котором они были выучены. Слово, которого не было в корпусе, просто останется разбитым на более мелкие куски — вплоть до отдельных символов.
В интерактиве ниже — игрушечный корпус из шести слов с частотами. Прогоните BPE по шагам: смотрите, какая пара побеждает, как растёт словарь мерджей и как перекраивается токенизация нового слова, которого в корпусе не было.
Семейство токенизаторов
- Byte-level BPE (GPT-2 и все потомки): стартовый алфавит — не символы, а 256 байтов. Любой Юникод, эмодзи и опечатка гарантированно токенизируются — токен UNK не нужен вовсе.
- WordPiece (BERT): сливает не самую частую пару, а ту, что сильнее всего увеличивает правдоподобие корпуса; куски внутри слова помечаются префиксом ##.
- SentencePiece: работает с сырой строкой без предварительного деления по пробелам (пробел — обычный символ ▁), что удобно для языков без пробелов вроде японского.
Практические следствия
Токенизация — не техническая мелочь, а источник вполне ощутимых эффектов:
- Токен ≠ слово. В английском токен — в среднем ~0.75 слова; в русском слов на токен приходится меньше, потому что словоформы дробятся.
- Редкие языки дороже. Токенизатор обучался на корпусе с преобладанием английского, поэтому текст на грузинском или хинди дробится на в разы больше токенов: тот же смысл стоит дороже и быстрее съедает контекстное окно.
- Посимвольные задачи страдают. «Сколько букв r в strawberry?» — модель видит один-два токена, а не десять букв; посимвольный состав слова ей напрямую недоступен.
- Арифметика хрупкая. Числа режутся нерегулярно («12345» может стать «123» + «45»), поразрядная структура скрыта от модели.
- Размер словаря — компромисс. Больше словарь → короче последовательности (дешевле инференс), но тяжелее эмбеддинг-матрица и хуже обучены редкие токены.
- «Почему подслова, а не слова или символы?» — словарь конечен, OOV исчезает, последовательности умеренной длины: компромисс между двумя крайностями.
- «Как BPE токенизирует слово, которого не было в корпусе?» — разбивает на символы и применяет выученные мерджи по порядку; в худшем случае слово остаётся набором символов/байтов.
- «Почему LLM ошибается, считая буквы в слове?» — слово для неё один-два токена, отдельные буквы не видны без явного разбиения.
- «На что влияет размер словаря?» — длина последовательностей против размера эмбеддинг-матрицы и качества редких токенов.