39.2_sum函数的实现
39.2 sum函数的实现
在DeZero的sum函数的反向传播中,梯度的元素会复制为输入变量的形状。然而反向传播需要对Variable实例进行计算,这意味着复制操作必须作为DeZero函数运行。

将元素复制为指定形状的操作与NumPy的广播功能相同。这个操作将在下一个步骤中通过broadcast_to(x, shape)函数实现。该函数用于将x(Variable实例)复制为shape的形状。
这里预先使用broadcast_to函数。这样一来,我们就可以用如下代码实现DeZero的Sum类和sum函数。
dezero/functions.py
class Sum(Function): def forward(self, x): self.x_shape = x.shape y = x.sum() return y def backward(self, gy): gx = broadcast_to(gy, self.x_shape) return gx
def sum(x): return Sum() (x)在上面的代码中,反向传播的处理使用了将在下一个步骤实现的broadcast_to函数。通过这个函数复制梯度gy的元素,使其与输入变量在形状上一致,这样就实现了sum函数。下面我们尝试使用一下刚刚实现的sum函数。
steps/step39.py
import numpy as np
fromdezero import Variable
importdezero-functionsasF
$\begin{array}{rl} & {\mathrm{x} = \mathrm{Variable}(\mathrm{np.array}([1,2,3,4,5,6]))}\\ & {\mathrm{y} = \mathrm{F.sum(x)}}\\ & {\mathrm{y/backward()}}\\ & {\mathrm{print(y)}}\\ & {\mathrm{print(x.grad)}} \end{array}$运行结果
variable(21)
variable([1 1 1 1 1 1])上面的代码正确地完成了加法运算并求出了梯度。sum函数也支持输入变量不是向量的情况。下面是对二维数组(矩阵)进行计算的结果。
steps/step39.py
$\mathbf{x} =$ Variable(np.array([[1,2,3],[4,5,6]]))
y $=$ F.sum(x)
y.backup()
print(y)
print(x.grad)运行结果
variable(21)
variable([[1 1 1]
[1 1 1]])如上面的结果所示,x.grad的形状和x的形状相同,输出的值也正确。通过以上代码,我们实现了“基础版”的sum函数。接下来,我们将扩展当前的sum函数,实现真正的sum函数。