线性回归之Nesterov梯度下降(nesterov)

对于梯度下降,只能说:没有最可怕,只有更可怕。
当动量梯度下降出来之后不久,就有大神再次提出nesterov梯度下降的方法,也是继承了动量梯度的思修,但是它认为,即使当前的梯度为0,由于动量的存在,更新梯度依然会存在并继续更新w。

而继续当前点w的梯度是不太有意义的,有意义的是,假设下一个点w(仅靠动量滚到下一个点的w)的梯度方向才是决定当前梯度的重要因素。

举个通俗的例子就是,你在下坡时,如果在下坡快到底,但又未到底时,动量梯度下降会让你冲到坡的对面去Nesterov梯度下降会预知你的下一步将会时到坡的对面去,所以会提示你提前刹车,避免过度冲到坡的对面去。这包含了一种提前计算下一步的梯度,来指导当前梯度的想法。

而这个怎么实现呢?先看公式:
o l d w = w oldw=w oldw=w
w = w − η ∗ l g ∗ d i s c o u n t w=w-\eta*lg*discount w=wηlgdiscount
计算下一个 w w w的梯度
w = o l d w w=oldw w=oldw
l g = l g ∗ d i s c o u n t + g lg=lg*discount+g lg=lgdiscount+g
w = w − η ∗ l g w=w-\eta*lg w=wηlg

就是每次计算梯的时候用下一次的权重,这样下一次的变化就会反应在这次计算的梯度上,如果下一次权重计算的梯度很大,则说明更新权重的时候更应该把下一次的梯度给加上去。

'''
普通的全梯度下降方法
'''
import numpy as np
import math 
import time

print(__doc__)

sample = 10
num_input = 5

#加入训练数据
np.random.seed(0)
normalRand = np.random.normal(0,0.1,sample)      # 10个均值为0方差为0.1 的随机数  (b)
weight = [5,100,-5,-400,0.02]                    # 1 * 5 权重
x_train = np.random.random((sample, num_input))  # x 数据(10 * 5)
y_train = np.zeros((sample,1))                   # y数据(10 * 1)

for i in range (0,len(x_train)):
    total = 0
    for j in range(0,len(x_train[i])):
        total += weight[j]*x_train[i,j]
    y_train[i] = total+ normalRand[i]

# 训练
np.random.seed(0)
weight = np.random.random(num_input+1)
np.random.seed(0)
recordGrade  = np.random.random(num_input+1)

discount = 0.9
rate = 0.02

start = time.clock()
for epoch in range(0,500):
    #预先走一步,计算下一个的权重w
    oldweight = np.copy(weight)
    for i in range(0,len(weight)):
        weight[i] = weight[i] - rate * discount *  recordGrade[i]

    # 计算loss
    predictY = np.zeros((len(x_train))) 
    for i in range(0,len(x_train)):
        predictY[i] = np.dot(x_train[i],weight[0:num_input])+ weight[num_input]

    loss = 0


    for i in range(0,len(x_train)):
        loss += (predictY[i]-y_train[i])**2     
    print("epoch: %d-loss: %f"%(epoch,loss))  #打印迭代次数和损失函数

    if loss < 0.1:
        end = time.clock()
        print("收敛时间:%s ms"%str(end-start))
        print("收敛成功%d-epoch"%epoch)
        break

    # 计算梯度并更新
    weight = oldweight

    for i in range(0,len(weight)-1):   #权重w
        grade = 0
        for j in range(0,len(x_train)):
            grade += 2*(predictY[j]-y_train[j])*x_train[j,i]
        #计算梯度用下一个权重,计算权重用原来的
        recordGrade[i] = recordGrade[i]*discount + grade
        weight[i] = weight[i] - rate*recordGrade[i]

    grade = 0
    for j in range(0,len(x_train)):    #偏差b

        grade += 2*(predictY[j]-y_train[j])
    recordGrade[num_input]   = recordGrade[num_input]*discount + grade
    weight[num_input] = weight[num_input] - rate*recordGrade[num_input]

print(weight)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值