Python 现代开发学习笔记

(九)从对应位置推导广播

1. 一份列偏移应用到每天

现在给早上加 1、晚上加 2。我们需要把 [1,2] 同时用于三天,每个结果仍有三行两列:

# 项目文件:demos/broadcast.py
# 先按末尾轴对齐:每列补偿用长度 2,每行补偿先变成三行一列。
import numpy as np

a = np.array([[10, 20], [30, 40], [50, 60]])
column_offsets = np.array([1, 2])
row_offsets = np.array([100, 200, 300])
print("每列", (a + column_offsets).tolist())
try:
    a + row_offsets
except ValueError:
    print("(3,2)与(3,)末尾2和3不匹配")
print("每行", (a + row_offsets[:, None]).tolist())
print("两边扩展", (np.array([1, 2, 3])[:, None] + np.array([10, 20])).tolist())

形状从右往左对齐:(3,2) 与 (2,) 对齐时,最后一轴都是 2;缺少的前轴按长度 1 参与匹配,成为 (1,2),再扩展到三行。结果为 [[11,22],[31,42],[51,62]]。

这类按照形状对齐的计算叫 广播。对应轴长度相等,或其中一边长度为 1,就能匹配。广播过程中可以重复读取同一份偏移,不必预先复制出三份偏移数组。广播规则

列偏移长度二先对齐最后一轴,前轴按一扩展,三天各自读取同一份早晚偏移

2. 每天的偏移需要保留列轴

若要给三天分别加 100、200、300,(3,) 会先与最后的时段轴 2 对齐,3 与 2 不匹配。把它变成 row_offsets[:,None],shape 为 (3,1):天轴 3 与 3 对齐,时段轴 1 扩展到 2。

于是得到 [[110,120],[230,240],[350,360]]。修正的依据是“同一天两项共用同一个偏移”,由这个对应关系决定在哪个位置插轴。

每天的偏移从三变为三乘一,保留天的对应关系,再沿时段轴展开到两列

3. 输出数组也要计算大小

(3,1) 与 (2,) 还可以共同展开为 (3,2),生成全部行列组合。若两个长度都为一百万,把它们改成列与行后相加,输出就有一万亿项;float64 元素数据约占 8 TB。广播能省去输入的重复复制,结果数组与中间数组仍然需要空间。较大的组合计算可以分批,后面用小批累计展示这种组织方式。

笔记正文与全部题解 · Ctrl / ⌘ K