机器学习(的过程)本质是通过数据的不断训练,使得模型在其对应的评价指标上表现越来越好的一个过程。
一、机器学习模型训练相关核心概念
**模型评估指标:**用于评估模型实际效果的数值型指标,如准确率;
**模型参数:**对于模型最终输出结果有影响的模型关键指标,如自变量加权求和汇总过程中的权重。
**模型训练:**指通过不断的数据输入,模型参数得到有效调整的过程,此处模型参数有效调整指的是调整之后能够提升模型表现。
二、机器学习概念补充
1. 经典统计分析方法与机器学习
线性回归是诞生统计学领域的一类模型,同时也是整个线性类模型的基础模型,是一类非常重要的统计学模型。在经典统计学领域,线性回归模型拥有坚实的数学理论作为支撑,曾在很长一段时间内都是数理统计分析建模最通用的模型之一。不过使用传统的统计学方法构建线性回归模型其实并不简单,如果要构建一个统计学意义的线性回归模型,至少需要掌握随机变量的基本分布、变量相关性和独立性、方差分析等基本统计学知识,才能够上手构建线性回归模型。而在机器学习领域的基本建模思路、流程和统计分析有很大区别,在构建线性回归模型时流程较为简单。
从机器学习的角度出发,所谓线性回归,指的是自变量(特征)加权求和汇总求得因变量(标签)的过程。例如的计算过程,就是一个简单的线性回归。
2. 数据与数据集相关概念
2.1数据与数据集
所谓数据,特指能够描绘某件事物的属性或运行状态的数值,并且一个数据集由多条数据构成。例如鸢尾花数据,就是描述鸢尾花一般属性的数据集。可以通过下列方式查看该数据集
# 导入相关包
import numpy as np
import pandas as pd
iris_df = pd.read_csv("iris.csv")
iris_df
# 输出如下

数据集描述鸢尾花基本信息如下:

在上述数据集中,每一行代表一朵花的记录结果,而其中每一列代表所有花的一项共同指标。类似这种二维表格数据,有时也被称为面板数据,属于结构化数据的一种。
2.2 特征与标签
鸢尾花数据集中的每一列是所有描述对象的一项共同指标,其中,前四列分别描述了鸢尾花的四项生物学形状,而最后一列则描述了每一朵花所属类别。当然如果上述表格的记录目的是通过记录鸢尾花的四个维度的不同属性的取值最终判别鸢尾花属于哪一类,则该数据集中的前四列也被称为数据集的特征(features),而最后一列被称为数据集的标签(labels)。据此在实际建模过程中,当需要利用模型进行预测时,也是通过输入模型的一些样本特征(一些鸢尾花的四个特征取值),让模型进行每个样本的标签判别(判别每一朵花应该属于哪一类)。所谓标签和特征,只是依赖模型预测目标进行的的围绕着数据集不同列进行的划分方式。如果模型的预测目标发生变化,则数据集的特征和标签也会发生变化。例如:如果围绕鸢尾花数据集我们最终进行的是每一朵花瓣宽(petal width)的预测,则上述数据集中的1、2、3、5就变成了标签。因此特征和标签本质上都是人工设置的。一般来说,标签列需要放在最后一列,数据集中的列也被称为字段,鸢尾花数据集总共有五列,也就是总共有五个字段。
2.3 连续变量和离散变量
对于鸢尾花数据而言,由于每一条数据都记录了一朵花的四个维度的属性以及花的所属类别,因此,从随机变量的角度出发,将每一组观测结果视为五个随机变量的一次观测值。例如,我们可以将花萼长(sepal length)看成一个随机变量,而第一条数据中的5.1cm,则可以看成这个随机变量的第一个观测值。
既然是随机变量,就有离散变量和连续变量之分。所谓连续变量,指的就是随机变量能够取得连续值,例如随机变量表示距离或者长度测算结果时,该变量就是连续性变量。而离散变量指的是随机变量只允许取得离散的整数,例如随机变量用0/1表示性别。不难发现,鸢尾花数据集中的前四个变量都是连续变量,而最后一个变量是离散型变量(或者说可以用离散变量表示)。总结:鸢尾花数据集的特征都连续型变量,而标签则是离散型标签。需要补充的一点是,在传统统计分析领域,对于离散型变量,还可以进一步细分为名义型变量和顺序变量。所谓名义变量,指的是随机变量取得不同离散值时,取值大小本身没有数值意义,只有指代意义。例如,用0/1代表男女,则该变量没有1>0的数值意义。但所谓顺序变量,则有大小方面的数值意义,例如使用0/1/2代表高中/本科/研究生学历,则可用2>1>0来表示学历的高低之分。
3. 模型类型
3.1 分类问题与回归问题
离散型变量和连续型变量在数理特征上有很大的区别。因此,对于预测类的机器学习建模来说。标签这一预测指标是连续型变量还是离散型变量,会对模型造成很大的影响。据此如果围绕离散型标签进行进行建模预测,则称任务为分类预测任务,该模型为解决分类任务的模型。如果是围绕连续型标签进行建模预测,则称该任务为回归预测任务,该模型为解决回归类问题的回归模型。
下边再介绍一个用于回归类问题建模的数据集,abalone。由于abalone数据集是txt格式的,列与列之间是通过空格进行分隔的,并且第一行没有列名,因此我们需要使用下述语句进行读取。
# pd.read_csv(),是pandas提供的函数,用于读取CSV(逗号分隔值)或其他分隔符文本文件,并将其转换为DataFrame对象
# header=None:表示文件没有标题行(即第一行不是列名)。如果不设置此参数,pandas会默认将第一行作为列名。
# DataFrame是pandas的核心数据结构,类似于Excel表格或SQL表。
ab_df = pd.read_csv("abalone.txt", sep='\t', header=None)
ab_df
# 读取结果如下

同时,该数据集各列名称如下:

修改数据集名称:
ab_df.columns = ['Gender', 'Length',
'Diameter', 'Height',
'Whole weight', 'Shucked weight',
'Viscera weight', 'Shell weight',
'Rings']
修改结果如下:

为了方便后续直接调用,我们可以将修改后的数据集保存在本地
ab_df.to_csv('abalone.csv', index=False)
和鸢尾花数据集一样,abalone dataset也是由专业人士精心统计汇总之后得到的数据集。目前来说,此类数据集往往用于机器学习初学者入门时候使用。不过值得一提的是,不同年代数据采集和获取的方式有很大区别。在统计学模型大行其道之年,人们获取数据主要都是通过手工测量和记录的方式(当然Abalone数据集没有那么久历史),并且多数情况下由专业人士进行,因此数据量较小,但数据质量较高,而经典统计学算法正是在这一背景下、针对这类数据诞生的方法。而伴随着大数据时代的到来,数据的生产和应用方式都发生了较大的变化,由于数据可以自动采集、传输和存储,因此数据采集的场景变得无处不在、数据量也呈现爆发式增长,同时数据质量也变得参差不齐。此外,在数据应用层面,实际应用的机器学习算法被要求能够及时运算。快速相应,并且对于质量参差不齐的数据要求产出相对稳定的结果,因此相较于经典统计学算法,机器学习算法计算效率更高、对数据质量要求更低,但同时也存在计算精度不高、计算结果不如统计方法稳定等一些列问题。当然这也是机器学习诞生之初饱受诟病的一点。但也正是机器学习不是那么精准但能应用于各个场景的特性,使得其称为大数据时代最为普适的算法。
三、线性回归模型建模准备
1. 数据准备
线性回归也属于回归类模型,是针对连续型变量进行数值预测的模型,因此我们需要选用abalone数据集进行建模。为了更清晰的展示建模过程中的内部计算细节,选取数据集中部分数据带入进行建模。

2. 模型准备
上述数据集是极端简化后的数据集,只有一个连续型特征和连续型标签,并且只包含两条数据。围绕只包含一个特征的数据所构建的线性回归模型,也被称为简单线性回归。简单线性回归的模型表达式为;

其中x表示自变量,即数据特征,w表示自变量系数,代表每次计算都需要相乘的某个数值,b表示截距项,代表每次计算都需要相加的某个数值,而y表示因变量,即模型输出结果。
除了简单线性回归外,线性回归主要还包括多元线性回归和多项式回归两类。
其中多元线性回归用于解决包含多个特征的回归类问题,模型基本表达式为:

其中x1...n表示n个自变量,对应数据集的n个特征,w1...n表示n个自变量的系数,b表示截距。此处加权求和汇总的计算过程较为明显,简单线性回归也是多元线性回归的一个特例。
此外,多项式回归则是在多元线性回归的基础上,允许自变量最高次超过1次,例如:

就代表着一个二元二次回归方程。
四、线性回归模型训练
1. 模型训练的本质:有方向的参数调整
1.1 模型训练与模型参数调整
模型训练就是指对模型参数进行有效调整。模型参数是影响模型输出的关键变量,例如本例中的模型包含两个参数,w1和b,当参数取得不同值时,模型将输出完全不同的结果。

其中简单线性回归计算过程为。需要说明的是,在很多场景下,我们会使用更加简洁的记号用于代表模型训练过程中的各项数值,用xi表示某条数值第i个特征的取值,使用yi作为某条数据的标签取值,使用y_hat表示数据带入模型之后模型的输出结果。从上边不难看出,模型参数取值不同模型输出的结果也不同,而不同组的参数取值似乎也有好坏之分,当参数组取值为(1,0)时的模型输出结果,要比参数组取值为(1,-1)时输出结果更加贴近真实值,。这其实也就说明第二组参数要好于第一组参数。而机器在学习的过程中,或者说模型训练过程,就是需要找到一组最优参数。
1.2 模型评估与损失函数
既然有了模型输出结果好与坏的判别,我们需要将这种反馈有效的传递给模型,才能够让模型在训练的过程中逐渐朝向好的方向发展。而要在模型训练过程中建立这种有效的反馈,必须要掌握模型评估指标与损失函数。
其中,模型评估指标是评估模型好与坏的标量计算结果,其最终结果一般由模型预测值y_hat和真实值y共同计算得出。我们在前边提到过的准确率即是一个分类模型的评估指标,并且是通过比较模型预测正确的样本数占总样本数的比例最终得出,而对于回归类问题,最重要的模型评估指标就是SSE------残差平方和。
所谓残差平方和,指的就是模型预测值y_hat和真实值y之间差值的平方和,计算结果表示预测值和真实值之间的差距,结果越小表示二者差越小,模型小国标越好。SSE的计算公式为:

其中n为样本数量。对应的,上述两组不同参数取值对应的模型残差平方和计算结果依次为:

能够看出,第二组参数对应模效果更好。据此,我们就找到了能够量化评估模型效果好坏的指标
有了模型评估指标之后,我们还需要将评估结果有效反馈给模型。这时就需引入损失函数(Loss Function)
和模型评估指标是真实值和预测值的计算结果不同,模型的损失函数都是关于模型参数的函数。损失函数本质上一个衡量模型预测结果和真实结果之间差异的计算过程,例如在SSE结果中带入模型参数,就嫩构成一个SSE损失函数,基本计算过程如下:


SSELoss的基本计算过程和SSE一致,只不过SSELoss中带入的是模型参数,而SSE带入的是确定参数数值之后的计算结果,因此我们也可以认为SSELoss和SSE来说,一个是带参数的方程,一个是确定方程参数之后的计算结果。
既然SSE和SSELoss的计算过程类似,那为何要区别损失函数和模型评估指标呢?主要有以下几点原因:
其一:对于很多模型(尤其是分类模型)来说,模型评估指标和模型损失函数的计算过程并不一致,例如准确率就很难转化为一个以参数为变量的函数表达式;
其二:模型评估指标和损失函数构建的目标不同,模型评估指标的计算目标是给模型性能一个标量计算结果,而损失函数的构建则是为了找到一组最优的参数结果。
除了SSE之外,常用的回归类问题的评估指标还有MSE(均方误差)和RMSE(均方根误差),其中MSE就是在SSE的基础上除以样本总量:

而RMSE则是在MSE基础之上开平方算得的结果:

对应的MSE和RMSE也有相对的损失函数。
1.3 损失函数与参数求解
**一旦损失函数构建完成,我们就可以围绕损失函数去寻找损失函数的最小值,以及求出损失函数取得最小值时候的自变量(也就是模型参数)的取值,此时参数的的取值就是原模型中参数最优取值结果。**这点从SSE和SSELoss彼此类似的计算过程中也能够容易看出来,由于我们最终建模目标是希望模型预测结果和真实结果一致,也就是SSE的值尽可能小,而SSE的值是SSELoss中的两个变量(w,b)取值决定的,因此如果我们能找到一组(w,b)使得SSE的最终计算结果尽可能的小,也就是相当于找到了一组模型的最佳参数。
至此我们就发现了损失函数的核心作用:搭建参数求解的桥梁,构建一个协助模型求解参数的方程。通过损失函数的构建,我们就可以将求解模型最优参数的问题转化为求解损失函数最小值的问题。至此也就完成了此前所说的向模型传递反馈的过程。
值得注意的是,损失函数的计算方程和实际带入进行建模的数据直接相关,上述SSELoss是带入两条数据的情况下构建的损失函数,而调整输入数据,损失函数实际计算方程也会发生变化。
2. 利用最优化方法求解损失函数
2.1 损失函数的求解
在构建好损失函数之后,接下来就是如何求解损失函数的最小值(及损失函数取最小值时w和b的取值)。值得注意的是,此时损失函数是一个关于模型参数的方程,也就是说模型参数此时成了损失函数的自变量。
而要求解损失函数最小值,就需要记住一些优化理论和优化方法。当然,此处的优化理论和优化算法都是一些无约束条件下进行函数极值求解方法。利用优化方法求解损失函数最小值及取得最小值时损失函数自变量(也就是模型参数)的取值过程,也被称为损失函数求解。
2.2 图形展示损失函数
为了更好讨论损失函数(SSELoss)求最小值的过程,对于上述二元损失函数来说,我们可以将其展示在三维空间内:三维空间坐标分别为w、b、SSELoss。此处我们可以使用Python中matplotlib和Axes3D函数进行三维图像绘制。

python
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-1,3,0.05)
y = np.arange(-1,3,0.05)
w, b = np.meshgrid(x, y)
SSE = (2 - w - b) ** 2 + (4 - 3 * w - b) ** 2
ax = plt.axes(projection='3d')
ax.plot_surface(w, b, SSE, cmap='rainbow')
ax.contour(w, b, SSE, zdir='z', offset=0, cmap="rainbow") #生成z方向投影,投到x-y平面
plt.xlabel('w')
plt.ylabel('b')
plt.show()

根据图像,我们大概能判断损失函数最小点位置
2.3 函数的凹凸性
初步探索函数图像,不难看出,目标函数是个整体看起来向下凸的函数。从理论出发我们知道,函数的凹凸性是函数的重要性质,也是设计到损失函数求解方法选取的重要性质。这里首先给出凸函数的一般定义,对于任意一个函数,如果函数f(x)上存在任意两个点,x1和x2,且

我们就判定,这个函数是凸函数。在这里我们需要知道的是,凸函数的定义存在一定的"不一致",和之前一样,在机器学习中我们以向下凸的函数作为凸函数的一般定义、此外,除了函数定义方法,我们还可以通过凸集/凹集来定义凸函数。同时,很多机器学习模型所构建的损失函数都是凸函数,因此关于凸函数的优化方法(找到最小值的方法)也就成了机器学习建模过程中最常用的优化方法。而凸优化的相关理论,也转件称为算法工程师的必修课。
典型的凸函数如,我们可以绘制函数图像如下:
python
x = np.arange(-10,10,0.1)
y = x ** 2
plt.plot(x, y, '-')
plt.show()

不难看出,函数上任意开两个点的y取值的均值(函数值的均值)都不少于这两个点均值的y的值(均值的函数值)

而对于一个凸函数来说,全域最小值明显存在。求解凸函数的最小值有很多种方法,其中最为基础的方法叫做最小二乘法。并且,虽然此处略过了相关证明过程,但对于上述SSELoss,本质上也是一个凸函数。因此我们是可以通过最小二乘法对SSELoss进行求解的。
3. 最小二乘法理论基础
通过上例,也就是函数不难看出,函数全域最小值为x=0点,同时该点对应的函数切线与x轴平行,也就是在最小值点,函数的导数为0.其实这并不难理解,在最小值点左边函数逐渐递减、而在最小值右边函数逐渐递增,最小值点左右两边单调性相反。而这种性质其实可以拓展为凸函数的一个关于求解最小值的一般性质,即:
(1)对于一元函数,如果存在导数为0的点,则该点就是最小值点;
(2)对于多元函数,如果存在某一点,使得函数的各个自变量的偏导数都为0,则该点就是最小值点。
据此,我们就找到了最小二乘法求解凸函数最小值的基本出发点:即通过寻找损失函数导函数(或者偏导函数联立的方程组)为0的点,求解损失函数的最小值。
关于驻点、临界点、边界点和拐点的概念讨论:
其实从更严格的意义上来说,凸函数的最小值点其实是根据边界点和驻点(导数为0的点)决定,如果没有边界点且没有驻点,则函数没有最小值(例如y=x),如果存在边界点,但没有驻点,则边界点的一侧就是最小值点,若果存在驻点(且左右两边单调性相反),则驻点就是最小值点,例如,对于而言,
时取值为0,也就是0点就是最小值点。
值得注意的是,驻点也可以说是临界点,但不是拐点,拐点特指左右两边函数凹凸性发生变化的点,切勿和驻点混淆。
3.1 最小二乘法求解SSELoss
接下来,尝试利用最小二乘法求解SSELoss。根据上述理论,我们使用最小二乘法求解SSELoss,即

本质上就是找到能够令损失函数偏导数取值都为0的一组(w,b)。SSELoss两个偏导数计算过程如下:

最终可得,损失函数最小值点为(1,1),即当w=1,b=1时模型损失函数计算结果最小、模型SSE取值最小、模型效果最好,此时SSE=0,线性回归模型计算结果为:

我们也可对比此前参数计算结果:

至此,我们就完成了一个机器学习建模的完整流程。
五、机器学习建模一般流程
下边整体梳理下机器学习的一般建模流程:
1. 提出基本模型
如本节中,我们尝试利用简单线性回归去捕捉一个简单数据集的基本数据规律,这里的y=wx+b就是我们所提出的基本模型。在提出模型时,我们往往会预设好一些影响模型结构或者实际判别性能的参数,如简单的现象回归中的w和b。
2. 确定损失函数
围绕建模的目标构建评估指标,并且围绕评估指标设置损失函数。在本例中,模型评估指标和损失函数的建模流程相同,需要知道的是,损失函数不是模型,而是模型参数所组成的一个函数。
3. 根据损失函数性质,选择优化方法
损失函数既然承载了我们优化的目标(让预测值和真实值尽可能接近),同时也是包含了模型参数的函数,当我们围绕目标函数求解最小值时,也就完成了模型参数的求解。当然,这个过程本质就是一个数学的最优化过程,求解目标函数最小值的本质也就是一个最优化问题,而要解决这个问题,我们就需要灵活适用一些最优化方法。在具体的最优化的选择上,函数本身的性质是重要影响因素,也就是说,不同类型、不同性质的函数会影响优化方法的选择。在简单线性回归中,由于目标函数是凸函数,我们根据凸函数性质,我们选取了最小二乘法作为该损失函数的优化方法。但实际上,简单线性回归的损失函数其实就是所有机器学习模型中最简答的一类损失函数。
4. 利用优化算法进行损失函数求解
在确定优化方法之后,我们就能够借助优化方法对损失函数进行求解,在大多数情况下我们都是求解损失函数的最小值。而伴随损失函数最小值点确定,我们也找到了一组对应的损失函数自变量的取值,而该组自变量的取值也就是模型的最佳参数。在本例中,通过优化方法求解损失函数的过程还是非常简答的。后续我们就会发现损失函数求解的过程才是建模的主体。