[ Python  Numpy  ]

Numpy 三种乘法的区别:dot/matmul/multiply

Numpy 中有三种常用的乘法:dotmatmulmultiply,对于新手来说很容易混淆三者的用法。

1. multiply: element-wise 乘法

这种乘法也叫 Hadamard productSchur product,在数学上是指“两个矩阵的对应元素相乘”:

但 Numpy 要更复杂一点,它操作的对象是 N 维的数组(或者更常见地叫 Tensor),不单是两个维度的矩阵;并且支持广播 (Broadcasting) 机制。

>>> a = np.array([1, 2, 3])
>>> b = np.array([4, 5, 6])
>>> np.multiply(a, b)
array([ 4, 10, 18])

>>> np.multiply(a, 2)  # 进行了广播
array([2, 4, 6])

Numpy 实现了运算符重载,使用 * 可以代替 np.multiply(),这也是官方推荐的做法。

>>> a * b  # 等价于 np.multiply(a, b)
array([ 4, 10, 18])

2. matmul: 矩阵乘法

这是最常见的矩阵乘法:

np.matmul(a, b) 的操作对象 a, b 只能是多维数组 (array-like),不能是标量 (scalar)。而如果 ab 中有一个的维度是1,即如果是向量,则会进行这样的转换:

运算完成后再去除多余的维度。这样才能进行正常的矩阵运算。

>>> A = np.array([[1, 2], [3, 4]])
>>> B = np.array([[1, 1], [1, 1]])
>>> np.matmul(A, B)
array([[3, 3],
       [7, 7]])

# 发生了维度转换,这和后面要讲的 np.dot 等价
>>> a = np.array([1, 2])
>>> b = np.array([3, 4])
>>> np.matmul(a, b)
11

Numpy 实现了运算符重载,使用 @ 可以代替 np.matmul()

>>> a @ b  # 等价于 np.matmul(a, b)
11

3. dot: 向量点乘

这是数学上的向量点乘:

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

这是它的本意。但实际上对于 np.dot(a, b)

所以 np.dot 的适用性最广,可以完成 np.matmulnp.multiply 的工作。但非常不建议这样做:这会降低代码的可读性!

4. 总结

基于操作对象的不同,应该选用不同的乘法,下面是我总结的用法:

除此之外,Numpy 还提供了其他的一些乘法,如 np.vdot(共轭点乘)、np.tensordot 等不太常见的操作,以后有时间再做整理。

参考

(完)