前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >问答记录贴 1 | 解析 NumPy 的广播(broadcasting)机制

问答记录贴 1 | 解析 NumPy 的广播(broadcasting)机制

作者头像
double
发布2018-07-25 17:45:41
4130
发布2018-07-25 17:45:41
举报
文章被收录于专栏:算法channel算法channel
建议阅读时间:5 分钟

1 问答记录系列

实践出真知,相互讨论碰撞出思想的火花。【原创互助答疑群】内有的问答很精彩。于是脑子里闪现出一个想法,为什么不把整个的问答过程记录总结下来,分享给更多的小伙伴呢? 于是就有了这个推送系列模块,相信大家能从中受益。欢迎小伙伴在群内积极参与讨论。

2 Python的 * 和 NumPy的广播

几天前,一个小伙伴问:Python的 * 和广播机制是一回事吗?它们相似,但实则不同!

1) 先了解下python中的 list * 标量,结果是复制对应的元素,如下所示:

代码语言:javascript
复制
a = [3,8,10]
print(a*3)

[3, 8, 10, 3, 8, 10, 3, 8, 10]



a = [[1,3,2],[6,4,3]]print(a*2)
[[1, 3, 2], [6, 4, 3], [1, 3, 2], [6, 4, 3]]

list * 标量等于按元素或按行的复制。

2) NumPy 的广播机制,先看一个例子,如下:

代码语言:javascript
复制
x = np.arange(4)
xx = x.reshape(4,1)
print(xx)
y = np.ones(5)
print(y)
print(xx + y) 


xx: array([ [0], [1], [2], [3] ])
y : array([  1,   1,   1,   1, 1 ])

xx + y : array(array([[ 1., 1., 1., 1., 1.], 
                      [ 2., 2., 2., 2., 2.], 
                      [ 3., 3., 3., 3., 3.], 
                      [ 4., 4., 4., 4., 4.]]) )

上面的例子,xx 的 shape是(4,1),y的 shape(5,),NumPy支持的这类操作,被称为广播机制。

3 NumPy广播 通用规则

注意,不是任意形状间的ndarray都能做广播,必须满足一定的约束条件。对两个NumPy的 ndarray 进行操作时,NumPy 会比较形状,开始于最靠后的维度(如5*4*6,最靠后的维度长度是6)。当以下情形出现时,维度是兼容的:

1) 相等

代码语言:javascript
复制
data_2d = np.arange(20).reshape(5,4) # 5 * 4 
data_1d = np.array([1,2,3,4])        #     4
print(data_2d * data_1d)             # 5 * 4
 
 
 array([[ 0,  2,  6, 12],           [ 4, 10, 18, 28],           [ 8, 18, 30, 44],           [12, 26, 42, 60],           [16, 34, 54, 76]])

2) 其中一个长度为 1

代码语言:javascript
复制
data_3d = np.arange(20).reshape(5,2,2) # 5 * 2 * 2 
data_1d = np.array([3])                #         1
print(data_2d * data_1d)               # 5 * 2 * 2

 [[[ 0  3]   [ 6  9]]    
   [[12 15]   [18 21]]    
   [[24 27]   [30 33]]    
   [[36 39]   [42 45]]    
   [[48 51]   [54 57]]]

可以看到,广播是按照右对齐的方式,其中长度为1的维度被自动广播。

4 NumPy广播 好处

先看一个例子。一个ndarray和一个标量相乘,这是广播机制:

代码语言:javascript
复制
a = np.array([1, 2, 3])
b = 2
print(a * b)
array([2, 4, 6])

如果我们不按照广播机制,我们可以这样写:

代码语言:javascript
复制
a = np.array([1, 2, 3])
b = np.array([2, 2, 2])
print(a * b)
array([2, 4, 6])

标量值 b 在计算时被伸展为 与 a 一样的形状,伸展后 b 的每一个元素都是原来标量值的复制。实际上,NumPy 并不需要真的复制这些标量值,所以广播运算在内存和计算效率上更高效。

最近推文:

探索下去,迎接未知的精彩。。。

Python神经网络| 一篇很棒的实战笔记,附源码

牢记初心,就是保持内心的几分纯真

3分钟理解 支持向量机中最出神的第一笔

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-06-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员郭震zhenguo 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档