【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/

相关文章
|
消息中间件 弹性计算 物联网
MQTT常见问题之发布MQTT主题消息失败如何解决
MQTT(Message Queuing Telemetry Transport)是一个轻量级的、基于发布/订阅模式的消息协议,广泛用于物联网(IoT)中设备间的通信。以下是MQTT使用过程中可能遇到的一些常见问题及其答案的汇总:
|
自然语言处理 算法 数据挖掘
【数据挖掘】十大算法之PageRank连接分析算法
文章介绍了PageRank算法的基本概念和数学模型,包括如何通过一阶马尔科夫链定义随机游走模型以及如何计算网页的重要性评分,并提供了PageRank迭代算法的具体步骤。
1265 1
|
JSON API 数据格式
BING壁纸免费API接口教程
接口简介:获取每日不同的必应官方壁纸。请求地址:https://cn.apihz.cn/api/img/bingapi.php,支持POST或GET请求。需提供用户ID、用户KEY及返回格式(JSON/TXT)。返回状态码和图片地址或错误信息。示例及详细文档见官网。
728 1
|
存储 开发框架 .NET
C#语言如何搭建分布式文件存储系统
C#语言如何搭建分布式文件存储系统
411 2
|
数据挖掘 数据处理 Python
python如何高效处理excel图表案例分享
python如何高效处理excel图表案例分享
455 2
|
缓存 监控 Java
如何在 Java 8 中创建和使用线程池?
【7月更文挑战第8天】
1086 9
如何在 Java 8 中创建和使用线程池?
|
机器学习/深度学习 存储 分布式计算
阿里开源首个DL框架,新型XDL帮你搞定大规模稀疏数据
12 月 21 日,阿里巴巴旗下的大数据营销平台阿里妈妈开源了其应用于自身广告业务的算法框架 X-Deep Learning(XDL)。该框架非常擅长处理高维稀疏数据,对构建推荐、搜索和广告系统非常有优势。此外,阿里还配套发布了一系列官方模型,它们都是阿里在实际业务或产品中采用的高效模型。
1929 0
阿里开源首个DL框架,新型XDL帮你搞定大规模稀疏数据
|
网络协议 测试技术 数据安全/隐私保护
ensp中高级acl (控制列表) 原理和配置命令 (详解)
ensp中高级acl (控制列表) 原理和配置命令 (详解)
2037 0
|
容器 网络架构 C#
WPF 控件库——可拖动选项卡的TabControl
原文:WPF 控件库——可拖动选项卡的TabControl 一、先看看效果   二、原理 1、选项卡大小和位置   这次给大家介绍的控件是比较常用的TabControl,网上常见的TabControl样式有很多,其中一部分也支持拖动选项卡,但是带动画效果的很少见。
1965 0
【Gurobi报错解决】Solver not applicable (gurobi does not support signomial constraints)
【Gurobi报错解决】Solver not applicable (gurobi does not support signomial constraints)
1322 0