【NumPy】*、np.multiply()、np.matmul()或@、np.dot()的异同

简介:

广播机制

*、np.multiply()、np.matmul() 或 @、np.dot()的异同

In [1]: import numpy as np

1、 尺寸相同的两个1-D array

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

结论:

np.multiply()*:array对应元素相乘

np.matmul()@np.dot():向量点积

备注:在numpy中可以使用@来替代matmul,即:

np.matmul(a, b)
# 可以被替代为:
(a @ b)

下文只考虑np.matmul(a,b)

2、 两个2-D array

对于尺寸不同但符合矩阵乘法规则的两个2-D array:

In [17]: a = np.array([i for i in range(6)]).reshape([3,2])

In [18]: a
Out[18]: 
array([[0, 1],
       [2, 3],
       [4, 5]])

In [19]: b=np.array([[0],[1]])

In [20]: b
Out[20]: 
array([[0],
       [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-D array:

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

In [30]: b=np.array([[0,1],[2,3]])

In [31]: a
Out[31]: 
array([[1, 2],
       [3, 4]])

In [32]: b
Out[32]: 
array([[0, 1],
       [2, 3]])

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]])

结论:

np.multiply()*:array对应元素相乘。不满足广播的条件则出错。

np.matmul()@np.dot():矩阵乘法

3、 两个 matrix

对于尺寸不同但符合矩阵乘法规则的两个 matrix:

In [48]: a = np.matrix([i for i in range(6)]).reshape([3,2])
Out[48]: 
matrix([[0, 1],
        [2, 3],
        [4, 5]])

In [49]: b=np.matrix([[0],[1]])
Out[49]: 
matrix([[0],
        [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]])

对于尺寸相同的两个matrix:

In [56]: a=np.matrix([[1,2],[3,4]])

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

In [58]: a
Out[58]: 
matrix([[1, 2],
        [3, 4]])

In [59]: b
Out[59]: 
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]])

结论:

np.multiply():matrix对应元素相乘。不满足广播的条件则出错。

*np.matmul()@np.dot():矩阵乘法

4、 np.matmul() vs. np.dot()

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

考虑2维以上array:
np.multiply()*依然是array对应元素相乘,不满足广播的条件则出错。这里略过相应代码,我们主要来看看np.matmul()np.dot()

In [95]: a = np.array([i for i in range(12)]).reshape([2,2,3])

In [96]: b = np.array([i for i in range(6)]).reshape([1,3,2])

In [97]: a
Out[97]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

In [98]: b
Out[98]: 
array([[[0, 1],
        [2, 3],
        [4, 5]]])

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)

In [103]: a = np.array([i for i in range(12)]).reshape([2,2,3])

In [104]: b = np.array([i for i in range(12)]).reshape([2,3,2])

In [105]: a
Out[105]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])

In [106]: b
Out[106]: 
array([[[ 0,  1],
        [ 2,  3],
        [ 4,  5]],

       [[ 6,  7],
        [ 8,  9],
        [10, 11]]])

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)


结论[1]:

np.matmul() 分别把数组的最后两个维度(组成矩阵)视为一个元素,并对其进行广播。
如上文中b.shape:[1,3,2]广播为[2,3,2]再与a相乘。

广播后两个数组matmul 即两个数组对应位置的矩阵相乘。在上面的例子中,两个数组分别由两个$2\times 3$和$3\times 2$的矩阵组成。通过对应位置矩阵进行矩阵乘法,得到结果为两个$2\times 2$的矩阵。

np.dot() 则对第一个数组的最后一个维度(行向量)以及第二个数组的倒数第二个维度(列向量)进行点积。在上面的例子中,a可以看作$2\times 2$个行向量。b可以看作$2\times 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

参考:

[1]https://www.delftstack.com/howto/numpy/numpy-dot-vs-matmul/

相关文章
|
传感器 机器学习/深度学习 自动驾驶
自动驾驶:BEV开山之作LSS(lift,splat,shoot)原理代码串讲
自动驾驶:BEV开山之作LSS(lift,splat,shoot)原理代码串讲
4922 0
自动驾驶:BEV开山之作LSS(lift,splat,shoot)原理代码串讲
Manacher(马拉车)算法详解
该文章详细解释了Manacher算法,这是一种高效找出给定字符串最长回文子串的算法,通过在字符串中插入特殊字符构建新的字符串,并利用中心扩展策略来找出最长回文序列,时间复杂度为O(N),空间复杂度为O(N)。
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
228 2
|
JavaScript 前端开发 程序员
非专业程序员常用vscode插件
这里的vscode插件, 有四分之一你没用过, 这里的vscode设置, 80%你没设置过, 挖宝随缘
222 5
|
网络协议 测试技术 数据安全/隐私保护
ensp中高级acl (控制列表) 原理和配置命令 (详解)
ensp中高级acl (控制列表) 原理和配置命令 (详解)
1117 0
|
Serverless Python
Python开根号的几种方式
Python开根号的几种方式
6977 0
|
机器学习/深度学习 存储 分布式计算
阿里开源首个DL框架,新型XDL帮你搞定大规模稀疏数据
12 月 21 日,阿里巴巴旗下的大数据营销平台阿里妈妈开源了其应用于自身广告业务的算法框架 X-Deep Learning(XDL)。该框架非常擅长处理高维稀疏数据,对构建推荐、搜索和广告系统非常有优势。此外,阿里还配套发布了一系列官方模型,它们都是阿里在实际业务或产品中采用的高效模型。
1462 0
阿里开源首个DL框架,新型XDL帮你搞定大规模稀疏数据
【Gurobi报错解决】Solver not applicable (gurobi does not support signomial constraints)
【Gurobi报错解决】Solver not applicable (gurobi does not support signomial constraints)
1045 0
|
网络协议 网络安全 虚拟化
DNS服务器搭建(Windows版本)
DNS服务器搭建(Windows版本)
1965 0
|
算法 安全 搜索推荐
matlab中P代码解析破解之道
matlab中P代码即P文件加密与逆向工程探讨

热门文章

最新文章