40.1_broadcast_to 函数和 sum_to 函数

40.1 broadcast_to函数和sum_to函数

首先看一下NumPy的nproadcast_to(x, shape)。这个函数复制x(ndarray实例)的元素,使结果的形状变为shape的形状。它的使用示例如下所示。

import numpy as np  
x = np.array([1, 2, 3])  
y = np broadcaster_to(x, (2, 3))  
print(y)

运行结果

[[123][123]

如上面的代码所示,原本形状为 (3,)(3,) 的一维数组,在元素被复制后变为 (2,3)(2, 3) 。那么在进行广播(即复制元素)之后,反向传播会变成什么样呢?

在DeZero中,同一个变量(Variable实例)可以多次用在计算中。比如 y=x+xy = x + x 这样的计算,我们可以把 x+xx + x 理解为“复制” xx 后再使用它的意思。在反向传播中,梯度两次传播到 xx ,梯度之间执行了加法运算。通过这个原理可知,复制元素之后,只需求梯度的和即可。

在复制元素之后,反向传播会求梯度之和。以nproadcast_to函数为例,其反向传播如图40-1所示。


图40-1 broadcast_to函数的反向传播

如图40-1所示,broadcast_to函数的反向传播会求梯度的和,以使梯度的形状变为输入x的形状。要实现这一点,只要使用一个叫sum_to(x, shape)的函数即可。sum_to函数会求x的元素之和,并将结果的形状变为shape的形状。有了这样的函数,就可以像图40-1这样在正向传播和反向传播之间建立联系了。

sum_to(x, shape) 函数用于求 xx 的元素之和并将结果的形状转变为 shape 的形状。不过 NumPy 中没有这样的函数。因此,DeZero 在dezero/util.py 中提供了一个 NumPy 版本的 sum_to 函数。使用该函数可以进行以下计算。

import numpy as np   
fromdezero.utilis import sum_to   
 $\mathrm{x} = \mathrm{np.array}([1,2,3],[4,5,6])$    
y  $=$  sum_to(x,(1,3))   
print(y)   
y  $=$  sum_to(x,(2,1))   
print(y)

运行结果

[[579]]  
[[6]  
[15]]

如上面的代码所示,sum_to(x, shape)函数会执行求和操作,并将结果的形状变为shape的形状。它的作用与np.sum函数的作用相同,但参数不同。

下面探讨sum_to函数的反向传播。sum_to(x, shape)用于求x的元素之和,使结果的形状变为shape的形状。它的反向传播可以直接使用broadcast_to函数,具体如图40-2所示。


图40-2 sum_to函数的反向传播是broadcast_to函数

如图40-2所示,sum_to函数的反向传播使用broadcast_to函数来复制梯度的元素,使结果的形状变为输入x的形状。以上就是NumPy版本的broadcast_to函数和sum_to函数。下面我们会实现DeZero版本的broadcast_to函数和sum_to函数。