神经网络技巧篇之寻找最优参数的方法【续】

        上一篇文章介绍了四种寻找最优参数的方法,这次做一个补充,对其中两种方法(Momentum和AdaGrad)做一些改进,让参数的更新收敛更快速
Nesterov
是对Momentum动量SGD的一个改进,在后面也会对两种方法以及改进的方法进行画图,进行比较。
数学式:\small v\leftarrow \alpha v; v\leftarrow v-\eta \frac{\alpha L}{\alpha W}; W\leftarrow W+\alpha \odot \alpha v; W\leftarrow W-(1+\alpha )\eta \frac{\alpha L}{\alpha W}

α=类似摩擦力,v是物理学上的速度,η是学习率,\small \frac{\alpha L}{\alpha W}是损失函数关于权重的梯度(导数)

class Nesterov:
    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 k,v in params.items():
                self.v[k]=np.zeros_like(v)

        for k in params.keys():
            self.v[k]=self.v[k]*self.momentum
            self.v[k]-=self.lr*grads[k]
            params[k]+=self.momentum*self.momentum*self.v[k]
            params[k]-=(1+self.momentum)*self.lr*grads[k]

RMSprop【Root Mean Square prop】
AdaGrad方法会记录过去所有梯度的平方和,因此,学习越深入,更新的幅度就越小。如果无止境地学习,更新量就会变为0,完全不再更新了。为了改善这个问题,使用RMSprop方法,这个方法并不是将过去所有的梯度一视同仁地相加,而是逐渐地遗忘过去的梯度,在做加法运算时,将新的梯度信息更多地反映出来。这样的操作叫做“指数移动平均”,呈指数函数式地减小过去的梯度的尺度
数学式:\small h\leftarrow h\beta ; h\leftarrow h+(1-\beta)\frac{\alpha L}{\alpha W}\odot \frac{\alpha L}{\alpha W}; W\leftarrow W-\eta \frac{1}{\sqrt{h}}\frac{\alpha L}{\alpha W}

其中参数β是衰减指数

class RMSprop:
    def __init__(self,lr=0.01,decay_rate=0.99):
        self.lr=lr
        self.decay_rate=decay_rate
        self.h=None

    def update(self,params,grads):
        if self.h is None:
            self.h={}
            for k,v in params.items():
                self.h[k]=np.zeros_like(v)

        for k in params.keys():
            self.h[k]=self.h[k]*self.decay_rate
            self.h[k]+=(1-self.decay_rate)*grads[k]*grads[k]
            params[k]-=self.lr*grads[k]/(np.sqrt(self.h[k])+1e-7)

进行画图对比:

import numpy as np
import matplotlib.pyplot as plt
from collections import OrderedDict
from common.optimizer import *

def f(x,y):
    return 1/20*x**2 + y**2

def df(x,y):
    '''f函数的偏导数'''
    return 1/10*x,2*y


params={}
#params['x'],params['y']=-7,2#从(-7,2)的位置开始搜索
grads={}
grads['x'],grads['y']=0,0

#使用有序字典保存四种方法,分别遍历进行画图
mySGDDict=OrderedDict()
mySGDDict['Momentum']=Momentum(lr=0.1)
mySGDDict['Nesterov']=Nesterov(lr=0.1,momentum=0.9)
mySGDDict['AdaGrad']=AdaGrad(lr=1.5)
mySGDDict['RMSprop']=RMSprop(lr=0.1,decay_rate=0.99)
idx=1
for k in mySGDDict:
    mySGD=mySGDDict[k]
    x_temp=[]
    y_temp=[]
    params['x'],params['y']=-7,2#分别从(-7,2)的位置开始搜索
    for i in range(30):
        x_temp.append(params['x'])
        y_temp.append(params['y'])
        grads['x'],grads['y']=df(params['x'],params['y'])
        mySGD.update(params,grads)

    #画函数f的等高线
    x=np.arange(-10,10,0.01)
    y=np.arange(-5,5,0.01)
    X,Y=np.meshgrid(x,y)
    Z=f(X,Y)
    plt.subplot(2,2,idx)#画子图
    idx+=1
    plt.plot(x_temp,y_temp,'o-',color='red')
    plt.contour(X,Y,Z)
    plt.plot(0,0,'+')
    plt.title(k)
plt.show()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

寅恪光潜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值