【Task6(2天)】PyTorch理解更多神经网络优化方法
-
了解不同优化器
SGD
随机梯度下降法是梯度下降法的一个小变形,就是每次使用一批(batch) 数掘进行梯度的计算,而不是计算全部数据的梯度.因为现在深度学习的数据量都特别大, 所以每次都计算所有数据的梯度是不现实的,这样会导致运算时间特别长,同时每次都计
算全部的梯度还失去了一些随机性, 容易陷入局部误差,所以使用随机梯度下降法可能每次都不是朝着真正最小的方向.但是这样反而容易跳出局部极小点。Momentum
第二种优化方法就是在随机梯度下降的同时,增加动量(Momentum) 。这来自于物理中的概念, 可以想象损失函数是一个山谷,一个球从山谷滑下来,在一个平坦的地势,球的滑动速度就会慢下来,可能陷入一些鞍点或者局部极小值点。这个时候给它增加动量就可以让它从高处滑落时的势能转换为平地的功能,相当于惯性增加f小球在平地滑动的速度,从而帮助其跳出鞍点或者局部极小点。动量的计算基于前面梯度,也就是说参数更新不仅仅基于当前的梯度,也基于之前的梯度。
通俗地说,梯度下降的方向是由这一点的方向导数决定的,如果我们考虑小球的惯性,除了这个点上的梯度会决定下一次的前进方向外,上一次前进方向由于惯性也会影响下一次的前进方向,这样两个方向的合力生成下一次小球的加速度。
RMSprop
RMSProp算法的全称叫 Root Mean Square Prop,是Geoffrey E. Hinton在Coursera课程中提出的一种优化算法,在上面的Momentum优化算法中,虽然初步解决了优化中摆动幅度大的问题。所谓的摆动幅度就是在优化中经过更新之后参数的变化范围,如下图所示,蓝色的为Momentum优化算法所走的路线,绿色的为RMSProp优化算法所走的路线。为了进一步优化损失函数在更新中存在摆动幅度过大的问题,并且进一步加快函数的收敛速度,RMSProp算法对权重 WW 和偏置 bb 的梯度使用了微分平方加权平均数。
其中,假设在第 tt 轮迭代过程中,各个公式如下所示:sdw=βsdw+(1−β)dW2sdw=βsdw+(1−β)dW2
sdb=βsdb+(1−β)db2sdb=βsdb+(1−β)db2
W=W−αdWsdw√+εW=W−αdWsdw+ε
b=b−αdbsdb√+εb=b−αdbsdb+ε算法的主要思想就用上面的公式表达完毕了。在上面的公式中sdwsdw和sdbsdb分别是损失函数在前t−1t−1轮迭代过程中累积的梯度梯度动量,ββ 是梯度累积的一个指数。所不同的是,RMSProp算法对梯度计算了微分平方加权平均数。这种做法有利于消除了摆动幅度大的方向,用来修正摆动幅度,使得各个维度的摆动幅度都较小。另一方面也使得网络函数收敛更快。(比如当 dWdW 或者 dbdb 中有一个值比较大的时候,那么我们在更新权重或者偏置的时候除以它之前累积的梯度的平方根,这样就可以使得更新幅度变小)。为了防止分母为零,使用了一个很小的数值 ϵϵ 来进行平滑,一般取值为10−810−8。
2.书写优化器代码
Momentum
#动量算法,我们希望每次累加的量但是更加重视当下的梯度,因此要做一个随着时间变化的加权平均
J=0
JJ=[]#用来记录梯度的值
for i in range(1000):
J=0.9J+0.1J_prime(1)
#我们对当下的梯度赋予一个权重,J_prime是当下梯度
JJ.append(J)
plt.plot(JJ)
#动量梯度下降法,一定要初始化v
w=1
epoch=100
lr=0.001
beta=0.5
y=[]
v=0
Loss=[]
W=[]
for i in range(epoch):
v=betav + (1-beta)J_prime(w)
#第一次的梯度是没有的,所以初始化为0,beta控制两次梯度的权重来合成新的梯度
w=w-lrv
#用v进行梯度更新
Loss.append(J(w))
W.append(w)
plt.plot(Loss)
plt.figure()
plt.plot(W)
w
#二维情况下的随机梯度下降
J = lambda w1,w2: w1**2 + 10w2**2
#是一个椭圆函数,w1和w2的初值差异比较大
J_prime1 = lambda w1: 2w1
J_prime2 = lambda w2:20w2
#设初值
w1 = 1
w2 = -1
epoch = 200
lr = 0.01
y = []
v = 0
s = 0
Loss = []
W1 = []
W2 = []
for i in range(epoch):
w1 = w1 - lr*(J_prime1(w1))
w2 = w2 - lr*(J_prime2(w2))
W1.append(w1)
W2.append(w2)
Loss.append(J(w1,w2))
plt.plot(Loss)
plt.figure()
plt.plot(W1)
plt.plot(W2)
w1,w2
Adagrad
#Ada自适应梯度调节法,为了解决两个参数优化是差异过大存在的问题,调节不同方向上梯度变化
J = lambda w1,w2: w12 + 10*w22
#是一个椭圆函数,w1和w2的初值差异比较大
J_prime1 = lambda w1: 2w1
J_prime2 = lambda w2:20w2
#设初值
w1 = 1
w2 = -1
epoch = 200
lr = 0.01
y = []
v = 0
s = 0
Loss = []
W1 = []
W2 = []
s1 = s2 = 0
for i in range(epoch):
s1 += J_prime1(w1)*2
w1 = w1 - lr(J_prime1(w1)/np.sqrt(s1))
#大的梯度变化会除以更大的归一化因子
s2 += J_prime2(w2)*2
w2 = w2 - lr(J_prime1(w2)/np.sqrt(s2))
W1.append(w1)
W2.append(w2)
Loss.append(J(w1,w2))
plt.plot(Loss)
plt.figure()
plt.plot(W1)
plt.plot(W2)
w1,w2#引入动量的思想
s = 0
S = []
beta = 0.8
for i in range(100):
s = 0.2s + 0.8J_prime1(w1)*2
S.append(np.sqrt(s))
w1 = w1 -lr(J_prime1(w1)/s)
W1.append(w1)
plt.plot(S)
plt.figure()
plt.plot(W1)RMSProp
J = lambda w1,w2: w12 + 10*w22
#是一个椭圆函数,w1和w2的初值差异比较大
J_prime1 = lambda w1: 2w1
J_prime2 = lambda w2: 20w2
#设初值
w1 = 1
w2 = -1
epoch = 200
lr = 0.01
beta2 = 0.5
y = []
v = 0
s = 0
Loss = []
W1 = []
W2 = []
s1 = s2 = 0
for i in range(epoch):
s1 = beta2s1 + (1-beta2)(J_prime1(w1)2)#引入动量的思想
s1_correct = s1/(1-beta2(i+1))#s1_correct随时间变化的函数
w1 = w1 - lr*(J_prime1(w1)/np.sqrt(s1))
s2 = beta2s2 + (1-beta2)(J_prime1(w2)2)
s2_correct = s2/(1-beta2(i+1))
w2 = w2 - lr*(J_prime1(w2)/np.sqrt(s2))
W1.append(w1)
W2.append(w2)
Loss.append(J(w1,w2))
plt.plot(Loss)
plt.figure()
plt.plot(W1)
plt.plot(W2)
w1,w2
- PyTorch种优化器选择