Линейная алгебра
Операции с матрицами
Обучение нейросети - это миллиарды операций сложения и умножения матриц на GPU. Каждый шаг forward pass - несколько матричных умножений. Без понимания базовых операций с матрицами невозможно разобраться в архитектуре ни одной современной модели.
- Нейросеть: каждый слой - умножение матрицы весов на батч входных векторов
- Компьютерная графика: преобразование координат - умножение на матрицу Model-View-Projection
- Физика: оператор поворота - матрица 3x3, применяется к каждому вектору
- Статистика: ковариационная матрица - основа PCA и многомерного анализа
- Оптимизация: матрица Гессе задаёт кривизну функции потерь
Операции с матрицами
Каждый проход ResNet-50 через одну картинку - это больше **25 миллионов** операций с матрицами. Каждый токен GPT-4 - умножение на матрицы размером ~12 288 × 12 288. Операции с матрицами - это не абстрактная алгебра, это буквально то, что делает GPU прямо сейчас, пока генерируется ответ ChatGPT. Разберёмся, что именно происходит.
**Три операции, которые нужно знать наизусть**: сложение матриц (residual connections в ResNet), умножение на скаляр (learning rate применяется к матрице градиентов), перемножение матриц (каждый линейный слой нейросети). Транспонирование - ключ к backprop и механизму attention.
Что главное в концепте «Операции с матрицами»?
Проверка усвоения материала концепта.
Сложение матриц: как работают residual connections
Сложение матриц: как работают residual connections
Складывать можно только матрицы **одинакового размера**. Элементы складываются поэлементно - i-й с i-м, j-й с j-м. Формула проста:
(A + B)_{ij} = a_{ij} + b_{ij} Пример: ┌ ┐ ┌ ┐ ┌ ┐ │ 1 2 │ + │ 5 6 │ = │ 6 8 │ │ 3 4 │ │ 7 8 │ │ 10 12 │ └ ┘ └ ┘ └ ┘ Одинаковые позиции складываются: 1+5=6, 2+6=8, 3+7=10, 4+8=12
Именно эта операция лежит в основе **residual connections** в ResNet. Идея Хе и соавторов (2015): вместо того чтобы слой учил полное преобразование H(x), пусть учит только остаток F(x) = H(x) - x. Тогда выход блока:
Обычный слой: y = H(x) Residual block: y = F(x) + x Где F(x) - выход двух свёрточных слоёв, x - исходный вход (shortcut connection) x (вход, shape [B, C, H, W]) │ ├──────────────────────┐ │ │ Conv → BN → ReLU │ shortcut Conv → BN │ │ │ └──────── + ───────────┘ │ output = F(x) + x ← матричное сложение! Результат: градиенты текут напрямую через shortcut. Именно это позволило обучать сети глубиной 152 слоя.
**Контр-интуитивный факт**: ResNet-50 содержит 16 таких residual-блоков. В каждом - одно матричное сложение. Это простейшая операция вида A + B, но именно она позволила обучать сети глубиной 100+ слоёв, что было невозможно до 2015 года.
Что главное в концепте «Сложение матриц: как работают residual connections»?
Проверка усвоения материала концепта.
Умножение на скаляр: learning rate в действии
Умножение на скаляр: learning rate в действии
Умножение матрицы на число - каждый элемент умножается на этот скаляр. Направление матрицы не меняется, масштаб меняется:
(k · A)_{ij} = k · a_{ij} Пример (k = 3): ┌ ┐ ┌ ┐ 3 · │ 1 2 │ = │ 3 6 │ │ 3 4 │ │ 9 12│ └ ┘ └ ┘
В машинном обучении это происходит на каждом шаге обучения. Градиентный спуск обновляет веса матрицы W по формуле:
W_new = W_old - lr * grad_W Где: W_old - матрица весов до шага [768 × 3072 в BERT] lr - learning rate (скаляр, например 0.001) grad_W - матрица градиентов того же размера [768 × 3072] lr * grad_W - это умножение матрицы 768×3072 на скаляр 0.001 Для BERT: 768 × 3072 = 2 359 296 умножений за один параметр. В BERT-base таких слоёв 12, и ещё attention, embedding... → ~110 миллионов параметров обновляются за один batch.
Что главное в концепте «Умножение на скаляр: learning rate в действии»?
Проверка усвоения материала концепта.
Перемножение матриц: сердце нейросети
Перемножение матриц: сердце нейросети
~Матрица~{Прямоугольный массив чисел m строк на n столбцов} A размером m × n умножается на матрицу B размером n × p. Результат - матрица размером m × p. Внутренние размерности должны совпасть - это правило без исключений.
(AB)_{ij} = сумма_{k=1}^{n} a_{ik} * b_{kj} Пример: A (2×3) умножить на B (3×2) = результат (2×2) ┌ ┐ ┌ ┐ A = │ 1 2 3 │ │ 7 8 │ │ 4 5 6 │ · │ 9 0 │ = C └ ┘ │11 2 │ └ ┘ C[0,0] = 1*7 + 2*9 + 3*11 = 7 + 18 + 33 = 58 C[0,1] = 1*8 + 2*0 + 3*2 = 8 + 0 + 6 = 14 C[1,0] = 4*7 + 5*9 + 6*11 = 28+ 45 + 66 = 139 C[1,1] = 4*8 + 5*0 + 6*2 = 32+ 0 + 12 = 44 ┌ ┐ C = │ 58 14 │ │ 139 44 │ └ ┘
Элемент C[i,j] - это **скалярное произведение** i-й строки матрицы A на j-й столбец матрицы B. Весь механизм attention в трансформерах основан именно на этом: QK^T - это матричное умножение, где каждый элемент результата - сходство i-го запроса с j-м ключом.
Умножение матриц **не коммутативно**: AB не равно BA. В общем случае BA может вообще не существовать (размерности не совпадут). В нейросетях порядок матриц критичен: W @ x - это линейный слой, x @ W - это другая операция с другой семантикой.
Свойства, которые выполняются:
- **Ассоциативность**: (AB)C = A(BC) - можно скобки переставлять
- **Дистрибутивность**: A(B + C) = AB + AC
- **Со скаляром**: k(AB) = (kA)B = A(kB)
- **Единичная матрица**: AI = IA = A
Что главное в концепте «Перемножение матриц: сердце нейросети»?
Проверка усвоения материала концепта.
Транспонирование: backprop и механизм attention
Транспонирование: backprop и механизм attention
~Транспонирование~{Операция замены строк и столбцов местами: (A^T)[i,j] = A[j,i]} - отражение матрицы относительно главной диагонали. Строки становятся столбцами, размер меняется с m × n на n × m.
┌ ┐ ┌ ┐ A = │ 1 2 3 │ A^T = │ 1 4 │ │ 4 5 6 │ │ 2 5 │ └ ┘ │ 3 6 │ └ ┘ 2×3 → 3×2 Формула: (A^T)_{ij} = A_{ji}
В механизме **self-attention** трансформера вычисляется QK^T - произведение матрицы запросов Q и транспонированной матрицы ключей K. Это даёт матрицу размером [seq_len × seq_len], где каждый элемент - сходство между двумя токенами.
Q: [seq_len, d_k] - запросы (queries) K: [seq_len, d_k] - ключи (keys) K^T: [d_k, seq_len] - транспонирование QK^T: [seq_len, seq_len] - матрица сходств Пример для seq_len=4, d_k=64: Q @ K.T -> матрица 4×4 ┌ ┐ │ s00 s01 s02 s03 │ s_ij = сходство токенов i и j │ s10 s11 s12 s13 │ │ s20 s21 s22 s23 │ │ s30 s31 s32 s33 │ └ ┘ Затем softmax → attention weights → умножить на V
Свойства транспонирования - три правила, которые нужно знать:
- $(A^T)^T = A$ - двойное транспонирование возвращает исходную матрицу
- $(A + B)^T = A^T + B^T$ - транспонирование суммы
- $(AB)^T = B^T A^T$ - **порядок меняется!** Это критично в backprop
Правило $(AB)^T = B^T A^T$ - это то, почему backpropagation работает именно так, как работает. При вычислении градиента по весам W приходится транспонировать матрицы активаций. Без этого правила вывод backprop не сходился бы.
Что главное в концепте «Транспонирование: backprop и механизм attention»?
Проверка усвоения материала концепта.
Специальные матрицы в ML
Специальные матрицы в ML
| Тип | Свойство | Где встречается в ML |
|---|---|---|
| Симметричная | A = A^T | Ковариационная матрица в PCA; матрица Гессе в оптимизации |
| Диагональная | a_ij = 0 при i != j | Scaling layer; диагональные аппроксимации Hessian (AdaGrad) |
| Ортогональная | A^T A = I | Матрицы поворота; инициализация весов (orthogonal init) |
| Верхнетреугольная | a_ij = 0 при i > j | LU-разложение; causal mask в autoregressive трансформерах |
**Causal mask в GPT** - это верхнетреугольная матрица из -inf, которая добавляется к матрице scores в attention перед softmax. Токен не должен смотреть в будущее - нижний треугольник заблокирован. Формально: ещё одна операция сложения матриц.
Что главное в концепте «Специальные матрицы в ML»?
Проверка усвоения материала концепта.
GPU как машина матричных умножений
GPU как машина матричных умножений
NVIDIA A100 выполняет **312 TFLOPS** операций с матрицами (tensor cores, FP16). Это 312 триллионов умножений в секунду. Весь дизайн современных GPU оптимизирован под одну операцию - **GEMM** (General Matrix Multiplication). Pytorch, TensorFlow, JAX - всё это в конечном счёте вызывает cuBLAS GEMM.
Где матричные операции работают прямо сейчас
Каждая из этих систем - это матричные операции под капотом
| Компонент | Роль | Детали |
|---|---|---|
| GPT-4 / Claude | Linear layers + attention (QK^T) | Каждый токен - умножение на матрицы [12288 x 12288]. Сотни миллиардов параметров. |
| ResNet / YOLO / CLIP | Conv + residual connections (F(x) + x) | ResNet-50: 25M параметров, 4.1 GFLOPs на одну картинку |
| Stable Diffusion | U-Net + cross-attention | Каждый denoising step: сотни матричных умножений в U-Net и attention |
| Gradient descent (Adam, SGD) | W = W - lr * grad_W | Скалярное умножение матрицы градиентов - происходит на каждом batch |
Что главное в концепте «GPU как машина матричных умножений»?
Проверка усвоения материала концепта.
Практика: Instagram sepia-фильтр
Практика: Instagram sepia-фильтр
Вопросы для собеседования
Почему в residual connections используется именно сложение матриц (F(x) + x), а не, например, конкатенация?
- При сложении градиент течёт напрямую через shortcut без затухания - это решает проблему vanishing gradients - Конкатенация удваивает размерность - нужен дополнительный слой чтобы вернуть исходный размер - Сложение не добавляет параметров, конкатенация требует дополнительный Linear слой - DenseNet использует конкатенацию - это другой подход с другими компромиссами
Матрица Q имеет форму [seq_len, d_k], матрица K имеет форму [seq_len, d_k]. Почему в attention вычисляется Q @ K.T, а не Q @ K?
- Q @ K невозможно: [seq_len, d_k] @ [seq_len, d_k] - внутренние размерности не совпадают - Q @ K.T: [seq_len, d_k] @ [d_k, seq_len] = [seq_len, seq_len] - матрица попарных сходств - Элемент [i,j] результата = скалярное произведение i-го запроса и j-го ключа = сходство токенов i и j - Масштабирование на 1/sqrt(d_k) нужно чтобы dot products не становились слишком большими при большом d_k
Почему порядок в правиле (AB)^T = B^T A^T меняется?
- A: [m, n], B: [n, p] -> AB: [m, p] -> (AB)^T: [p, m] - B^T: [p, n], A^T: [n, m] -> B^T A^T: [p, m] - размерности совпадают - A^T B^T: [n, m] @ [p, n] - умножение невозможно, размерности не совпадают - Это правило прямо применяется в backprop: grad_input = W^T @ grad_output
Что главное в концепте «Практика: Instagram sepia-фильтр»?
Проверка усвоения материала концепта.
Что унести из урока
- **Сложение** A + B: поэлементно, только одинаковые размеры - основа residual connections в ResNet
- **Скалярное умножение** k*A: каждый элемент на k - именно так learning rate применяется к градиентам
- **Матричное умножение** AB: внутренние размерности должны совпасть; [m,n]@[n,p]=[m,p] - основа Linear слоёв
- **Транспонирование** A^T: строки и столбцы меняются местами; (AB)^T = B^T A^T с переворотом порядка
- **AB не равно BA** - порядок матриц имеет значение; в нейросетях это всегда так
- **QK^T** в attention - транспонирование K обязательно для правильных размерностей матрицы сходств
- **GPU = машина GEMM** - весь deep learning сводится к одной операции матричного умножения
Куда дальше
Операции с матрицами - строительный блок для более сложных концепций
- Матрицы: что они делают? — Геометрический смысл матрицы как трансформации пространства
- Обратная матрица — Операция, обратная умножению - нормальное уравнение в линейной регрессии
- Собственные векторы и SVD — Что происходит с матрицей при многократном умножении - PCA и LoRA