带你读《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

相关文章
|
1月前
|
算法 前端开发 数据处理
小白学python-深入解析一位字符判定算法
小白学python-深入解析一位字符判定算法
47 0
|
1月前
|
机器学习/深度学习 算法 搜索推荐
从理论到实践,Python算法复杂度分析一站式教程,助你轻松驾驭大数据挑战!
【10月更文挑战第4天】在大数据时代,算法效率至关重要。本文从理论入手,介绍时间复杂度和空间复杂度两个核心概念,并通过冒泡排序和快速排序的Python实现详细分析其复杂度。冒泡排序的时间复杂度为O(n^2),空间复杂度为O(1);快速排序平均时间复杂度为O(n log n),空间复杂度为O(log n)。文章还介绍了算法选择、分而治之及空间换时间等优化策略,帮助你在大数据挑战中游刃有余。
60 4
|
8天前
|
机器学习/深度学习 人工智能 算法
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
垃圾识别分类系统。本系统采用Python作为主要编程语言,通过收集了5种常见的垃圾数据集('塑料', '玻璃', '纸张', '纸板', '金属'),然后基于TensorFlow搭建卷积神经网络算法模型,通过对图像数据集进行多轮迭代训练,最后得到一个识别精度较高的模型文件。然后使用Django搭建Web网页端可视化操作界面,实现用户在网页端上传一张垃圾图片识别其名称。
36 0
基于Python深度学习的【垃圾识别系统】实现~TensorFlow+人工智能+算法网络
|
8天前
|
机器学习/深度学习 人工智能 算法
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
手写数字识别系统,使用Python作为主要开发语言,基于深度学习TensorFlow框架,搭建卷积神经网络算法。并通过对数据集进行训练,最后得到一个识别精度较高的模型。并基于Flask框架,开发网页端操作平台,实现用户上传一张图片识别其名称。
28 0
【手写数字识别】Python+深度学习+机器学习+人工智能+TensorFlow+算法模型
|
8天前
|
机器学习/深度学习 人工智能 算法
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
蔬菜识别系统,本系统使用Python作为主要编程语言,通过收集了8种常见的蔬菜图像数据集('土豆', '大白菜', '大葱', '莲藕', '菠菜', '西红柿', '韭菜', '黄瓜'),然后基于TensorFlow搭建卷积神经网络算法模型,通过多轮迭代训练最后得到一个识别精度较高的模型文件。在使用Django开发web网页端操作界面,实现用户上传一张蔬菜图片识别其名称。
43 0
基于深度学习的【蔬菜识别】系统实现~Python+人工智能+TensorFlow+算法模型
|
12天前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
29 2
|
1月前
|
存储 机器学习/深度学习 算法
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
蓝桥杯Python编程练习题的集合,涵盖了从基础到提高的多个算法题目及其解答。
60 3
蓝桥杯练习题(三):Python组之算法训练提高综合五十题
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
阿里云人工智能平台 PAI 团队发表的图像编辑算法论文在 MM2024 上正式亮相发表。ACM MM(ACM国际多媒体会议)是国际多媒体领域的顶级会议,旨在为研究人员、工程师和行业专家提供一个交流平台,以展示在多媒体领域的最新研究成果、技术进展和应用案例。其主题涵盖了图像处理、视频分析、音频处理、社交媒体和多媒体系统等广泛领域。此次入选标志着阿里云人工智能平台 PAI 在图像编辑算法方面的研究获得了学术界的充分认可。
【MM2024】阿里云 PAI 团队图像编辑算法论文入选 MM2024
|
21天前
|
算法 测试技术 开发者
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗
在Python开发中,性能优化和代码审查至关重要。性能优化通过改进代码结构和算法提高程序运行速度,减少资源消耗;代码审查通过检查源代码发现潜在问题,提高代码质量和团队协作效率。本文介绍了一些实用的技巧和工具,帮助开发者提升开发效率。
23 3
|
26天前
|
机器学习/深度学习 数据可视化 Python
使用最小二乘法进行线性回归(Python)
【10月更文挑战第28天】本文介绍了使用Python实现最小二乘法进行线性回归的步骤,包括数据准备、计算均值、计算斜率和截距、构建线性回归方程以及预测和可视化结果。通过示例代码展示了如何从创建数据点到最终绘制回归直线的完整过程。