46.4_SGD以外的优化方法
46.4 SGD以外的优化方法
基于梯度的优化方法多种多样。比较有代表性的方法有Momentum、AdaGrad(参考文献[27])、AdaDelta(参考文献[28])和Adam(参考文献[29])等。引入Optimizer类是为了轻松切换这些不同的优化方法,这里我们通过继承基类Optimizer来实现其他优化方法。本节将实现Momentum这一优化方法。

AdaGrad、AdaDelta和Adam等优化方法的代码在dezero/optimizers.py中。本书不对这些方法进行讲解。感兴趣的读者请参考《深度学习入门:基于Python的理论与实现》的6.1节。
Momentum方法的式子如下所示。
其中, 是需要更新的权重参数, 是梯度(损失函数 对 的梯度), 是学习率。另外, 相当于物理学中的速度。式子46.1表示这样一个物理法则:物体在梯度方向上受到一个力,这个力使物体加速。式子46.2表示物体以该速度移动位置(参数)。

式子46.1中有一个 。该项的作用是让物体在没有受任何力的作用时逐渐减速(可将 设置为0.9这样的值)。
Momentum的代码如下所示,类名为MomentumSGD。
dezero/optimizers.py
import numpy as np
class MomentumSGD(Optimizer): def__init__(self,lr $= 0.01$ ,momentum $\equiv 0.9$ super().__init_(self.lr $=$ lr self.momentum $=$ momentum self.vs $=$ {} defupdate_one(self,param): v_key $=$ id(param) ifv_keynot in self.vs: self.vs[v_key] $=$ np.zeros_like(param.data) v $=$ self.vs[v_key] v $\ast =$ self.momentum v $= =$ self.lr \* param_grad.data param.data $+ =$ v上面的每个参数都拥有相当于速度的数据。因此,在上面的代码中字典的实例变量被设置为self.vs。vs在初始化时是空的,但当update_one()第一次被调用时,它会创建在形状上与参数相同的数据。之后,将式子46.1和式子46.2用代码实现即可。

dezero/optimizers.py中MomentumSGD类的代码与上面的代码有些不同。
dezero/optimizers.py中为了支持GPU,在np.ones_like方法之前根据数据类型调用了CuPy的copy.ones_like方法。步骤52中会实现对GPU的支持。
以上就是Momentum的代码。现在我们可以把之前实现的训练代码中的优化方法轻松切换到Momentum。只要将optimizer = SGD(lr)替换为optimizer = MomentumSGD(lr)即可,不需要进行其他任何修改。这样我们就可以轻松切换各种优化方法了。
步骤47
softmax函数和交叉熵误差
此前我们使用神经网络解决了回归问题,现在开始我们要挑战新的问题——多分类。顾名思义,多分类是将数据分类为多个值的问题。对未分类的对象,我们推断它属于哪一个类别。本步骤为进行多分类做准备,下一个步骤将使用DeZero实现多分类。