问题引入
现有一组训练数据train_x
和train_y
:
train_x = [1, 2, 3, 5, 6]
train_y = [2, 4, 5, 7, 9]
执行下述代码后
mp.scatter(train_x, train_y)
mp.show()
得到散点图:
通过观察我们可以发现, 训练集中的5个点近似分布在一条直线上, 我们将这条直线用y = w0 + w1*x
表示. 线性回归的目的, 就是求出一组合适的w0
和w1
损失函数
我们如何判断求得的w0
和w1
是否合适呢? 显然, 我们求得的直线应该尽可能地靠近训练集中的5个点.
我们用损失函数loss_function
来描述数据"靠近"回归直线的程度.
假设对于某一个x
, x
对应的值为y
, 我们将’x’带入直线方程中得到为y'
, 则损失定义为0.5*(y'-y)^2
, 即0.5*(w0+w1*x-y)^2
. 损失函数即为全部数据损失的和.
此时, 问题转化成了: 如何求得一组w0
和w1
, 使得损失函数取得极小值.
梯度下降法
梯度下降法能够帮助我们高效地找到损失函数的极小值(或近似极小值), 思路如下:
- 规定梯度下降次数
times
和学习率lrate
times = 1000
lrate = 0.01
- 随机选择一组
w0
和w1
的取值
w0, w1 = 1, 1
- 对
w0
和w1
分别求偏导数d0
和d1
d0 = (w0 + w1 * train_x - train_y).sum()
d1 = (train_x * (w0 + w1*train_x - train_y)).sum()
- 更新
w0
和w1
的值
w0 = w0 - lrate*d0
w1 = w1 - lrate*d1
- 重复步骤
3,4
, 次数为times
完整代码
times = 1000
lrate = 0.01
w0, w1 = 1, 1
for i in range(0, times):
d0 = (w0 + w1 * train_x - train_y).sum()
d1 = (train_x * (w0 + w1*train_x - train_y)).sum()
w0 = w0 - lrate * d0
w1 = w1 - lrate * d1
print("w0=", w0)
print("w1=", w1)
# w0= 1.0116288204591268
# w1= 1.2906974643094398
得到的回归直线如下图所示: