找到最佳拟合线的方法是使用梯度下降,我们将随机绘制一条线,计算该线的误差
- 计算误差
给定m和b,我们将计算直线的误差。Eeeor用sigma表示法表示
def compute_error_for_line_given_points(b, m, points):
totalError = 0
for i in range(0, len(points)):
x = points[i, 0]
y = points[i, 1]
totalError += (y - (m * x + b)) ** 2
return totalError / float(len(points))
2.梯度下降
接下来我们要最小化这个误差,这个误差基本上是一个信号,对我们来说是一个指南针,告诉我们要变小,这就是梯度下降的作用
error,m,b构成一个三维图,执行梯度下降来获得最小点。就像把球放到碗里面,找到球停止的端点,也是最低点。我们沿着碗下降,知道通过迭代到达。
一旦我们计算出误差,梯度意味着斜率的起点,就像一个指南针,总是指向碗底。为了得到他,我们需要计算每个点b和m的偏导数(用损失函数求偏导)
称为偏导数,是因为没有告诉我们整个故事
对所有点的偏导数求和,再用设置的学习率来更新m和b,m和b的偏导数将为我们提供一个方向,我这里把损失函数的梯度理解为一个总向量,m和b的偏导数是梯度的两个分量
def step_gradient(b_current, m_current, points, learningRate):
b_gradient = 0
m_gradient = 0
N = float(len(points))
for i in range(0, len(points)):
x = points[i, 0]
y = points[i, 1]
b_gradient += -(2/N) * (y - ((m_current * x) + b_current))
m_gradient += -(2/N) * x * (y - ((m_current * x) + b_current))
new_b = b_current - (learningRate * b_gradient)
new_m = m_current - (learningRate * m_gradient)
return [new_b, new_m]
def gradient_descent_runner(points, starting_b, starting_m, learning_rate, num_iterations):
b = starting_b
m = starting_m
for i in range(num_iterations):
b, m = step_gradient(b, m, array(points), learning_rate)
return [b, m]
(pythonbase) PS E:\OneDrive\aidev\linear_regression_live> e:; cd 'e:\OneDrive\aidev\linear_regression_live'; & 'd:\miniconda\envs\pythonbase\python.exe' 'c:\Users\daichang\.vscode\extensions\ms-python.debugpy-2024.6.0-win32-x64\bundled\libs\debugpy\adapter/../..\debugpy\launcher' '4493' '--' 'E:\OneDrive\aidev\linear_regression_live\demo.py'
Starting gradient descent at b = 0, m = 0, error = 5565.107834483211
Running...
After 1000 iterations b = 0.08893651993741346, m = 1.4777440851894448, error = 112.61481011613473
(pythonbase) PS E:\OneDrive\aidev\linear_regression_live>
完整代码
https://github.com/daichang01/linear_regression_live/tree/dev