吴恩达-机器学习-第二周

多变量线性回归(Linear Regression with Multiple Variables)

多维特征

吴恩达-机器学习-第二周_第1张图片

n 代表特征的数量

{x^{\left( i \right)}}代表第 i 个训练实例,是特征矩阵中的第i行,是一个向量(vector)。

比方说,上图的

{x}^{(2)}\text{=}\begin{bmatrix} 1416\\ 3\\ 2\\ 40 \end{bmatrix}

{x}_{j}^{\left( i \right)}代表特征矩阵中第 i 行的第 j 个特征,也就是第 i 个训练实例的第 j 个特征。
如上图的x_{2}^{\left( 2 \right)}=3,x_{3}^{\left( 2 \right)}=2

支持多变量的假设 h 表示为:
h_{\theta}\left( x \right)={\theta_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}}+...+{\theta_{n}}{x_{n}}
这个公式中有n+1个参数和n个变量,为了简化表示,引入x_{0}=1,则公式转化为:h_{\theta} \left( x \right)={\theta_{0}}{x_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}}+...+{\theta_{n}}{x_{n}}

此时模型中的参数和任何一个训练实例都是n+1维的向量, 因此公式可以简化为:h_{\theta} \left( x \right)={\theta^{T}}X(其中上标T代表矩阵转置)。

多变量梯度下降

与单变量线性回归类似,在多变量线性回归中,我们也构建一个代价函数,则这个代价函数是所有建模误差的平方和,即:J\left( {\theta_{0}},{\theta_{1}}...{\theta_{n}} \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( h_{\theta} \left({x}^{\left( i \right)} \right)-{y}^{\left( i \right)} \right)}^{2}}}

其中:h_{\theta}\left( x \right)=\theta^{T}X={\theta_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}}+...+{\theta_{n}}{x_{n}}

吴恩达-机器学习-第二周_第2张图片
单变量和多变量

我们的目标和单变量线性回归问题中一样,是要找出使得代价函数最小的一系列参数。 多变量线性回归的批量梯度下降算法为:

吴恩达-机器学习-第二周_第3张图片

即:

吴恩达-机器学习-第二周_第4张图片

求导后得到:

吴恩达-机器学习-第二周_第5张图片

n>=1时, {{\theta }*{0}}:={{\theta }*{0}}-a\frac{1}{m}\sum\limits_{i=1}^{m}{({{h}*{\theta }}({{x}^{(i)}})-{{y}^{(i)}})}x*{0}^{(i)}

{{\theta }*{1}}:={{\theta }*{1}}-a\frac{1}{m}\sum\limits_{i=1}^{m}{({{h}*{\theta }}({{x}^{(i)}})-{{y}^{(i)}})}x*{1}^{(i)}

{{\theta }*{2}}:={{\theta }*{2}}-a\frac{1}{m}\sum\limits_{i=1}^{m}{({{h}*{\theta }}({{x}^{(i)}})-{{y}^{(i)}})}x*{2}^{(i)}

我们开始随机选择一系列的参数值,计算所有的预测结果后,再给所有的参数一个新的值,如此循环直到收敛。

代码示例:

计算代价函数 J\left( \theta \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( {h_{\theta}}\left( {x^{(i)}} \right)-{y^{(i)}} \right)}^{2}}} 其中:{h_{\theta}}\left( x \right)={\theta^{T}}X={\theta_{0}}{x_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}}+...+{\theta_{n}}{x_{n}}

Python 代码:

def computeCost(X, y, theta):
    inner = np.power(((X * theta.T) - y), 2)
    return np.sum(inner) / (2 * len(X))

梯度下降法实践1-特征缩放

在我们面对多维特征问题的时候,我们要保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛

以房价问题为例,假设我们使用两个特征,房屋的尺寸和房间的数量,尺寸的值为 0-2000平方英尺,而房间数量的值则是0-5,以两个参数分别为横纵坐标,绘制代价函数的等高线图能,看出图像会显得很扁,梯度下降算法需要非常多次的迭代才能收敛。

吴恩达-机器学习-第二周_第6张图片

解决的方法是尝试将所有特征的尺度都尽量缩放到-1到1之间。这个范围根据经验来定,比如-3到3或者-\frac{1}{3}\frac{1}{3}可以接受,但若是-0.001到0.001或者-100到100就太大了。如图:

吴恩达-机器学习-第二周_第7张图片
image.png

最简单的方法是令:normalized feature: {{x}_{n}}=\frac{{{x}_{n}}-{{\mu}_{n}}}{{{s}_{n}}},其中 {\mu_{n}}是平均值,{s_{n}}是标准差或者范围(最大值-最小值)。

梯度下降法实践2-学习率

梯度下降算法收敛所需要的迭代次数根据模型的不同而不同,我们不能提前预知,我们可以绘制迭代次数和代价函数的图表来观测算法在何时趋于收敛。


吴恩达-机器学习-第二周_第8张图片

可以看出300到400次迭代后接近收敛。

也有一些自动测试是否收敛的方法,例如将代价函数的变化值与某个阀值\epsilon(例如0.001)进行比较,但通常合适阀值比较难以确定。所以看图更清晰。

正确的J(θ)曲线每次迭代应该是下降的。
梯度下降算法的每次迭代受到学习率的影响,如果学习率\alpha过小,则达到收敛所需的迭代次数会非常高。
(If α is too small: slow convergence)
如果学习率\alpha过大,每次迭代可能不会减小代价函数,会越过局部最小值导致无法收敛。
(If α is too large: J(θ) may not decrease on every iterration, may not converge)

吴恩达-机器学习-第二周_第9张图片

合适的学习率保证了正确和效率。

通常可以考虑尝试些学习率:
(按3倍)
\alpha=0.001,0.003,0.01,0.03,0.1,0.3,1,3,10

特征和多项式回归

如房价预测问题,

吴恩达-机器学习-第二周_第10张图片

h_{\theta}\left( x \right)={\theta_{0}}+{\theta_{1}}\times{frontage}+{\theta_{2}}\times{depth}

{x_{1}}=frontage(临街宽度),{x_{2}}=depth(纵向深度),我们选择更合适的 x=frontage*depth=area(面积)作为特征,则:{h_{\theta}}\left( x \right)={\theta_{0}}+{\theta_{1}}x。 线性回归并不适用于所有数据,有时我们需要曲线来适应我们的数据,比如一个二次方模型:h_{\theta}\left( x \right)={\theta_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}^2} 或者三次方模型: h_{\theta}\left( x \right)={\theta_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}^2}+{\theta_{3}}{x_{3}^3}

选择合适的特征和得到更适合的模型。
要根据数据模型选择合适的函数模型来拟合。
注:如果我们采用多项式回归模型,在运行梯度下降算法前,特征缩放非常有必要。

正规方程(normal equation)

到目前为止,我们都在使用梯度下降算法,但是对于某些线性回归问题,正规方程方法是更好的解决方案。如:
先假设θ属于实数:


吴恩达-机器学习-第二周_第11张图片

正规方程是通过求解下面的方程来找出使得代价函数最小的参数的:\frac{\partial}{\partial{\theta_{j}}}J\left( {\theta_{j}} \right)=0 。 假设我们的训练集特征矩阵为 X(包含了 {{x}_{0}}=1)并且我们的训练集结果为向量 y,则利用正规方程解出向量 \theta ={{\left( {X^T}X \right)}^{-1}}{X^{T}}y 。 上标T代表矩阵转置,上标-1 代表矩阵的逆。设矩阵A={X^{T}}X,则:{{\left( {X^T}X \right)}^{-1}}={A^{-1}} 以下表示数据为例:

吴恩达-机器学习-第二周_第12张图片

即:
吴恩达-机器学习-第二周_第13张图片

运用正规方程方法求解参数:
吴恩达-机器学习-第二周_第14张图片

Octave 中,正规方程写作:

pinv(X'*X)*X'*y

pinv计算逆矩阵

注: 正规方程不需要特征缩放

注:对于那些不可逆的矩阵(通常是因为特征之间不独立,如同时包含英尺为单位的尺寸和米为单位的尺寸两个特征,也有可能是特征数量大于训练集的数量),正规方程方法是不能用的。

梯度下降与正规方程的比较:

梯度下降 正规方程
需要选择学习率 不需要
需要多次迭代 一次运算得出
当特征数量大时也能较好适用 需要计算 ({X}^{T}X)^{-1},如果特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为O(n^3),通常来说当小于10000 时还是可以接受的
适用于各种类型的模型 只适用于线性模型,不适合逻辑回归模型等其他模型

Conclusion: 只要特征变量的数目并不大,标准方程是一个很好的计算参数的替代方法。具体地说,只要特征变量数量小于一万,我通常使用标准方程法,而不使用梯度下降法。
随着我们要讲的学习算法越来越复杂,例如,当我们讲到分类算法,像逻辑回归算法,我们会看到,实际上对于那些算法,并不能使用标准方程法。对于那些更复杂的学习算法,我们将不得不仍然使用梯度下降法。因此,梯度下降法是一个非常有用的算法,可以用在有大量特征变量的线性回归问题。或者我们以后在课程中,会讲到的一些其他的算法,因为标准方程法不适合或者不能用在它们上。但对于这个特定的线性回归模型,标准方程法是一个比梯度下降法更快的替代算法。所以,根据具体的问题,以及你的特征变量的数量,这两种算法都是值得学习的。

正规方程的python实现:

    
 def normalEqn(X, y):
    
   theta = np.linalg.inv(X.T@X)@X.T@y #X.T@X等价于X.T.dot(X)
    
   return theta

正规方程及不可逆性(选修)

当计算 θ=inv(X'X ) X'y,那对于矩阵的结果是不可逆的情况咋办呢? 如果你懂一点线性代数的知识,你或许会知道,有些矩阵可逆,而有些矩阵不可逆。我们称那些不可逆矩阵为奇异或退化矩阵。 问题的重点在于的不可逆的问题很少发生,在Octave里,如果你用它来实现的计算,你将会得到一个正常的解。在Octave里,有两个函数可以求解矩阵的逆,一个被称为pinv(),另一个是inv(),这两者之间的差异是些许计算过程上的,一个是所谓的伪逆,另一个被称为逆。即便矩阵是不可逆的,使用pinv() 函数也可计算出值。

在线性代数中的定义:
奇异矩阵指矩阵的行列式|A|是等于0,称矩阵A为奇异矩阵;若不等于0,称矩阵A为非奇异矩阵。 同时,由|A|≠0可知矩阵A可逆,这样可以得出另外一个重要结论:可逆矩阵就是非奇异矩阵,非奇异矩阵也是可逆矩阵。 如果A为奇异矩阵,则AX=0有无穷解,AX=b有无穷解或者无解。如果A为非奇异矩阵,则AX=0有且只有唯一零解,AX=b有唯一解。

如果矩阵中有一些多余的特征,比如是线性相关的,像x_1是以英尺为尺寸规格计算的房子,x_2是以平方米为尺寸规格计算的房子,两个特征值将始终满足约束:x_1=x_2*(3.28)^{2},那么矩阵是不可逆的,就可以删除这些重复特征。因此,首先应该通过观察所有特征检查是否有多余的特征,尽量用较少的特征来反映尽可能多内容,否则我会考虑使用正规化方法。 如果矩阵是不可逆的,(通常来说,不会出现这种情况),如果在Octave里,可以用伪逆函数pinv() 来计算。这种使用不同的线性代数库的方法被称为伪逆。即使的结果是不可逆的,但算法执行的流程是正确的。

正规方程公式的推导:

\theta ={{\left( {X^{T}}X \right)}^{-1}}{X^{T}}y 的推导过程:

J\left( \theta \right)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{\left( {h_{\theta}}\left( {x^{(i)}} \right)-{y^{(i)}} \right)}^{2}}} 其中:{h_{\theta}}\left( x \right)={\theta^{T}}X={\theta_{0}}{x_{0}}+{\theta_{1}}{x_{1}}+{\theta_{2}}{x_{2}}+...+{\theta_{n}}{x_{n}}

将向量表达形式转为矩阵表达形式,则有J(\theta )=\frac{1}{2}{{\left( X\theta -y\right)}^{2}} ,其中Xmn列的矩阵(m为样本个数,n为特征个数),\thetan行1列的矩阵,ym行1列的矩阵,对J(\theta )进行如下变换

J(\theta )=\frac{1}{2}{{\left( X\theta -y\right)}^{T}}\left( X\theta -y \right)

=\frac{1}{2}\left( {{\theta }^{T}}{{X}^{T}}-{{y}^{T}} \right)\left(X\theta -y \right)

=\frac{1}{2}\left( {{\theta }^{T}}{{X}^{T}}X\theta -{{\theta}^{T}}{{X}^{T}}y-{{y}^{T}}X\theta -{{y}^{T}}y \right)

接下来对J(\theta )偏导,需要用到以下几个矩阵的求导法则:

-\frac{dAB}{dB}={{A}^{T}}\frac{d{{X}^{T}}AX}{dX}=2AX

(可以看:闲话矩阵求导,
求导规则参考:http://files.cnblogs.com/files/leoleo/matrix_rules.pdf)

所以有:

\frac{\partial J\left( \theta \right)}{\partial \theta }=\frac{1}{2}\left(2{{X}^{T}}X\theta -{{X}^{T}}y -{}({{y}^{T}}X )^{T}-0 \right)

=\frac{1}{2}\left(2{{X}^{T}}X\theta -{{X}^{T}}y -{{X}^{T}}y -0 \right)

={{X}^{T}}X\theta -{{X}^{T}}y

\frac{\partial J\left( \theta \right)}{\partial \theta }=0,

则有\theta ={{\left( {X^{T}}X \right)}^{-1}}{X^{T}}y


常用数学符号的 LaTeX 表示方法

本文数学公式使用 LaTeX
(以下内容主要摘自“一份不太简短的 LATEX2e 介绍”)

1、指数和下标可以用^和_后加相应字符来实现。比如:

吴恩达-机器学习-第二周_第15张图片

2、平方根(square root)的输入命令为:\sqrt,n 次方根相应地为: \sqrt[n]。方根符号的大小由LATEX自动加以调整。也可用\surd 仅给出
符号。比如:

吴恩达-机器学习-第二周_第16张图片

3、命令\overline 和\underline 在表达式的上、下方画出水平线。比如:

4、命令\overbrace 和\underbrace 在表达式的上、下方给出一水平的大括号。

5、向量(Vectors)通常用上方有小箭头(arrow symbols)的变量表示。这可由\vec 得到。另两个命令\overrightarrow 和\overleftarrow在定义从A 到B 的向量时非常有用。

6、分数(fraction)使用\frac{...}{...} 排版。一般来说,1/2 这种形式更受欢迎,因为对于少量的分式,它看起来更好些。

吴恩达-机器学习-第二周_第17张图片

7、积分运算符(integral operator)用\int 来生成。求和运算符(sum operator)由\sum 生成。乘积运算符(product operator)由\prod 生成。上限和下限用^ 和_来生成,类似于上标和下标。

吴恩达-机器学习-第二周_第18张图片

附加小菜: (小技巧)

  • 分数

(\frac{1}{m+\frac{1}{2}})

\left(\frac{1}{m+\frac{1}{2}} \right)

\left(\frac{1}{2} \right)
用\left(   \right)括起来就可以把分数包的很好,很漂亮。
  • 矩阵

bmatrix:
{x}^{(2)}\text{=}\begin{bmatrix} 数字 \end{bmatrix}
{x}^{(2)}\text{=}\begin{bmatrix} 1416\\ 3\\ 2\\ 40 \end{bmatrix}

matrix:
{x}^{(2)}\text{=}\begin{matrix} 数字 \end{matrix}
{x}^{(2)}\text{=}\begin{matrix} 1416\\ 3\\ 2\\ 40 \end{matrix}

  • 求和符号
    \sum_{k=1}^N k^2
    \sum_{k=1}^N k^2
    \sum\limits_{i=1}^{m} k^2
    \sum\limits_{i=1}^{m} k^2

  • 代码
    如果要标记一小段行内代码,你可以用反引号把它包起来,例如:
    Use the `printf()` function.
    Use the printf() function.
    一大段则使用 ```code ```

code

你可能感兴趣的:(吴恩达-机器学习-第二周)