NumPy 广播机制

什么是广播机制?

在 NumPy 中,广播(broadcasting)是一种非常强大的功能。广播机制使得我们在执行数组算术运算(如加、减、乘、除等)时,可以处理形状不同的数组。简单来说,广播机制帮助我们解决不同形状数组之间的运算问题。

例如,当一个数组与一个常数(标量)相加,或一个二维数组与一个一维数组相乘时,广播机制会自动扩展维度,使得它们的形状匹配,从而可以执行加、减、乘、除等操作。

当对两个数组进行算术操作时,NumPy 会逐个元素比较它们的形状。需要注意的是,只有在以下情况下,两个数组才能进行广播:

  • 形状完全相同的两个数组:比如两个形状都是 (3, 4) 的数组。
  • 维度不同时,两个数组的 “后缘维度” 相同:这里的 “后缘维度” 是指数组形状的最后一个维度。例如,形状为 (3, 4) 和 (4,) 的数组,它们的后缘维度相同,可以进行广播。
  • 维度相同,其中一个数组某个维度的长度为 1这种情况下,NumPy 会将长度为 1 的维度 “拉伸” 以匹配另一个数组相应维度的长度。
  • 较少维度的数组会自动补上维度,直到它们的维度数相同:例如,形状 (3, 4) 和 (4,) 可以通过补充维度后变为 (3, 4) 和 (1, 4),使其形状一致。

如果两个数组的形状不符合这些规则,NumPy 会抛出 ValueError 异常,表示形状不兼容。

在 NumPy 中,广播机制应用非常广泛,主要包括以下几个方面:

  • 数组与标量运算:比如为所有数组元素加上一个常数。
  • 不同维度的数组运算:比如二维数组与一维数组相加。
  • 机器学习中的特征归一化、矩阵 - 向量计算
  • 图像处理中多通道操作

NumPy 广播应用

接下来,我们通过几个简单的例子来讲解一下 NumPy 广播机制是怎样的。

1. 数组与标量的广播

在 NumPy 中,当一个数组与一个标量进行算术运算时,标量会被广播到数组的每一个元素上。也就是说,此时数组每个元素都会对标量进行相同运算操作。

示例 1:数组与标量的广播

import numpy as np

arr = np.array([1, 2, 3])
scalar = 5
result = arr + scalar

print(arr)
print(scalar)
print(result)

运行结果如下。

[1 2 3]
5
[6 7 8]

分析:

在这个例子中,标量 5 被广播到了数组 [1, 2, 3] 的每一个元素上,从而使得数组中每个元素都进行加 5 的操作。

2. 二维数组与一维数组的广播(行广播)

在 NumPy 中,当 “一个形状为 (m, n) 的二维数组” 与 “一个形状为 (n, ) 的一维数组” 进行算术运算时,一维数组会沿着二维数组的每一行进行广播。

示例 2:行广播

import numpy as np

arr2d = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])
arr1d = np.array([10, 20, 30])
result = arr2d + arr1d

print(arr2d)
print(arr1d)
print(result)

运行结果如下。

[[1 2 3]
 [4 5 6]
 [7 8 9]]

[10 20 30]

[[11 22 33]
 [14 25 36]
 [17 28 39]]

分析:

在这个例子中,一维数组 [10, 20, 30] 被广播到了二维数组的每一行上,从而实现了二维数组的每一行都加上这个一维数组的操作。

3. 二维数组与一维数组的广播(列广播)

在 NumPy 中,如果我们想要实现列广播,需要确保一维数组的形状与二维数组的列数相匹配,或者使用 reshape() 函数将一维数组转换为列向量(形状为 (m, 1))。

示例 3:列广播

import numpy as np

arr2d = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])
arr1d = np.array([10, 20, 30]).reshape(3, 1)
result = arr2d + arr1d

print(arr2d)
print(arr1d)
print(result)

运行结果如下。

[[1 2 3]
 [4 5 6]
 [7 8 9]]

[[10]
 [20]
 [30]]

[[11 12 13]
 [24 25 26]
 [37 38 39]]

分析:

在这个例子中,我们使用 reshape(3, 1) 将一维数组转换为列向量后,它会被广播到二维数组的每一列上,从而实现了二维数组的每一列都加上这个列向量的操作。

4. 形状不兼容的广播

在 NumPy 中,如果两个数组的形状不满足广播规则,则会直接报错。

示例 4:形状不兼容的广播

import numpy as np

arr1 = np.array([[1, 2],
                  [3, 4]])
arr2 = np.array([10, 20, 30])

try:
    result = arr1 + arr2
    print(result)
except ValueError as e:
    print(e)

运行结果如下。

(报错)operands could not be broadcast together with shapes (2,2) (3,)

分析:

在这个例子中,arr1 的形状是 (2, 2),而 arr2 的形状是 (3, ),此时 arr1 和 arr2 的形状是不兼容的,因此无法进行广播操作。

最后来总结一下,如果想要判断两个数组是否可以广播,我们可以按照以下步骤:

  1. 比较两个数组的维度数。如果维度数不同,将维度较小的数组在其形状前部补上 1,直到维度数相同。
  2. 从后向前比较两个数组的形状。
  3. 对于每个维度,如果长度相等,或者其中一个数组的长度为 1,则它们在该维度上是兼容的。
  4. 如果所有维度都兼容,则可以进行广播。否则,不可以进行广播。

上一篇: NumPy 求分位数

下一篇: NumPy 集合操作

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号