吴恩达机器学习笔记(2)—单变量线性回归(附代码)

在本篇内容中,我们将介绍第一个机器学习算法——线性回归算法。更重要的是,我们将借助这个算法,带你了解一个完整的监督学习流程

一、模型表示

我们通过一个例子来开始:预测房价。我们拥有一个数据集,记录了美国俄勒冈州波特兰市的若干房子面积及其对应的成交价格。横轴表示房子的面积(平方英尺),纵轴表示房价(千美元)。如果有一套房子面积是 1250 平方英尺,想知道大概能卖多少钱。你可以通过构建一个预测模型来实现,比如你可以用一条直线来拟合数据,从而推断出:这套房子可能值大约 22 万美元左右。

​​​​在这里插入图片描述

这是监督学习算法的一个例子。 因为在训练过程中,每个数据样本都包含一个“正确答案”,也就是我们已经知道的真实输出(每个房子的实际售价)。而且这还是一个回归问题的例子,因为预测一个具体的数值输出(房子的价格)。

在监督学习中我们有一个数据集,这个数据集被称训练集,如下图。

在这里插入图片描述

在课程中,使用以下符号来描述训练集和模型结构

m m m :训练样本数量
x x x :特征/输入变量(例如房子面积)
y y y :目标变量/输出变量(例如房子价格)
( x ( i ) , y ( i ) ) ({{x}^{(i)}},{{y}^{(i)}}) (x(i),y(i)) : 第 i 个训练样本
h h h :学习算法输出的假设函数(hypothesis)

一个典型的监督学习过程如下:

在这里插入图片描述

  1. 收集训练数据,比如不同面积的房子及其对应价格。
  2. 将这些数据输入给学习算法。
  3. 算法“学习”出一个函数 h h h,也就是我们的预测模型
  4. 当想预测一套房子的售价时,只需将其面积作为输入,使用这个函数 h h h 得到预测价格。

换句话说,我们希望找到一个函数 h h h,使得它能近似地预测出输入 x x x(房屋面积)对应的输出 y y y(价格)。这可以用线性函数表示为:
h θ ( x ) = θ 0 + θ 1 x h_\theta \left( x \right)=\theta_{0} + \theta_{1}x hθ(x)=θ0+θ1x

因为这里只有一个特征(房子面积),所以我们称这种情况为单变量线性回归

二、代价函数

在这一节中我们将定义代价函数的概念,这有助于我们弄清楚如何把最有可能的直线与我们的数据相拟合。在上一节中,我们得到的假设函数为一个线性函数形式:
h θ ( x ) = θ 0 + θ 1 x h_\theta \left( x \right)=\theta_{0} + \theta_{1}x hθ(x)=θ0+θ1x

选择不同的参数 θ 0 \theta_{0} θ0 θ 1 \theta_{1} θ1 会得到不同的假设函数 h θ ( x ) h_\theta \left( x \right) hθ(x) ,如下图。

在这里插入图片描述

θ i \theta_{i} θi 称为模型参数,我们要做的是选择出一组合适的参数 θ 0 \theta_{0} θ0 θ 1 \theta_{1} θ1,使得模型预测值 h θ ( x ) h_\theta \left( x \right) hθ(x) 与实际值 y y y 的差距最小。这里给出标准定义,在线性回归中要解决的是最小化问题。

最小化公式,加平方是为了使差距极其小
min ⁡ θ 0 ,   θ 1 ( h θ ( x ) − y ) 2 \min_{\theta_0,\, \theta_1} \quad (h_\theta(x) - y)^2 θ0,θ1min(hθ(x)y)2
对所有训练样本的差距进行求和, 1 2 m \frac{1}{2m} 2m1 是为了尽量减少平均误差
min ⁡ θ 0 ,   θ 1 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 \min_{\theta_0,\, \theta_1} \quad \frac{1}{2m} \sum_{i=1}^{m} \left(h_\theta(x^{(i)}) - y^{(i)}\right)^2 θ0,θ1min2m1i=1m(hθ(x(i))y(i))2
由于假设函数表示为
h θ ( x ( i ) ) = θ 0 + θ 1 x ( i ) h_\theta(x^{(i)}) = \theta_{0} + \theta_{1}x^{(i)} hθ(x(i))=θ0+θ1x(i)
因此问题变成找到 θ 0 \theta_{0} θ0 θ 1 \theta_{1} θ1 的值,使以下公式最小
min ⁡ θ 0 ,   θ 1 J ( θ 0 , θ 1 ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 \min_{\theta_0,\, \theta_1} \quad J(\theta_0, \theta_1) = \frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 θ0,θ1minJ(θ0,θ1)=2m1i=1m(hθ(x(i))y(i))2

J ( θ 0 , θ 1 ) J(\theta_0, \theta_1) J(θ0,θ1) 就是代价函数,这个函数也叫作平方误差代价函数,它是回归问题中最常见也是最合理的选择之一。

三、代价函数的直观理解(1)

在这一节中,为了更好地使代价函数J可视化,我们使用一个简化的代价函数,可以让我们更好的理解代价函数的概念。

将假设函数的参数 θ 0 \theta_{0} θ0 视为 0
h θ ( x ( i ) ) = θ 1 x ( i ) h_\theta(x^{(i)}) = \theta_{1}x^{(i)} hθ(x(i))=θ1x(i)
那么代价函数就变为
min ⁡ θ 1 J ( θ 1 ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 \min_{\theta_1} \quad J(\theta_1) = \frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 θ1minJ(θ1)=2m1i=1m(hθ(x(i))y(i))2
优化目标就是尽量减少 J ( θ 1 ) J(\theta_1) J(θ1) 的值

实际上,有两个关键函数是我们需要去了解的。一个是假设函数 h θ ( x ) h_\theta(x) hθ(x) ,第二个是代价函数 J ( θ 1 ) J(\theta_1) J(θ1) 。假设函数 h h h 是对于给定的 θ 1 \theta_1 θ1 的值,是一个关于 x x x 的函数。代价函数 J J J 是关于参数 θ 1 \theta_1 θ1 的函数。假设有三个点的训练集 ( 1 , 1 ) ( 2 , 2 ) ( 3 , 3 ) (1,1) (2,2) (3,3) (1,1)(2,2)(3,3),当 θ 1 = 1 \theta_1=1 θ1=1 时,代价函数 J J J 的值计算如下。

J ( θ 1 ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 = 1 2 m ∑ i = 1 m ( θ 1 x ( i ) − y ( i ) ) 2 = 1 2 m ( 0 2 + 0 2 + 0 2 ) = 0 \begin{aligned} J(\theta_1) &= \frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 \\ &= \frac{1}{2m} \sum_{i=1}^{m} \left( \theta_{1}x^{(i)} - y^{(i)} \right)^2 \\ &= \frac{1}{2m}(0^2+0^2+0^2) \\ &= 0 \end{aligned} J(θ1)=2m1i=1m(hθ(x(i))y(i))2=2m1i=1m(θ1x(i)y(i))2=2m1(02+02+02)=0
得出当 θ 1 = 1 \theta_1=1 θ1=1 时, h θ ( x ( i ) ) = y ( i ) h_\theta(x^{(i)}) = y^{(i)} hθ(x(i))=y(i) ,因此 J ( 1 ) = 0 J(1) = 0 J(1)=0

绘制的两个函数的图形如下。

在这里插入图片描述

θ 1 = 0.5 \theta_1=0.5 θ1=0.5 时,代价函数 J J J 的值计算如下。

J ( θ 1 ) = 1 2 m ∑ i = 1 m ( θ 1 x ( i ) − y ( i ) ) 2 = 1 2 ∗ 3 [ ( 0.5 − 1 ) 2 + ( 1 − 2 ) 2 + ( 1.5 − 3 ) 2 ] ≈ 0.58 \begin{aligned} J(\theta_1) &= \frac{1}{2m} \sum_{i=1}^{m} \left( \theta_{1}x^{(i)} - y^{(i)} \right)^2 \\ &= \frac{1}{2*3}[(0.5-1)^2+(1-2)^2+(1.5-3)^2] \\ &\approx 0.58 \end{aligned} J(θ1)=2m1i=1m(θ1x(i)y(i))2=231[(0.51)2+(12)2+(1.53)2]0.58
得出当 θ 1 = 0.5 \theta_1=0.5 θ1=0.5 时, J ( 0.5 ) ≈ 0.58 J(0.5) \approx 0.58 J(0.5)0.58

绘制的两个函数的图形如下。

在这里插入图片描述

同理,计算出其它代价函数 J J J 的值,比如:
θ 1 = 0 \theta_1=0 θ1=0 时, J ( 0 ) ≈ 2.3 J(0) \approx 2.3 J(0)2.3
θ 1 = − 0.5 \theta_1=-0.5 θ1=0.5 时, J ( − 0.5 ) ≈ 5.25 J(-0.5) \approx 5.25 J(0.5)5.25

最终,得到的代价函数J的图形如下。

在这里插入图片描述

学习算法的优化目标,是通过选择 θ 1 \theta_1 θ1 的值,获得最小的 J ( θ 1 ) J(\theta_1) J(θ1) 。在这条曲线中,当 θ 1 = 1 \theta_1 = 1 θ1=1 时, J ( θ 1 ) J(\theta_1) J(θ1) 最小。通过观察也可以得出,这是条完美拟合训练集数据的直线。

四、代价函数的直观理解(2)

在本节课程中,我们将更深入地学习代价函数的作用,并借助图形化方式(等高线图)来帮助我们直观地理解其行为与最小值位置。下面是本节用到的公式,与上节不一样的是保留参数 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1

假设函数: h θ ( x ) = θ 0 + θ 1 x h_\theta \left( x \right)=\theta_{0} + \theta_{1}x hθ(x)=θ0+θ1x
模型参数: θ 0 , θ 1 \theta_0,\theta_1 θ0,θ1
代价函数: J ( θ 0 , θ 1 ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta_0, \theta_1) = \frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 J(θ0,θ1)=2m1i=1m(hθ(x(i))y(i))2
优化目标: min ⁡ θ 0 ,   θ 1 J ( θ 0 , θ 1 ) \min_{\theta_0,\, \theta_1} J(\theta_0, \theta_1) minθ0,θ1J(θ0,θ1)

采用关于住房价格的训练集,假设 θ 0 = 50 , θ 1 = 0.06 \theta_0=50,\theta_1=0.06 θ0=50,θ1=0.06,绘制假设函数h和代价函数 J J J 的图形。其中,代价函数 J J J 是关于 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 的函数,是一个3D曲面图,横轴为 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 ,竖轴为代价函数 J J J

在这里插入图片描述

为了更好地展现图形, 我们使用等高线图来展示代价函数,轴为 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 ,每个椭圆形显示一系列 J ( θ 0 , θ 1 ) J(\theta_0, \theta_1) J(θ0,θ1) 值相等的点,这些同心椭圆的中心点是代价函数的最小值。右下图是代价函数的等高线图,左下图是代价函数的最小值(椭圆的中心点)对应的假设函数的图形。

在这里插入图片描述

五、梯度下降

在本节课程中,我们将使用梯度下降法替代在上节中的人工方法,来自动寻找代价函数 J J J 最小值对应的参数 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 ,也更适合处理在遇到更复杂、更高维度、更多参数的难以可视化的情况。

问题概述:假设有个代价函数 J ( θ 0 , θ 1 ) J(\theta_0, \theta_1) J(θ0,θ1) ,我们需要用一个算法来最小化这个代价函数。
梯度下降法的思路:首先给定 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 的初始值,通常为 θ 0 = 0 , θ 1 = 0 \theta_0=0,\theta_1=0 θ0=0,θ1=0 ,然后不停地一点点地改变 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 的值来使 J J J 变小,直到找到 J J J最小值或局部最小值

通过图像可以更直观地理解梯度下降法是如何最小化代价函数 J J J 的。下图是横轴为 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 ,竖轴为代价函数 J J J ,并对 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 赋以不同的初始值。

在这里插入图片描述

把这个图像想象为公园中的两座山,然后你正站在山上的一个点上,在梯度下降算法中,我们要做的就是旋转 360度,看看周围,并问自己要尽快下山的话,我应该朝什么方向迈步?然后你按照自己的判断迈出一步,重复上面的步骤,从这个新的点,你环顾四周,并决定从什么方向将会最快下山,然后又迈进了一小步,并依此类推,直到你接近局部最低点的位置。 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 赋以不同的初始值,会得到如图中两个不同的局部最低点,这是梯度下降法的一个特点

如下图是梯度下降法的数学定义,将会重复更新 θ j \theta_j θj 的步骤,直到收敛。

在这里插入图片描述

其中是 α α α 学习率,用来控制梯度下降时迈出的步子有多大。如果 α α α 值很大,会用大步子下山,梯度下降就很迅速;如果 α α α 值很小,会迈着小碎步下山,梯度下降就很慢。 ∂ ∂ θ j J ( θ 0 , θ 1 ) \frac{\partial}{\partial \theta_j} J(\theta_0, \theta_1) θjJ(θ0,θ1)代价函数 J J J 的导数,这跟微积分有关系。

要正确实现梯度下降法,还需要同时更新 θ 0 \theta_0 θ0 θ 1 \theta_1 θ1 ,左下图的同时更新是正确的,右下图没有同时更新是错误的。

在这里插入图片描述

六、梯度下降的直观理解

梯度下降算法的数学定义如下,其中, α α α 是学习率, ∂ ∂ θ j J ( θ 0 , θ 1 ) \frac{\partial}{\partial \theta_j} J(\theta_0, \theta_1) θjJ(θ0,θ1) 是导数项。本节课程将直观认识这两部分的作用,以及更新过程有什么意义。

在这里插入图片描述

下面将直观解释导数项的意义,如下图像,是一个只有参数 θ 1 \theta_1 θ1 的简化的代价函数 J ( θ 1 ) J(\theta_1) J(θ1) 的图像,梯度下降算法的更新规则: θ 1 : = θ 1 − α ∂ ∂ θ 1 J ( θ 1 ) \theta_1:=\theta_1-\alpha\frac{\partial}{\partial \theta_1} J(\theta_1) θ1:=θ1αθ1J(θ1)

在这里插入图片描述

导数项 ∂ ∂ θ 1 J ( θ 1 ) \frac{\partial}{\partial \theta_1} J(\theta_1) θ1J(θ1) 可以说是 θ 1 \theta_1 θ1 点关于代价函数 J ( θ 1 ) J(\theta_1) J(θ1) 的切线的斜率,斜率可以表示 k = t a n β k=tan\beta k=tanβ 其中, β β β 是直线与 x x x 轴正方向的夹角。因此,图中是个正斜率,也就是正导数,同时学习率 α α α 永远是个正数,所以 θ 1 \theta_1 θ1 更新后变小了,要往左移,更接近最低点。

在这里插入图片描述

取另一个点 θ 1 \theta_1 θ1 ,如上图,计算得出是负斜率,也就是负导数,所以 θ 1 \theta_1 θ1 更新后变大了,要往右移,更接近最低点。

接下来介绍学习率 α α α 的作用,如果 α α α 太小,如下图,结果就是会一点点地挪动,需要很多步才能到达全局最低点。

在这里插入图片描述

如果 α α α 太大,如下图,那么梯度下降法可能会越过最低点,甚至可能无法收敛或者发散。

在这里插入图片描述

如果 θ 1 \theta_1 θ1 已经处在一个局部的最低点,如下图,由于最低点的斜率为 0,也就是导数等于 0,所以 θ 1 \theta_1 θ1 将保持不变,那么梯度下降法更新其实什么都没做,它不会改变参数的值。

在这里插入图片描述

接下来解释即使学习速率 α α α 保持不变时,梯度下降也可以收敛到局部最低点。如下图,在梯度下降法的更新过程中,随着越接近最低点,导数(斜率)越来越小,梯度下降将自动采取较小的幅度, θ 1 \theta_1 θ1 更新的幅度就会越小,直到收敛到局部极小值,这就是梯度下降的做法。所以实际上没有必要再另外减小 α α α

在这里插入图片描述

七、线性回归的梯度下降

在本节课程,我们要将梯度下降法和代价函数结合,得到线性回归的算法,它可以用直线模型来拟合数据。如下图,是梯度下降算法和线性回归模型,线性回归模型包含了假设函数和平方差代价函数。

在这里插入图片描述
将梯度下降法和代价函数结合,即最小化平方差代价函数,关键在于求出代价函数的导数

∂ ∂ θ j J ( θ 0 , θ 1 ) = ∂ ∂ θ j 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 = ∂ ∂ θ j 1 2 m ∑ i = 1 m ( θ 0 + θ 1 x ( i ) − y ( i ) ) 2 \begin{aligned} \frac{\partial}{\partial \theta_j} J(\theta_0, \theta_1) &= \frac{\partial}{\partial \theta_j}\frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 \\ &= \frac{\partial}{\partial \theta_j}\frac{1}{2m} \sum_{i=1}^{m} \left( \theta_{0} + \theta_{1}x^{(i)} - y^{(i)} \right)^2\end{aligned} θjJ(θ0,θ1)=θj2m1i=1m(hθ(x(i))y(i))2=θj2m1i=1m(θ0+θ1x(i)y(i))2
根据微积分公式,在 j j j 等于0和1时,推导出的偏导数公式如下

∂ ∂ θ 0 J ( θ 0 , θ 1 ) = 1 m ∑ i = 1 m ( θ 0 + θ 1 x ( i ) − y ( i ) ) \frac{\partial}{\partial \theta_0} J(\theta_0, \theta_1) = \frac{1}{m} \sum_{i=1}^{m} \left( \theta_{0} + \theta_{1}x^{(i)} - y^{(i)} \right) θ0J(θ0,θ1)=m1i=1m(θ0+θ1x(i)y(i))

∂ ∂ θ 1 J ( θ 0 , θ 1 ) = 1 m ∑ i = 1 m ( ( θ 0 + θ 1 x ( i ) − y ( i ) ) ∗ x ( i ) ) \frac{\partial}{\partial \theta_1} J(\theta_0, \theta_1) = \frac{1}{m} \sum_{i=1}^{m} \left(( \theta_{0} + \theta_{1}x^{(i)} - y^{(i)} )*x^{(i)}\right) θ1J(θ0,θ1)=m1i=1m((θ0+θ1x(i)y(i))x(i))

根据公式计算出偏导数项的值,就可以代入到梯度下降法中,不断地对参数进行同步更新,直到收敛,得到线性回归的全局最优解

在这里插入图片描述
在上面的算法中,有时也称为“批量梯度下降”,指的是在梯度下降的每一步中,我们都用到了所有的训练样本。在梯度下降中,在计算微分求导项时,我们需要进行求和运算,需要对所有 m m m 个训练样本求和。而事实上,有时也有其他类型的梯度下降法,不是这种"批量"型的,不考虑整个的训练集,而是每次只关注训练集中的一些小的子集。

如果之前有学过高等线性代数,应该知道有一种计算代价函数 J J J 最小值的解法,而不需要使用梯度下降这种迭代算法。这是另一种称为正规方程(normal equations)的方法。实际上在数据量较大的情况下,梯度下降法比正规方程要更适用一些。

八、代码实现

下面以 Coursera 上的一元线性回归数据集 ex1data1.txt 为例实现代码:

import numpy as np
import matplotlib.pyplot as plt

# load data, data.shape = (97, 2)
data = np.loadtxt('ex1data1.txt', delimiter=',', usecols=(0, 1))
x = data[:, 0]
y = data[:, 1]
m = y.size

# parameters
alpha = 0.01
num_iters = 5000
theta = np.zeros(2)

# X.shape = (97, 2), y.shape = (97, ), theta.shape = (2, )
X = np.c_[np.ones(m), x]  # 增加一列 1 到 矩阵 X,实现多项式运算

# Gradient Descent
for _ in range(0, num_iters):
    error = (X @ theta).flatten() - y  # error.shape = (97, )
    theta -= (alpha / m) * np.sum(X * error[:, np.newaxis], 0) # 0 表示每列相加

# plot
print(theta)
plt.scatter(x, y)
x_plot = np.array([np.min(x), np.max(x)])
y_plot = theta[0] + x_plot * theta[1]  # NumPy Broadcast
plt.plot(x_plot, y_plot, c="m")
plt.show()

得到的 ( θ 0 , θ 1 ) (\theta_0, \theta_1) (θ0,θ1) 结果是: [ − 3.8953 , 1.1929 ] [-3.8953, 1.1929] [3.8953,1.1929],作图如下:

在这里插入图片描述

向量化:在 Python 或 Matlab 中进行科学计算时,如果有多组数据或多项式运算,转化成矩阵乘法会比直接用 for 循环高效很多,可以实现同时赋值且代码更简洁。
这是由于科学计算库中的函数更好地利用了硬件的特性,更好地支持了诸如循环展开、流水线、超标量等技术。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值