为什么需要优化算法
有了模型和初始参数,我们便得到了预测目标值;有了预测目标值和真实标签值,代入到损失函数便可以得到误差;那么如何根据这个误差去优化模型,就像在辨认鹿的过程中给予的纠正一样呢?神经网络训练使用的就是优化算法。
损失函数即预测值和真实值的误差是关于网络模型参数的函数,优化算法就是用来更新网络模型参数,使得训练样本的平均损失最小。
当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解(analytical solution)。然而,大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解(numerical solution)。
优化算法有哪些
那么优化算法是如何迭代更新网络模型参数的?核心是利用损失函数关于网络模型参数的梯度。不同的算法无非是怎样更好地改进利用梯度。下面我们详细看一下。
首先再次明确一下对于优化算法,优化的目标是网络模型中的参数θ(是一个集合,θ1、θ2、θ3 ......),而且是不同网络层的参数都会优化;
优化的目标函数为网络模型的损失函数(每个样本损失函数的叠加求均值):
这个损失函数L的变量就是θ,其中L中的参数是整个训练集,换句话说,目标函数(损失函数)是通过整个训练集来确定的,训练集全集不同,则损失函数的图像也不同。
基于此,我们学习一下有哪些优化算法。
1.批量梯度下降法(Batch Gradient Descent,BGD)
最直接的算法就是把整个数据集的所有样本的损失函数对同一个参数的梯度加在一起然后再除以样本总数得到平均梯度,这就是所说的批量梯度下降法。
这里的批量batch指的是所有样本数据(成千上万),不是训练过程中批量大小的batch(训练时一般为32等)
问题在于由于这种方法是在一次更新中,就对整个数据集计算梯度,所以计算起来非常慢,遇到很大量的数据集也会非常棘手,而且不能投入新数据实时更新模型,因为每次投入新数据都需要重新训练更新模型。
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
我们会事先定义一个迭代次数 epoch,首先计算梯度向量 params_grad,然后沿着梯度的方向更新参数 params,learning rate 决定了我们每一步迈多大。
Batch gradient descent 对于凸函数可以收敛到全局极小值,对于非凸函数可以收敛到局部极小值。
2.随机梯度下降法(Stochastic Gradient Descent,SGD)
梯度更新规则:
和 BGD 的一次用所有数据计算梯度相比,SGD 每次更新时,只需要选取一个样本数据进行梯度更新,然后遍历数据集的所有样本,这样相比BGD计算所有样本只更新一次,SGD会更新样本总数次。
另外,对于很大的数据集来说,可能会有相似的样本,这样 BGD 在计算梯度时会出现冗余,而 SGD 一次只进行一次更新,就没有冗余,而且比较快,并且可以新增样本。
for i in range(nb_epochs):
np.random.shuffle(data)
for example in data:
params_grad = evaluate_gradient(loss_function, example, params)
params = params - learning_rate * params_grad
看代码,可以看到区别,就是整体数据集是个循环,其中对每个样本进行一次参数更新。