Модуль 5. Современные механизмы внимания
Сначала попробуйте решить упражнение. Ответы, подробные решения и проектные ориентиры раскрываются отдельно и сохраняют своё состояние при переключении RU/EN.
Скачать файлы курса (.zip) 2588,1 КБАрхив содержит файлы на обоих языках и вспомогательные материалы с сохранением структуры каталогов.
У1. Содержимое KV-кэша
Для 36-слойной модели с , , , bf16 и контекстом 131 072 вычислите кэш при полном хранении во всех слоях. Затем замените половину слоёв окном 128. Считайте одну последовательность и только содержимое K/V; локальные кэши ограничены окном.
Показать ответ и решение
Решение. На каждом слое для одного сохранённого токена нужны и ключ, и значение:
Поэтому кэш полных слоёв равен GiB. В гибриде 18 полных слоёв занимают GiB, а 18 локальных хранят только окно: MiB. Сумма: 4.5043945 GiB. Число голов запросов в этой формуле не участвует: K/V хранятся по .
У2. Online softmax
Для логитов [2,1,3,0.5] и значений [1,2,3,4] обработайте первые два и последние два элемента отдельными блоками. Воспроизведите , , коэффициент перенормировки и итог .
Показать ответ и решение
Решение. Для первого блока берём максимум :
Для второго блока , поэтому и . Общий максимум ; статистики первого блока нужно перенести в эту шкалу множителем :
Итоговый выход внимания . Перенормировка и позволяет объединять блоки без хранения всей матрицы логитов.
У3. Обучаемый sink
Покажите, что обучаемый sink эквивалентен дополнительному логиту с нулевым вектором значения. Объясните, почему обычный фиксированный ключ не создаёт произвольный постоянный логит для всех запросов.
Показать ответ и решение
Решение. Добавим к обычным логитам ещё один логит и соответствующее значение . Тогда
Этот дополнительный столбец логитов может получить часть вероятностной массы, не добавляя собственного вклада в выход. У фиксированного ключа логит равен и меняется вместе с запросом. Вектор даёт только константу 0; произвольную обучаемую константу для всех нужно задавать отдельным скаляром или смещением.
У4. Порядок голов GQA
Постройте малый пример с , и докажите, что repeat по каждой KV-голове совпадает с групповой формулой, а tile меняет соответствие голов.
Показать ответ и решение
Решение. Размер группы равен , поэтому голова запроса использует KV-голову : головы 0–3 получают KV0, а 4–7 — KV1. Если обозначить их значениями [10, 20], правильное расширение равно
repeat_interleave(4): [10, 10, 10, 10, 20, 20, 20, 20]Это и есть групповая формула. tile(4) даёт [10, 20, 10, 20, 10, 20, 10, 20]: размер тензора верен, но головы запросов связываются с другими KV-головами. Следовательно, одной проверки формы массива недостаточно.
У5 [проект]
На GPU сравните прямой PyTorch attention и доступную реализацию SDPA/Flash для . Измерьте время, пиковую память и максимальную ошибку относительно эталона float64.
Демо и критерии проекта
Демо к этому проектному упражнению: русскоязычный demo-notebook модуля 5, разделы «Демо 1» и «Демо 2» как отправная точка для проектной работы модуля. Он показывает компактный воспроизводимый пример на малых данных, а не готовое решение полномасштабного проекта.
У6. Маска после префикса
Для запроса в позиции 5 и ключей 0–5 выпишите маску полного внимания и окна . Сравните с tril(ones(1, 6)).
Показать ответ и решение
Решение. Причинное ограничение сравнивает абсолютные позиции: ключ разрешён при . Поэтому полная строка маски равна [1,1,1,1,1,1]. Окно ширины 3 добавляет условие , то есть оставляет позиции 3, 4 и 5: [0,0,0,1,1,1].
У tril(ones(1,6)) единственная строка имеет локальный индекс 0, поэтому результат [1,0,0,0,0,0]. Эта операция ничего не знает о пяти уже обработанных позициях. Чтобы получить нужную маску, нужно сравнивать абсолютные индексы или передать соответствующее смещение. В ноутбуке повторите рассуждение для нескольких новых запросов: у каждой строки будет своя абсолютная позиция.
У7. Поглощение MLA
Задайте , , семь латентов размерности 4 и три запроса размерности 6. Сверьте логиты и выход до и после переноса проекций; затем добавьте позиционную ветвь. Объясните, почему перенос вращения на запрос зависит от позиции ключа.
Показать ответ и решение
Решение. Соберём запросы строками , а латенты — строками . В прямом варианте имеет форму , а — . Содержательные логиты равны
Справа сначала вычисляется формы , затем матрица логитов формы . В обеих ветвях добавим одну и ту же позиционную часть и применим одинаковые масштабирование, маску и softmax. Получим одинаковые веса . Для выхода:
Прямой путь сначала восстанавливает семь значений ширины 5. Переставленный путь смешивает латенты в формы и лишь затем расширяет результат до . При выходной матрице можно заранее объединить ; результат сохраняется.
Если RoPE вращает восстановленный ключ, эффективный запрос становится : он зависит от позиции ключа . Это не одно преобразование, которое можно сохранить для всех ключей. Отдельная позиционная ветвь обходит именно эту зависимость. Опыт §8 ноутбука проверяет логиты, выход и выходную проекцию с допуском ; контрпример с другой позицией ключа проверяет предел перестановки.
Для GPU-проекта сначала сравните точность на малой последовательности с одной головой и эталоном FP64. Затем измеряйте выбранные большие размеры: одинаковые входы, маски и точности, прогрев, no_grad, синхронизация CUDA перед замером и после него, сброс пикового счётчика. Указывайте, входят ли проекции, создание маски и кэш в измерение; фиксируйте выбранное ядро и различайте выделенную и зарезервированную память. Уменьшите размер при нехватке памяти; не стройте большой FP64-эталон лишь ради проверки скорости.