带你读《Python机器学习》之三:线性回归算法

简介: 本书讲解了如何使用Python的核心元素以及强大的机器学习库,同时还展示了如何正确使用一系列统计模型。本书可作为学习数据科学的初学者及想进一步拓展数据科学领域认识的读者的参考书。同样,本书也适合计算机等相关专业的本科生、研究生阅读。全书共13章,除了简要介绍机器学习及Python在机器学习中的应用,还系统讲述了数据分类、数据预处理、模型优化、集成学习、回归、聚类、神经网络、深度学习等内容。本书将机器学习背后的基本理论与应用实践联系起来,通过这种方式让读者聚焦于如何正确地提出问题、解决问题。

点击查看第一章
点击查看第二章

第3章

线性回归算法

3.1 算法概述

简单来说,回归就是用一条曲线对数据点进行拟合,该曲线称为最佳拟合曲线,这个拟合过程称为回归。回归问题的求解过程就是通过训练分类器采用最优化算法来寻找最佳拟合参数集。当该曲线是一条直线时,就是线性回归。
对于一个拥有m个对象、n个属性的样本数据集而言,线性回归的目的就是建立一个线性函数,它能对待测对象x,预测其对应的一个或者多个输出结果。以银行贷款为例,银行会了解贷款人的年龄和工资等信息,然后根据这些数据给出相应的贷款额度,工资和年龄都会最终影响贷款的额度,那么它们各自有多大的影响呢?这就需要用到线性回归的思想。
机器学习中,线性回归思想示意图如图3-1所示。线性回归是机器学习的基础,“线性”指一次,“回归”实际上就是拟合。线性回归一般用来做连续值的预测,预测的结果是一个连续值。在训练学习样本时,不仅需要提供学习的特征向量X,还需要提供样本的实际结果(标记label),因此线性回归模型属于监督学习里的回归模型。

image.png

3.2 算法流程

线性回归算法流程如图3-2所示。

image.png

3.3 算法步骤

1.模型建立
在线性回归中,假定输入x与输出y之间具有线性相关的关系。当特征向量X中只有一个特征时,需要学习的函数应是一个一元线性函数image.png。当情况复杂时,给定由d个属性描述的示例image.png,其中xi是X在第i个属性上的取值,线性模型(linear model)试图学得一个通过属性的线性组合来进行预测的函数,考虑X存在n个特征的情形,我们往往需要得到更多的系数。将X到y的映射函数记作函数image.png
image.png
其中,为了在映射函数hθ(X)中保留常数项,令x0为1,所以特征向量X={1, x1, x2,…,xn},
特征系数向量θ={θ0, θ1, θ2,…, θn}。
2.参数估计
用线性回归拟合出来的模型hθ(X)给出的预测值f与真实值y(i)之间肯定存在差异image.png,其中image.png。对于每一个样本而言,满足:
image.png
误差image.png相互独立且具有相同的分布,服从均值为0、方差为0^2的高斯分布。由于误差image.png服从高斯分布,将image.png代入高斯公式得
image.png
将式(3-2)代入式(3-3)可得:
image.png
为让预测值成为真实值的可能性最大,进行最大似然估计:
image.png
对该似然函数累乘不容易求解,且每项元素均大于零,对式(3-5)两边取对数,将乘法转换成加法:
image.png
对式(3-6)进行化简得
image.png
3.损失函数
对似然函数求对数以后,似然函数的值越大越好,前半部分属于常数值部分,不做考虑,因此式(3-7)后半部分的取值越小越好。令
image.png
运用最小二乘法对式(3-8)进行求解:
image.png
对式(3-9)中的θ求偏导以得到极小值点:
image.png
令偏导值为0,得θ:
image.png
4.梯度下降
在求解极小值的过程中,当数据量比较小的时候,可以通过式(3-11)的方式来求解最优的θ值,但是当数据量和特征值非常大,例如有几万甚至上亿的数据和特征值时,运用矩阵求逆的方法就变得不太现实,而梯度下降法给出了不错的选择。
梯度是一个向量,是一个n元函数f关于n个变量的偏导数,如三元函数f的梯度为
(fx, fy, fz),二元函数f的梯度为(fx, fy),一元函数f的梯度为fx。二元函数梯度下降示意图如图3-3所示。梯度函数的方向就是上述案例中上山最陡峭的地方,是函数f增长最快的方向,而梯度的反方向就是f的函数值降低最快的方向,沿着该方向更容易找到函数的最小值。

image.png

梯度下降法的基本思想可以类比为一个下山的过程。假设一个人站在山顶,由于浓雾使得他并不容易找到山谷(山的最低点),而必须利用自身周围的信息去找到下山的路径。此时,就可以利用如下方法来找到下山的途径:以他当前所处的位置为基准,寻找当前位置最陡峭的地方,然后朝着山的高度下降的地方走。反复采用该方法,最后就能成功抵达山谷。
在线性回归算法中,损失函数如下:
image.png
式中hθ(x(i))代表输入为x(i)时,在当时θ参数下的输出值:
image.png
使用梯度下降法求取J(θ)的最小值,实现目标函数J(θ)按梯度下降的方向进行减少,有
image.png
其中,j为特征值权重的编号,α为学习率或步长,需要人为指定,若取值过大则会导致目标函数不收敛,若取值过小则会导致总体迭代次数过多,收敛速度很慢。
当下降的高度小于某个设定的值时,停止下降。对线性回归算法损失函数J(θ)求梯度,得
image.png
据式(3-13)与式(3-14),单个特征的迭代式如下:
image.png
由单个特征迭代式推得多特征迭代式,见式(3-16):
image.png
对每个j迭代求值,再对式(3-16)迭代直至该式收敛。上述所讲即为梯度下降算法(Gradient Descent),当前后两次迭代的值不再发生变化时,说明它已收敛,退出迭代。在一般情况下,会设置一个具体的参数,当前后两次的迭代差值小于该值时迭代结束。
总的来说,在梯度下降的参数中,初始值和学习率都是人工设置的,同时梯度下降法对这些参数又是敏感的。初始值的设置会影响到最终J(θ)的最小值,使得结果可能是局部最小值(Local Minima),也可能是全局最小值(Global Minima),如图3-4所示。同时,学习率的设置也会影响梯度下降的性能和结果,当学习率值设置过小时,由于沿着最陡峭方向每次迈进的步伐太小,会导致收敛时间过长,但最终会找到全局最优解;当学习率值设置过大时,很有可能会直接越过全局最小值,因而无法得到J(θ)的最小值。

image.png

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

image.png

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所示。

image.png

3.6 算法的改进与优化

利用普通最小二乘法建立多元线性回归模型(Multiple Linear Regression,MLR),当对回归方程中的变量与样本进行增减时,其他变量回归系数可能有较大的变化,甚至改变符号,与实际问题产生矛盾。然而,在实际问题中变量间存在线性关系的现象却是普遍存在的,为消除这种现象给回归建模带来的不良影响,化学家S. Wold于 1983年提出了一种偏最小二乘回归(Partial Least Squares Regression,PLS)方法。
在偏最小二乘回归中,设由观测数据得到资料阵image.png和y,记image.pngimage.png分别是X和y经标准化处理后的观测数据矩阵,其中image.png。得到的预测模型效果优于普通最小二乘法。
当数据间存在线性关系时,用普通最小二乘方法建模得到的结果误差会很大,甚至会出现和实际相悖的情况,在这种情况下,普通最小二乘方法是失效的。偏最小二乘回归在某种程度上改善了普通最小二乘法对变量间存在线性关系时建模的弊端。

3.7 本章小结

本章主要介绍了机器学习中的线性回归算法。首先,对线性回归算法进行简要介绍,该算法通过对历史数据的学习得到估计函数,运用该函数可以对新的数据产生新的估计。其次,以流程图的形式对该算法从整体上进行讲解,然后对算法流程中的各环节进行简要介绍并给出相关公式的推导过程,之后,在算法实例部分给出了该算法的实现过程。最后,在算法应用部分,结合实际情况通过波士顿房价预测的实例加深读者对线性回归算法的理解,并给出对该算法的改进与优化。学完本章之后,读者应该对线性回归算法有深刻的了解,掌握并熟练地使用它。

3.8 本章习题

1. 选择题
(1)在下面的两个图中,右图给出关于θ0和θ1的损失函数J(θ0, θ1),左图给出相同损失函数的等值线图。根据该图,选择正确的选项(多选题)。(  )

image.png

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的值为   

image.png

(2)假设使用题(1)中的训练集,定义损失函数image.png,则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代码,运用线性回归的思想建立怀孕与是否患糖尿病之间的联系,绘制一条直线,使得数据集中所有样本到直线上的距离的剩余平方和最小,并且与相应预测线逼近,最终给出回归方程相关系数值。

image.png

相关文章
|
3天前
|
机器学习/深度学习 数据采集 算法
Python机器学习:Scikit-learn库的高效使用技巧
【10月更文挑战第28天】Scikit-learn 是 Python 中最受欢迎的机器学习库之一,以其简洁的 API、丰富的算法和良好的文档支持而受到开发者喜爱。本文介绍了 Scikit-learn 的高效使用技巧,包括数据预处理(如使用 Pipeline 和 ColumnTransformer)、模型选择与评估(如交叉验证和 GridSearchCV)以及模型持久化(如使用 joblib)。通过这些技巧,你可以在机器学习项目中事半功倍。
13 3
|
6天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
10 3
|
8天前
|
机器学习/深度学习 人工智能 算法
机器学习基础:使用Python和Scikit-learn入门
机器学习基础:使用Python和Scikit-learn入门
20 1
|
9天前
|
机器学习/深度学习 人工智能 算法
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
车辆车型识别,使用Python作为主要编程语言,通过收集多种车辆车型图像数据集,然后基于TensorFlow搭建卷积网络算法模型,并对数据集进行训练,最后得到一个识别精度较高的模型文件。再基于Django搭建web网页端操作界面,实现用户上传一张车辆图片识别其类型。
26 0
【车辆车型识别】Python+卷积神经网络算法+深度学习+人工智能+TensorFlow+算法模型
|
13天前
|
机器学习/深度学习 算法 Java
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
机器学习、基础算法、python常见面试题必知必答系列大全:(面试问题持续更新)
|
19天前
|
机器学习/深度学习 人工智能 算法
机器学习基础:使用Python和Scikit-learn入门
【10月更文挑战第12天】本文介绍了如何使用Python和Scikit-learn进行机器学习的基础知识和入门实践。首先概述了机器学习的基本概念,包括监督学习、无监督学习和强化学习。接着详细讲解了Python和Scikit-learn的安装、数据处理、模型训练和评估等步骤,并提供了代码示例。通过本文,读者可以掌握机器学习的基本流程,并为深入学习打下坚实基础。
16 1
|
20天前
|
机器学习/深度学习 API 计算机视觉
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
18 2
|
20天前
|
机器学习/深度学习 存储 算法
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(上)
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(上)
22 1
|
2天前
|
机器学习/深度学习 人工智能 算法
探索机器学习中的决策树算法
【10月更文挑战第29天】本文将深入浅出地介绍决策树算法,一种在机器学习中广泛使用的分类和回归方法。我们将从基础概念出发,逐步深入到算法的实际应用,最后通过一个代码示例来直观展示如何利用决策树解决实际问题。无论你是机器学习的初学者还是希望深化理解的开发者,这篇文章都将为你提供有价值的见解和指导。
|
6天前
|
机器学习/深度学习 数据采集 算法
探索机器学习中的线性回归
【10月更文挑战第25天】本文将深入浅出地介绍线性回归模型,一个在机器学习领域中广泛使用的预测工具。我们将从理论出发,逐步引入代码示例,展示如何利用Python和scikit-learn库实现一个简单的线性回归模型。文章不仅适合初学者理解线性回归的基础概念,同时也为有一定基础的读者提供实践指导。