numpy之广播

广播的原则:

       如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为他们是广播兼容的。广播会在缺失和(或)长度为1的维度长进行。

看几个例子理解一下:

In [223]: arr = np.arange(4)
In [224]: arr
Out[224]: array([0, 1, 2, 3])
In [225]: arr*3               #  比较简单的广播的例子
Out[225]: array([0, 3, 6, 9])

低维度的值可以被广播到数组的任意维度:

In [226]: arr = np.array([[1],[2],[3]])
In [227]: arr
Out[227]: 
array([[1],[2],[3]])
In [228]: arr.shape
Out[228]: (3, 1)
In [229]: other_arr = np.array([1,2,3])
In [230]: arr + other_arr
Out[230]: 
array([[2, 3, 4],
       [3, 4, 5],
       [4, 5, 6]])
In [231]: other_arr.shape
Out[231]: (3,)

arr的shape是(3,1)后缘维度长度为1,other_arr的shape是(3, ),other_arr低维度的值被广播到arr高维度的任意维度。

在看一个例子:

In [232]: arr = np.random.randn(4,3)
In [233]: m = arr.mean(0)
In [234]: m
Out[234]: array([ 0.10478714,  0.93317107, -0.01853336])
In [235]: arr - m
Out[235]: 
array([[ 0.53074894, -1.43334657,  1.11937261],
       [-0.09741141,  1.83929851,  0.91581349],
       [-0.51180403,  0.51003558,  0.1602767 ],
       [ 0.07846651, -0.91598753, -2.19546281]])
In [236]: (arr - m).mean(0)
Out[236]: array([2.08166817e-17, 1.38777878e-16, 0.00000000e+00])
上面这个例子的arr.shape是(4,3)后缘维度是3,而m的长度为3,所以可以在0轴上进行广播。

看图理解一下:


上面的那个例子如果在行上计算平均值就不一样:

In [240]: m = arr.mean(1)
In [241]: m
Out[241]: array([ 0.41206661,  1.22570848,  0.39264437, -0.6711
8633])
In [242]: arr - m
---------------------------------------------------------------
ValueError                    Traceback (most recent call last)
<ipython-input-242-33627b173828> in <module>()
----> 1 arr - m
ValueError: operands could not be broadcast together with shape
s (4,3) (4,)
In [243]: arr - m.reshape(4,1)
Out[243]: 
array([[ 0.22346946, -0.91224211,  0.68877264],
       [-1.21833276,  1.54676111, -0.32842835],
       [-0.79966126,  1.05056229, -0.25090103],
       [ 0.85443997,  0.68836987, -1.54280984]])

上面这个例子的arr.shape是(4,3)后缘维度是3,而m的长度为4,不符合广播原则,所以出错。要想正确在行上做减法,就必须改变其shape为(4,1)

看一下多维的情况:


第一个数组的后缘维度是(4,2) ,第二个数组的shape是(4,2),符合广播原则

对于多维的情况,任何一维上的广播就是将数据重塑为兼容的形状。

下图是三维数组各维度上广播形状的需求:


为了简化重塑形状的过程,numpy提供了一个通过索引机制插入轴来重塑形状 的特殊语法。

In [246]: arr = np.zeros((4,4))
In [247]: re_arr = arr[:,np.newaxis,:]
In [248]: re_arr.shape
Out[248]: (4, 1, 4)
In [250]: arr = np.array([1,2,3])
In [251]: arr.shape
Out[251]: (3,)
In [252]: arr_1 = arr[:,np.newaxis]
In [253]: arr_1.shape
Out[253]: (3, 1)
In [254]: arr_1 = arr[np.newaxis,:]
In [256]: arr_1.shape
Out[256]: (1, 3)

看一个栗子,对一个三维数组的轴2距平化:

In [257]: arr = np.random.randn(3,4,5)
In [258]: m2 = arr.mean(2)
In [259]: m2
Out[259]: 
array([[ 0.13649416,  0.10628038, -0.07967465,  0.77251529],
       [-0.02079456, -0.26046433, -0.03397547, -0.00820266],
       [-0.17323542,  0.23429955, -0.76819986, -0.18061328]])
In [260]: re = arr - m2[:,:,np.newaxis]
In [262]: re.mean(2)           #  结果大概就都是0
Out[262]: 
array([[ 2.22044605e-17, -2.22044605e-17,  2.22044605e-17,
         2.22044605e-17],
       [ 4.44089210e-17,  0.00000000e+00,  0.00000000e+00,
         1.11022302e-17],
       [ 0.00000000e+00,  3.88578059e-17, -8.88178420e-17,
         4.44089210e-17]])

猜你喜欢

转载自blog.csdn.net/qq_42413820/article/details/80798908
今日推荐