详解Numpy中的广播原则/机制
本文深入解析Numpy中的广播(Broadcasting)原则,阐述如何通过后缘维度轴长度判断数组兼容性。通过具体代码示例,展示一维与多维数组在加减乘除运算中的形状扩展逻辑,帮助开发者高效处理不同形状数组的计算问题。
广播的原则
当两个数组的后缘维度(即从末尾开始计算的维度)的轴长度相等,或者其中一方的轴长度为1时,这两个数组被视为广播兼容。在此情况下,广播操作会在缺失的维度以及轴长度为1的维度上自动进行扩展。
以计算数组arr每一列的平均值并从原数组中减去的例子为例,arr的后缘维度为3,而arr.mean(0)的结果后缘维度同样为3,这满足了轴长度相符的条件。因此,广播机制将在缺失的维度上执行操作。
此处可能存在一个容易混淆的点:缺失的维度并非axis=1,而是axis=0。个人理解是,“缺失维度”指的是两个参与运算的数组中,除了轴长度已匹配的维度之外的其他维度。在上述示例中,恰好对应的是axis=0。欢迎读者对此观点进行指正或补充。
arr.mean(0)沿着axis=0进行广播,这可以形象地理解为将arr.mean(0)在竖直方向上复制4份。也就是说,在广播过程中,arr.mean(0)等效于一个形状为(4, 3)的数组,且该数组的每一行内容完全相同,均等于arr.mean(0)的计算结果。
为了更直观地理解这一原则,我们首先通过一组具体的代码示例来进行说明。
# 数组直接对一个数进行加减乘除,产生的结果是数组中的每个元素都会加减乘除这个数。
In [12]: import numpy as np
In [13]: a = np.arange(1,13).reshape((4, 3))
In [14]: a * 2
Out[14]: array([[ 2, 4, 6],
[ 8, 10, 12],
[14, 16, 18],
[20, 22, 24]])
# 接下来我们看一下数组与数组之间的计算
In [17]: b = np.arange(12,24).reshape((4,3))
In [18]: b
Out[18]: array([[12, 13, 14],
[15, 16, 17],
[18, 19, 20],
[21, 22, 23]])
In [19]: a + b
Out[19]: array([[13, 15, 17],
[19, 21, 23],
[25, 27, 29],
[31, 33, 35]])
In [20]: c = np.array([1,2,3])
In [21]: a+c
Out[21]: array([[ 2, 4, 6],
[ 5, 7, 9],
[ 8, 10, 12],
[11, 13, 15]])
In [22]: d = np.arange(10,14).reshape((4,1))
In [23]: d
Out[23]: array([[10],
[11],
[12],
[13]])
In [24]: a + d
Out[24]: array([[11, 12, 13],
[15, 16, 17],
[19, 20, 21],
[23, 24, 25]])
# 从上面可以看出,和线性代数中不同的是,m*n列的m行的一维数组或者n列的一维数组也是可以计算的。
那么,这种运算背后的原因是什么呢?这涉及到Numpy的核心广播原则。
如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。
在上述代码示例中,数组a的维度为(4, 3),数组c的维度为(1, 3),而数组d的维度为(4, 1)。假设我们有两个数组,第一个数组的维度为(x_1, y_1, z_1),第二个数组的维度为(x_2, y_2, z_2),要判断这两个数组能否进行计算,可以遵循以下判断逻辑:
if z_1 == z_2 or z_1 == 1 or z_2 == 1: if y_1 == y_2 or y_1 == 1 or y_2 == 1: if x_1 == x_2 or x_1 == 1 or x_2 == 1: 可以运算 else: 不可以运算 else: 不可以运算 else: 不可以运算
需要特别注意:形状为(3, 3, 2)的数组与形状为(3, 2)的数组是可以进行运算的。这是因为对于二维数组(3, 2),可以将其视为(1, 3, 2),从而完全套用上述的广播规则。同理,形状为(4, 2, 5, 4)的数组与形状为(2, 1, 4)的数组也是可以进行运算的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









