Неделя 20. Мультимодальность и длинный контекст
Учиться в приложении: тьютор, задачи с кодом →
Ядро: ViT, CLIP и контрастный лосс, проектор LLaVA, экстраполяция RoPE · Глубина: cross-attention и Q-Former, диффузия (05-ГЛУБИНА) · ≈ 10 ч ядро / 22 ч всё
Две темы с общим корнем: трансформеру всё равно, откуда пришли векторы последовательности. Мультимодальность отвечает на вопрос, **как превратить изображение или звук в токены. Длинный контекст отвечает на вопрос, как ведут себя позиции там, где модель их никогда не видела**.
Часть 1. ViT
На пальцах. Картинка 224×224 режется на квадраты 16×16: 14 по горизонтали, 14 по вертикали, всего 196 патчей.
В каждом патче 16·16·3 = 768 чисел, и линейный слой превращает их в вектор размера D.
Дальше картинка превращается в предложение из 196 «слов», и трансформер обрабатывает его как текст.
Картинка 448×448 даёт уже 784 «слова», вчетверо больше, а пар для внимания 784² / 196² = 16 раз больше.
- Изображение режется на патчи
P×P, каждый линейно проецируется вD. Это ровно свёртка с ядромPи шагомP. При 224×224 иP = 16получается 196 токенов - Вывод про стоимость: разрешение ×2 → токенов ×4 → внимание ×16. Поэтому мультимодальные модели так борются за число визуальных токенов
- Выученные позиционные эмбеддинги привязывают модель к разрешению (при смене разрешения нужна интерполяция). 2D-RoPE (позиция = строка и столбец) эту привязку снимает
- Необязательно: напиши на NumPy свёртку
conv2d(x, w, stride, padding)и проверь, что при ядре и шагеPбез паддинга она совпадает с нарезкой на патчи и линейным слоем. Размер выхода⌊(n + 2·pad − P)/stride⌋ + 1, гдеnсторона картинки, на собеседованиях спрашивают отдельно
Часть 2. CLIP и контрастное обучение
На пальцах. Батч из 4 пар: 4 картинки и 4 подписи. Считаем сходство каждой картинки с каждой подписью, получается таблица 4×4. Для картинки 1 правильная подпись первая, остальные три служат неправильными вариантами. Каждая строка таблицы это классификация на 4 класса, правильный ответ на диагонали. То же по столбцам: для подписи ищем её картинку. При батче 32 768, как у CLIP, у каждой строки 32 767 негативов.
- Контрастное обучение: сближать представления правильных пар и раздвигать неправильные.
Nпар (картинка, текст) → матрица сходствN×N, симметричная кросс-энтропия по строкам и столбцам, правильный ответ на диагонали - Вывод: это классификация, где классами служат остальные элементы батча. Размер батча равен числу негативов, поэтому CLIP учат огромными батчами. SigLIP заменяет softmax на сигмоиду по каждой паре и снимает нормировку по всему батчу
Часть 3. Соединение модальностей
- Проектор (LLaVA): MLP переводит выход визуального энкодера в пространство эмбеддингов LLM, визуальные токены вставляются в последовательность как обычные
- Cross-attention (Flamingo): отдельные слои, где текст смотрит на изображение
- Q-Former (BLIP-2, «querying transformer»): фиксированное число обучаемых запросов сжимает изображение
в
Kтокенов. Общий компромисс: число визуальных токенов против детализации - Аудио: Whisper устроен как энкодер-декодер над лог-мел-спектрограммой (энергия звука по частотам во времени, в логарифмической шкале). Нейрокодеки (сети, сжимающие звук в поток дискретных кодов) дают дискретные аудио-токены, и звук можно генерировать как текст
Часть 3б. Генерация без авторегрессии
Картинки в мультимодальных системах почти всегда рисует не авторегрессия. Чтобы понять почему, сначала точно скажем, что такое LLM.
На пальцах. Словарь {а, б}, длина 2. Модель выдаёт p(а) = 0.6 и p(б | а) = 0.3. Тогда p(аб) = 0.6·0.3 = 0.18.
Вероятность любой из четырёх строк считается точно, умножением.
- LLM моделирует явную факторизацию
p(x) = Π_{t=1..T} p(x_t | x_<t)(цепное правило, верное для любого распределения). Кросс-энтропия по позициям (неделя 4) равна ровно−log p(x). Цена: генерация занимаетTпоследовательных шагов - Остальные семейства иначе отвечают на два вопроса: что учит модель и как получить из неё образец
| Семейство | Что моделирует | Как сэмплирует | Правдоподобие |
|---|---|---|---|
| Авторегрессия | вероятность следующего токена при префиксе | токен за токеном, T шагов | точное |
| VAE (вариационный автоэнкодер) | кодер в латент z и декодер из z ~ N(0, I) в данные | взять z, один проход декодера | нижняя оценка (ELBO) |
| Диффузия | шумоподавитель: какой шум подмешан на уровне t | от чистого шума, M шагов очищения | нижняя оценка |
| Flow matching | поле скоростей v(x, t) от шума к данным | решить ОДУ, от 1 до десятков шагов | через ОДУ, дорого |
| GAN (генеративно-состязательная сеть) | генератор без плотности плюс дискриминатор | один проход генератора | нет |
| EBM (энергетическая модель) | энергию U(x), p(x) ∝ exp(−U(x)) | MCMC (блуждание, сходящееся к p), много шагов | до константы |
Softmax из недели 4 это EBM на конечном множестве: логиты служат минус энергиями, а статсумму можно посчитать.
Диффузия (DDPM, Ho et al., 2020). На пальцах. Один «пиксель» x₀ = 3, уровень шума с ᾱ = 0.64 (доля сигнала по дисперсии).
Зашумлённая версия: x_t = √0.64·3 + √0.36·ε = 2.4 + 0.6·ε, ε ~ N(0, 1). Выпало ε = −1, получили x_t = 1.8.
Модель видит 1.8 и номер уровня и угадывает ε. Угадала −1: чистое значение восстанавливается, (1.8 + 0.6)/0.8 = 3.
0.64 + 0.36 = 1, поэтому у данных с дисперсией 1 зашумлённая версия тоже с дисперсией 1, а на последнем уровне остаётся чистый N(0, 1).
- Прямой процесс:
x_t = √ᾱ_t·x₀ + √(1 − ᾱ_t)·ε,ᾱ_tубывает от почти 1 до почти 0. Любой уровень получается одним шагом - Обучение: случайный уровень, случайный
ε, лосс‖ε − ε_θ(x_t, t)‖². Обычная MSE-регрессия, без состязания и без MCMC - Генерация: старт из
N(0, I), затемMраз (M: число шагов) вычесть предсказанный шум и подмешать немного свежего (в DDPM сотни шагов, быстрые сэмплеры доводят до десятков). Все позиции очищаются одновременно, порядка «слева направо» нет - Условие (текст) входит в шумоподавитель через cross-attention. Classifier-free guidance: смешивают предсказания с условием и без него и сдвигаются дальше в сторону условного
Латентная диффузия (Rombach et al., 2022). Картинка 512×512×3 это 786 432 числа. Автоэнкодер (VAE из таблицы) сжимает её
в латент 64×64×4, то есть в 16 384 числа, в 48 раз меньше, и диффузия идёт в латентах; декодер один раз возвращает пиксели.
Мелкие детали берёт на себя автоэнкодер, дорогая итеративная часть работает с сутью. Родственная идея: VQ-коды
(номера векторов из выученного словаря) как «визуальные токены», которые можно генерировать авторегрессией.
Маскированная диффузия для текста (MDLM, Sahoo et al., 2024; LLaDA, Nie et al., 2025). На пальцах. Шум для текста
не гауссиана, а маска. Уровень t = 0.5: из 8 токенов закрыто 4, модель предсказывает все 4 сразу, CE считается по закрытым.
Генерация: 8 масок, за 4 шага раскрываем по 2 токена, в которых модель увереннее всего.
- Отличие от BERT (энкодер, которого учат угадывать закрытые токены): там закрыта фиксированная доля, около 15%, а здесь уровень случаен от 0 до 1, и модель умеет стартовать с полностью закрытой строки, то есть генерировать. Плюсы: внимание в обе стороны, несколько токенов за шаг, правка середины. Минусы: привычного KV-кэша нет, правдоподобие только снизу
Flow matching (Lipman et al., 2023; rectified flow, Liu et al., 2023). На пальцах. Шум z = −2, данные x = 4.
Соединим прямой: x_t = (1 − t)·z + t·x; при t = 0.25 точка −0.5, скорость на всём пути x − z = 6.
Модель v_θ(x_t, t) учится MSE предсказывать эту скорость. Генерация: взять шум и решить dx/dt = v_θ(x, t) методом Эйлера.
Одной паре хватило бы одного шага −2 + 6 = 4, но прямые разных пар пересекаются, модель выучивает их среднее,
и пути изгибаются, поэтому шагов несколько. Диффузию тоже можно записать как ОДУ: flow matching просто выбирает пути попроще.
- Вывод: текст держится за авторегрессию из-за точного правдоподобия, KV-кэша и дискретности. Диффузия сильна там, где данные непрерывны и все позиции связаны (пиксели, звук). Маскированная диффузия пробует отвоевать текст параллельной генерацией
Часть 4. Длинный контекст
На пальцах. Голова H = 128, база Θ = 10 000. Самая быстрая пара RoPE поворачивается на 1 радиан за позицию:
полный круг каждые ~6 позиций, и за обучение она видит все углы. Самая медленная делает оборот примерно за 54 000 позиций.
При обучении на 4096 токенах она успевает повернуться лишь на ~27°. На позиции 16 384 угол будет ~108°, такого модель не видела.
Position interpolation делит позиции на 4: углы снова в пределах 27°,
но соседние токены теперь отличаются на четверть шага, в том числе у быстрых пар.
- Из недели 7: медленные пары RoPE за всё обучение не успевают сделать полный оборот. Вывод: за пределами обучающей длины ломаются именно они: их углы вне распределения, а быстрые пары видели все углы
- Position interpolation: сжать позиции
m → m·L/L', тогда углы в пределах виденного, но быстрые частоты теряют разрешение между соседями. УвеличениеΘ(NTK-aware) растягивает медленные частоты сильнее быстрых. YaRN задаёт разные правила для разных частотных диапазонов плюс поправка температуры внимания - Перплексия на длинном тексте не доказывает использования контекста. Нужны needle-in-a-haystack (спрятать факт в длинном тексте и спросить о нём) и RULER (набор синтетических задач на длинный контекст); «Lost in the Middle»: извлечение хуже из середины
Код → nanolm/vit.py: минимальный ViT-энкодер: patchify, CLS-токен (дополнительный токен,
чей выход служит представлением всей картинки),
выученные позиционные эмбеддинги, двунаправленное внимание. Проверка:
pytest tests/test_vit.py -v; ключевой тест test_linear_patch_embedding_equals_strided_conv:
линейный слой над вытянутыми патчами и Conv2d со stride = P дают одно и то же.
scripts/rope_extrapolation.py: обучить на окнах длины S, замерить перплексию
на S и 2S отдельно для позиций < S и ≥ S, затем повторить с базой Θ ×4 и ×8.
Средняя перплексия по окну разрыв прячет; видно его только по позициям.
Математика (трек D): D31: контрастный лосс и температура; D32: coupon collector.
Интервью-вопрос недели: «Модель обучена на 4k, нужен контекст 32k. Что делаешь?»
Структура: диагноз (медленные частоты RoPE вне распределения) → варианты
(PI, увеличение Θ, YaRN) → короткое дообучение на длинных документах →
стоимость (KV-кэш ×8; внимание: FlashAttention, GQA) → проверка не перплексией,
а поиском по позициям.
Источники: Dosovitskiy et al., ViT (2020); Radford et al., CLIP (2021); Liu et al., LLaVA (2023); Chen et al., Positional Interpolation (2023); Peng et al., YaRN (2023); Liu et al., Lost in the Middle (2023); Kingma & Welling, Auto-Encoding Variational Bayes (2013); Goodfellow et al., GAN (2014); Ho et al., DDPM (2020); Rombach et al., Latent Diffusion (2022); Lipman et al., Flow Matching (2023); Sahoo et al., MDLM (2024); Nie et al., LLaDA (2025).
Глубже: 05-ГЛУБИНА, разделы «★★ Недели 16 и 20. Генеративные модели за пределами авторегрессии» и «Что ещё добавить по мелочи».
Результаты недели
- Могу реализовать ViT-энкодер с нуля и посчитать число токенов и стоимость внимания для заданного разрешения.
- Могу записать лосс CLIP и объяснить, почему размер батча равен числу негативов.
- Могу сравнить проектор, cross-attention и Q-Former по числу токенов и стоимости за 3 минуты.
- Могу объяснить, какие частоты RoPE ломаются при экстраполяции, и показать это замером перплексии по позициям.
- Могу сравнить авторегрессию, VAE, диффузию, flow matching, GAN и EBM: что моделирует каждое семейство и как сэмплирует.
Самопроверка
- Почему у ViT квадратичная зависимость стоимости от разрешения, а не линейная?
- Чем position interpolation отличается от увеличения
Θи что теряет каждый способ? - Почему хорошая перплексия на 32k ещё не значит, что модель использует контекст?
- Почему LLM даёт точное правдоподобие строки, а диффузия только нижнюю оценку? Чем за точность платит LLM?
Mock-интервью недели (3 и 4 из 12). (3) ML coding, сессия B: генерация с KV-кэшем и проверка совпадения с полным проходом. (4) Дизайн эксперимента, сессия C: «Пользуется ли модель контекстом длиннее 32k или только не ломается на нём?»