资讯动态

Python 数组的「广播机制」

发布时间:2026/8/21 7:10:33 来源:尧图企业网站定制
文章目录一、为什么你需要知道广播二、广播到底是什么三、广播的三条黄金规则四、由浅入深的 5 个例子例 1标量 × 数组最基础的广播例 2一维数组「加」到二维数组的每一行例 3列向量「加」到每一列例 4用 None 索引做外积例 5实战——批量图像去中心化五、广播 vs np.tile性能差在哪六、新手最容易踩的 3 个坑七、总结一张表记住广播八、动手练一练NumPy 的广播Broadcasting是让向量化代码又快又优雅的核心秘密。本文用 5 个由浅入深的例子带你从「看不懂」到「用得爽」。一、为什么你需要知道广播先看一段你一定写过的代码把一组温度从摄氏度转成华氏度。temps_c[20,22,25,18,30]temps_f[]fortintemps_c:temps_f.append(t*9/532)逻辑没错但有两个痛点慢——Python 的for循环是解释执行的数据量一大就卡。啰嗦——明明是「每个元素都加 32」却要写一整行循环。NumPy 的解法只有一行importnumpyasnp temps_cnp.array([20,22,25,18,30])temps_ftemps_c*9/532这里temps_c * 9/5没问题数组乘标量但 32呢temps_c是长度为 5 的数组而32只是一个数字形状明明不一样为什么能直接相加答案就是广播Broadcasting。二、广播到底是什么一句话广播是 NumPy 在「形状不同」的两个数组之间进行算术运算时自动把较小数组「虚拟拉伸」成较大数组形状的规则。注意是虚拟拉伸——它不会真的复制数据只是让运算在逻辑上「对齐」。所以广播既省内存又跑得飞快。三、广播的三条黄金规则NumPy 从**最右边的维度尾轴**开始向左逐一比较两个数的形状规则 1相等即可两个维度大小相同直接对齐。规则 2一方为 1 可拉伸两个维度大小不同但其中一个是1那么大小为1的维度会被「复制」成对方的大小。规则 3缺失即补 1如果某一方的维度数更少就在前面补1。只要从尾轴往左每一步都满足「相等或一方为 1」广播就能成功否则抛出ValueError: operands could not be broadcast together。记忆口诀「从右往左比相等或有一方是 1缺的维度补 1」。四、由浅入深的 5 个例子例 1标量 × 数组最基础的广播anp.array([1,2,3])ba5print(b)# [6 7 8]print(b.shape)# (3,)5的形状是()标量按规则 3 补成(1,)再按规则 2 拉伸成(3,)。本质是5被「虚拟地」复制了 3 份。例 2一维数组「加」到二维数组的每一行Anp.array([[1,2,3],[4,5,6]])# shape (2, 3)vnp.array([10,20,30])# shape (3,)print(Av)# [[11 22 33]# [14 25 36]]对齐过程A的形状(2, 3)v的形状(3,)→ 补成(1, 3)规则 3尾轴都是3→ 相等规则 1第 0 轴2vs1→ 一方为 1拉伸规则 2于是v被复制成[10,20,30]的两行分别与A相加。这正是「给每一行加上同一个偏置」的标准写法。例 3列向量「加」到每一列如果反过来想给每一列加不同的值Anp.array([[1,2,3],[4,5,6]])# shape (2, 3)colnp.array([[100],[200]])# shape (2, 1)print(Acol)# [[101 102 103]# [204 205 206]]col形状(2, 1)尾轴1vs3→ 拉伸成3第 0 轴都是2。于是列向量被横向复制 3 列。关键洞察(3,)和(2,1)形状不同但都能和(2,3)广播只是方向不同——一个是按行加一个是按列加。形状里的那个1决定了广播沿着哪个轴展开。例 4用None索引做外积想得到一个i j的矩阵传统写法要双层循环广播一行搞定inp.arange(3)# [0 1 2], shape (3,)jnp.arange(3)# [0 1 2], shape (3,)matrixi[:,None]j[None,:]print(matrix)# [[0 1 2]# [1 2 3]# [2 3 4]]i[:, None]变成(3, 1)j[None, :]变成(1, 3)两者广播成(3, 3)。这种「列向量 行向量」的模式在网格计算、距离矩阵、卷积核构造里极其常见。例 5实战——批量图像去中心化假设有 100 张 32×32 的 RGB 图数据形状是(100, 32, 32, 3)样本数、高、宽、通道。要减去每个通道的均值imagesnp.random.rand(100,32,32,3)mean_per_channelimages.mean(axis(0,1,2))# shape (3,)normalizedimages-mean_per_channelmean_per_channel形状(3,)会自动广播到(1,1,1,3)再拉伸成(100,32,32,3)。无需任何循环一行完成 100 张图、307200 个像素的标准化。这正是深度学习数据预处理每天都在用的写法。五、广播 vsnp.tile性能差在哪有人会想我先用np.tile把小数组真的复制成大数组再相加效果不是一样吗# 方式 A广播推荐resultAv# 方式 B先复制再相加不推荐resultAnp.tile(v,(2,1))两者结果相同但区别巨大内存np.tile真的复制了数据广播只是「逻辑对齐」几乎不占额外内存。速度广播由底层 C 实现避免中间数组的创建与销毁通常快数倍到数十倍。结论能广播就别tile能向量化就别写循环。六、新手最容易踩的 3 个坑坑 1维度对不上却以为能广播anp.array([1,2,3])# (3,)bnp.array([1,2])# (2,)ab# ValueError: operands could not be broadcast together with shapes (3,) (2,)尾轴3vs2既不相等也都不是 1直接报错。坑 2误以为广播会修改原数组广播只是运算时的「临时对齐」不会把小数组真的变大原数组形状始终不变。七、总结一张表记住广播场景小数组形状与大数组广播方向标量运算()任意方向铺满行偏置(n,)复制到每一行列偏置(m,1)复制到每一列外积(m,1)(1,n)展开成(m,n)矩阵最后送你一句口诀「从右往左比形状相等或一为 1缺失补 1 自然齐写前先想轴方向少写循环多广播。」八、动手练一练用广播把np.array([1,2,3,4])的每个元素平方后加 10。构造形状(4,1)和(1,5)两个数组用广播得到4×5的减法表。给定M np.arange(12).reshape(3,4)如何将每一列都减去该列的均值欢迎在评论区写下你的代码下期我们聊聊「np.newaxis与广播的配合技巧」。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价