梯度下降

简介

监督学习模型通常都有一个目标函数,用来描述预测值和真实值之间的差异。训练模型就是要寻找可以取到目标函数最小值的参数,而梯度下降(Gradient Descent)就是一种求解的方法。

网上通常用下山描述这种方法:

  • 在当前位置寻找山坡最陡峭的方向
  • 水平迈出一步,落到新的位置
  • 重复以上,直到垂直高度不再降低,也就是到达山底。

这里的山坡可以看作二元二次函数,最陡峭的方向就是梯度的方向,也就是两个未知数偏导数切线矢量和的方向。设步长为s,切线斜率为\theta ,对于水平的一步s来说,垂直方向下降的距离是s\times\theta(这里s是固定的,\theta 是会变的,不同的未知数有不同的\theta),当垂直下降的距离小于某个值的时候,就可以认为已经达到最低点了。这种算法很好理解,但是自己实现的话又觉得一些细节不是很清楚,所以在这里总结一下。

举例

以一元线性回归模型为例,假设
X = \begin{vmatrix} 1 & 1 \\ 2 & 1 \end{vmatrix} , Y = \begin{vmatrix} 0 \\ 1 \end{vmatrix}
(其中X中第二列为截距),很容易算出模型是y = x - 1,现在使用GD计算其参数。

设模型为y = ax + b,该模型的目标函数是MSE
L = \frac {1}{2m}\sum(\hat{y} -y)^2=\frac{1}{4}((a + b)^2 + (2a + b -1)^2)
现在要寻找使的L最小的a和b的值。

  • 先求偏导数

\theta_a = \frac{1}{2} ((a+b)\times1+(2a+b-1)\times2) = 2.5a +1.5b -1 \\ \theta_b = \frac{1}{2} ((a+b)\times1+(2a+b-1)\times1) = 1.5a +b -0.5

  • 再按照a = a - \theta_a \times s, b=b-\theta_b\times s的方法不停迭代,直到找到合适的a,b

Python代码如下,计算出来的结果是a= 0.9999999915660277 ,b= -0.9999999863535461

def theta_a(a, b):
    return 2.5 * a + 1.5 * b - 1

def theta_b(a, b):
    return 1.5 * a + b - 0.5

a = 0
b = 0
s = 0.1
t = 1e-10

while True:
    desc_a = theta_a(a, b) * s
    desc_b = theta_b(a, b) * s
    
    if abs(desc_a) < t and abs(desc_b) < t:
        break
    a = a - desc_a
    b = b - desc_b

print(a, b)

由偏导数求解可以看出,\theta_a = mean((\hat{y}-y)\times X_a), \theta_b = mean((\hat{y}-y)\times X_b),可以用矩阵运算改进上述算法。

import numpy as np
s = 0.1
t = 1e-10

X = np.array([[1,1],[2,1]])
y = np.array([[0], [1]])
param = np.array([[0.0], [0.0]])

while True:
    desc = (np.dot(X, param) - y) * X
    desc = desc.mean(0) * s
    if np.all(np.abs(desc) < t):
        break
    param -= desc.reshape(-1, 1)
    
print(param)

总结

这里主要介绍了GD算法,我觉得容易迷糊是因为公式中既有X,y又有a,b,而这里X,y是已知的,要求解的是a,b;另一个问题是矩阵运算容易搞不清楚。因此找个实例一步步算下来,对于搞清这个问题是个不错的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。