经过第1章的介绍,我们已经完成了Python开发环境的安装与配置。现在,我们就正式开始介绍第1个算法: 线性回归(Linear Regression)。 按照前言中介绍的学习方法,整个线性回归的学习路线如图2-1所示。由于这是介绍的第1个算法,所以我们会介绍很多基础的内容,导致看起来内容繁多,因此,对于整个线性回归的学习我们将会通过7个小节的内容进行介绍,但是,值得高兴的是只要完成了前面4个步骤的学习就基本上达到了阶段一的要求。下面就正式开始介绍线性回归。

图 2-1 线性回归学习路线图

2.1 模型的建立与求解#

2.1.1 理解线性回归模型#

通常来讲,机器学习中的每个算法都是为了解决某一类问题而诞生的。换句话说,也就是在实际情况中的确存在一些问题能够通过线性回归来解决,例如对房价的预测。但是有人可能会问,为什么对于房价的预测就应该用线性回归,而不是其他算法模型呢?其原因就在于常识告诉我们房价是随着面积的增长而增长的,且总体上呈线性增长的趋势。那有没有当面积大到一定程度后价格反而降低,因此不符合线性增长的呢?这当然也可能存在,但在实际处理中肯定会优先选择线性回归模型,当效果不佳时我们会尝试其他算法,因此,当学习过多个算法后,在得到某个具体的问题时,就需要考虑哪种模型更适合来解决当前这个问题了。

例如某市的房价走势如图2-2所示,其中横坐标为面积,纵坐标为价格,并且房价整体上呈线性增长的趋势。假如现在随意告诉你一个房屋的面积,要怎样才能预测(或者叫计算)出其对应的价格呢?

图 2-2 某市的房价走势图

2.1.2 建立线性回归模型#

一般来讲,当我们得到一个实际问题时,首先会根据问题的背景结合常识选择一个合适的模型。同时,现在常识告诉我们房价的增长更优先符合线性回归这类模型,因此可以考虑建立一个如下所示的线性回归模型。

$$ \hat{y}=h(x)=wx+b\tag{2-1} $$

其中$w$叫权重参数(Weight),$b$叫偏置(Bias)或者截距(Intercept)。当通过某种方法求解得到未知参数$w$和$b$之后,也就意味着我们得到了这个预测模型,即给定一个房屋面积$x$,就能够预测出其对应的房价$\hat{y}$。

注意: 在机器学习中所谓的模型,可以简单理解为一个函数。

2.1.3 求解线性回归模型#

当建立好一个模型后,自然而然想到的就是如何通过给定的数据,也叫训练集(Training Data),来对模型 $h(x)$进行求解。在中学时期我们学过如何通过两个坐标点来求解过这两点的直线,可在上述的场景中这种做法显然是行不通的(因为所有的点并不在一条直线上),那有没有什么好的解决的办法呢?

此时就需要我们转换一下思路,既然不能直接进行求解,那就换一种间接的方式。现在来想象一下,当 $h(x)$ 满足一个什么样的条件时,它才能称得上是一个好的$h(x)$? 回想一下求解$h(x)$的目的是什么,不就是希望输入面积$x$后能够输出“准确”的房价$\hat{y}$吗?既然直接求解$h(x)$不好入手,那么我们就从“准确”来入手。

可又怎样来定义准确呢?在这里,我们可以通过计算每个样本的真实房价与预测房价之间的均方误差来对“准确”进行刻画,即

$$ \begin{cases} J(w,b)=\frac{1}{2m}\sum\limits_{i=1}^{m}{{{({{y}^{(i)}}-{{{\hat{y}}}^{(i)}})}^{2}}}\\[2ex] {{{\hat{y}}}^{(i)}}=h({{x}^{(i)}})=w{{x}^{(i)}}+b \end{cases} \tag{2-2} $$

其中,$m$表示样本数量; $x^{(i)}$表示第$i$个样本的取值,也就是第$i$个房屋的面积; $y^{(i)}$表示第$i$个房屋的真实价格; $y^{(i)}$表示第$i$ 个房屋的预测价格。

由式(2-2)可知,当函数$J(w,b)$取最小值时的参数$\hat{w}$和$\hat{b}$,就是要求的目标参数。为什么?因为当$J(w,b)$取最小值时就意味着此时所有样本的预测值与真实值之间的误差(Error)最小。如果极端一点,当所有预测值都等同于真实值,那么此时的$J(w,b)$就是0了。因此,对于如何求解模型 $h(x)$ 的问题就转换成了如何最小化函数$J(w,b)$的问题,而$J(w,b)$也有一个专门的术语叫作目标函数(Objective Function)或者代价函数(Cost Function)抑或损失函数(Loss Function)。

至此,我们离第一阶段的学习目标就只有一步之遥了,那就是如何通过开源框架进行建模求解,并进行预测。至于求解过程到底怎样及如何进行的,那就是第二阶段的任务了,下面开始完成第一阶段的最后一步。

2.1.4 sklearn简介#

如图2-3所示,scikit-learn简称sklearn。它是一个开源的机器学习框架,包含了数十种常用的机器学习算法,例如线性回归、逻辑回归、决策树、支持向量机、决策树以及聚类分析等。同时,其Python化的设计风格对于Python用户来讲也十分友好且易于上手,并且每个算法都给了相应的示例及API文档,因此,对于入门机器学习来讲,利用sklearn进行建模是一个不二的选择。

图 2-3 sklearn介绍

2.1.5 安装sklearn及其他库#

在第1章内容中,我们已经介绍了如何配置Python环境,下面就开始在第1章中所创建的Python虚拟环境里安装所需要的包(库)。如果已经按照第1.1.4节中的步骤完成了本书所有Python包的安装,则可以跳过本小节内容。

1. 打开终端

如果是在Windows环境中,则应先单击“开始”按钮,然后找到Anaconda Prompt并打开,最后激活相应的Python虚拟环境即可。如果是在Linux环境中,则可直接打开命令行终端,然后激活相应的虚拟环境。

2. 安装Python包

为了完成整个线性回归的建模任务及结果的可视化,需要安装sklearn和matplotlib这两个Python包。如果之前在配置环境的时候,已将pip源地址替换为清华大学镜像,则下载的速度会更快,如图2-4所示。

图 2-4 sklearn安装

由于在安装相应的Python包后PyCharm会建立新的包索引,所以需要等待几分钟,如图2-5所示。

图 2-5 Python包索引

2.1.6 线性回归示例代码#

在安装完成相应的Python包后就可以正式地对线性回归进行建模与求解了,详细完整的代码见AllBook/Chapter02/01_house_price_train.py文件。

1. 导入包

首先需要将用到的相关Python包进行导入,代码如下:

1 import numpy as np
2 from sklearn.linear_model import LinearRegression
3 import matplotlib.pyplot as plt

2. 制作样本(数据集)

制作用于训练模型的数据集,代码如下:

1 def make_data():
2     np.random.seed(20)
3     x = np.random.rand(100) * 30 + 50  # 面积
4     noise = np.random.rand(100) * 50
5     y = x * 8 - 127 - noise            # 价格
6     return x,y

在上述代码中,第4行的作用是在数据集中加入一定的噪声(误差),以模拟真实情况。

3. 定义模型并求解

通过sklearn中的LinearRegression类来对线性回归模型的参数进行求解与预测,代码如下:

1 def main(x, y):
2     model = LinearRegression()          # 定义模型
3     x = np.reshape(x, (-1, 1))
4     model.fit(x, y)# 求解模型
5     y_pre = model.predict(x) # 预测
6     print(y_pre)

在上述代码中,第2行np.reshape(x,(-1,1))表示把x变成[n,1]的形状,至于n到底是多少,将通过np.reshape函数自己推导。例如a的行形状为[4,5],如果想把a改成[2,10]形状,则可以使用a.reshape([2,10]),或者使用a.reshape([2,-1])进行形状的变换。第4行是通过fit()方法来求解模型中的参数,即式(2-1)中的$w$和$b$。第5行是根据房屋面积来预测其价格。

4. 运行结果

最后,调用定义好的函数运行程序,并输出最后训练得到的参数结果,示例代码如下:

1 if __name__ == '__main__':
2     x, y = make_data()
3     main(x, y)			
4     #参数w=[7.97699647],b=-154.31885006061555
5     #面积50的房价为: [244.53097351]

从上述输出结果可以发现,参数$w=7.97$、$b=-154.32$,这就意味着$h(x)=7.97x-154.32$。在这之后,便可以通过$h(x)$来对新的输入进行预测了。同时,还能够根据求解后的模型画出对应拟合出的直线,如图2-6所示。

图 2-6 房价预测走势图

到此,便完成了对于线性回归第一阶段的学习。以上代码可参见 AllBookCode/Chapter02/C02_house_price_train.py 文件。

2.1.7 小结#

在本节内容中,我们首先通过一个实际的场景介绍了什么是线性回归,接着介绍了如何建立一个简单的线性模型,然后引导读者如何将模型的求解问题转换为目标函数的最小化问题,最后通过开源框架sklearn搭建了一个简单的线性回归模型并进行了求解。虽然内容不多,但是体现了整个线性回归算法的核心思想。