美文网首页IT@程序员猿媛Python数据科学程序员
深度学习入门--参数更新的优化

深度学习入门--参数更新的优化

作者: 爱吃西瓜的番茄酱 | 来源:发表于2019-04-05 16:54 被阅读6次

    神经网络学习的目的是找到使损失函数的值尽可能小的参数。这是寻找最优参数的问题,解决这个问题的过程称为最优化。而在深度神经网络中,参数的数量非常庞大,最优化问题也就十分复杂。

    之前我们学过随机梯度下降法(SGD)来寻找最优参数,大致思路是:将参数的梯度作为线索,沿梯度方向更新参数,并重复步骤多次,从而逐渐靠近最优参数。

    在随机梯度下降法中有两种求梯度的方式:

    • 利用数值微分求梯度(简单、速度慢)
    • 利用误差反向传播法求梯度(复杂、速度快)

    将SGD实现为一个Python类:

    class SGD:
        def __init__(self, lr=0.01):
            self.lr = lr  # 学习率
    
        def update(self, params, grads):
            for key in params.keys():
                params[key] -= self.lr * grads[key]
    

    虽然SGD简单,但在解决某些问题时,也会显得十分低效。低效的根本原因是:梯度的方向并没有指向最小值的方法。

    为了避免SGD的缺点,还有Momentum、AdaGrad、Adam这三种方法可以取代SGD。。

    Momentum

    Momentum是“动量”的意思,和物理有关。用Python表示如下:

    class Momentum:
        def __init__(self, lr=0.01, momentum=0.9):
            self.lr = lr
            self.momentum = momentum
            self.v = None
    
        def update(self, params, grads):
            if self.v is None
                self.v = {}
                for key, val, in params.items():
                    self.v[key] = np.zeros_like(val)
    
            for key in params.keys():
                self.v[key] = self.momentum*self.v[key] - self.lr*grads[key]
                params[key] += self.v[key]
    

    AdaGrad

    在神经网络的学习中,学习率的值lr很重要,学习率过小,会导致学习花费过多时间;反过来,学习率过大会导致学习发散而不能正确进行。

    在关于学习率的有效技巧中,有一种被称为学习率衰减的方法,即随着学习的进行,学习率不断减小。AdaGrad正是基于这种思想,AdaGrad会为参数的每一个元素适当的调整学习率。

    class AdaGrad:
        def __init__(self, lr=0.01):
            self.lr = lr
            self.h = None
            
        def update(self, params, grads):
            if self.h is None:
                self.h = {}
                for key, val in params.items():
                    self.h[key] = np.zeros_like(val)
                    
            for key in params.keys():
                self.h[key] += grads[key] * grads[key]
                params[key] -= self.lr * grads[key] / (np.sqrt(self.h[key]) + 1e-7) # 加上微小值1e-7,防止除数为零
    

    Adam

    Adam融合了Momentum和AdaGrad两个方法的优点,有望实现参数空间的高效搜索。此外,进行超参数的“偏置校正”也是Adam的特征。

    class Adam:
        def __init__(self, lr=0.001, beta1=0.9, beta2=0.999):
            self.lr = lr
            self.beta1 = beta1
            self.beta2 = beta2
            self.iter = 0
            self.m = None
            self.v = None
            
        def update(self, params, grads):
            if self.m is None:
                self.m, self.v = {}, {}
                for key, val in params.items():
                    self.m[key] = np.zeros_like(val)
                    self.v[key] = np.zeros_like(val)
            
            self.iter += 1
            lr_t  = self.lr * np.sqrt(1.0 - self.beta2**self.iter) / (1.0 - self.beta1**self.iter)         
            
            for key in params.keys():
                self.m[key] += (1 - self.beta1) * (grads[key] - self.m[key])
                self.v[key] += (1 - self.beta2) * (grads[key]**2 - self.v[key])
                params[key] -= lr_t * self.m[key] / (np.sqrt(self.v[key]) + 1e-7)
    

    对于SGD、Momentum、AdaGrad和Adam这四种更新参数的方式。它们各自的最优化的更新路径如下图:



    其中SGD最简单,使用也最广泛。Adam的综合性能最好,最受欢迎。

    我们以MNIST手写数字集为例,比较SGD、Momentum、AdaGrad和Adam这四种方法在学习进展上有多大程度的差异:

    如上图所示,SGD的学习进度最慢,损失函数的值最大;Momentum、AdaGrad和Adam这三种方法的学习进度较快,其中AdaGrad的学习效果最好。

    每天学习一点点,每天进步一点点。

    相关文章

      网友评论

        本文标题:深度学习入门--参数更新的优化

        本文链接:https://www.haomeiwen.com/subject/gnnvbqtx.html