[译] 使用梯度下降做线性回归

原文: Linear Regression using Gradient Descent

在本教程中,你可以学习梯度下降法(gradient descent algorithm)是如何工作的,并使用 python 从头开始实现它。首先我们看看线性回归(linear regression)是什幺,然后定义损失函数(loss function)。我们学习梯度下降算法是如何工作的,最后我们将在给定的数据集上实现它并进行预测。

m 和 c 的值在每次迭代中被更新以获得最优解

本文是这个视频 的文字版,如果你更喜欢视频就观看它吧!

线性回归

在统计学里,线性回归是一种对一个因变量和一个或多个自变量之间的关系进行建模的线性方法。设 X 是自变量, Y 是因变量。我们将为这两个变量定义如下的线性关系:

来源: http://www.nabla.hr/SlopeInterceptLineEqu.gif

这是你在高中时就学过的直线的方程。 m 是斜率, c 是 y 轴的截距。今天,我们将用给定的数据集使用这个方程来训练我们的模型,并对任意给定的 X 预测对应的 Y 。我们今天的挑战是确定 m 和 c 的值,使得这些值对应的直线是最佳拟合线或者误差是最小的。

损失函数

损失(loss)是我们预测的 m 和 c 的误差。我们的目标是最小化这个误差以获得 m 和 c 的最精确的值。我们将使用均方误差函数(the Mean Squared Error function)来计算损失。这个函数有三个步骤:

    1. 对给定 x,求出实际 y 值和预测 y 值(y = mx + c)的差。
    1. 对差取平方。
    1. 对 X 中的所有值,都如上取平方,然后计算平均数。

均方误差函数

这里 是实际值, 是预测值。让我们替换 的值:

也就是说我们把误差平方然后求出了平均值,也就是均方差这个名字的由来。现在我们已经定义了损失函数,让我们进入最有意思的部分:最小化它并找到 m 和 c 。

梯度下降法

梯度下降是一种寻找函数最小值的迭代优化算法。在这里,这个函数就是我们的损失函数。

理解梯度下降

想象有一个山谷和一个想要到达山谷的底部但没有方向感的人。他沿着斜坡走下去,当斜坡很陡时,他走一大步,当斜坡不太陡时,他走一小步。他根据他目前的位置来决定他的下一个位置,并且当他到达谷底,也就是他的目标时就会停下来。

让我们尝试将梯度下降应用到 m 和 c ,并一步一步逼近它:

    1. 初始时让 m = 0,c = 0。使用 L 作为我们的学习速率(learning rate),它控制了 m 在每一步变化的大小。准确起见 L 可以设置一个小的值比如 0.0001。
    1. 计算损失函数对 m 的偏导数并代入当前的 x、y、m 和 c,得到导数 D 。

对 m 的导数

是对 m 的偏导数的值。同样,让我们求出对 c 的偏导数 :

对 c 的导数

    1. 现在我们使用下面的等式更新当前的 m 和 c 的值:
    1. 我们重复这个过程,直到我们的损失函数是一个非常小的值或理想的 0(这意味着误差为 0 或 100% 的精确)。我们现在剩下的 m 和 c 也就是最优值。

现在回到我们的类比, m 可以看作是人的当前位置。 D 相当于坡度, L 是他移动的速度。现在我们用上面的等式计算的 m 的新值将是他的下一个位置, 是他的下一步的大小。当坡度越陡( D 越大)时,他走更长一步;当坡度越小( D 越小)时,他走更短一步。最后他到达了谷底,对应于我们的损失 = 0。

现在有了 m 和 c 的最佳值,我们的模型就可以进行预测了!

实现模型

现在让我们把上面的一切都转换成代码,看看我们的模型起作用!

# Making the imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (12.0, 9.0)
# Preprocessing Input data
data = pd.read_csv('data.csv')
X = data.iloc[:, 0]
Y = data.iloc[:, 1]
plt.scatter(X, Y)
plt.show()

linear_regression_gd1.py

# Building the model
m = 0
c = 0
L = 0.0001  # The learning Rate
epochs = 1000  # The number of iterations to perform gradient descent
n = float(len(X)) # Number of elements in X
# Performing Gradient Descent 
for i in range(epochs): 
    Y_pred = m*X + c  # The current predicted value of Y
    D_m = (-2/n) * sum(X * (Y - Y_pred))  # Derivative wrt m
    D_c = (-2/n) * sum(Y - Y_pred)  # Derivative wrt c
    m = m - L * D_m  # Update m
    c = c - L * D_c  # Update c
    
print (m, c)

linear_regression_gd2.py

输出 1.4796491688889395 0.10148121494753726

# Making predictions
Y_pred = m*X + c
plt.scatter(X, Y) 
plt.plot([min(X), max(X)], [min(Y_pred), max(Y_pred)], color='red')  # regression line
plt.show()

linear_regression_gd3.py

梯度下降是机器学习中最简单、应用最广泛的算法之一,主要是因为它可以应用到任何函数去优化它。学习它为掌握机器学习奠定基础。

数据集和代码在这里: 02 Linear Regression using Gradient Descent