Как влияет размер словаря токенизатора на количество параметров модели и скорость инференса?
Краткий тезис
Размер словаря (vocab_size) токенизатора напрямую определяет количество параметров в слоях, работающих с токенами: матрица эмбеддингов и языковая голова (LM head). Увеличение vocab_size на десятки тысяч единиц может добавить сотни миллионов параметров, что замедляет инференс из-за роста объёма матричных умножений и требований к памяти GPU. Однако больший словарь позволяет разбить текст на меньшее число токенов, сокращая длину последовательности и ускоряя обработку в трансформере — возникает ключевой trade-off.
-----|------------|-----------|-------------------------------|----------------------| | GPT-2 (small) | 50 257 | 768 | ~77 млн | ~37 % (общее 124 млн) | | BERT-base | 30 522 | 768 | ~46,9 млн | ~30 % (общее 110 млн) | | LLaMA-7B | 32 000 | 4096 | ~262 млн | ~3,7 % | | CodeGen 350M | 50 432 | 1024 | ~103 млн | ~29 % |
Для моделей малого и среднего размера доля параметров токенизационной части может достигать 30–40 %, а для крупных моделей (7B+) — становится менее заметной на фоне огромных скрытых слоёв.
Вывод: увеличение vocab_size на каждые 10 000 токенов при embed_dim = 768 добавляет ~15,4 млн параметров (embedding + LM head). Это приводит к росту объёма памяти и числа операций на forward-проходе.
2. Влияние на скорость инференса
Увеличение vocab_size замедляет инференс по нескольким причинам:
2.1 Матричные умножения на последнем слое
При вычислении логитов (logits) для каждого токена последовательности выполняется умножение скрытого состояния на транспонированную матрицу LM head. Сложность операции — O(sequence_length × hidden_dim × vocab_size). Удвоение vocab_size удваивает время этого шага.
2.2 Память и bandwidth
Матрица эмбеддингов и LM head весят 2 × vocab_size × embed_dim × 2 байт (для half precision). Например, для vocab_size = 100 000 и embed_dim = 768 это ~307 МБ. При загрузке модели на GPU потребляется дополнительная память, а при inference с batch > 1 — растёт pressure на memory bandwidth, так как матрица LM head часто читается целиком для каждого токена.
2.3 Softmax над словарём
После получения logits размером (batch, seq_len, vocab_size) требуется softmax, суммирующий все вероятности. Его вычислительная сложность — O(seq_len × vocab_size). Увеличение vocab_size линейно увеличивает затраты.
2.4 Компромисс: длина последовательности
Большой словарь (например, 100 000 токенов) позволяет разбить текст на меньшее число токенов за счёт выделения целых слов и частых подслов. Сокращение seq_len уменьшает время на self-attention (квадратичная сложность) и на матричные умножения скрытых слоёв. Если seq_len падает в 2 раза, то для моделей с глубокими трансформерами выигрыш может перевесить проигрыш от увеличения vocab_size. Однако на практике этот эффект значим только для очень больших словарей (128k и выше) и коротких текстов.
3. Trade-off: меньше токенов на текст vs больше параметров
Выбор vocab_size — задача оптимизации:
- Маленький словарь (10 – 20 k): меньше параметров, но больше токенов на текст (так как редко встречающиеся символы или слова разбиваются на несколько подслов). Увеличивается длина последовательности, что замедляет self-attention и увеличивает требования к памяти для хранения hidden states.
- Большой словарь (50 – 200 k): больше параметров, но токенизация эффективнее (меньше токенов). При фиксированной длине последовательности модель может обрабатывать более длинные тексты в пределах
max_seq_len. Однако обучение такого словаря требует больше данных и может страдать от переобучения редких токенов.
Современные исследования (например, SentencePiece с Unigram) показывают, что оптимальный vocab_size лежит в диапазоне 30 – 50 k для большинства языков. Для мультиязычных моделей (XLM-R, mT5) часто используют 250 k, чтобы покрыть все символы и подслова разных языков.
Формула оценки trade-off:
- Затраты на embedding/LM head =
2 × vocab_size × embed_dim. - Затраты на self-attention =
O(L^2 × d)(приближённо). - Средняя длина последовательности L обратно пропорциональна vocab_size при условии оптимального словаря.
- Найти такой vocab_size, при котором суммарное время минимально — задача численного поиска для конкретного датасета.
4. Пет-проект для закрепления
Задача: экспериментально сравнить инференс модели с двумя токенизаторами разного размера (например, 50 k и 100 k) на одном корпусе текстов, замерить количество токенов на текст и время forward-прохода.
Инструменты:
- Hugging Face Transformers (например, загрузить предобученные GPT-2 с vocab_size 50k и GPT-2 с расширенным словарём, или использовать SentencePiece для построения своего токенизатора).
- PyTorch или TensorFlow для замеров.
- GPU (можно Collab Free, но есть риск OOM).
- Библиотека
time,torch.cuda.Eventдля измерения времени.
Шаги:
- Взять модельную архитектуру (например, GPT-2 small) с оригинальным токенизатором (50k).
- Построить токенизатор с бóльшим словарём (100k) на том же корпусе (например, русский текст из Wiki или английский из OSCAR). Для этого использовать
train_new_from_iteratorв HuggingFace или обучение SentencePiece. - Расширить матрицу эмбеддингов и LM head до нового vocab_size (случайная инициализация новых эмбеддингов или копирование существующих).
- Подготовить датасет из 1000 одинаковых текстов, затокенизировать обоими токенизаторами.
- Прогнать forward одного батча (batch_size=1 или 4) с последовательностями переменной длины без градиентов, замеряя среднее время.
- Сравнить общее время, количество токенов в каждом тексте, потребление GPU памяти.
Ожидаемый результат:
- Вы увидите, что при 50k словаре средняя длина токенов больше (например, 512 токенов на текст), а время forward может быть заметно меньше, чем при 100k (512 → ~400 токенов). Однако прирост скорости от уменьшения длины может быть съеден дополнительными расчётами на LM head. На практике для подобной модели (GPT-2 small) выигрыш от меньшего числа токенов обычно не компенсирует рост параметров, поэтому 50k окажется быстрее.
Связь с другими вопросами
Навигация
- Предыдущий: 929
- Следующий: 931
- Индекс: 00. Индекс разборов