Два преобразования подряд
Матрица A удваивает первую координату: A = [[2, 0], [0, 1]]. Матрица B меняет координаты местами: B = [[0, 1], [1, 0]].
Задача: Вы применяете сначала B (поменять местами), потом A (удвоить первую). Что произойдёт с вектором (3, 5)? Какой вектор получится?
Подсказка: сначала примените B к вектору, потом к результату примените A.
Складывать матрицы просто — поэлементно, как векторы. Но умножение — совсем другая история. Почему нельзя просто перемножить элементы на тех же местах? Потому что матрица — это не просто таблица чисел. Это преобразование.
Матрица берёт вектор и превращает его в другой вектор. Поворачивает, растягивает, отражает, сжимает. И умножение матриц — это применение двух преобразований подряд. Начнём с главного: матрица × вектор. Возьмём матрицу A и вектор v:
A = [[2, 1], v = (1, 3)
[0, 3]]
Как получить результат? Берём первую строку матрицы (2, 1) и считаем скалярное произведение с вектором: 2·1 + 1·3 = 5. Это первая компонента результата. Берём вторую строку (0, 3): 0·1 + 3·3 = 9. Это вторая компонента.
A · v = (2·1 + 1·3, 0·1 + 3·3) = (5, 9)
Каждая строка матрицы «допрашивает» вектор через скалярное произведение и выдаёт одно число. Сколько строк — столько компонент в ответе.
Обратите внимание на размеры: матрица 2×2 умножается на вектор из 2 компонент → результат из 2 компонент. Если бы матрица была 3×2, результат имел бы 3 компоненты. Число столбцов матрицы должно совпадать с числом компонент вектора — иначе скалярное произведение не посчитать. Теперь — матрица × матрица. Здесь та же идея: каждый столбец правой матрицы — это вектор. Умножаем левую матрицу на каждый такой вектор по отдельности. Результаты ставим рядом — получается новая матрица.
A = [[1, 2], B = [[5, 7],
[3, 4]] [6, 8]]
Первый столбец B — вектор (5, 6). Умножаем A на него:
A · (5, 6) = (1·5 + 2·6, 3·5 + 4·6) = (17, 39)
Второй столбец B — вектор (7, 8):
A · (7, 8) = (1·7 + 2·8, 3·7 + 4·8) = (23, 53)
Собираем столбцы обратно в матрицу:
A · B = [[17, 23],
[39, 53]]
Можно запомнить иначе: элемент в строке i и столбце j — это скалярное произведение i-й строки левой матрицы и j-го столбца правой.
Теперь ключевой факт: A·B ≠ B·A. Порядок имеет значение.
Вернёмся к задаче. A удваивает первую координату, B меняет координаты местами. Применим к вектору (3, 5):
Сначала B, потом A: (3,5) → (5,3) → (10,3)
Сначала A, потом B: (3,5) → (6,5) → (5,6)
Разные ответы. «Сначала поменять, потом удвоить» — не то же самое, что «сначала удвоить, потом поменять». Это не баг — это фундаментальное свойство. Сложение матриц коммутативно (A + B = B + A). Умножение — нет.
A · B = [[2,1], · [[0,1], = [[1, 2],
[0,3]] [1,0]] [3, 0]]
B · A = [[0,1], · [[2,1], = [[0, 3],
[1,0]] [0,3]] [2, 1]]
A·B ≠ B·A. Когда пишут A·B, это значит: сначала применяется B (правая), потом A (левая). Читается справа налево — как вложенные функции: A(B(v)). Зачем это всё? Потому что матричное умножение — это язык преобразований. Поворот на 30° — матрица. Масштабирование вдвое — матрица. Нужно сделать оба? Перемножьте матрицы — получится одна матрица, делающая оба преобразования сразу.
В компьютерной графике каждый кадр — тысячи вершин, каждую нужно повернуть, масштабировать и сместить. Три матрицы перемножаются один раз, результат применяется к каждой вершине. Одно умножение вместо трёх — на тысячах вершин это решает всё.
В нейронных сетях прохождение сигнала через слой — это умножение матрицы весов на вектор входов. Вся сеть — цепочка таких умножений. Именно поэтому GPU, созданные для графики (то есть для массового матричного умножения), оказались идеальными для машинного обучения.
Матрица × вектор: каждая строка матрицы берёт скалярное произведение с вектором. Матрица m×n × вектор n → вектор m.
Матрица × матрица: элемент (i, j) результата = скалярное произведение i-й строки левой и j-го столбца правой. Размеры: (m×n)·(n×p) = m×p.
Порядок важен: A·B ≠ B·A. Правая матрица применяется первой.
Смысл: умножение матриц = последовательное применение преобразований.