相信大家在使用numpy和tensorflow的时候都会遇到如下的错误,
ValueError: operands could not be broadcast together with shapes (4,3) (4,)
这是由于numpy和tensorflow中的张量在进行运算的时候形状不满足广播机制的要求,不理解广播机制的同学可能会通过各种魔改代码来让代码正常运行起来,但是却不知道为什么那样改就可以。
本文将从原理上介绍张量运算中经常用到的广播机制。
广播(broadcasting)指的是不同形状的张量之间的算数运算的执行方式。
通过两个例子直观了解广播
数组与标量值的乘法
import numpy as np
arr = np.arange(5)
arr #-> array([0, 1, 2, 3, 4])
arr * 4 #-> array([ 0, 4, 8, 12, 16])
在上面的乘法运算中,标量值4被广播到了其他所有元素上
通过减去列平均值的方式对数组每一列进行距平化处理
arr = np.random.randn(4,3)
arr #-> array([[ 1.83518156, 0.86096695, 0.18681254],
# [ 1.32276051, 0.97987486, 0.27828887],
# [ 0.65269467, 0.91924574, -0.71780692],
# [-0.05431312, 0.58711748, -1.21710134]])
arr.mean(axis=0) #-> array([ 0.93908091, 0.83680126, -0.36745171])
关于mean
中的axis
参数,可以这样理解:
在numpy
中,axis = 0
为行轴(竖直方向),axis = 1
为列轴(水平方向),指定axis
表示该操作沿axis
进行,得到结果将是一个shape
为除去该axis
的array
,对于多维张量,axis=i
是指运算操作沿着底i
个张量下标变化的方向进行。
在上例中,arr.mean(axis=0)
表示对arr
沿着轴0(竖直方向)求均值。显然,第0
个下标变化的方向即为竖直方向,以第一列为例,4个元素的下标分别为[(0,0),(1,0),(2,0),(3,0)]
。
而arr
的shape为(4,3)
,除去axis=0
的shape,结果为(1,3)
或者(3,)
,这与上面的代码运行结果相符。
广播机制的原理
如果两个数组的后缘维度(从末尾开始算起的维度)的轴长度相符或其中一方的长度为1,则认为它们是广播兼容的。广播会在缺失维度和(或)轴长度为1的维度上进行。
demeaned = arr - arr.mean(axis=0)
demeaned
> array([[ 0.89610065, 0.02416569, 0.55426426],
[ 0.3836796 , 0.1430736 , 0.64574058],
[-0.28638623, 0.08244448, -0.