(二)线性回归问题
首先我们来看一个方程:
y
=
w
∗
x
+
b
y = w * x + b
y=w∗x+b
这里我们只要得到两组
x
x
x和
y
y
y的值就可以对
w
w
w和
b
b
b精确求解。
但是在实际问题中我们得到线性方程不会是这样,而是:
y
=
w
∗
x
+
b
+
ϵ
y = w * x + b + \epsilon
y=w∗x+b+ϵ
这里的
ϵ
\epsilon
ϵ就是我们实际生活中的一些干扰因素,这里我们称作噪声(noise)
这时我们仅用两组
x
x
x和
y
y
y的值就无法求解,所以我们需要得到很多的方程组才能求解。这里我们给出如下公式
l
o
s
s
=
(
w
x
+
b
−
y
)
2
loss = (wx + b - y)^2
loss=(wx+b−y)2
这里我们只要通过很多方程组去求解
w
w
w和
b
b
b使得
l
o
s
s
loss
loss尽可能接近为0这样虽然无法很精确求解,但是也能很好满足我们求解实际问题的需要
这样我们通过数据的很多组 x x x和 y y y的值就可以让我们方程更加精确,具体如下:
下面说明最小化 l o s s loss loss的思路:
(1)求偏导,通过偏导数可以得到
l
o
s
s
loss
loss对
w
w
w和
b
b
b的当前位置的梯度信息
∂
l
o
s
s
∂
w
=
2
x
(
w
x
+
b
−
y
)
\frac{\partial loss}{\partial w} = 2x(wx + b - y)
∂w∂loss=2x(wx+b−y)
∂ l o s s ∂ b = 2 ( w x + b − y ) \frac{\partial loss}{\partial b} = 2(wx + b - y) ∂b∂loss=2(wx+b−y)
(2)以下
w
w
w和
b
b
b的迭代更新公式,我们让当前的
w
w
w和
b
b
b的值减去各自当前位置的梯度就能让
w
w
w和
b
b
b去不断逼近其梯度为0的点,这样
l
o
s
s
loss
loss函数就能不断逼近其极小值点,而这就是我们想要的结果。
w
′
=
w
−
l
r
∗
Δ
l
o
s
s
Δ
w
w' = w - lr * \frac{\Delta loss}{\Delta w}
w′=w−lr∗ΔwΔloss
b ′ = b − l r ∗ Δ l o s s Δ b b' = b - lr * \frac{\Delta loss}{\Delta b} b′=b−lr∗ΔbΔloss
我们通过每次计算的 w w w和 b b b的梯度来迭代更新 w w w和 b b b的值
求解思路很简单,下面我们来进行下简单的实战。
这里我们sample一些点的数据,第一个数为 x x x,第二个数为 y y y
下面为代码:
import numpy as np
def step_gradient(points, learningRate, w_current, b_current):
"""
这个函数用来计算梯度
:param points: 点的数据,第一列为x, 第二列为y
:param learningRate: 学习率
:param w_current: 当前w的值
:param b_current: 当前b的值
:return: 使用公式新的计算的w,b的值
"""
w_gradient = 0
b_gradient = 0
n = len(points)
for i in range(n):
x = points[i][0]
y = points[i][1]
w_gradient += 2 * x * (w_current * x + b_current - y)
b_gradient += 2 * (w_current * x + b_current - y)
w_new = w_current - w_gradient / n * learningRate
b_new = b_current - b_gradient / n * learningRate
return [w_new, b_new]
def gradient_iterate(points, learnRate, iterations, w_gradient, b_gradient):
"""
函数进行梯度的迭代
:param points: 点的数据,第一列为x, 第二列为y
:param learnRate: 学习率
:param iterations: 迭代次数,即训练次数
:param w_gradient: 当前w的值
:param b_gradient: 当前b的值
:return: 迭代最后的w,b的值
"""
n = len(points)
for i in range(iterations):
[w_gradient, b_gradient] = step_gradient(points, learnRate, w_gradient, b_gradient)
return [w_gradient, b_gradient]
def loss_calculate(points, w_gradient, b_gradient):
"""
计算总的loss
:param points: 点的数据,第一列为x, 第二列为y
:param w_gradient: w的梯度
:param b_gradient: b的梯度
:return: 总的loss
"""
lossTotal = 0 # 总的loss
for i in range(len(points)):
x = points[i][0]
y = points[i][1]
lossTotal += (w_gradient * x + b_gradient - y) ** 2
return lossTotal
if __name__ == '__main__':
points = np.genfromtxt("data.csv", dtype=float, delimiter=',') # 导入数据
w_initial = 0 # 初始化w
b_initial = 0 # 初始化b
learningRate = 0.0001 # lr设置小一点,这样结果会比较好
iterations = 1000 # 迭代次数
[w, b] = gradient_iterate(points, learningRate, iterations, w_initial, b_initial)
loss = loss_calculate(points, w, b)
print("w = %f, b = %f, loss = %f" % (w, b, loss))
计算结果如上。