【Numpy乘法详解】np.multiply()、np.matmul()、np.dot()等

【Numpy乘法详解(代码示例)】np.multiply()、np.matmul()、np.dot()等

1. 介绍

  1. 星号(*):array对应元素相乘,不满足广播的条件则出错、矩阵乘法。
  2. np.multiply():array(matrix)对应元素相乘,不满足广播的条件则出错。
  3. np.matmul():向量点积、矩阵乘法。
  4. 艾特(@):向量点积、矩阵乘法。注意:在numpy中可以使用@来替代np.matmul,下面不做赘述。
  5. np.dot():向量点积、矩阵乘法。

2. 代码示例

2.1 一维数组(np.array__1D)

In [2]: a=np.array([1,2])
In [3]: b=np.array([3,4])

In [4]: a*b
Out[4]: array([3, 8])

In [5]: np.multiply(a,b)
Out[5]: array([3, 8])

In [6]: np.matmul(a,b)
Out[6]: 11

In [7]: np.dot(a,b)
Out[7]: 11

In [8]: a@b
Out[8]: 11

2.2 二维(多维)数组(np.array__xD)

多维数组对于np.dot和np.matual会有一些不同,下面2.4中会举例说明。

2.2.1 满足矩阵乘法,但尺寸不同
In [18]: a = np.array([[0, 1],[2, 3],[4, 5]]) # (3, 2)
In [19]: b = np.array([[0],[1]]) # (2, 1)

In [21]: a*b
---------------------------------------------------------------------------
ValueError: operands could not be broadcast together with shapes (3,2) (2,1)

In [22]: np.multiply(a,b)
---------------------------------------------------------------------------
ValueError: operands could not be broadcast together with shapes (3,2) (2,1)

In [23]: np.matmul(a,b)
Out[23]: 
array([[1],
       [3],
       [5]])

In [24]: np.dot(a,b)
Out[24]: 
array([[1],
       [3],
       [5]])
2.2.2 满足矩阵乘法,且尺寸相同
In [29]: a=np.array([[1,2],[3,4]])	# (2, 2)
In [30]: b=np.array([[0,1],[2,3]])	# (2, 2)

In [33]: a*b
Out[33]: 
array([[ 0,  2],
       [ 6, 12]])

In [34]: np.multiply(a,b)
Out[34]: 
array([[ 0,  2],
       [ 6, 12]])

In [35]: np.matmul(a,b)
Out[35]: 
array([[ 4,  7],
       [ 8, 15]])

In [36]: np.dot(a,b)
Out[36]: 
array([[ 4,  7],
       [ 8, 15]])
2.2.3 不满足矩阵乘法,但尺寸相同
>>> a = np.array([[0, 1],[2, 3],[4, 5]])	#(3, 2)
>>> b = np.array([[0, 1],[2, 3],[4, 5]])	#(3, 2)

>>> a*b
array([[ 0,  1],
       [ 4,  9],
       [16, 25]])

>>> np.multiply(a,b)
array([[ 0,  1],
       [ 4,  9],
       [16, 25]])

>>> np.matmul(a,b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0, with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 3 is different from 2)

>>> np.dot(a, b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<__array_function__ internals>", line 6, in dot
ValueError: shapes (3,2) and (3,2) not aligned: 2 (dim 1) != 3 (dim 0)

2.3 矩阵(np.matrix)

2.3.1 矩阵尺寸不同,但符合矩阵乘法
In [48]: a = np.matrix([[0, 1],
        				[2, 3],
        				[4, 5]])	#(3, 2)
In [49]: b=np.matrix([[0],
					  [1]])			#(2, 1)
# 出现不同!!!!
In [50]: a*b
Out[50]: 
matrix([[1],
        [3],
        [5]])

In [51]: np.multiply(a,b)
---------------------------------------------------------------------------
ValueError: operands could not be broadcast together with shapes (3,2) (2,1)

In [52]: np.matmul(a,b)
Out[52]: 
matrix([[1],
        [3],
        [5]])

In [53]: np.dot(a,b)
Out[53]: 
matrix([[1],
        [3],
        [5]])
2.3.2 矩阵尺寸相同
In [56]: a=np.matrix([[1,2],[3,4]])

In [57]: b=np.matrix([[0,1],[2,3]])

In [60]: a*b	# 矩阵乘法
Out[60]: 
matrix([[ 4,  7],
        [ 8, 15]])

In [61]: np.multiply(a,b)	# 点积
Out[61]: 
matrix([[ 0,  2],
        [ 6, 12]])

In [62]: np.matmul(a,b)
Out[62]: 
matrix([[ 4,  7],
        [ 8, 15]])

In [63]: np.dot(a,b)
Out[63]: 
matrix([[ 4,  7],
        [ 8, 15]])

2.4 np.matmul()__vs__np.dot()

上面五种情况np.matmul()和. np.dot()的结果都是相同的,我们来看看它们之间的差别。

差别在于2维以上np.array数组
np.multiply()和*依然是array对应元素相乘,不满足广播的条件则出错。接下来主要分析np.matmul()和np.dot()。

In [97]: a = np.array([[[ 0,  1,  2],
        				[ 3,  4,  5]],
					   [[ 6,  7,  8],
        				[ 9, 10, 11]]])	# (2, 2, 3)

In [98]: b = np.array([[[0, 1],
        				[2, 3],
        				[4, 5]]]) 		# (1, 3, 2)

In [99]: np.dot(a,b)
Out[99]: 
array([[[[10, 13]],
        [[28, 40]]],
        
       [[[46, 67]],
        [[64, 94]]]])
 
In [100]: np.dot(a,b).shape
Out[100]: (2, 2, 1, 2)

In [101]: np.matmul(a,b)
Out[101]: 
array([[[10, 13],
        [28, 40]],
        
       [[46, 67],
        [64, 94]]])
        
In [102]: np.matmul(a,b).shape
Out[102]: (2, 2, 2)		# 比dot少了一维!!!!!

In [105]: a = np.array([[[ 0,  1,  2],
        				 [ 3,  4,  5]],
						[[ 6,  7,  8],
        				 [ 9, 10, 11]]])	# (2, 2, 3)

In [106]: b = np.array([[[ 0,  1],
        				 [ 2,  3],
        				 [ 4,  5]],
						[[ 6,  7],
        				 [ 8,  9],
        				 [10, 11]]])		# (2, 3, 2)

In [107]: np.dot(a,b)
Out[107]: 
array([[[[ 10,  13],
         [ 28,  31]],

        [[ 28,  40],
         [100, 112]]],


       [[[ 46,  67],
         [172, 193]],

        [[ 64,  94],
         [244, 274]]]])
         
In [118]: np.dot(a,b).shape
Out[118]: (2, 2, 2, 2)

In [109]: np.matmul(a,b)
Out[109]: 
array([[[ 10,  13],
        [ 28,  40]],

       [[172, 193],
        [244, 274]]])

In [110]: np.matmul(a,b).shape
Out[110]: (2, 2, 2)		# 比dot少了一维!!!!!

获得结论:

  • np.matmul() 分别把数组的最后两个维度(组成矩阵)视为一个元素,并对其进行广播。
     
    如上文中b.shape:[1,3,2],广播为[2,3,2]再与a相乘。广播后两个数组matmul 即两个数组对应位置的矩阵相乘。在上面的例子中,最终结果分别由两对2 × 3 和 3 × 2 的矩阵乘法得到两个2 × 2矩阵,即2 × 2 × 2。

  • np.dot() 则对第一个数组的最后一个维度(行向量)以及第二个数组的倒数第二个维度(列向量)进行点积。
     
    在上面的例子中,a可以看作2 × 2个行向量。b可以看作2 × 2个列向量。np.dot会将a的每一个行向量与b的全部列向量进行点积,每一个行向量都能得到一个二维数组,占据结果的后两维。属于同一个二维数组的行向量,得到的结果又合并为一个三维数组。这个三维数组又与其他二维数组的行向量得到的三维数组合并成四维数组。

注意:np.matmul() 和np.dot() 还有一个区别是:np.matmul() 无法用于标量与array相乘。

In [113]: a=np.array([1,2,3])

In [114]: np.dot(a, 2)
Out[114]: array([2, 4, 6])

In [115]: np.matmul(a,2)
ValueError: Scalar operands are not allowed, use '*' instead

3. 参考

【1】https://www.delftstack.com/howto/numpy/numpy-dot-vs-matmul/
【2】https://blog.csdn.net/weixin_44378835/article/details/117028708

### 回答1: np.matmulnp.dot都是numpy库中的矩阵乘法函数,但是它们的用法和计算方式略有不同。 np.matmul是矩阵乘法函数,它的输入可以是两个二维矩阵,也可以是一个多维矩阵和一个二维矩阵。当输入是两个二维矩阵时,np.matmul计算的是矩阵乘积,即第一个矩阵的行与第二个矩阵的列的乘积。当输入是一个多维矩阵和一个二维矩阵时,np.matmul会将二维矩阵广播到多维矩阵的最后两个维度上,然后计算矩阵乘积。 np.dot也是矩阵乘法函数,但它的计算方式略有不同。当输入是两个一维数组时,np.dot计算的是它们的点积。当输入是两个二维矩阵时,np.dot计算的也是矩阵乘积,但是它会将第一个矩阵的列与第二个矩阵的行的乘积相加,得到一个新的二维矩阵。 因此,np.matmulnp.dot虽然都是矩阵乘法函数,但是它们的输入和计算方式略有不同。在使用时需要根据具体情况选择合适的函数。 ### 回答2: numpy中的matmuldot都是用来进行矩阵乘法运算的函数,但是它们的差别在于Matrix和Array的处理方式不同,具体如下: np.dotnp.dot函数计算的是两个数组之间的点积,即在对应位置的元素分别相乘再相加的结果。而当其中一个参数是表现为矩阵的时候,则进行矩阵乘法运算,得到一个矩阵结果。此函数没有对于Matrix的处理方法,所以如果需要将Matrix进行点积运算,则需要将其转换为ndarray。 np.matmulnp.matmul函数在进行点积运算时,如果其中一个参数是表现为Matrix的话,则会采用Matrix所对应的乘法规则,即将左边矩阵的每一行依次与右边矩阵的每一列进行向量积运算,得到矩阵乘积结果。而当两个参数都是表现为ndarray时,则跟np.dot一样按照元素位置依次相乘再相加,得到一个ndarray的结果。 综上所述,np.matmul函数更适合做矩阵乘法的运算,而np.dot函数一般用于做点积运算,如果要在矩阵上做点积运算,推荐使用np.matmul函数。因此,在使用矩阵运算的时候,我们需要根据实际需求的不同来选择不同的方法。 ### 回答3: 在numpy中,np.matmulnp.dot都是用来做矩阵乘法运算的函数。它们虽然功能类似,但在使用时还是有一些区别的。 1. 形状要求有所不同 np.dot函数是用于执行标准的矩阵乘法。它要求两个矩阵形状必须匹配。尤其是第一个矩阵的列数与第二个矩阵的行数必须相等,否则无法执行乘法运算。如果两个矩阵形状不匹配,则会报错。 而np.matmul函数则更加灵活,它不仅支持标准矩阵乘法,还支持批量矩阵乘法。批量矩阵乘法通常用于处理多个输入矩阵的情况。在执行批量矩阵乘法时,np.matmul函数允许两个矩阵的形状不必完全相同,只要满足一定的要求即可。 2. 数据类型转换不同 使用np.dot函数进行矩阵乘法运算时,如果两个矩阵的数据类型不同,那么np.dot函数会将它们转换为相同的数据类型,然后再执行乘法运算。这种数据类型转换可能会带来一些性能上的损失。 而np.matmul函数在执行乘法运算时则不进行数据类型转换。如果两个矩阵的数据类型不同,那么np.matmul函数会报错。因此,使用np.matmul函数时需要保证两个矩阵的数据类型相同。 综上所述,np.matmulnp.dot虽然功能类似,但在使用时还是需要注意它们的区别。如果需要进行批量矩阵乘法运算,应该使用np.matmul函数;如果需要进行标准的矩阵乘法运算,应该使用np.dot函数。同时,在使用这两个函数时还需要注意数据类型的匹配问题。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秋冬无暖阳°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值