这篇博客的内容是为了介绍梯度下降算法在模型优化中的作用,也就是说,正常的顺序是我们要学习一个模型(确定模型参数),在优化这么未知模型的时候,使用的是梯度下降算法。 那么为了先理解下什么是梯度下降,我们假设损失函数是已知的 — y=x^2,一个小学的时候就认识的函数。 在此对这个函数做两点说明: 1.x是一个变量,不是一个向量,所以输入特征就是一维的。 2.该损失函数前没有加1/2,在下面的损失函数定义中加了1/2只是为了求导方便而已,其实他们没有什么区别。
所以,这么损失函数如下:
我们的目标是min(y),也就是让损失函数最小(目标与实际作为接近),那么梯度下降法为什么能让损失函数朝着最小的方向优化呢? 上述损失函数的梯度为:g(x)=2x,设步长为alpha,其最小的y=0,此时对应的x=0,所以x=0是我们的最终目标。
如果在x0>0的初值位置开始下降,则下一次的值是x1=x0-2*alpha*x0,它比x0更接近原点; 如x0=2,alpha=0.1,则x1=2-2*0.1*2=1.6。显然x=1.6时,损失函数比x=2时更小了,我们离目标更近了一步。 如果在x<0的初值位置开始下降,则下一次的值是x1=x0-2*alpha*x0,由于x0是负数,它依然比x0更接近原点。 如x0=-2,alpha=0.1,则x1=-2-2*0.1*(-2)=-1.6。显然x=-1.6时,损失函数比x=-2时更小了,我们离目标也会更近了一步。
而在机器学习的模型优化中,模型是未知的(目的就是为了训练模型),所以损失函数也是未知的,我们希望用梯度下降法找到最小的损失函数,此时对应的权值就是我们想要的最终结果。 需要注意的地方是,上面的内容,我们的变量是x,梯度下降算法每一次改变的也是x的值,而在机器学习中我们的变量是权系数,而已知量是我们的数据,所以下面的内容梯度下降算法每次改变的值是w!!!!!!!
梯度下降法(gradient descent)是一个最优化算法,通常也称为最速下降法。梯度下降法是求解无约束优化问题最简单和最古老的方法之一,现在更多的用于机器学习中用来递归性地逼近最小偏差模型。尤其是对于神经网络中的反向传播算法,梯度下降法为其提供了理论基础。 在理解Logistic回归算法原理与Python实现的文章中提到过一般的机器学习步骤,而梯度下降算法在这其中的作用为优化模型,所以在这之前我们需要先假设一个损失函数(loss function)以确定要优化的目标。损失函数的定义有很多种,最为常见的就是差平方了:
随后我们就可以使用梯度下降算法去求得满足条件的一组权系数。
梯度的基本概念: 梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数沿着梯度方向变化最快,变化率最大,在二维平面中梯度也可以表示斜率。
而确定下降方向就是通过确定权系数向量中每一个系数,将上式中的权系数向量写成分量形式:
其中:
现在回到问题最开始的地方,在确定了损失函数后,一共有D个训练样本,每一个训练样本都有i个特征,对应的权系数向量中也就有i个分量。那么批量梯度下降的流程即为:
从批量梯度下降算法可以看到,每一次下降过程都需要所有样本的参与,在样本数量很大的时候批量梯度下降算法就会有很大的运算量,随机梯度下降算法能够有效解决这个问题。 随机梯度下降算法每次只随机选择一个样本来更新模型权值,得到近似的梯度下降搜索。这意味着我们需要重新定义模型的损失函数为单个随机样本d的平方差:
根据批量梯度下降算法中的推导过程,我们可以得出:
所以,随机梯度下降算法的过程为:
可见,随机梯度下降算法与批量梯度下降算法的区别就在于前者随机选择某一个样本决定下降的梯度,而后者选用全部样本。这也带来了随机梯度下降算法的一些其他特性: (1)如果损失函数有多个局部最小点,随机梯度下降算法能更好的避免陷入局部最小。这样便可能对于非凸函数,最终收敛于一个较好的局部极值点,甚至全局极值点。 (2)随机梯度下降算法由于选用单个点,所以每一次下降的方向可能不是朝着最小值的方向,者带来了收敛速度变慢,但是相比于节省下来的计算消耗,整体速度会更快一些。 (3)由于随机梯度下降算法一次更新的速度远远小于批量梯度下降算法(尤其在大样本情况下),所以前者的步长往往会更小。
当我们理解了SGD(Gradient descent variants)和SGD(Stochastic gradient descent)各自的特点之后,小批量梯度下降(Mini-batch gradient descent)也就自然明白了,它每一次下降的梯度方向由一个小批量的样本决定(所有样本中的一小部分),也就是在Deep Learning中经常能够看到的那个Mini-batch,所以可以说深度学习中用的都是小批量的思想,只是对应不同的梯度下降算法(动量,冲量等等)。 小批量梯度下降的优势在于它克服了批量梯度下降算法的计算时间长,同时梯度的计算又比随机梯度下降更准确。
注意,下面的代码更像是三个伪代码,并不能真正的执行,更多是像强调三种算法间的区别: 批量梯度下降:
for i in range(nb_epochs):
params_grad = evaluate_gradient(loss_function, data, params)
params = params - learning_rate * params_grad
在上述代码中,nb_epochs为迭代次数;data是所有的数据;params_grad是每一个权系数的梯度方向,显然它是一个向量;learning_rate * params_grad 就是权系数要改变的量。
随机梯度下降:
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
参考上面的代码,data变成了example ,所以BGD变成了SGD。
小批量梯度下降:
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
再参考上面代码,这次变成了batch,所以就是Mini-batch gradient descent了,绕来绕去的高大上的名词,其实就是这么简单。
最后,需要说明的是,权系数每一次改变就是负梯度的方向,而不同的模型与损失函数求取梯度时也将不同,本文的公式推导与代码针对于开头处的假设条件。