Numpy广播

Numpy广播 broadcasting

ufunc函数在对两个数组进行计算时,如果两个数组的形状不相同,则会进行广播处理,其处理的规则为:

  • 让所有数组都向其中维数最多的数组看齐,shape属性中不足的部分都通过在前面加1补齐;

  • 输出数组的shape属性是输入数组shape属性在各轴上的最大值;

  • 如果输入数组的某个轴长度为1或与输出数组对应轴的长度相同,这个数组就能够用来计算,否则出错;

  • 当输入数组的某个轴长度为1时,沿着此轴运算时都用此轴上的第一组值;

如:

1
2
a = np.array(0,60,10).reshape(-1,1)
b = np.array(0,5)

两个数组,其中a.shape = (6,1), b.shape=(5,),广播处理过程为:

  • b数组向a数组看齐,并且在shape属性前面加1,此时,b.shape = (1,5)

  • 输出数组的shape为(6,5),是数组shape各轴上的最大值;

  • a.shape = (6,1),0轴与输出数组长度相同,1轴为1,可以用来计算;b.shape = (1,5),0轴为1,1轴与输出数组长度相同,可以用来计算;

  • a数组的1轴长度为1,故a数组在1轴上的值都沿用 a[:,0]的值;b数组的0轴长度为1,故b数组0轴上的值都沿用 b[0,:]的值,此时,a,b数组可以看做:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    a = array([[0, 0, 0, 0, 0],
    [10,10,10,10,10],
    [20,20,20,20,20],
    [30,30,30,30,30],
    [40,40,40,40,40],
    [50,50,50,50,50]])
    b = array([[0, 1, 2, 3, 4],
    [0, 1, 2, 3, 4],
    [0, 1, 2, 3, 4],
    [0, 1, 2, 3, 4],
    [0, 1, 2, 3, 4],
    [0, 1, 2, 3, 4]])

此时,a和b数组就可以进行相应的ufunc操作了;

numpy在内部真正运算时,并不会对数组进行重复的填充操作,这样太浪费空间;

事实上,numpy还提供了一个常用的网格对象来进行常用的广播操作:ogrid和mgrid

其中,np.ogrid必须对其进行切片操作,并且返回一个数组,数组的每个值都是一个只有单一轴的数组,如:

1
2
np.ogrid[:5,:4] =[array([[0],[1],[2],[3],[4]]),
array([[0, 1, 2, 3]])]

而np.mgrid则是填充后的结果(由于比较消耗内存,应该使用ogrid代替):

1
2
3
4
5
6
7
8
9
10
np.mgrid[:5,:5] = array([[[0, 0, 0, 0],
[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3],
[4, 4, 4, 4]],
[[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3],
[0, 1, 2, 3]]])