简介
监督学习模型通常都有一个目标函数,用来描述预测值和真实值之间的差异。训练模型就是要寻找可以取到目标函数最小值的参数,而梯度下降(Gradient Descent)就是一种求解的方法。
网上通常用下山描述这种方法:
- 在当前位置寻找山坡最陡峭的方向
- 水平迈出一步,落到新的位置
- 重复以上,直到垂直高度不再降低,也就是到达山底。
这里的山坡可以看作二元二次函数,最陡峭的方向就是梯度的方向,也就是两个未知数偏导数切线矢量和的方向。设步长为s,切线斜率为 ,对于水平的一步s来说,垂直方向下降的距离是(这里s是固定的, 是会变的,不同的未知数有不同的),当垂直下降的距离小于某个值的时候,就可以认为已经达到最低点了。这种算法很好理解,但是自己实现的话又觉得一些细节不是很清楚,所以在这里总结一下。
举例
以一元线性回归模型为例,假设
(其中X中第二列为截距),很容易算出模型是,现在使用GD计算其参数。
设模型为,该模型的目标函数是MSE
现在要寻找使的L最小的a和b的值。
- 先求偏导数
- 再按照的方法不停迭代,直到找到合适的 。
Python代码如下,计算出来的结果是
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)
由偏导数求解可以看出,,可以用矩阵运算改进上述算法。
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;另一个问题是矩阵运算容易搞不清楚。因此找个实例一步步算下来,对于搞清这个问题是个不错的方法。