Introduction to Gradient Descent Algorithm (along with variants) in Machine Learning

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_24133491/article/details/84399195

本文是对此篇文章的翻译

介绍机器学习中梯度下降算法及其变体(Introduction to Gradient Descent Algorithm (along with variants) in Machine Learning)

简介(Introduction)

无论您是处理实际问题还是构建软件产品,优化始终是最终目标。作为一名计算机科学专业的学生,我一直在优化我的代码,以至于我可以夸耀它的快速执行。
优化最基本的含义就是为您的问题获得最优输出。如果你读过最近一篇关于优化的文章,你将会了解优化如何在我们的现实生活中发挥重要作用。
机器学习中的优化略有不同。通常,在优化时,我们确切的知道我们的数据时什么样子的,以及我们希望改进哪些方面。但是在机器学习中,我们不知道我们的“新数据”是什么样子的,更不用说对它进行优化了。
因此,在机器学习中,我们对训练数据进行优化,并对新的验证数据进行性能检验。

优化的广泛应用(Broad applications of Optimization)

有各种各样的优化技术被应用于各个领域,例如:

  • 力学(Mechanics):航天设计的表面
  • 经济学(Economics):成本最小化
  • 物理学(Physics):量子计算中的优化时间

优化还具有决定运输最优路线、货架空间优化等更先进的应用。
许多流行的机器学习算法依赖于优化技术,例如线性回归、k近邻、神经网络等。优化的应用是无限的,是学术界和工业界广泛研究的课题。
在本文中,我们将介绍一种称为Gradient Descen的特定优化技术。它是处理机器学习时最常用的优化技术。

1. 什么是梯度下降?(What is Gradient Descent?)

为了解释梯度下降,我将使用经典的登山例子。
假设你在山顶,你必须到达位于山的最低点(山谷)的湖泊。一个转折点是你被蒙上眼睛,无法看见你所处的位置。那么,你将采取什么办法到大湖泊。
登山图片
最好的方法是查看你附近的地面,观察哪个地方有下降的趋势。这会让你知道应该朝哪个方面迈出第一步。如果你沿着下降的路径走,很可能会到达湖泊。
以图形表示如下图:
梯度下降图形表示
现在让我们用数学术语描述这个场景。
假设我们想要找出学习算法的最佳参数( θ \theta 0)和( θ \theta 1)。与上面的类比相似,当我们绘制“代价空间”时,会发现类似的山脉和山谷。代价空间只不过是我们在为参数选择特定值时算法的执行方式。
所以在y轴上,我们由x轴和z轴上的参数 θ \theta 0 θ \theta 1得到代价J( θ \theta )。这里,用红色代表山丘,代价高;用蓝色代表山谷,代价低。
现在有许多梯度下降算法。它们主要通过两种方法分类:

  • 在数据获取的基础上(On the basis of data ingestion)
    1. 全批处理梯度下降算法
    2. 随机梯度下降算法

在全批处理梯度下降算法中,一次使用全部数据来计算梯度;而在随机梯度下降算法中,在计算梯度时只取一个样本。

  • 在微分技术的基础上(On the basis of differentiation techniques)
    1. 一阶微分
    2. 二阶微分

梯度下降需要通过代价函数的微分来计算梯度。我们可以用一阶微分或者二阶微分。

2. 执行梯度下降的挑战(Challenges in executing Gradient Descent)

梯度下降是一种适用于大多数情况的技术。但在许多情况下,梯度下降不能正常工作或无法工作。发生这种情况的主要原因有三个:

  1. 数据的挑战
  2. 梯度的挑战
  3. 实现的挑战

2.1 数据的挑战(Data Challenges)

  • 如果数据以非凸优化问题的方式排列。利用梯度下降法进行优化是非常困难的。梯度下降法只适用于定义良好的凸优化问题
  • 即使在优化凸优化问题时,也可能存在许多极小值点。最低点称为全局最小值,而其余点称为局部最小值。我们的目标是在避免局部最小值的同时达到全局最小值。
  • 还有一个鞍点问题。这是数据中梯度为零但不是最优点。我们没有具体的方法来避免这一定,这仍然是一个活跃的研究领域

2.2 梯度的挑战(Gradient Challenges)

  • 如果在使用梯度下降时执行不当,可能会导致梯度消失或梯度爆炸问题。这些问题的产生是由于梯度太小或太大。并且,由于这个问题会导致我们的算法无法收敛。

2.3 实现的挑战(Implementation Challenges)

  • 大多数神经网络实践者一般不关注实现,但是研究网络对资源的利用是非常重要的。例如:在实现梯度下降时,注意需要多少资源时非常重要的。如果内存对程序来说太小,那么神经网络就无法实现。
  • 另外,跟踪浮点数因素和硬件/软件先决条件等事项非常重要

3. 梯度下降算法的变体(Variants of Gradient Descent algorithms)

让我们看看最常用的梯度下降算法及其实现。

3.1 简单的梯度下降法(Vanilla Gradient Descent)

这是梯度下降法最简单的形式。这里的vanilla意指纯粹的/不掺假的。它的主要特点是通过对代价函数进行梯度,在极小值方向上采取小步骤。
让我们来看看它的伪代码:

update = learning_rate * gradient_of_parameters
parameters = parameters - update

在这里,我们通过对参数进行梯度变换来更新参数。然后乘以一个学习率,这个学习率本质上是一个常数,表示我们要以多快的速度前往最小值。学习率是一个超参数,在选择学习率的值时应慎重对待。
学习率曲线图

3.2 动量梯度下降法(Gradient Descent with Momentum)

在这里,我们对上述算法进行了调整,以便在采取下一步之前注意前面的步骤。
下面是伪代码:

update = learning_rate * gradient
velocity = previous_update * momentum
parameter = parameter + velocity - update

这里,我们的更新与简单的梯度下降法相同。但是我们引入了一个新的术语叫做速度,它考虑了之前的更新和一个称为动量的常数。
动量更新

3.3 ADAGRAD

ADAGRAD采用自适应技术提高学习速率。在这个算法中,基于梯度在之前所有迭代中的变化,我们试图改变学习速率。
下面是伪代码:

grad_component = previous_grad_component + (gradient * gradient)
rate_change = square_root(grad_component) + epsilon
adapted_learning_rate = learning_rate * rate_change

update = adapted_learning_rate * gradient
parameter = parameter - update

在上面的代码中,epsilon是一个用来控制学习率的变化率的常数。

3.4 ADAM

ADAM是一种基于adagrad的自适应技术,进一步降低了adagrad的缺点。换句话说,你可以把它看作动量+ADAGRAD。
下面是伪代码:

adapted_gradient = previous_gradient + ((gradient - previous_gradent) * (1 - beta1))

gradient_component = (gradient_change - previous_learning_rate)
adapted_learning_rate = previous_learning_rate + (gradient_component * (1 - beta2))

update = adapted_learning_rate * adapted_gradient
parameter = parameter - update

这里的beta1和beta2是常数,用于控制梯度和学习速率的变化。
还有像I-BFGS这样的二阶微分法。你可以在scipy库中看到该算法的实现。

4. 梯度下降的实现(Implementation of Gradient Descent)

现在我们来看一个使用python的梯度下降的基本实现。
在这里,我们将使用梯度下降优化,为我们的深度学习模型在图像识别问题的应用中找到最佳参数。我们的问题是图像识别,从给定的28x28图像中识别数字。我们有一步分数据集用于训练模型,其余的用于测试模型。在本文中,我们将研究如何定义梯度下降,并查看我们的算法如何执行。有关使用python的端到端实现,请参阅本文
下面是定义简单的梯度下降法的主要代码:

params = [weights_hidden, weights_output, bias_hidden, bias_output]

def sgd(cost, params, lr=0.5):
    grads = T.grad(cost=cost, wrt=params)
    updates = []
    
    for p, g in zip(params, grads):
        updates.append([p, p - g * lr])
        
    return updates

updates = sgd(cost, params)

现在我们把它分解以便更好的理解它。
我们定义了一个参数为cost、params和lr的sgd函数。这些代表如前面所见的J( θ \theta ),即我们的深度学习算法的参数和我们的学习率。我们将默认学习率设为0.05,当这可以根据我们的喜好轻松更改。

def sgd(cost, params, lr=0.05):

然后我们根据代价函数定义参数的梯度。在这里,我们使用theano库来找到梯度,并将theano导入为T。

grads = T.grad(cost=cost, wrt=params)

最后遍历所有参数,找出所哟可能参数的更新。你可以看到这里我们使用的是简单的梯度下降法。

for p, g in zip(params, grads):  
   updates.append([p, p - g * lr])  

我们可以用这个函数为我们的神经网络找到最有的参数。使用这个函数,我们发现我们的神经网络在找到图像中的数字方面做的足够好,如下所示:
预测数字
在这个实现中,我们看到使用梯度下降法可以为我们的深度学习算法找到最优参数。

5. 应用梯度下降的实用技巧(Practical tips on applying gradient descent)

上述梯度下降算法各有优缺点。我只提一些可能帮助你选择正确算法的小技巧。

  • 对于想快速得到模型,使用自适应技术,如Adam/Adagrad。这可以帮助你付出更少的努力获得更快的结果。在这里,不需要太多的超参数优化
  • 为了得到最好的结果,你应该使用简单的梯度下降或动量梯度下降。虽然梯度下降的速度慢,当大多优于自适应下降法
  • 如果你的数据量很小,并且可以在一次迭代中使用,那么你可以使用像I-BFGS这样的二阶技术。这是因为二阶技术非常快速和准确,但只有在数据量足够小的情况下才可行
  • 还有一种新型的方法(我还没有尝试过,但看起来很有前途)使用学习特性来预测梯度下降的学习速率。详细阅读本文

神经网络不能学习的原因有很多。但是如果你能监控你的算法哪里出了问题,它会非常有用。
在应用梯度下降法时,你可以看看一下这些点,它们可能有助于解决这些问题:

  • 错误率(Error rates):在特定的迭代之后,你应该检查训练和测试的错误,并确保他们都减少了。如果不是这样,可能会有问题
  • 隐藏层中的梯度流(Gradient flow in hidden layers):检查网络是否存在梯度消失或者梯度爆炸的问题
  • 学习率(Learning rate):在使用自适应技术时应该检查学习率

6. 其他资源(Additional Resource)

猜你喜欢

转载自blog.csdn.net/qq_24133491/article/details/84399195