机器学习入门——多变量线性回归

回顾了线性代数的相关知识后,我们可以将它应用于比较复杂的算法设计。本节内容是第二节(单变量的线性回归)的拓展,结合线性代数的使用,可以简单的实现出来。


4 多变量的线性回归

本节内容,将介绍更加通用,更贴近实际应用的线性回归算法——多变量线性回归。同时,会详细讲解梯度下降法的设计和使用一种新的方法求解θ。下面以课程中的估计房子价格的例子进行详细说明。


4.1 多特征

多特征,就是从多个参数的特性来判断预测函数。在本例中,就是从更多的方面去预测房子的价格。训练数据如下表所示:



由训练数据所示,房子的价格是由房子大小、卧室数量、楼层数量和房龄确定的。这里,我们设:

x1 : 房子大小, x2 : 卧室数量, x3 : 楼层数量, x4 : 房龄, y : 房子的价格,则有:


4.2 多变量预测函数

对于单变量而言,其预测函数为:



而对于多变量,则比较复杂,有:



这时,使用线性代数表示更为方便。我们假设,x0=1



此时,假设函数表示为:


4.3 多变量梯度下降

多变量梯度下降,是单变量的拓展。现在,我们就将两者的数学原理进行对比。



由上表同样可以看出,多变量是单变量的拓展。当我们假设,同时n=1,则多变量就会退化为单变量。

4.3.1 特征缩放

特征缩放(Feature scaling),在这里我认为它是对用于梯度下降法的数据进行处理的方法。它的作用是,将多个特征的数据的取值范围处理在相近的范围内,从而使梯度下降更快地收敛。

exp:
( #指数量 )

显然,这两者的取值范围相差很大。这样导致的后果,就是代价函数关于这两个特征的参数θ1和θ2的图像是一个又瘦又长的椭圆等高线图,这样,梯度下降会很难收敛,或者说,收敛得很慢。这时可以使用特征缩放,而特征缩放的方法有很多,下面介绍几种。

(1)

该特征的值/该特征的最大值。对于所举的例子而言,就有:



经过处理之后,图像偏移会减少,变得更圆,有利于快速收敛。显然,在此例中,通过这种方法进行特征缩放,数据范围会在0和1之间。

(2)

(该特征值-该特征最大取值的一半)/(该特征的最大值)。对于所举的例子而言,有:



这样,x的取值范围大概在-0.5和0.5之间。

缩放范围的讨论

讲解了两种缩放的方法,那么究竟要缩放到什么程度才是最合适的呢?

答案是,接近[-1,1]即可,没有一个确切的范围。下面给出一些例子:



其实,特征缩放不需要十分精确,只是让梯度下降运行得更快一点即可。

4.3.2 学习速率

除了特征的缩放会影响梯度下降的运算,学习速率也会直接影响。这里所说的“学习速率”,指的是梯度下降表达式中的α。

如何判断学习速率是否合适?

最直接的方法是,画出训练后代价函数和迭代数的图像,根据图像去判断调整。除此之外,还可以使用自动检测法。即当代价函数在迭代中,小于一个很小的值时,我们就认为梯度下降收敛。但是,这个“很小的值”是很难确定的,一般可取1e-3。当然,还是优先选择第一种方法判断!下面就列举几种常见情况进行讲解。



数学原理证明,只要学习速率足够小,代价函数一定会减小,只是学习速率太小的话,迭代的次数会增加。

总的来说,α的取值太小,收敛速度缓慢,需要大量的迭代实现;取值太大,代价函数可能不会一直下降,甚至会导致不收敛。

在具体实现时,α的取值可以通过不断尝试,不断调整,最终确定。可尝试的值:0.001,0.003,0.01,0.03,0.1,0.3,1

4.4 正规方程

对于求解预测函数的θ参数,除了使用梯度下降法,还可以使用标准方程(Normal equation)。

假设训练数据有m个,有n个特征,则有:(下面讲解假设:)

(m×(n+1)的矩阵)

((n+1)×1的矩阵)

((n+1)×1的矩阵)

由线性代数运算,可得:



这就是正规方程

观察该方程,也许你会有疑问:如果不可逆的时候,怎么办呢?

首先,我们要搞明白什么时候会使它不可逆。原因:

1.特征中,有冗余的特征向量,如:向量之间互为线性;
2.训练数据太少,特征太多。

解决方法:针对第一个原因,我们可以删除冗余的特征;针对第二个,我们可以适当去掉一些不那么重要的特征,或者使用正规化方法。

总的来说,标准方程不可逆是很少见的,而且有些编程语言使用伪逆克服这一点(如:Octive),因此,在大多数实现线性回归中,出现不可逆的问题也不需要过分重视。

下面我们就以第二节单变量线性回归为例子,编程实现θ的求解。

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 22 14:27:15 2017
@author: louishao
"""
import numpy as np
#train data
train_x = np.mat([[1,1],[1,2],[1,3],[1,4],[1,5],[1,6],[1,7],[1,8],[1,9],[1,10],[1,11],[1,12],[1,13],[1,14]])
train_y = np.mat([3.0,5.0,7.0,9.0,11.0,13.0,15.0,17.0,19.0,21.0,23.0,25.0,27.0,29.0])
# transpose the train_y
y = np.transpose(train_y)
#transpose the train_x
transposex = np.transpose(train_x)
#the inverse 
invx = np.linalg.inv(transposex*train_x)

theta = invx*transposex*y

theta1 = float(theta[1][0])
theta0 = float(theta[0][0])

print "the predict function is y=%sx+%s"%(theta1,theta0)

运行结果

the predict function is y=2.0x+1.0

显然,结果正确。仔细思考,标准方程可以一步就求出θ参数,而且不需要迭代,好像比梯度下降好很多。这个说法对不对呢?下面我们对两者进行比较。

梯度下降(Gradient descent)和正规方程(Normal equation)的比较


你可能感兴趣的:(机器学习入门)