为什么需要梯度下降法
在上一篇内容中我们讲到了对于一个损失函数 ,其中 是自变量,我们希望 最小,那么就相当于要寻找一个 ,使得个 为所有 中的最小值。
那么如何得到这个 呢?
当时我的第一反应是:咱高数课不是学过吗?极值点要么就是不可导的点,要么就是导数为0的点(大概就这么个意思,具体条件有点记不清了)。那么我直接求导使得 ,解方程然后把每个解代入 其中值最小的一个不就是 了吗?和我想法一样的同学请举手哈哈哈。
理论上当然是可以的,然而实际上 通常非常非常非常复杂,所以一般解不出来~~囧放弃这个思路。在讲梯度下降法之前我们先回顾一下导数。
导数的物理含义
我们在高等数学中学习过导数,对于一个函数 ,在 点的导数为 ,直观一点理解就是**的自变量在处产生一个微小的变化后,函数的变化趋势**。举个例子,假设
那么 。
我们知道最低点为 。
当 时,,当 时,,
导数取值的方向是当前点使得 增大的方向,与当前点与最低点的方向相反。显然,如果我们希望自变量 朝最低点移动,那么 的变化方向就应当和导数方向相反。
当 时,,当 时,,
导数的大小代表了当前点的斜率大小。显然,我们希望在移动地更快,加快接近的速度,而在处移动慢一些避免越过最低点。因此 变化的大小应该和导数的大小成正比。
换言之,想要使得函数变小,自变量应该往与导数相反的方向移动,移动的长度应该和导数值的大小成正比。
梯度下降法
理解了导数的物理意义,我们理解梯度下降法就很简单了。如果 是一个多维向量 ,
它的损失函数为 ,
那么它的梯度就是 ,
说白了就是对各个变量的导数组成的向量。那么我们可以把上一部分的结论改为:想要使得函数变小,自变量应该往与梯度相反的方向移动,移动的长度应该和梯度值的大小成正比 ,写成公式就是:
,其中 是更新前的自变量值, 是更新后的自变量值。 是移动的步长,它是一个超参数,需要自己设定,它的选择在实践中非常重要
沿着梯度的方向损失函数一定是变小的吗?
真…不一定。我们来看一个例子。
在数值为30的点,它在x,y方向显然应该是向上和向右,但是叠加之后的梯度却是增大的,所以其实沿着梯度的方向损失函数未必是减小的。怎么办?好像也没啥更好的办法。。。。
学习率
我们知道了想要使得函数变小,自变量应该往与梯度相反的方向移动,移动的长度应该和梯度值的大小成正比。但是每次移动的多少是一个很重要的问题,为什么很重要呢?我们来看下图:
显然,我们使用红,绿、蓝、黄三种方式都满足沿着与梯度相反的方向移动这个条件,但步子太大容易扯着蛋,比如黄线直接跳过了最低点。蓝色步子太小等到天荒地老,而绿色就更有意思了,来回震荡徘徊无法收敛,而红色则恰到好处。但是显然我们无法在实践中画出loss的真正曲线(几万个神经元的神经网络,随时函数复杂的可怕),那么我们怎么判断呢?我们可以看损失函数在每个参数取值时的大小,也就是每更新一次,我算一下损失值,然后看损失的变化。那么对应四种颜色的直线大概是如下图所示:
所以,如果你在训练一个网络,发现损失函数飙升,那么显然步子太大扯着蛋了(学习率过大),如果一直在减小但是减小速度极慢,那么你可能可以考虑把学习率调大一些。那么如果损失函数一直不变了(此时导数接近0)是否就说明我们找到了最优的函数参数了呢?答案是否定的,如下图
显然右边的红色箭头指向的是最低点,但是左边红色箭头的终点导数也为0,也是个极小值点。还有一种极其容易被忽略的情况,大家可以看上图的四个边附近都是平行的平面区域,这些点也是导数为0的点哦。
上图中的鞍点也是导数为0的点。那么怎么办?怎么办?怎么办?
随机梯度下降和批梯度下降
解决的办法有很多,这里只介绍其中一种,随机梯度下降和批梯度下降。
我们假设损失函数为,损失函数与所有的样本都有关系,那么就意味着我们每更新一次参数,都需要对于所有的样本进行一次计算,显然这样做每更新一次参数的计算量是非常大的,我们假设一个epoch为对于所有的样本进行一次计算,那么我们计算n个epoch就只能更新n次参数。那如果我们每次更新参数只用一个样本呢?假设有m个样本,我们同样计算n个epoch,那么那么我们计算n个epoch就可以更新n*m次参数,可以大大加快参数更新的速度!这种每次更新参数只用一个样本的方法就叫随机梯度下降法。
但是我们将了半天只能说明随机梯度下降更新参数的效率比梯度下降高,和解决梯度为0的点不是最优解有啥关系呢?我们知道梯度下降法每次参数更新的方向与梯度相反的方向移动,所以对于一个给定的样本,它的更新方向是固定的,但是随机梯度下降则不是,它使得参数更新的方向有了随机性,因为你随机取了一个样本,但是,梯度为0的点使用随机梯度下降法很可能梯度不为0,那么就可以避免我们的参数更新停在某个梯度为0但是不是最优解的点。说白了就是随机梯度下降引入了随机性。真是法如其名啊哈哈。而且需要注意的是,虽然随机梯度下降引入了随机性,但是并不影响随机梯度的期望,可以理解为它的平均梯度方向还是之前计算的所有样本的梯度方向,但是方差很大。
但是!我们看随机梯度下降似乎还是在瞎走?对啊,因为方差很大,一个样本的梯度和整个损失函数的梯度不是一码事,咋办?批梯度下降应运而生,一个样本的方向不够准确,方差大,我多用几个不就行了?批梯度下降每次更新参数只用多个样本,事实上,由于gpu可以并行计算多个样本,现在的深度学习基本都是使用这种方法。那么问题又来了:多个是多少个?个数(batch size)的大小又对结果有什么影响呢?结合我们之前讲的内容我们可以得到以下结论:
- 批梯度下降的batch size越大,方差越小,下降的方向就越接近梯度的反方向,就是走的方向越准
- 批梯度下降的batch size越大,参数更新的效率越低,我们计算n个epoch就可以更新参数的次数为m*n / batch size,但是多个训练数据loss function求和后,只做一次梯度下降,加速计算。
- 批梯度下降的batch size越大,随机性就越小,参数的更新方向就越固定,可能导致损失函数停留在梯度为0但是不是最优解的点**
- 由于batch size越小,随机性就越大,因此在使用较小的batch size时,尽量不要选择太大的学习率,可能导致不收敛
- 一个常见的方法是线性缩放规则 :当批量大小放大m倍时, 学习率也放大m倍,线性缩放规则往往在batch size比较小时适用, 当批量大小非常大时, 线性缩放会使得训练不稳定
梯度下降与特征归一化
我们在机器学习任务中,常常需要对特征做归一化,也就是把所有的特征映射到同一个取值区间。这么做是为什么呢?我们首先假设损失函数为,对于,它们的导数为,其中是一个固定值,那么和的值的大小显然对于参数更新是有影响的,如果学习率是一个固定值,和的值相差数万倍(完全有可能),那么和的更新也就相差数万倍,这样学习的难度就会增加,因此特征归一化对于使用梯度下降法的算法来说是很重要的。上述过程可以用下图表示:
回顾一下, 这篇博客主要讲了什么是梯度下降法,主要内容有:
-
1.不能通过求解导数为0的方程来最小化损失函数的原始是通常损失函数都比较复杂,难以求解该方程。
-
2.导数的物理含义::想要使得函数变小,自变量应该往与导数相反的方向移动,移动的长度应该和导数值的大小成正比。
-
3.梯度就是对各个变量的导数组成的向量,因此,根据结论2,我们可以知道:想要使得函数变小,自变量应该往与梯度相反的方向移动,移动的长度应该和梯度值的大小成正比。,梯度下降法就是基于这种思想。
-
4.学习率是很重要的超参数,反映了参数更新的步长。
-
5.我们了解了随机梯度下降和批梯度下降,它们使得参数更新的方向有了随机性,可以避免陷入梯度为0但是不是最优解的点。
-
6.为什么要使用特征归一化?特征归一化对于使用梯度下降法的算法来说为什么是很重要的?
希望这篇博客能对大家有所帮助。