之前在 机器学习算法数学基础之 —— 线性代数篇 里,总结过求解线性回归的两种方法:

  1. 最小二乘法
  2. 梯度下降法

这篇文章重点总结一下梯度下降法中的一些细节和需要注意的地方。


梯度下降法是什么

假设有一个估计函数: 机器学习:用梯度下降法实现线性回归 - 图1

其代价函数(cost function)为: 机器学习:用梯度下降法实现线性回归 - 图2

这个代价函数是 x(i) 的估计值与真实值 y(i) 的差的平方和,前面乘上 1/2,是因为在求导的时候,这个系数就不见了。

梯度下降法的流程:

1)首先对 θ 赋值,这个值可以是随机的,也可以让 θ 是一个全零的向量。
2)改变 θ 的值,使得 J(θ) 的值按梯度下降的方向减小。

机器学习:用梯度下降法实现线性回归 - 图3

参数 θ 与误差函数 J(θ) 的关系图

红色部分表示 J(θ) 有着比较高的取值,我们希望能够让 J(θ) 的值尽可能的低,也就是取到深蓝色的部分。θ0、θ1 表示 θ 向量的两个维度。上面提到梯度下降法的第一步,是给 θ 一个初值,假设随机的初值位于图上红色部分的十字点。然后我们将 θ 按梯度下降的方向进行调整,就会使 J(θ) 往更低的方向进行变化,如图所示,算法的结束将在 θ 下降到无法继续下降为止。

θ 的更新: 机器学习:用梯度下降法实现线性回归 - 图4

θi 表示更新前的值,减号后边的部分表示按梯度方向减少的量,α 表示步长,也就是每次按梯度减少的方向变化多少。

梯度是有方向的,对于一个向量 θ,每一维分量 θi 都可以求出一个梯度的方向,我们就可以找到一个整体的方向,在变化的时候,我们就朝着下降最多的方向进行变化,就可以达到一个最小点,不管它是局部的还是全局的。

所以梯度下降法的原理简单来说就是:

在变量空间的某个点,函数沿梯度方向的变化率最大,所以在优化目标函数的时候,沿着负梯度方向减小函数值,可以最快达到优化目标。


特征缩放(Feature Scaling)

在 Stanford 的 Machine Learning 课程中,老师提到了使用梯度下降法时可能用到的特征缩放法,为的是当所要研究的数据集中出现数据值范围相差较大的 feature 时,保证所有 feature 有相近范围内的值。

以课程中的房价问题为例,数据集的 feature 中有房屋尺寸 机器学习:用梯度下降法实现线性回归 - 图5
和房间数量 机器学习:用梯度下降法实现线性回归 - 图6
两项,房屋尺寸的范围是 0~2000 feet^2,房间数量的范围是 1~5。此时以两个参数 机器学习:用梯度下降法实现线性回归 - 图7
机器学习:用梯度下降法实现线性回归 - 图8
为横纵坐标,绘制代价函数 机器学习:用梯度下降法实现线性回归 - 图9
的等高线图如下:

机器学习:用梯度下降法实现线性回归 - 图10

代价函数的等高线图

解决方法是对两个 feature 进行归一化处理:

x1 = size / 2000
x2 = number of rooms / 5

进行特征缩放后,代价函数的等高线图就变成了这样:

机器学习:用梯度下降法实现线性回归 - 图11

特征缩放后的代价函数等高线图

很明显,归一化处理前,代价函数的等高线图高又窄,在梯度下降过程中,需要反复迭代很多次,才能达到理想的位置,会花费较长的时间。归一化处理后,两个 feature 的数值大小处于相近的范围内,因此横纵坐标 机器学习:用梯度下降法实现线性回归 - 图12
机器学习:用梯度下降法实现线性回归 - 图13
两个参数的变化范围也变得相近,对 机器学习:用梯度下降法实现线性回归 - 图14
的影响不再有 feature 值在范围大小伤的影响,从而反映代价函数上。在等高线图上,梯度下降过程中变化受 x1 大小影响的 机器学习:用梯度下降法实现线性回归 - 图15
的变化减小了,变得和 x2 的变化趋势一致,从而等高线图近似圆形。

至于把 feature 缩小到什么范围,没有特别的要求,只要各个 feature 的数值范围相近就可以了,只是为了计算速度可以有所提升。

顺便引用一下 Andrew Ng 老师在课程中用到的例题:

机器学习:用梯度下降法实现线性回归 - 图16


步长 α(学习率)的选择

在参数 机器学习:用梯度下降法实现线性回归 - 图17
的更新式: 机器学习:用梯度下降法实现线性回归 - 图18
中, 机器学习:用梯度下降法实现线性回归 - 图19
称为步长,决定了参数每次被增加或减小的大小,步长如何选择是决定梯度下降法表现的一个因素。如果步长过大,可能会直接越过最佳点,导致无法收敛,甚至发散;如果步长过小,可能导致迭代次数过多,降低效率。

机器学习:用梯度下降法实现线性回归 - 图20

步长的选择过大时,导致越过最佳点

关于步长的选择,有很多种方法,如果初始步长不合适,在后边要不断进行调整,调整的方法有很多种,关于这个问题国内外也有很多论文对其研究过。一旦找到了合适的步长,大多数情况下就不需要再改变了,有人会觉得随着 机器学习:用梯度下降法实现线性回归 - 图21
越来越小,如果步长不变,更新式中第二项的值也会越来越小,迭代的进度会慢下来。但是,随着越来越接近最佳点,梯度也会越来越大,也就是 机器学习:用梯度下降法实现线性回归 - 图22
的微分值也会越来越大,所以迭代的速度并不会变慢。

最常用的选择步长的方法是按 3 倍调整,即:0.001、0.003、0.01、0.03、0.1、0.3、1 …… 按这个倍率进行测试,寻找能使 机器学习:用梯度下降法实现线性回归 - 图23
下降速度最快的步长范围,确定范围后再对其进行微调。


用 Python 实现梯度下降法

import numpy as np import random def gradient_descent(alpha, x, y, ep=0.0001, max_iter=10000): converged = False iter = 0 m = x.shape[0] # 数据的行数 # 初始化参数(theta) t0 = np.random.random(x.shape[1]) t1 = np.random.random(x.shape[1]) # 代价函数, J(theta) J = sum([(t0 + t1*x[i] - y[i])**2 for i in range(m)]) # 进行迭代 while not converged: # 计算训练集中每一行数据的梯度 (d/d_theta j(theta)) grad0 = 1.0/m * sum([(t0 + t1*x[i] - y[i]) for i in range(m)]) grad1 = 1.0/m * sum([(t0 + t1*x[i] - y[i])*x[i] for i in range(m)]) # 更新参数 theta # 此处注意,参数要同时进行更新,所以要建立临时变量来传值 temp0 = t0 - alpha * grad0 temp1 = t1 - alpha * grad1 t0 = temp0 t1 = temp1 # 均方误差 (MSE) e = sum( [ (t0 + t1*x[i] - y[i])**2 for i in range(m)] ) if abs(J-e) <= ep: print 'Converged, iterations: ', iter, '!!!' converged = True J = e # 更新误差值 iter += 1 # 更新迭代次数 if iter == max_iter: print 'Max interactions exceeded!' converged = True return t0,t1

参考:3 Types of Gradient Descent Algorithms for Small & Large Data Sets


相关文章:


第一时间了解更多大数据相关内容,欢迎关注微信公众号【数据池塘】:
https://zhuanlan.zhihu.com/p/33992985