广播机制 (Broadcasting)

1. 定义

广播 (Broadcasting) 是 NumPy / PyTorch 里的一套规则:当两个形状不同的数组做逐元素运算时,自动把小的那个”拉伸/复制”到和大的对齐,从而无需手写循环。

一句话:形状不一样也能直接算,NumPy 会自动把维度补齐。 比如一个矩阵每行都加同一个向量,不用循环,直接 matrix + vector 就行。

2. 解决了什么问题

没有广播,形状不同就得手动扩展或写循环:

# 想给 (3,3) 矩阵每一行都加上 [1,2,3]
# 笨办法:循环
for i in range(3):
    A[i] = A[i] + np.array([1, 2, 3])
 
# 广播:一行搞定,还更快
A + np.array([1, 2, 3])

广播让代码更短、更快(底层 C 实现,无 Python 循环),是向量化编程的核心。

3. 广播三条规则

两个数组做运算时,NumPy 从最右边的维度开始逐维比较:

  1. 维度数不同:给短的那个在左边补 1,直到维度数相同
    • (3,)(2,3)(3,) 补成 (1,3)
  2. 每一维比较:这一维两者要么相等,要么其中一个是 1
  3. **是 1 的那一维被”拉伸”**到另一个的大小(逻辑上复制,不真占内存)

若某一维两者既不相等、也都不是 1 → 报错(不兼容)。

示例:(2,3) + (3,)
  (2, 3)
  (   3)   → 左补1 → (1, 3)
  ─────────
  逐维:2 vs 1 → 拉伸 1 到 2 ✅ ;3 vs 3 → 相等 ✅
  结果:(2, 3)

4. 常见例子

import numpy as np
 
# ① 矩阵 + 标量(标量广播到每个元素)
A = np.array([[1, 2, 3], [4, 5, 6]])   # (2,3)
A + 10                                  # 每个元素 +10
 
# ② 矩阵 + 行向量(每行都加这个向量)
A + np.array([10, 20, 30])              # (2,3)+(3,) → 每行加 [10,20,30]
 
# ③ 矩阵 + 列向量(每列都加)—— 需要 reshape 成 (2,1)
col = np.array([100, 200]).reshape(2, 1)  # (2,1)
A + col                                   # 每行分别加 100 / 200
 
# ④ 行向量 + 列向量 → 外积式扩展成矩阵
row = np.array([1, 2, 3])          # (3,) → (1,3)
col = np.array([10, 20]).reshape(2, 1)  # (2,1)
row + col                          # (2,3):每个位置 = col[i] + row[j]

5. 一个高频实战:数据标准化

广播最典型的用途——对每一列做归一化(减均值除标准差):

X = np.random.randn(100, 5)     # 100 个样本,5 个特征
mean = X.mean(axis=0)           # (5,) 每列均值
std = X.std(axis=0)             # (5,) 每列标准差
X_norm = (X - mean) / std       # (100,5) - (5,) → 广播,每行都减/除

(100,5)(5,) 相减,(5,) 被广播成 (1,5) 再拉伸到 (100,5)——一行代码完成对所有样本的标准化。

6. 常见坑

  • 行向量 vs 列向量搞错(3,) 默认当行向量 (1,3) 广播;要按列广播必须 reshape(-1,1) 变成列向量
  • 一维数组的歧义(3,)(3,1)(1,3) 广播行为不同,明确意图时显式 reshape
  • 意外的形状爆炸(1000,1) + (1,1000) 会得到 (1000,1000) 的大矩阵,可能瞬间爆内存
  • 以为报错其实静默广播:本想逐元素运算两个”应该同形”的数组,结果一个是 (n,) 一个是 (n,1),被广播成 (n,n),结果全错但不报错——多用 .shape 检查
  • 广播不复制内存但结果会:广播本身不占额外内存,但运算结果是新数组,大形状仍会占内存

7. 延伸阅读 / 关联概念

  • NumPy 基础 — 广播依附于 NumPy 数组;见 numpy-basics.md
  • 矩阵运算 — 广播用于逐元素运算,和矩阵乘法 @ 是不同机制;见 matrix-operations.md
  • PyTorch — 张量广播规则与 NumPy 完全一致;见 torch.md
  • 向量化 (Vectorization) — 用数组运算替代 Python 循环的编程范式,广播是其基石
  • 官方文档:https://numpy.org/doc/stable/user/basics.broadcasting.html