第3章
线性回归算法
3.1 算法概述
简单来说,回归就是用一条曲线对数据点进行拟合,该曲线称为最佳拟合曲线,这个拟合过程称为回归。回归问题的求解过程就是通过训练分类器采用最优化算法来寻找最佳拟合参数集。当该曲线是一条直线时,就是线性回归。
对于一个拥有m个对象、n个属性的样本数据集而言,线性回归的目的就是建立一个线性函数,它能对待测对象x,预测其对应的一个或者多个输出结果。以银行贷款为例,银行会了解贷款人的年龄和工资等信息,然后根据这些数据给出相应的贷款额度,工资和年龄都会最终影响贷款的额度,那么它们各自有多大的影响呢?这就需要用到线性回归的思想。
机器学习中,线性回归思想示意图如图3-1所示。线性回归是机器学习的基础,“线性”指一次,“回归”实际上就是拟合。线性回归一般用来做连续值的预测,预测的结果是一个连续值。在训练学习样本时,不仅需要提供学习的特征向量X,还需要提供样本的实际结果(标记label),因此线性回归模型属于监督学习里的回归模型。
3.2 算法流程
线性回归算法流程如图3-2所示。
3.3 算法步骤
1.模型建立
在线性回归中,假定输入x与输出y之间具有线性相关的关系。当特征向量X中只有一个特征时,需要学习的函数应是一个一元线性函数。当情况复杂时,给定由d个属性描述的示例,其中xi是X在第i个属性上的取值,线性模型(linear model)试图学得一个通过属性的线性组合来进行预测的函数,考虑X存在n个特征的情形,我们往往需要得到更多的系数。将X到y的映射函数记作函数:
其中,为了在映射函数hθ(X)中保留常数项,令x0为1,所以特征向量X={1, x1, x2,…,xn},
特征系数向量θ={θ0, θ1, θ2,…, θn}。
2.参数估计
用线性回归拟合出来的模型hθ(X)给出的预测值f与真实值y(i)之间肯定存在差异,其中。对于每一个样本而言,满足:
误差相互独立且具有相同的分布,服从均值为0、方差为0^2的高斯分布。由于误差服从高斯分布,将代入高斯公式得
将式(3-2)代入式(3-3)可得:
为让预测值成为真实值的可能性最大,进行最大似然估计:
对该似然函数累乘不容易求解,且每项元素均大于零,对式(3-5)两边取对数,将乘法转换成加法:
对式(3-6)进行化简得
3.损失函数
对似然函数求对数以后,似然函数的值越大越好,前半部分属于常数值部分,不做考虑,因此式(3-7)后半部分的取值越小越好。令
运用最小二乘法对式(3-8)进行求解:
对式(3-9)中的θ求偏导以得到极小值点:
令偏导值为0,得θ:
4.梯度下降
在求解极小值的过程中,当数据量比较小的时候,可以通过式(3-11)的方式来求解最优的θ值,但是当数据量和特征值非常大,例如有几万甚至上亿的数据和特征值时,运用矩阵求逆的方法就变得不太现实,而梯度下降法给出了不错的选择。
梯度是一个向量,是一个n元函数f关于n个变量的偏导数,如三元函数f的梯度为
(fx, fy, fz),二元函数f的梯度为(fx, fy),一元函数f的梯度为fx。二元函数梯度下降示意图如图3-3所示。梯度函数的方向就是上述案例中上山最陡峭的地方,是函数f增长最快的方向,而梯度的反方向就是f的函数值降低最快的方向,沿着该方向更容易找到函数的最小值。
梯度下降法的基本思想可以类比为一个下山的过程。假设一个人站在山顶,由于浓雾使得他并不容易找到山谷(山的最低点),而必须利用自身周围的信息去找到下山的路径。此时,就可以利用如下方法来找到下山的途径:以他当前所处的位置为基准,寻找当前位置最陡峭的地方,然后朝着山的高度下降的地方走。反复采用该方法,最后就能成功抵达山谷。
在线性回归算法中,损失函数如下:
式中hθ(x(i))代表输入为x(i)时,在当时θ参数下的输出值:
使用梯度下降法求取J(θ)的最小值,实现目标函数J(θ)按梯度下降的方向进行减少,有
其中,j为特征值权重的编号,α为学习率或步长,需要人为指定,若取值过大则会导致目标函数不收敛,若取值过小则会导致总体迭代次数过多,收敛速度很慢。
当下降的高度小于某个设定的值时,停止下降。对线性回归算法损失函数J(θ)求梯度,得
据式(3-13)与式(3-14),单个特征的迭代式如下:
由单个特征迭代式推得多特征迭代式,见式(3-16):
对每个j迭代求值,再对式(3-16)迭代直至该式收敛。上述所讲即为梯度下降算法(Gradient Descent),当前后两次迭代的值不再发生变化时,说明它已收敛,退出迭代。在一般情况下,会设置一个具体的参数,当前后两次的迭代差值小于该值时迭代结束。
总的来说,在梯度下降的参数中,初始值和学习率都是人工设置的,同时梯度下降法对这些参数又是敏感的。初始值的设置会影响到最终J(θ)的最小值,使得结果可能是局部最小值(Local Minima),也可能是全局最小值(Global Minima),如图3-4所示。同时,学习率的设置也会影响梯度下降的性能和结果,当学习率值设置过小时,由于沿着最陡峭方向每次迈进的步伐太小,会导致收敛时间过长,但最终会找到全局最优解;当学习率值设置过大时,很有可能会直接越过全局最小值,因而无法得到J(θ)的最小值。
3.4 算法实例
下面是一个简单的模型,是对3.3节提出的线性回归梯度下降算法的实现,具体程序代码如下。
#!/usr/bin/python
#coding=utf-8
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
# 构造训练数据
x = np.arange(0., 10., 0.2)
m = len(x) # 训练数据点数目
print(m)
x0 = np.full(m, 1.0)
input_data = np.vstack([x0, x]).T # 将偏置b作为权向量的第一个分量
target_data = 2 * x + 5 + np.random.randn(m)
# 两种终止条件
loop_max = 10000 # 最大迭代次数(防止死循环)
epsilon = 1e-3
# 初始化权值
np.random.seed(0)
theta = np.random.randn(2)
alpha = 0.001 # 步长(注意取值过大会导致振荡即不收敛,过小收敛速度变慢)
diff = 0.
error = np.zeros(2)
count = 0 # 循环次数
finish = 0 # 终止标志
while count < loop_max:
count += 1
# 标准梯度下降是在权值更新前对所有样例汇总误差,而随机梯度下降的权值是通过考察某个训练样例来更新的
# 在标准梯度下降中,权值更新的每一步对多个样例求和,需要更多的计算
sum_m = np.zeros(2)
for i in range(m):
dif = (np.dot(theta, input_data[i]) - target_data[i]) * input_data[i]
sum_m = sum_m + dif # 当alpha取值过大时,sum_m会在迭代过程中溢出
theta = theta - alpha * sum_m # 注意步长alpha的取值,过大会导致振荡
# theta = theta - 0.005 * sum_m # alpha取0.005时产生振荡,需要将alpha调小
# 判断是否已收敛
if np.linalg.norm(theta - error) < epsilon:
finish = 1
break
else:
error = theta
print( 'loop count = %d' % count, '\tw:', theta)
print ('loop count = %d' % count, '\tw:', theta)
# 用SciPy线性回归检查
slope, intercept, r_value, p_value, slope_std_error = stats.linregress(x, target_data)
print ('intercept = %s slope = %s' % (intercept, slope))
plt.plot(x, target_data, 'g*')
plt.plot(x, theta[1] * x + theta[0], 'r')
plt.xlabel("X")
plt.xlabel("Y")
plt.show()
运行结果如图3-5所示。
50
loop count = 1 w: [2.3221664 3.74752288]
loop count = 2 w: [2.03227017 1.54546032]
loop count = 3 w: [2.29637407 2.97515749]
loop count = 4 w: [2.19699697 2.02832888]
loop count = 5 w: [2.33456174 2.63686952]
loop count = 6 w: [2.31615581 2.22769658]
......
loop count = 300 w: [5.63766048 1.88345245]
loop count = 301 w: [5.63868679 1.88329572]
loop count = 302 w: [5.63970019 1.88314097]
loop count = 303 w: [5.64070083 1.88298817]
loop count = 304 w: [5.64168888 1.88283729]
intercept = 5.719194774079044 slope = 1.871001842016462
3.5 算法应用
线性回归是机器学习中最基础的算法,它研究的是样本目标和特征变量之间是否存在线性关系。现有506条有关波士顿房价的综合数据,包括每间住宅的平均房间数RM、一氧化氮浓度(每千万份)NOX、房子所在区的犯罪率CRIM、城镇的黑人比例B、高速公路条数RAD、城镇的学生与教师比例PTRATIO等。每条数据就是一个样本,房价就是目标变量,其他数据可看作特征变量。下面算法中选取房间数RM作为特征变量,房价PRICE作为目标变量,通过使用Scikit-learn中内置的回归模型对“美国波士顿房价”数据进行预测,最终给出房价PRICE的预测。
import pandas as pd
import numpy as np
from sklearn import datasets
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
#把数据转化成Pandas的形式,在列尾加上房价PRICE
boston_dataset=datasets.load_boston()
data=pd.DataFrame(boston_dataset.data)
data.columns=boston_dataset.feature_names
data['PRICE']=boston_dataset.target
#取出房间数和房价并转化成矩阵形式
x=data.loc[:, 'RM'].as_matrix(columns=None)
y=data.loc[:, 'PRICE'].as_matrix(columns=None)
#进行矩阵的转置
x=np.array([x]).T
y=np.array([y]).T
#训练线性模型
l=LinearRegression()
l.fit(x, y)
#画图显示
plt.scatter(x, y, s=10, alpha=0.3, c='green')
plt.plot(x, l.predict(x), c='blue', linewidth='1')
plt.xlabel("Number of Rooms")
plt.ylabel("House Price")
plt.show()
运行结果如图3-6所示。
3.6 算法的改进与优化
利用普通最小二乘法建立多元线性回归模型(Multiple Linear Regression,MLR),当对回归方程中的变量与样本进行增减时,其他变量回归系数可能有较大的变化,甚至改变符号,与实际问题产生矛盾。然而,在实际问题中变量间存在线性关系的现象却是普遍存在的,为消除这种现象给回归建模带来的不良影响,化学家S. Wold于 1983年提出了一种偏最小二乘回归(Partial Least Squares Regression,PLS)方法。
在偏最小二乘回归中,设由观测数据得到资料阵和y,记和分别是X和y经标准化处理后的观测数据矩阵,其中。得到的预测模型效果优于普通最小二乘法。
当数据间存在线性关系时,用普通最小二乘方法建模得到的结果误差会很大,甚至会出现和实际相悖的情况,在这种情况下,普通最小二乘方法是失效的。偏最小二乘回归在某种程度上改善了普通最小二乘法对变量间存在线性关系时建模的弊端。
3.7 本章小结
本章主要介绍了机器学习中的线性回归算法。首先,对线性回归算法进行简要介绍,该算法通过对历史数据的学习得到估计函数,运用该函数可以对新的数据产生新的估计。其次,以流程图的形式对该算法从整体上进行讲解,然后对算法流程中的各环节进行简要介绍并给出相关公式的推导过程,之后,在算法实例部分给出了该算法的实现过程。最后,在算法应用部分,结合实际情况通过波士顿房价预测的实例加深读者对线性回归算法的理解,并给出对该算法的改进与优化。学完本章之后,读者应该对线性回归算法有深刻的了解,掌握并熟练地使用它。
3.8 本章习题
1. 选择题
(1)在下面的两个图中,右图给出关于θ0和θ1的损失函数J(θ0, θ1),左图给出相同损失函数的等值线图。根据该图,选择正确的选项(多选题)。( )
A. 如果从B点开始,具有良好学习率的梯度下降最终帮助我们到达或接近A点,因为损失函数J(θ0, θ1)的值在A点处最小
B. 点P(右图的全局最小值)对应于左图中的点A
C. 如果从B点开始,具有良好学习率的梯度下降最终帮助我们到达或接近C点,因为损失函数J(θ0, θ1)的值在C点处最小
D. 如果从B点开始,具有良好学习率的梯度下降最终帮助我们到达或接近A点,因为损失函数J(θ0, θ1)的值在A点处最大
E. 点P(右图的全局最小值)对应于左图中的点C
(2) 假设对于某些线性回归问题(例如预测住房价格)我们有一些训练集,对于训练集,设法找到θ0、θ1,使得J(θ0, θ1)=0。下面哪个叙述是正确的?( )
A. 即使对于尚未看到的新例子,我们也可以完美地预测y的值(例如,可以完美地预测我们还没有看到的新房子)
B. 为使上式成立,我们必须令θ0=0和θ1=0从而使得hθ(x)=0
C. 对于满足J(θ0, θ1)的θ0和θ1的值,对每个训练样本(x(i), y(i))都有hθ(x(i))=y(i)
D. 这是不可能的,根据J(θ0, θ1)=0的定义,不可能存在θ0和θ1使得J(θ0, θ1)=0
2. 填空题
(1)已知小张在大学一年级的学习成绩,预测一下她在大学二年级的学习成绩。具体来说,让x等于小张在大学第一年(新生年)收到的A等级(包括A-、A和A+等级)的数量。我们要预测y的值,将其定义为她在第二年(大二)获得的A等级的数量。在线性回归中,假设,使用m来表示训练样本数量。根据下面给出的训练集,m的值为 。
(2)假设使用题(1)中的训练集,定义损失函数,则J(0,1)= 。
(3)假设θ0=-1,θ1=0.5,则hθ(5)= 。
3.判断题
(1) 机器学习线性回归模型是一种有监督的学习方式。( )
(2) 梯度下降算法是一种求解全局最优解的方法。( )
(3) 使用最小二乘法求解损失函数时,将数据点代入假设方程求得观测值,求使得实际值与观测值相减的平方和最小的参数。( )
4.编程题
据美国疾病预防中心数据显示,美国约1/7的成年人患有糖尿病,到2050年,这个比例将会快速增长至高达1/3。在UCL机器学习数据库里面有一个糖尿病数据集,该数据集由768条数据组成,每条数据有9个特征,分别是怀孕次数、血糖、血压、皮脂厚度、胰岛素、BMI身体质量指数、糖尿病遗传函数、年龄和结果(0代表未患糖尿病,1代表患有糖尿病)。部分数据如下表所示。利用该数据集的第一个特征,编写一段Python代码,运用线性回归的思想建立怀孕与是否患糖尿病之间的联系,绘制一条直线,使得数据集中所有样本到直线上的距离的剩余平方和最小,并且与相应预测线逼近,最终给出回归方程相关系数值。