Умножение матриц с помощью np.matmul и @
Корректно перемножайте матрицы с помощью np.matmul и оператора @, отличая поэлементное умножение * от настоящего матричного умножения
«Умножение матриц с помощью np.matmul и @» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Зачем нужно умножение матриц
Умножение матриц лежит в основе анализа данных и машинного обучения. Оно используется в нейронных сетях, снижении размерности и линейных преобразованиях. В Python NumPy предоставляет два удобных способа перемножать матрицы: функцию np.matmul() и оператор @, появившийся в Python 3.5. Оба способа работают быстро, используют векторизацию и значительно эффективнее вложенных циклов Python.
Правила умножения матриц
Для двух матриц A и B произведение A @ B допустимо только тогда, когда число столбцов в A равно числу строк в B. Если A имеет форму (m, n), а B — форму (n, k), результат будет иметь форму (m, k). Это правило называется ограничением внутренних размерностей и действует независимо от используемой функции NumPy.
import numpy as np
A = np.array([[1, 2], [3, 4]]) # shape (2, 2)
B = np.array([[5, 6], [7, 8]]) # shape (2, 2)
C = A @ B
print(C) # [[19 22] [43 50]]np.matmul и оператор @
np.matmul(A, B) и A @ B дают одинаковые результаты для двумерных массивов. Оператор @ — всего лишь синтаксический сахар: за кулисами он вызывает __matmul__, который NumPy реализует с помощью той же процедуры BLAS на уровне C. Используйте @ в обычном коде для удобства чтения, а np.matmul — когда нужно передать функцию как вызываемый объект или явно обработать особые случаи.
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print(np.matmul(A, B)) # same as A @ B
print(A @ B) # same resultРазличия между @, * и np.dot
В NumPy есть три функции умножения, которые легко перепутать. A * B — это поэлементное умножение (произведение Адамара). np.dot(A, B) ведёт себя как np.matmul для двумерных массивов, но имеет другую семантику для массивов большей размерности. A @ B — это именно матричное умножение, строго соответствующее математическому определению; для работы с матрицами предпочтительнее использовать его, а не np.dot.
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[5, 6], [7, 8]])
print('element-wise:', A * B) # [[5 12] [21 32]]
print('matmul:', A @ B) # [[19 22] [43 50]]Умножение матриц не является коммутативным
В отличие от умножения скаляров, матричное умножение не является коммутативным: A @ B обычно не равно B @ A. Формы матриц могут быть несовместимы даже в одном из направлений. Это важно при записи преобразований: порядок операций меняет результат. Всегда отслеживайте, какая матрица находится слева, а какая — справа.
import numpy as np
A = np.array([[1, 2], [3, 4]])
B = np.array([[0, 1], [1, 0]])
print('A @ B:', A @ B) # [[2 1] [4 3]]
print('B @ A:', B @ A) # [[3 4] [1 2]] -- different!Пакетное умножение матриц
Когда Ваши массивы имеют более двух измерений, np.matmul и @ рассматривают дополнительные ведущие измерения как пакетные измерения и перемножают матрицы параллельно. Например, умножение массива формы (32, 3, 4) на массив формы (32, 4, 5) даёт результат формы (32, 3, 5) — одновременно выполняются 32 независимых умножения 3×4 @ 4×5. Именно так фреймворки глубокого обучения эффективно обрабатывают мини-пакеты.
import numpy as np
batch_A = np.random.rand(32, 3, 4)
batch_B = np.random.rand(32, 4, 5)
result = batch_A @ batch_B
print(result.shape) # (32, 3, 5)Умножение матрицы на вектор
Распространённый частный случай — умножение матрицы на вектор. Если A имеет форму (m, n), а v — это одномерный массив длины n, то A @ v создаёт одномерный массив длины m. NumPy автоматически согласует формы, поэтому преобразовывать v в вектор-столбец не нужно. Этот шаблон встречается повсюду: при применении весов в линейной регрессии, проецировании признаков и одновременном вычислении скалярных произведений для каждой строки.
import numpy as np
A = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
v = np.array([1, 0, -1]) # (3,)
print(A @ v) # [1-3, 4-6] = [-2, -2]Производительность: @ и циклы Python
Матричное умножение NumPy вызывает оптимизированные процедуры BLAS/LAPACK и выполняется в скомпилированном коде C. Чистый вложенный цикл Python, реализующий ту же операцию, обычно работает в 100–1000 раз медленнее на больших матрицах. Если в pipeline обработки данных нужны повторяющиеся произведения матриц — для преобразования признаков, проекций PCA или обновления весов, — всегда используйте @ или np.matmul и никогда не реализуйте внутренний цикл самостоятельно.
import numpy as np, time
A = np.random.rand(500, 500)
B = np.random.rand(500, 500)
t0 = time.time()
C = A @ B
print(f'NumPy: {(time.time()-t0)*1000:.1f} ms') # single-digit msЦепочки произведений нескольких матриц
Можно объединить несколько операций @ в одном выражении: A @ B @ C вычисляется слева направо. NumPy не оптимизирует порядок умножения автоматически (в отличие от MATLAB с его mtimes), поэтому при сильно различающихся размерах матриц порядок может влиять на скорость. Для трёх и более матриц рассмотрите np.linalg.multi_dot([A, B, C]): эта функция автоматически выбирает наиболее эффективную группировку.
import numpy as np
A = np.random.rand(100, 20)
B = np.random.rand(20, 50)
C = np.random.rand(50, 10)
result = np.linalg.multi_dot([A, B, C])
print(result.shape) # (100, 10)Распространённые ошибки форм и способы их исправления
Самая распространённая ошибка при умножении матриц — несовпадение форм: ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0. Чтобы исправить её, проверьте формы с помощью A.shape и убедитесь, что внутренние размерности совпадают. Если у Вас есть вектор-строка формы (n,), который нужно рассматривать как вектор-столбец формы (n, 1), используйте v.reshape(-1, 1). Если нужна транспонированная матрица, используйте A.T.
import numpy as np
A = np.ones((3, 4))
B = np.ones((3, 4)) # wrong -- inner dims 4 != 3
try:
A @ B
except ValueError as e:
print('Error:', e)
print('Fix:', (A @ B.T).shape) # (3, 3)Практический пример: преобразование признаков
Типичный пример из анализа данных: у Вас есть набор данных X формы (n_samples, n_features) и матрица весов W формы (n_features, n_outputs). Произведение матриц X @ W одновременно применяет линейное преобразование к каждому образцу и создаёт результат формы (n_samples, n_outputs). Это основное вычисление линейного слоя нейронной сети и прогнозирования в линейной регрессии.
import numpy as np
n_samples, n_features, n_outputs = 200, 10, 3
X = np.random.rand(n_samples, n_features)
W = np.random.rand(n_features, n_outputs)
b = np.zeros(n_outputs)
predictions = X @ W + b # shape (200, 3)
print(predictions.shape)Быстрая проверка
Проверьте своё понимание матричного умножения NumPy.
Повторение урока
В этом уроке Вы узнали, что np.matmul и @ реализуют настоящее матричное умножение, а не поэлементное; внутренние размерности двух матриц должны совпадать; и @ поддерживает пакетное умножение по ведущим измерениям. Далее мы рассмотрим определители, обратные матрицы и транспонирование — операции, которые показывают, можно ли «отменить» преобразование матрицы.
Часто задаваемые вопросы
Урок «Умножение матриц с помощью np.matmul и @» бесплатный?
Да — полный текст урока «Умножение матриц с помощью np.matmul и @» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Умножение матриц с помощью np.matmul и @»?
Корректно перемножайте матрицы с помощью np.matmul и оператора @, отличая поэлементное умножение * от настоящего матричного умножения Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Умножение матриц с помощью np.matmul и @»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Умножение матриц с помощью np.matmul и @
- Определители, обратные матрицы и транспонирование
- Решение систем линейных уравнений
- Собственные значения и обзор SVD