NumPy 矩阵相乘

在线性代数中,矩阵相乘(又称矩阵乘法)是一种核心运算,需满足特定维度条件:若矩阵 A 的维度为 (m, n),矩阵 B 的维度为 (n, p),则它们的乘积 AB 的维度为 (m, p)。

其中,矩阵相乘具有以下性质:

  • 矩阵相乘不满足交换律,即 AB ≠ BA。
  • 矩阵相乘满足结合律,即 (AB)C = A(BC)。
  • 矩阵相乘满足分配律,即 A(B+C) = AB + AC。

NumPy 提供了 3 种矩阵相乘的方法,适用于不同的场景。

NumPy 矩阵相乘的方法
方法 说明
numpy.dot() 计算两个数组的点积
numpy.matmul() 计算两个数组的矩阵乘积
ndarray @ ndarray 计算两个数组的矩阵乘积,等价于 numpy.matmul()

在实际开发中,我们应该遵循以下 2 个最佳实践:

  • 优先使用 matmul() 函数或 “@” 运算符来执行矩阵运算,避免 dot() 函数在复杂维度下的意外行为。
  • 处理向量时,显式使用 reshape() 方法可以确保维度正确(如将一维数组转为二维行 / 列向量)。

numpy.dot() 实现矩阵相乘

在 NumPy 中,我们可以使用 dot() 函数来计算两个数组的点积。dot() 函数的行为取决于输入的维度:

  • 一维数组:计算向量内积(等价于标量积)。
  • 二维数组:标准的矩阵乘法。
  • 高维数组(≥3)​:按最后一个轴与倒数第二个轴进行乘积。

语法:

numpy.dot(arr1, arr2, out=None)

说明:

dot() 函数接收以下 3 个参数。

  • arr1(必选):第 1 个输入数组。
  • arr2(必选):第 2 个输入数组。
  • out(可选):用于指定输出数组(需与结果维度匹配)。

示例 1:二维矩阵相乘(标准用法)

import numpy as np

a = np.array([[1,2], [3,4]])
b = np.array([[5,6], [7,8]])
result = np.dot(a, b)

print(result)

运行结果如下。

[[19 22]
 [43 50]]

示例 2:一维向量内积

import numpy as np

a = np.array([1, 2])
b = np.array([3, 4])
result = np.dot(a, b)

print(result)

运行结果如下。

11

分析:

当输入是一维数组时,dot() 会计算它们的内积,其结果为一个标量(即一个单一的数值):1*3 + 2*4 = 11。

示例 3:三维张量积(广播规则)

import numpy as np

a = np.ones((2, 3, 4))
b = np.ones((2, 4, 5))
result = np.dot(a, b).shape

print(result)

运行结果如下。

(2, 3, 2, 5)

分析:

在这个例子中,dot() 函数会将最后一个轴(4)与第二个数组的倒数第二个轴(4)相乘,从而生成四维数组(2, 3, 2, 5)。

numpy.matmul() 实现矩阵相乘

在 NumPy 中,我们还可以使用 matmul() 函数来计算两个数组的矩阵乘积。

语法:

numpy.matmul(arr1, arr2, out=None)

说明:

matmul() 函数常用参数有以下 3 个。

  • arr1(必选):第 1 个输入数组。
  • arr2(必选):第 2 个输入数组。
  • out(可选):用于指定输出数组。

matmul() 是专用的矩阵乘法函数,它严格遵循线性代数规则:

  • 不支持标量乘法:输入必须是至少二维数组
  • 批量处理:若输入为三维数组(如形状为 (k, m, n) 和 (k, n, p)),则返回形状为 (k, m, p) 的数组。
  • 广播规则:允许数组在非矩阵维度上广播(如形状为 (m, n) 和 (n, p) 的数组可与 (j, m, n) 和 (j, n, p) 广播)。

示例 4:标准二维矩阵乘法

import numpy as np

a = np.array([[1,2], [3,4]])
b = np.array([[5,6], [7,8]])
result = np.matmul(a, b)

print(result)

运行结果如下。

[[19 22]
 [43 50]]

分析:

np.matmul(a, b) 与 np.dot(a, b) 结果是一样的。

示例 5:批量矩阵乘法(三维数组)

import numpy as np

a = np.array([[[1,2], [3,4]], [[5,6], [7,8]]])           # 形状:(2, 2, 2)
b = np.array([[[9,10], [11,12]], [[13,14], [15,16]]])    # 形状:(2, 2, 2)
result = np.matmul(a, b)

print(result.shape)    # 形状
print(result[0])       # 第一个批量结果

运行结果如下。

(2, 2, 2)
[[31 34]
 [71 78]]

分析:

matmul() 会将两个 2×2×2 的数组看作是两个 “批次” 的 2×2 矩阵。它分别计算第一个批次的 a[0] 和 b[0] 的乘积,以及第二个批次的 a[1] 和 b[1] 的乘积,并将结果合并成一个形状为 (2, 2, 2) 的新数组。

示例 6:自动广播

import numpy as np

a = np.array([[1,2], [3,4]])          # (2, 2)
b = np.array([[[5,6], [7,8]]])        # (1, 2, 2)
result = np.matmul(a, b).shape

print(result)

运行结果如下。

(1, 2, 2)

分析:

当形状 (2, 2) 与 (1, 2, 2) 的矩阵进行相乘时,前者会被广播为 (1, 2, 2),因此最终结果的形状为 (1, 2, 2)。

对于广播规则是怎样的,我们在后续的 “NumPy 广播机制” 一节中会详细介绍。

“@” 实现矩阵相乘

在 NumPy 中,我们还可以使用 “@” 运算符来计算两个数组的矩阵乘积。

语法:

ndarray @ ndarray

说明:

这里的 ndarray 指的是 ndarray 对象。

提示: @ 是 Python 3.5+ 引入的矩阵乘法运算符,它与 matmul() 函数是完全等价的。你可以将其看成是 matmul() 函数的 “语法糖”,主要用于提高代码的可读性。

示例 7:@ 运算符的基本用法

import numpy as np

arr1 = np.array([[1, 2], [3, 4]])
arr2 = np.array([[5, 6], [7, 8]])
arr3 = arr1 @ arr2         # 矩阵相乘

print(arr3)

运行结果如下。

[[19 22]
 [43 50]]

分析:

arr1 @ arr2 的结果与 numpy.matmul(arr1, arr2) 完全相同,但语法更简洁,也更直观。在实际开发中,如果想要进行矩阵乘法,我们更加推荐使用 “arr1 @ arr2” 这种方式。

上一篇: NumPy 对角矩阵

下一篇: NumPy 逆矩阵

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号