在很多机器学习和深度学习的应用中,我们发现用的最多的优化器是 Adam,为什么呢?
下面是 TensorFlow 中的优化器:
在 keras 中也有 SGD,RMSprop,Adagrad,Adadelta,Adam 等。
我们可以发现除了常见的梯度下降,还有 Adadelta,Adagrad,RMSProp 等几种优化器,都是什么呢,又该怎么选择呢?
在 SebasTIan Ruder 的这篇论文中给出了常用优化器的比较,本文将梳理:
每个算法的梯度更新规则和缺点
为了应对这个不足而提出的下一个算法
超参数的一般设定值
几种算法的效果比较
选择哪种算法
优化器算法简述
首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD,
这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度,
这样的话自然就涉及到一个 trade-off,即参数更新的准确率和运行时间。
梯度更新规则:
BGD 采用整个训练集的数据来计算 cost funcTIon 对参数的梯度:
缺点:
由于这种方法是在一次更新中,就对整个数据集计算梯度,所以计算起来非常慢,遇到很大量的数据集也会非常棘手,而且不能投入新数据实时更新模型
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梯度更新规则:
和 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
看代码,可以看到区别,就是整体数据集是个循环,其中对每个样本进行一次参数更新。
缺点:
但是 SGD 因为更新比较频繁,会造成 cost function 有严重的震荡。
BGD 可以收敛到局部极小值,当然 SGD 的震荡可能会跳到更好的局部极小值处。
当我们稍微减小 learning rate,SGD 和 BGD 的收敛性是一样的。
3. Mini-batch gradient descent梯度更新规则:
MBGD 每一次利用一小批样本,即 n 个样本进行计算。这样它可以降低参数更新时的方差,收敛更稳定。另一方面可以充分地利用深度学习库中高度优化的矩阵 *** 作来进行更有效的梯度计算。
和 SGD 的区别是每一次循环不是作用于每个样本,而是具有 n 个样本的批次
for i in range(nb_epochs):
np.random.shuffle(data)
for batch in get_batches(data, batch_size=50):
params_grad = evaluate_gradient(loss_function, batch, params)
params = params - learning_rate * params_grad
超参数设定值:
n 一般取值在 50~256
缺点:
不过 Mini-batch gradient descent 不能保证很好的收敛性,
learning rate 如果选择的太小,收敛速度会很慢,如果太大,loss function 就会在极小值处不停地震荡甚至偏离。
有一种措施是先设定大一点的学习率,当两次迭代之间的变化低于某个阈值后,就减小 learning rate,不过这个阈值的设定需要提前写好,这样的话就不能够适应数据集的特点。
此外,这种方法是对所有参数更新时应用同样的 learning rate,如果我们的数据是稀疏的,我们更希望对出现频率低的特征进行大一点的更新。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)