当一些运算涉及不止多个变量而这些变量之间的维度并不匹配时, 就需要将其中一些较小维度的变量进行“广播”, 使其和其他变量匹配. 而这里的维度匹配, 一般是指维度一致, 因为很多操作是 element-wise 的.

这种广播最简单的例子就是将一个标量扩张成一个对应的多维数组, 比如一个 3x5 数组乘上 9, 实际上是将这个数字扩张成了一个 3x5 的所有元素为 9 的矩阵然后进行 element-wise product.

但是对于更加普遍的情形, 广播机制要稍微复杂一些. 考虑有两个数组参与运算的情形. Numpy 和 PyTorch 会在运算前比较他们的维度. 并且都是从最后一个维度逐个向前比较. 对于比较过程中的某一个维度而言, 当他们的尺寸是一样的或者其中一个为 1 的时候, 我们认为在这个维度上两个数组是兼容的. 因为 1)当尺寸一致时自然可以进行 element-wise 操作 2) 当其中一个为 1 时, 我们可以将那个维度的数据 “复制” (实际上并不是, 内存是不变的) 多次直至其尺寸和另一个一致. 如此一来, 我们一直检测到第一个维度, 如果中间有不符合的地方直接认为无法计算.

注意, 两个数组不需要维数完全一样, 对于其中低维度的可以直接将其和高维度的数组想差的维度看做 1. 也就是说, 当 2x3x4 数组 A 和 一个 1x4 数组 B 操作时, 我们会将 B 扩展成 1x1x4, 然后再扩展成 2x3x4.

不过需注意, 在 PyTorch 中, 对数组进行 inplace 操作时, 被操作的数组不可以进行广播.

Julia 中的广播算子

在 Numpy 和 PyTorch 中, 广播是自动进行的, 但是在 Julia 中, 这个操作需要显式地通过 broadcast 函数或者 dot operator 来进行. 比如 [1,2,3] .^ 3 等价于 broadcast(^, [1,2,3], 3). 这在某种程度上其实是个好事, 它让用户更难犯错了.