前言
np.dot() 和 np.matmul() 这两个函数一直困惑了我好久,他们之间的区别到底在哪?
其实在有二维数组参与运算时,他们的运算结果是一样的,区别就在于一维与一维的内积。另外在有一维数组和二维数组混合运算时,时常会将概念混淆,要弄清这个问题,就要分清一维与二维。
一、一维向量与二维数组
首先按我的理解,给出一下概念
- 一维向量:用一对 [ ] 定义
- 二维数组:用两对 [ ] 定义
???这就完了???对,就这么简单!!!
首先你要明确,如果你在程序中打印它们的类型,那么没有任何区别。通过np.array()
定义的 numpy 数组,只有一种类型:<class 'numpy.ndarray'>
。
但是你要是打印他们的 shape
,区别立刻显现,请看。
A = np.array([1, 2, 3])
B = np.array([[1, 2, 3]])
C = np.array([[1, 2, 3], [4, 5, 6]])
print("A:", A.shape) # A: (3,)
print("B:", B.shape) # B: (1, 3)
print("C:", C.shape) # C: (2, 3)
C
毋庸置疑,就是一个 2 * 3 的二维数组,或者说是矩阵。
区别就在 A
B
之间。根据上述定义,A
是向量,B
是数组,区别就在于数组的形状一定是二维及以上。
注意:所有的一维向量,单独看时,都当成是列向量(竖着放的),虽然打印的时候是横着放的。
二、np.dot() 与 np.matmul() 的区别
1维 x 1维
前面已经说过,有二维数组参与运算时没有区别。
但有了前面一维和二维的概念,我想他们从本质上是没有任何区别,即相同。
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])
# print(a.shape) # (3,)
print(a.dot(b)) # 求内积 1*4+2*5+3*6=32 np.dot(a, b) <-> a.dot(a, b)
print(np.matmul(a, b)) # 矩阵乘法 也是三十二
两个一维向量运算,两个函数得到了相同的结果。np.dot() 是求内积毋庸置疑,那何以 np.matmul() 的结果也相同,矩阵乘法的条件(a的列数=b的行数)满足吗?
a,b的shape为 (3, ),计算 a*b
关键就在这一步的转换,不同于上述单独看向量,此处有两个向量相乘,那么:
谁在左边,就在左边添加维度1:a 在左,那么 a 的 shape 运算时为 (1,3)
谁在右边,就在右边添加维度1:b 在右,那么 b 的 shape 运算时为 (3,1)
满足矩阵乘法的条件:(1,3)* (3,1) -> (1, 1)
1维 与 多维 混合
a = np.array([[1, 2, 3], [4, 5, 6]]) # (2, 3)
b = np.array([1, 2, 3]) # (3,)
print(a.dot(b)) # [14 32] (2,3)* (3,1) -> (2,1)
print(np.matmul(a, b)) # [14 32] (2,3)* (3,1) -> (2,1)
# 如果是 b.dot(a)
# b 在左, (1, 3) * (2, 3) 报错
# 如果把 a 换成 (3,2),就可以运算
# 按照上边的变换,可以动手试一下。