0Pricing
Pandas & NumPy Academy · Урок

Умножение матриц с помощью 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 — локальная установка не требуется.

Все уроки этого курса

  1. Умножение матриц с помощью np.matmul и @
  2. Определители, обратные матрицы и транспонирование
  3. Решение систем линейных уравнений
  4. Собственные значения и обзор SVD
← Назад к Pandas & NumPy Academy