Numpy中的广播操作(broadcasting)

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时,沿着此轴运算时都用此轴上的第一组值

具体实现就是
1、会检查两个矩阵维数是否相同,如果不同,对维数少的补一,如一个二维矩阵(n,d)和一个一维数组(m,)相乘,补一操作就是把一维数组变成(1,m),补一总是在shape数组的开始补一。

2、输出的数组是输入数组各维度的最大值,比如(2,3)和(3,)相乘,第一步会把(3,)变成(1,3),然后比较第一维2和1,选择2 ,比较第二维3和3 选择3,所以输出数组维度是(2, 3)。
3、输入数组各维的值和输出数组各位的关系,要么相等,要么为一。
例如第二步的例子中,输入数组(2,3)和输出数组(2,3)在各维的值都相等,而(1,3)和(2,3)虽然第一维不想等,但是却是1,所以可以计算。再举个反例,(2,4)和(3,)相乘,第一步转成(2,4)和(1,3),第二步比较各维,输出为(2,4),然后进行第三步,(2,4)和(2,4)的各维相等,(1,3)和(2,4)的第二维既不等于4 也不是1,计算就会出错。

Numpy中的广播操作(broadcasting)_第1张图片
我们要明白广播的4条原则是什么意思,简而言之就是“就高不就低”原则。同时还要明白第3条原则,某个维度只有在一行或一列的情况下才能够广播,为什么呢?因为当只有一行(或一列)时才能够毫无歧义地扩展,把那仅有的一行(或一列)通过复制填满那个维度,这样不会出错。设想一下,如果b有两行,该选择哪一行进行复制延伸呢?就会无所适从了。所以第3条原则规定仅当某个维度长度为1或者跟最长的一样长(此时不需要广播)时才能参与计算。a是一维列矩阵(6,1),b是一维行矩阵(1,5),注意这里b是补充了维度的。在行和列方向上分别取最大值,结果就应该是(6,5)的矩阵。a和b在参与计算之前都要先进行广播,即复制延伸。a延伸成了:[[0, 0, 0, 0, 0], [1, 1, 1, 1, 1], [2, 2, 2, 2, 2], [3, 3, 3, 3, 3], [4, 4, 4, 4, 4], [5, 5, 5, 5, 5]]b延伸成了:[[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都是(6,5)的矩阵了,然后按照对应元素相加就得到最终结果了。

参考文章:
https://blog.csdn.net/yangnanhai93/article/details/50127747
https://www.cnblogs.com/sgdd123/p/7600283.html

你可能感兴趣的:(python)