numpy广播

Numpy的Universal functions 中要求输入的数组shape是一致的,当数组的shape不想等的时候,则会使用广播机制,调整数组使得shape一样,满足规则,则可以运算,否则就出错 。

广播:对形状不同的数组,采取的运算操作。但被操作的数组中必须至少有一个某轴长度为1;或者缺少一个维度(这时候会自动补全,但是此时补全只会是在前面补1,这时候可能需要手动reshape为(n, 1)而不是(n,))。
换句话说,通过对两个数组中的一个或者多个在行、列上进行复制元素扩展,如果最后能形成两个shape一样的数组,就进行广播运算,结果与这两个shape相同的数组正常运算结果相同。

四条规则如下:

  1. All input arrays with ndim smaller than the input array of largest ndim, have 1’s prepended to their shapes.
  2. The size in each dimension of the output shape is the maximum of all the input sizes in that dimension.
  3. An input can be used in the calculation if its size in a particular dimension either matches the output size in that dimension, or has value exactly 1.
  4. If an input has a dimension size of 1 in its shape, the first data entry in that dimension will be used for all calculations along that dimension. In other words, the stepping machinery of the ufunc will simply not step along that dimension (the stride will be 0 for that dimension).

中文

  1. 让所有输入数组都向其中shape最长的数组看齐,shape中不足的部分都通过在前面加1补齐
  2. 输出数组的shape是输入数组shape的各个轴上的最大值
  3. 如果输入数组的某个轴和输出数组的对应轴的长度相同或者其长度为1时,这个数组能够用来计算,否则出错
  4. 当输入数组的某个轴的长度为1时,沿着此轴运算时都用此轴上的第一组值

以下通过实例来说明这些问题

一般情况下,numpy 都是采用一一对应的方式(element-by-element )进行计算

例子1:

>>> from numpy import array 
>>> a = array([1.0,2.0,3.0])
>>> b = array([2.0,2.0,2.0])
>>> a * b
array([ 2.,  4.,  6.])
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

当不相等时,则会采用规则对其:

>>> from numpy import array
>>> a = array([1.0,2.0,3.0])
>>> b = 2.0
>>> a * b
array([ 2.,  4.,  6.])
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

a.shape得到的是(3,) b是一个浮点数,如果转换成array,则b.shape是一个(),a的1轴对齐,补齐为1,a.shape(3,1),b对齐,则对齐也为(3,1),然后按照一一对应的方式计算

或许上述例子不是太明确,下面采用一个更加确切的例子说明:

>>> import numpy as np
>>> a = np.arange(0, 6).reshape(6, 1)
>>> a
array([[ 0], [1], [2], [3], [4], [5]])
>>> a.shape
(6, 1)
>>> b = np.arange(0, 5)
>>> b.shape
(5,)
>>> c = a + b
>>> print c
[[0 1 2 3 4]
 [1 2 3 4 5]
 [2 3 4 5 6]
 [3 4 5 6 7]
 [4 5 6 7 8]
 [5 6 7 8 9]]
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在上述实例中,当使用+运算时,由于shape不一致,按照规则1,会对b进行 
reshape,b.reshape成(1,5),可能会问为什么不是(5,1),因为这个就不能计算了,那么如果b的shape是(6,)的时候呢,都可以运算;所以对于对齐本身我自己是没有理解太过透彻,所以,我找了一下官方文档,其中的一个图是这样的: 
 
我理解是,其本身的形状是不能改变的,只能在原来的基础上延伸,像上述的例子中,如果b的shape是(6,),如果在broadcasting的时候reshape(6,1)则已经是属于改变了原来的数组的形状,进行了翻转,而不是延伸。

接着上述实例,对于b则reshape成了(1,5),a则保持(6,1),按照规则2,则输出为每个轴上的最大值,则c.shape为(6,5);

对于规则3和规则4,都是在描述延伸的条件和方式,所以对于我的理解我也更加确信了,如果有大侠觉得有问题,请帮忙指正

参考:

NumPy-快速处理数据(http://old.sebug.net/paper/books/scipydoc/numpy_intro.html) 
Array Broadcasting in numpy(http://scipy.github.io/old-wiki/pages/EricsBroadcastingDoc) 
NumPy Reference(http://docs.scipy.org/doc/numpy-1.10.0/reference/ufuncs.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值