Модуль 2. Токенизация и эмбеддинги
Сначала попробуйте решить упражнение. Ответы, подробные решения и проектные ориентиры раскрываются отдельно и сохраняют своё состояние при переключении RU/EN.
Скачать файлы курса (.zip) 2588,1 КБАрхив содержит файлы на обоих языках и вспомогательные материалы с сохранением структуры каталогов.
У1. Байтовая арифметика
Сколько базовых byte-level токенов дают Привет, мир!, Hello, world!, наивный 🚀?
Показать ответ и решение
Решение. До BPE-слияний каждый байт UTF-8 является отдельным базовым токеном. В Привет, мир! девять кириллических букв (Привет — 6, мир — 3) занимают байт; запятая, пробел и ! добавляют ещё 3. Итого 21. Hello, world! целиком состоит из 13 ASCII-символов, поэтому даёт 13 байтов. В наивный 🚀 семь кириллических букв дают 14 байт, пробел — 1, эмодзи — 4: всего 19. Проверка без токенизатора: len(text.encode("utf-8")).
У2. Encode по рангам
Реализуйте кодирование, которое на каждом шаге выбирает присутствующую пару с минимальным рангом.
Показать ответ и решение
Решение.
def encode_by_rank(text, merges):
chunks = re.findall(PAT, text)
out = []
for chunk in chunks:
ids = list(chunk.encode("utf-8"))
while len(ids) > 1:
pairs = set(zip(ids[:-1], ids[1:]))
best = min(pairs, key=lambda pair: merges.get(pair, float("inf")))
if best not in merges:
break
ids = merge([ids], best, merges[best])[0]
out.extend(ids)
return outНа инференсе нет частот корпуса: порядок задаётся рангами, сформированными во время обучения.
Алгоритм сначала применяет предварительное разбиение и обрабатывает каждый чанк независимо. Внутри чанка он перечисляет соседние пары, выбирает пару с минимальным числовым рангом и сливает все её допустимые вхождения. Если ни одной присутствующей пары нет в merges, обработка чанка завершена. Частоту пары заново считать нельзя: частоты использовались при обучении BPE, а при кодировании их результат уже зафиксирован в рангах.
У3. Протокол fertility
Зафиксируйте корпус, правило определения слова и способ агрегации. Считайте отношение суммарных токенов к суммарным словам и рядом публикуйте bytes/token. Объясните, почему среднее fertility по строкам может дать иной вес коротким примерам.
Показать ответ и решение
Решение. Воспроизводимый протокол должен фиксировать: точный снимок корпуса и его срезы, нормализацию и правило выделения слов, имя и ревизию токенизатора, а также режим добавления специальных токенов. Для каждой строки считаем число UTF-8-байтов , слов и токенов (обычно без служебных маркеров начала и конца последовательности — BOS, beginning of sequence, и EOS, end of sequence), после чего агрегируем
Это micro-агрегация: каждое слово имеет одинаковый вес. Среднее даёт каждой строке одинаковый вес, поэтому короткая строка из одного слова влияет так же, как длинное предложение; строки с дополнительно требуют отдельного правила. В отчёте нужно опубликовать также , , и число исключённых строк — тогда результат можно перепроверить.
У4 [проект]. Многоязычная карта
Возьмите FLORES-200 и опубликованные токенизаторы o200k_base, Llama 4, Qwen3, Gemma 3, DeepSeek V4 и Kimi K3. Постройте таблицу «язык × fertility» и обязательно запишите revision каждого артефакта. Не задавайте заранее ожидаемого победителя: сравнение должно быть результатом эксперимента.
Демо и критерии проекта
Демо к этому проектному упражнению: русскоязычный проектный ноутбук модуля 2, раздел «1. Что именно стоит в знаменателе?». Он показывает компактный воспроизводимый пример на малых данных, а не готовое решение полномасштабного проекта.
Для каждого языка задайте подходящее правило сегментации слов либо сравнивайте токены на выровненное предложение. Регулярное выражение непрерывных букв считает китайскую строку одним фрагментом; это не одно лингвистическое слово. Демо показывает знаменатели и число единиц на предложение, а его wordrun_proxy не является WordPiece.
У5 [проект]. Аудит Harmony
В необязательной сетевой ячейке основного ноутбука загрузите o200k_harmony, посчитайте имена и уникальные ID, найдите алиас 200018 и разделите имена на протокольные и reserved.
Демо к этому проектному упражнению: русскоязычный проектный ноутбук модуля 2, раздел «2. Почему число имён не равно числу ID?». Он показывает компактный воспроизводимый пример на малых данных, а не готовое решение полномасштабного проекта.
Демо и критерии проекта
Ожидаемый результат для снимка 11 октября 2026: 1091 имя, 1090 уникальных специальных ID, 10 протокольных имён, 1081 имя reserved; вместе с 199 998 обычных ID получается n_vocab=201088.
У6. Эмбеддинг и один шаг обучения
Для из §11 вычислите E[[0,2,0]], E[0] @ E.T и BF16-память связанных весов при . Затем минимизируйте для нулевых целевых векторов и ID [0,2,0]: чему равен градиент по каждой строке E?
Показать ответ и решение
Решение. Выбранные строки равны [[1,0],[0,1],[1,0]], логиты — [1,2,0], максимум имеет ID 1. Параметров , BF16-память равна байт = 16 MiB. Повторяющийся ID 0 накапливает два вклада: градиент [[2,0],[0,0],[0,1]]. При шаге 0.1 новая таблица [[0.8,0],[2,0],[0,0.9]], а уменьшается с 1.5 до 1.045. В ноутбуке градиент независимо проверяется конечными разностями; упражнение показывает, как выбор строк передаёт градиент таблице; семантические свойства этой игрушечной целью не проверяются.