带动量的随机梯度下降算法-从原理到实践

Posted by TheMatrix on 2020-04-03

Stochastic Gradient Descent

       大家都知道标准的随机梯度下降算法通过在每次迭代中沿Loss的负梯度方向采取小步长来更新网络参数(权重和偏差)以最小化损耗函数,更新为:

其中l是迭代数,α> 0是学习率,θ是参数向量,E(θ)是损失函数。 在标准梯度下降算法中,使用整个训练集评估损失函数的梯度)E(θ),而标准梯度下降算法立即使用整个数据集。相比之下,在每次迭代中,随机梯度下降算法会使用训练数据的子集评估梯度并更新参数。 每次迭代使用一个不同的子集,称为mini-baches。 训练算法在整个训练集中使用小批量通过整个训练集是一个epoch。 随机梯度下降是随机的,因为使用小批量计算的参数更新是由于使用完整数据集而导致的参数更新的嘈杂估计。

Stochastic Gradient Descent with Momentum

       随机梯度下降算法可以沿最速下降路径向最优路径振荡。 在参数更新中添加动量项是减少这种振荡的一种方法, 具有动量的随机梯度下降(SGDM)更新为:

其中,γ确定前一个梯度步骤对当前迭代的贡献,其代表动量因子,值越大代表“更相信”以前的梯度方向。

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
%% 测试sgdmupdate函数(R2019b及以后新版本)的工作原理
params = rand(3,3,4);
grad = ones(3,3,4);
vel = [];
learnRate = 0.05;
momentum = 0.95;

paramsPrevious = params(1:3,1,1);
paramsPost = paramsPrevious;
velCal = vel;
testNums = 3;
for i = 1:testNums
[params,vel] = sgdmupdate(params,grad,vel,learnRate,momentum);
fprintf('%s\n',['--------------','当前迭代次数:',num2str(i),'-----------']);
fprintf('%s\n','通过sgdmupdate函数更新的参数和速度为:')
params(1:3,1,1),vel(1:3,1,1)

tt = -learnRate.*grad(1:3,1,1)+momentum.*(paramsPost-paramsPrevious);
temp = paramsPost-learnRate.*grad(1:3,1,1)+momentum.*(paramsPost-paramsPrevious);
paramsPrevious = paramsPost;
fprintf('%s\n','通过sgdm公式计算更新的参数和速度为:')
paramsPost = temp
velCal = tt
end

输出结果为:
--------------当前迭代次数:1-----------
通过sgdmupdate函数更新的参数和速度为:
ans =
0.0475
0.2285
0.4969
ans =
-0.0500
-0.0500
-0.0500
通过sgdm公式计算更新的参数和速度为:
paramsPost =
0.0475
0.2285
0.4969
velCal =
-0.0500
-0.0500
-0.0500
--------------当前迭代次数:2-----------
通过sgdmupdate函数更新的参数和速度为:
ans =
-0.0500
0.1310
0.3994
ans =
-0.0975
-0.0975
-0.0975
通过sgdm公式计算更新的参数和速度为:
paramsPost =
-0.0500
0.1310
0.3994
velCal =
-0.0975
-0.0975
-0.0975
--------------当前迭代次数:3-----------
通过sgdmupdate函数更新的参数和速度为:
ans =
-0.1926
-0.0116
0.2568
ans =
-0.1426
-0.1426
-0.1426
通过sgdm公式计算更新的参数和速度为:
paramsPost =
-0.1926
-0.0116
0.2568
velCal =
-0.1426
-0.1426
-0.1426

从上面结果可以看出,通过自写的带动量随机梯度下降算法与官方函数结果一致,从而验证了方法的正确性。