在机器学习中,线性回归(Linear Regression) 是一种解决回归问题的经典算法。线性回归在假设特证满足线性关系的情况下,根据给定的训练数据训练一个模型,并用此模型进行预测。本文将记录吴恩达机器学习课程中线性回归主要部分内容。接下来会通过一个房屋价格数据集,使用线性代数与微积分去建立基于一元线性回归的房价预测模型,最终能够输入房屋面积就能预测出房屋的价格,一元线性回归(Linear Regression with One Variable) 是机器学习中线性回归的简化版本,也是机器学习中最基础的算法之一。

模型描述(Model Representation)

监督学习(Supervised Learning) 中,一定会有一个数据集(Data Set),这个数据集被称为训练集(Training Set)
先举一个简单的例子:设一个线性方程为 $y=5x+30$ ,定义 $x$ 为房屋面积,$y$ 为住房价格,当房屋面积为 $x=200$ 时,我们就可以通过该线性方程计算出房价 $y=1030$ 。这是一个回归(Regression) 问题,因为它的输出是连续(Continuous) 的,而分类(Classification) 问题的输出则是离散(Discrete ) 的。

https://s1.ax1x.com/2018/11/17/izGYNt.jpg

它接收输入的房屋面积 $x$ ,输出房屋的价格 $y$ ,通过不断地把训练集中的数据喂给线性回归模型,并使模型尽量的去拟合这些数据,最终模型训练完毕后,输入合理的房屋面积 $x$ ,模型都能准确的预测对应的房屋价格 $y$ 。

https://s1.ax1x.com/2018/11/17/izGJAI.jpg

这就是一个典型的监督学习算法的工作方式。更具体的来说,我们使用hypothesis(假设),通常写为小写 $h$ ,$h$ 表示一个函数,输入是房屋面积的大小,根据输入的 $x$ 值来得出 $y$ 值,$y$ 值对应房屋的价格,因此,$h$ 是一个从 $x$ 到 $y$ 的函数映射(mapping)

假设函数(hypothesis)

假设我们回归问题的训练集为下表所示(一共有47个训练样本):

面积($x$)价格/k($y$)
2104450
1416232
1534315
852178

根据房屋交易问题,我们可以到得一种可能描述该问题的表达式:

$$
h_{\theta}(x)=\theta_{0}+\theta_{1} x
$$

有时我们会将假设函数 $h_{\theta}(x)$ 简写为 $h(x)$ ,它接收一个输入 $x$ 并输出一个 $y$ ,拥有两个参数(parameters)$\theta_{0}$ 和 $\theta_{1}$ ,它们其实就是回归方程中的斜率和截距。

如果我们就这样用普通的方式去计算这个函数完全没有问题,因为我们的训练集只有 47 个样本数据,可在实际的模型训练中,样本数量往往会是万级、十万级的数据,甚至会有百万上千万级的大数据集。通过普通的方式去计算它们会非常耗时,而且效率极低。

我们通常会使用线性代数的方法去计算它们,因为像 $h(x)$ 这样的模型可以很容易的改写为矩阵运算的形式。使用矩阵运算,我们可以一步求解批量的样本数据,同时许多机器学习和深度学习框架支持通过 GPU 进行矩阵运算,这将充分发挥计算机的性能优势。

可以把训练集中的样本数据写成向量(Vector)矩阵(Matrix) 的形式:

注意:机器学习中的向量和矩阵与你所知的线性代数可能会有些差别,比如在机器学习中允许一维的矩阵存在。

$$
X=\left[\begin 2104 \ 1416 \\ 1534 \ 852 \ \vdots \end\right] \quad y=\left[\begin 450 \ 232 \ 315 \ 178 \ \vdots \end\right] \quad \theta=\left[\begin \theta_{0} & \theta_{1} \ \vdots & \vdots \end\right] \quad m=47
$$

  •  $X$ 表示训练集中的输入数据,它是一个形状为 $(47 \times 1)$ 的矩阵。
  •  $y$ 表示训练集中的输出数据,它是一个形状为 $(47 \times 1)$ 的向量。
  •  $\theta$ 表示对应于特征 x 的参数值,它是一个形状为 $(47 \times 2)$ 的矩阵。
  •  $m$ 表示训练样本的数目 $(m=47)$ 。

我们通常用大小写来区分表示矩阵和向量,至于为什么 X 是一个矩阵,因为我们想要将 $h_{\theta}(x)=\theta_{0}+\theta_{1} x$ 改写为矩阵运算的形式,就需要将 $X$ 增加一列,所以我们设 $X_{0}=1$ ,此时矩阵 $X$ 的形状为 $(47 \times 2)$ :

$$
X=\left[\begin 1 & 2104 \ 1 & 1416 \ 1 & 1534 \ 1 & 852 \ \vdots & \vdots \end\right]
$$

增加了一维后的 $X$ ,就与 $\theta$ 拥有了线性关系:

$$h_{\theta}(x)=\theta_{0} x_{0}+\theta_{1} x_{1}$$

转置 $\theta$ 后就满足了矩阵乘法的要求:

$$h_{\theta}(x)=\theta^{\top} X$$

$$
h_{\theta}(x)=\left[\begin \theta_{0} & \cdots \ \theta_{1} & \cdots \end\right] \times\left[\begin 1 & 2104 \ 1 & 1416 \ 1 & 1534 \ 1 & 852 \ \vdots & \vdots \end\right]
$$

  • Matlab 中的矩阵转置操作:matrix'
  • Python-Numpy 包中的矩阵转置操作:matrix.T
  • TensorFlow 中的矩阵转置操作:tf.transpose(matrix)

我们可以试着改变参数 $\theta_0$ 和 $\theta_1$ 的值,去观察它们对于整个模型的拟合有着怎样的影响:

https://s1.ax1x.com/2018/11/17/izGc40.jpg

可以看到 $\theta_0$ 和 $\theta_1$ 对于我们模型的拟合来说是至关重要的,它们就直接控制着我们线性模型的斜率和截距,但是要如何选择这两个参数就是我们需要重点关心的问题。如果试图从视觉的角度来考虑这个问题:训练数据集散落在 x-y 的平面上,我们的最终目标是试图建立一条直线(由 $h_{\theta}(x)$ 定义),它将以最好的方式穿过这些散乱的数据点。

代价函数(Cost Function)

我们需要弄清楚如何把最有可能的直线与我们的数据相拟合,我们选择的参数决定了我们得到的直线相对于我们的训练集的准确程度,模型所预测的值 $\hat$ 与训练集中实际值 $y$ 之间的差距,就是建模误差(modeling error)。我们的目标是得到尽可能好的直线。最可能的直线是这样的,从这条线上散落点的平均平方垂直距离将是最小的。

https://s1.ax1x.com/2018/11/17/izG8HA.jpg

我们可以使用**均方误差(mean-square error, MSE)**公式来帮助我们计算出平均的平方垂直距离与样本真实值之间的误差:

$$
M S E=\frac{1}
\sum_\left(\hat{(i)}-y{(i)}\right){2}
$$

均方误差是衡量平均误差(mean error) 的一种较方便的方法,也是回归任务中常用的性能度量,是参数估计值与参数真值之差的平方的期望值,用来表示估计值于观测值之间的偏差。基于均方误差最小化来进行模型求解的方法称为最小二乘法。使用均方误差方法,就可以着手构建我们的代价函数(Cost Function)

$$
J\left(\theta_{0}, \theta_{1}\right)=\frac{1}{2 m} \sum_
\left(h_{\theta}\left(x{(i)}\right)-y{(i)}\right){2}
$$

为了便于梯度下降(Gradient Descent)的计算,我们通常会乘上一个 $\frac{1}{2}$ ,因为平方函数的导数项将抵消 $\frac{1}{2}$ 。

理想情况下,这条线应该通过我们训练数据集的所有点,这时 $J\left(\theta_{0}, \theta_{1}\right)$ 的值应该为 0 。既然 $J\left(\theta_{0}, \theta_{1}\right)$ 是一个预测值与实际值之间的误差值,所以我们要尽可能的让代价函数 $J\left(\theta_{0}, \theta_{1}\right)$ 的值更小,而 $\theta_0$ 和 $\theta_1$ 的大小会直接影响到 $J$ 的值,所以我们接下来我们的问题将会进一步到达新的一个层面——如何找到最小的 $\theta_0$ 和 $\theta_1$ 使得 $J$ 最小?

梯度下降(Gradient Descent)

梯度下降(Gradient Descent) 是一种迭代法,主要用于求解函数最小值,通过不断的迭代,就像一个人下山的过程,只要周围有低的地方就走下去,直到走到周围没有任何一处比当前区域更低的地方。我们选取一组 $\theta$ 并把 $J\left(\theta_{0}, \theta_{1}\right)$ 的 3D 图像作在 x-y-z 坐标系中:

https://s1.ax1x.com/2018/11/17/izGU9f.jpg

可以看 $\theta_0$ 和 $\theta_1$ 的交错点中,一定会有一个能够使得 $J$ 值最小的点,这就是我们需要寻找的最低点。如果把这张图作垂直照射的话可以得到一张等高线图:

https://s1.ax1x.com/2018/11/17/izGdgS.jpg

图像稀疏的区域是扁平端,在这里的 $J$ 值下降速度比较缓慢,而比较紧凑的区域则是陡峭端,这里的函数下降速度很快,同一个颜色线上的点,$J$ 值都是相同的,但是所对应的 $\theta_0$ 和 $\theta_1$ 却是不同的,因为它们并不是在同一空间位置上的点,不过最终目的都是要走到最低点。

常见的 $J\left(\theta_{0}, \theta_{1}\right)$ 并不都是一个碗状,比较常见的是这种:

https://s1.ax1x.com/2018/11/17/izGDBj.jpg

有时 $J\left(\theta{0}, \theta_{1}\right)$ 并不是只有一个低谷。_

梯度下降背后的思想是:开始时我们随机选择一个参数的组合,计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到得到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。就像下山时一开始选择的路径,也许最后到达的低谷只是周围的低谷而已,并不是全局的低谷,但周围附近的确没有比此地更低的地方了,你依然会认为已经达到目标后而选择停下脚步,所以我们一开始选取的参数组合就决定了我们最终走向的是局部最低点还是全局最低点。

https://s1.ax1x.com/2018/11/17/izGwjg.jpg

https://s1.ax1x.com/2018/11/17/izGyEn.jpg

什么是梯度?这里的梯度就是表示某一函数在该点处的方向导数沿着该方向取得较大值,即函数在当前位置上的导数。在梯度下降算法中,我们要做的就是旋转360度,看看我们的周围,并问自己要在某个方向上,用小碎步尽快下山。这些小碎步需要朝什么方向?如果我们站在山坡上的这一点,你看一下周围,你会发现最佳的下山方向,你再看看周围,然后再一次想想,我应该从什么方向迈着小碎步下山?然后你按照自己的判断又迈出一步,重复上面的步骤,从这个新的点,你环顾四周,并决定从什么方向将会最快下山,然后又迈进了一小步,并依此类推,直到你接近局部最低点的位置,这个过程就是运行批量梯度下降(batch gradient descent, BGD) 的过程:

https://s1.ax1x.com/2018/11/17/izGBuQ.jpg

循环直到收敛 {
$$
\theta_
:=\theta_-\alpha \frac{\partial}{\partial \theta_} J\left(\theta_{0}, \theta_{1}\right) \quad(\text \quad j=0 \quad \text \quad j=1)
$$
}

$\alpha$ 为学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向下迈出的步子有多大。

求导的目的是取这个红点的切线,与函数相切于这一点,这条直线的斜率正好是这个三角形的高度除以这个水平长度,现在,这条线有一个正斜率,也就是说它有正导数。因此,我得到的新的 $\theta$ ,$\theta$ 更新后等于 $\theta$ 减去一个正数乘以 $\alpha$ 。

这就是我们梯度下降的更新规则,每一次都同时让所有的参数减去学习速率乘以代价函数的导数:

$$\begin



\theta_{1} &:=t e m p_{1}
\endt e m p_{0} &:=\theta_{0}-\alpha \frac{\partial}{\partial \theta_{0}} j\left(\theta_{0}, \theta_{1}\right) \t e m p_{1} &:=\theta_{1}-\alpha \frac{\partial}{\partial \theta_{1}} j\left(\theta_{0}, \theta_{1}\right) \\theta_{0} &:=t e m p_{0} \
$$

注意:$\theta_0$ 和 $\theta_1$ 是同时更新的。

学习率 $\alpha$ 的选择直接关系到了梯度下降算法的命运,如果学习率小了收敛时间就会变长,如果学习率过大就可能会难以收敛甚至发散。$\alpha$ 就好像人在下山时迈出的步子有多大,如果迈小了可能下到最低处需要的时间就会很久,如果步子迈大了就可能会越过最低点。

https://s1.ax1x.com/2018/11/17/izGrHs.jpg

把公式进行求导后,就可以应用于我们的一元线性回归模型:

$$\alpha \frac{\partial}{\partial \theta_} J\left(\theta_{0}, \theta_{1}\right)=\alpha \frac{\partial}{\partial \theta_} \frac{1}{2 m} \sum_\left(h_{\theta}\left(x{(i)}\right)-y{(i)}\right){2}$$

$$
\begin

\frac{\partial}{\partial \theta_{0}} J\left(\theta_{0}, \theta_{1}\right) &=\frac{1}
\sum_\left(h_{\theta}\left(x{(i)}\right)-y
\frac{\partial}{\partial \theta_{1}} J\left(\theta_{0}, \theta_{1}\right) &=\frac{1}{(i)}\right) &(j=0) \
\sum_
\left(\left(h_{\theta}\left(x{(i)}\right)-y{(i)}\right) \cdot x^{(i)}\right) & &(j=1)
\end

$$

通过循环同时更新 $\theta_0$ 和 $\theta_1$ :


$$
\begin循环 {

\theta_{0}:=\theta_{0}-\alpha \frac{1}
\sum_\left(h_{\theta}\left(x
\theta_{1}:=\theta_{1}-\alpha \frac{1}{(i)}\right)-y^{(i)}\right) \
\sum_\left(\left(h_{\theta}\left(x{(i)}\right)-y{(i)}\right) \cdot x{(i)}\right)
\end

$$
}

小结

现在我们拥有了寻找 $J\left(\theta_{0}, \theta_{1}\right)$ 最小值的方法,我们就可以描述一元线性回归问题:通过梯度下降获取使得代价函数 $J$ 最小的参数 $\theta_0$ 和 $\theta_1$ ,最后确定我们的线能很好的拟合这些数据点时,就可以把房屋面积 $x$ 给假设函数 $h$ 计算出想要预测房屋价格 $y$ 。

https://s1.ax1x.com/2018/11/17/izG6Nq.jpg

在一元线性回归中虽然只有一个房屋面积的特征,但是相对来说我们更倾向于多元线性回归,因为要预测一个值,往往不是一个特征就能够将其描述完整的,我们需要一个能够支持多个特征的模型来完善我们的线性回归算法。

References

[1]Andrew Ng.Machine Learning.Coursera.2014

[2]深度碎片.吴恩达机器学习图解笔记.Bilibili.2018-3

[3]黄海广.斯坦福大学2014机器学习教程笔记.GitHub.2018-5


《吴恩达机器学习系列课程》笔记