0
点赞
收藏
分享

微信扫一扫

python 中的 NumPy 库中的广播规则

早安地球 2024-11-18 阅读 14

在 Python 中的 NumPy 库中,**广播**(broadcasting)是一种用于在不同形状的数组间执行元素级运算的机制。广播允许我们在不显式复制数据的情况下执行计算,自动扩展数组的形状以匹配彼此,从而简化代码,提高运算效率。

### 广播规则
当 NumPy 尝试广播两个数组时,会遵循以下规则:

1. **从后往前比较维度**:
   - 从两个数组的最后一个维度开始逐个比较,如果维度相同,或者其中一个维度是 1,则继续比较下一个维度。
   
2. **维度不兼容时自动扩展为相同形状**:
   - 如果一个数组的维度为 1,而另一个数组的维度不同,则 NumPy 会将该维度的大小扩展为匹配的维度。

3. **广播成功条件**:
   - 两个数组的维度要么相等,要么其中一个维度为 1,否则无法广播。

### 广播的例子

#### 例 1:标量与数组广播
```python
import numpy as np

a = np.array([1, 2, 3])
b = 2
result = a + b  # 结果:[3, 4, 5]
```
这里 `b` 是标量,NumPy 自动将 `b` 扩展为 `[2, 2, 2]`,然后和 `a` 相加。

#### 例 2:一维数组和二维数组广播
```python
import numpy as np

a = np.array([1, 2, 3])         # 形状为 (3,)
b = np.array([[10], [20], [30]]) # 形状为 (3, 1)

result = a + b
# 结果:
# [[11, 12, 13],
#  [21, 22, 23],
#  [31, 32, 33]]
```
在这里,`a` 的形状是 `(3,)`,`b` 的形状是 `(3, 1)`。NumPy 会将 `a` 的形状扩展为 `(3, 3)`,将 `b` 的形状扩展为 `(3, 3)`,然后进行元素级相加。

#### 例 3:不同大小的二维数组广播
```python
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])  # 形状为 (2, 3)
b = np.array([[10], [20]])            # 形状为 (2, 1)

result = a + b
# 结果:
# [[11, 12, 13],
#  [24, 25, 26]]
```
这里 `a` 的形状是 `(2, 3)`,`b` 的形状是 `(2, 1)`。NumPy 会将 `b` 的形状扩展为 `(2, 3)`,然后逐元素相加。

#### 例 4:广播失败的情况
```python
import numpy as np

a = np.array([1, 2, 3])        # 形状为 (3,)
b = np.array([[1, 2], [3, 4]]) # 形状为 (2, 2)

# result = a + b  # 报错:operands could not be broadcast together
```
在这种情况下,`a` 的形状是 `(3,)`,`b` 的形状是 `(2, 2)`。两者的维度不兼容,无法广播,因此运算失败。

在这个例子中,`a` 和 `b` 可以广播的原因是:

- **数组 `a` 的形状**是 `(2,)`。
- **数组 `b` 的形状**是 `(2, 2)`。

根据广播规则,**从后往前**比较两个数组的维度(并在需要时补齐前面的维度):

1. `a` 的形状 `(2,)` 可以理解为 `(1, 2)`,这样就和 `b` 的形状 `(2, 2)` 有了匹配的维度。
2. 按照广播规则,如果两个维度中的一个是 1,那么 NumPy 会将这个维度扩展到与另一数组的维度相同。

因此,`a` 会被扩展为形状 `(2, 2)`,具体扩展为:

```
a: [[1, 2],
    [1, 2]]
```

此时 `a` 和 `b` 的形状匹配,就可以逐元素运算了。

举报

相关推荐

0 条评论