Skip to content

本章内容

本节尝试在一个手动构建的数据集上进行完整的线性回归模型建模。

不过,在进行线性回归的手动建模实验过程中,一如既往我们需要补充很多关于机器学习的基础理论以及一些常用技巧,同时,我们也需要搭建一个更加完善的建模实验环境,因此本节内容总共分为四个小节,分别是:

Lesson 3.1 变量相关性基础理论

  • 相关系数基本概念;
  • 相关系数计算公式及实现方法;
  • 相关系数解读;
  • 利用相关性,构建具备一定规律数据集;

Lesson 3.2 数据生成器与Python模块编写

  • 手动生成规律可控的实验数据;
  • 创建回归类数据集生成器;
  • 随机数种子的基本使用方法;
  • Python模块编写方法;

Lesson 3.3 线性回归的手动实现与模型局限

  • 根据机器学习建模流程构建线性回归;
  • 线性回归模型局限与解决思路;

Lesson 3.4 机器学习模型结果可信度理论与交叉验证基础

  • 结果可信度基本理论;
  • 数据集划分方法;
  • 测试集悖论;
  • 交叉验证基本概念;

Lesson 3.1 变量相关性基础理论

变量彼此之间的相关性,是我们探究数据规律的重要手段。尽管相关性理论发源于经典统计理论体系,但对于机器学习,相关性也是数据探索、特征工程环节的重要理论。本节将先介绍关于连续变量相关性的基础理论,并且在该理论基础之上,探讨关于规律捕捉和规律创造的相关话题,为下一节创建数据生成器做准备。

相关系数基本解释与相关系数计算公式

线性回归模型,捕捉的实际上是数据集的线性相关的规律。所谓线性相关,简单来说就是数据的同步变化特性。例如此前数据集:

image-20240916133248271

体重越大的鲍鱼、年龄越大,并且体重每增加2、年龄也增加2。这种同步变化特性用更加专业的角度来描述就是变量之间的相关性。这种相关性可以用一个计算公式算得,也就是相关性系数计算公式: $$ Correlation = \frac{Cov(X, Y)}{\sqrt {Var(X) * Var(Y)}} $$ 其中,$X$和$Y$是两个随机变量(对应数据集也就代表两个字段),$Var(X)、Var(Y)$为$X、Y$的方差,$Cov(X,Y)$为$X$和$Y$这两个变量的协方差,具体计算公式为: $$ Cov(X, Y) = E(X-E(X))E(Y-E(Y)) =E(XY)-E(X)E(Y) $$ 其中$E(X)、E(Y)$为$X、Y$期望计算结果。

关于相关系数的计算有很多种方法,此处介绍的相关系数计算也被称为皮尔逊相关系数,最早由统计学家卡尔·皮尔逊提出,是目前最为通用的相关系数计算方法。

相关系数计算在NumPy中的实现

image-20240916134601075

该函数最终返回的是相关系数矩阵$A_{2*2}$,其中$a_{i,j}$表示第i、j两个变量之间的相关系数。很明显,相关系数矩阵是一个对角线元素全是1的矩阵,并且上三角和下三角元素对应位置元素相等。当然,对于A中的两个数组相关系数计算结果为0.933。

相关系数计算结果解读

相关系数的计算结果取值为[-1,1],取值为负时代表两个变量同步变化关系为负,也就是其中一个数值增加、另一个数值减少。例如:

image-20240916134714400image-20240916134816644

  

总体来说,相关系数绝对值越大两个变量的相关性越强,绝对值为1时候代表完全相关,两个变量完全线性同步变化,其中一个变量可以由另一个变量线性表出。而绝对值为0时,则表示完全线性无关,两个变量没有线性同步变化规律,这两个变量没有线性关系。当绝对值介于0和1之间时候,

image-20240916134915135

捕捉规律与创造规律

捕捉规律

创建模型的主要目的是捕捉数据集中的某种规律。举个例子:

  • 线性回归模型:其目标是捕捉自变量(特征)和因变量(目标变量)之间的线性相关关系。模型的形式通常是:$y = \beta_0 + \beta_1 x + \epsilon$ 其中,$\beta_0$ 和$\beta_1$是模型的参数,$\epsilon$是误差项。

线性回归模型的目标是通过调整参数 $\beta_0$ 和$\beta_1$ 来最小化预测值与实际观测值之间的误差,从而准确捕捉特征与目标变量之间的线性关系。

创造规律

按照以下步骤,创建和使用合成数据集来测试模型:

  1. 生成合成数据
    • 定义规律:选择一种已知的规律或模式(如线性关系、非线性关系等),并创建一个合成数据集。可以使用数学公式生成数据点,也可以添加噪声来模拟实际情况。
    • 设置参数:为合成数据设置特定的参数,比如线性回归中的斜率和截距,或非线性回归中的多项式系数。
  2. 训练模型
    • 选择模型:选择一个适合的模型(如线性回归、决策树、神经网络等),并用合成数据集进行训练。
    • 调整参数:根据模型的性能来调整超参数,优化模型的效果。
  3. 评估模型
    • 使用合成数据:将生成的数据集分为训练集和测试集,训练模型并在测试集上进行评估。
    • 检查效果:评估模型的性能,比如计算均方误差(MSE)、决定系数(R2R^2R2)等指标,以判断模型是否能够有效地捕捉生成数据中的规律。
  4. 验证模型的鲁棒性
    • 扰动数据:通过在数据集中添加不同程度的噪声或扰动,测试模型在面对不完美数据时的表现。
    • 观察变化:分析模型在不同扰动系数下的表现,查看模型是否仍然能够捕捉到数据中的规律。

下图就是创造的添加了不同的噪声情况下的用于线性回归的数据集,代码在代码.ipynb

Lesson 3.2 数据生成器与Python模块编写

在有了相关性理论基础之后,我们即可创建一个可用于回归模型实验的数据生成器。

我们自己创建一个数据生成器,用于自主生成一些符合某些条件、难度可控、具备某些特性的数据集。通过创建一些用于试验的数据,深入了解模型原理,

和Lesson 1中介绍的一样,课程中案例分为三类,分别是基础阶段的手动创建数据集、实战阶段的竞赛数据集和企业应用实战阶段的企业数据集。

手动生成数据

先手动生成一些数据,然后把他们封装成函数

去看代码.ipynb

代码.ipynb中通过两种方式对建模增加了难度

  • 创建了曲线规律的数据集(二元一次方程)
  • 将扰动项绝对数值delta从0.01增加到了2

此时需要注意的是,无论是创建了曲线规律的数据集,还是增加了扰动项绝对数值,都会对建模造成困难。

但二者的造成困难的方式是不同的。

但本节内,无论是曲线规律还是白噪声数值过大,都会对线性方程建模造成困难。

这也就是控制数据集建模难度的最基础的抓手。

补充:随机数种子的使用

  • np.random.seed()

创建数据集时,我们使用了随机数种子,以确保随机结果的可重复性。

当我们设置某个随机数种子之后,每次随机过程都是可重复的:我们只需要再次调用相同随机种子,就可以重复此前随机过程。

image-20240916165858900

Python模块的自定义与调用

  1. 将自定义的函数保存为py文件

  2. 添加sys path:

    • python
      import sys
      sys.path.append('~/Desktop') # 假设py文件的路径在桌面
  3. 直接导包即可

    • python
      import <py文件的名字>  # 不需要加 `.py`

Lesson 3.3 线性回归的手动实现与模型局限

在创建好了数据生成器之后,接下来即可进行手动线性回归建模实验。

线性回归的手动实现

接下来,我们尝试进行线性回归模型的手动建模实验。建模过程将遵照机器学习的一般建模流程,并且借助NumPy所提供的相关工具来进行实现。通过本次实验,我们将进一步深化对机器学习建模流程的理解,并且也将进一步熟悉对编程基础工具的掌握。

手动建模实验就是将训练所得的参数,和我们创建数据时的参数做对比,来判断模型效果

步骤:

  1. 数据准备
  2. 选择模型和参数
  3. 构造损失函数和选择评价指标
  4. 最小二乘法求损失函数的解(模型参数)

代码去看代码.ipynb

线性回归模型的局限

此外,除了受到非线性数据集和白噪声很大的数据集的影响之外,线性回归还会受到最小二乘法的条件限制,但这个问题不大,可以将优化算法换成梯度下降

为了验证上述内容,下面进行两组建模测试:

  • 对于非线性数据集,使用线性回归模型进行建模测试
  • 对于噪声很大的数据集,使用线性回归模型进行建模测试

限制一:对于非线性数据集

为了验证上述内容,我们创建一个满足$y=x^3+1$,并且白噪声很小的数据集进行建模测试

代码去看代码.ipynb

image-20240916205608071

限制二:对于噪声很大的数据集

代码去看代码.ipynb

image-20240916210234449

限制三:最小二乘法条件限制

$$ \hat w = (X^TX)^{-1}X^Ty $$

线性回归模型还面临这一个重大问题就是,如果特征矩阵的交叉乘积($X^TX$)不可逆,则最小二乘法求解过程就不成立了。

当 $X^TX$不可逆时,矩阵方程$\hat w = (X^TX)^{-1}X^Ty$的解可能是无穷多个(即无唯一解),或者无解。

解决该问题的方法有很多种,从数学角度出发,我们可以从以下三个方面入手:

  • 其一,对数据进行降维处理
      首先,可考虑进一步对数据集进行SVD分解或PCA主成分分析,在SVD或PCA执行的过程中会对数据集进行正交变换,最终所得数据集各列将不存在任何相关性。当然此举会对数据集的结构进行改变,且各列特征变得不可解释。

  • 其二,更换求解损失函数的优化算法:
      我们可以试图求解原方程的广义逆矩阵,对于某些矩阵方程来说,通过求解广义逆矩阵,也可以得到近似最优解;此外,我们还可以通过使用其他最优化求解方法,如梯度下降算法等来进行求解;

  • 其三,修改求解损失函数的优化算法:
      其实可以修改原损失函数,令其满足最小二乘法求解条件即可。如果$X^TX$不可逆,那么我们可以通过试图在损失函数中加入一个正则化项,从而令损失函数可解。

在sklearn中sklearn.linear.LinearRegression的默认优化算法是最小二乘法,不是梯度下降

搞数学看看为什么加入正则化项可以解决$X^TX$不可逆的问题

根据Lesson 2中的公式推导,目前根据SSE所构建的损失函数如下: $$ SSELoss(\hat w) = ||y - X\hat w||_2^2 = (y - X\hat w)^T(y - X\hat w) $$ 加入正则化项后,最小二乘法计算结果由无偏估计变为有偏估计(无偏,有偏估计下面备注了)。以加入L2范数举例,当我们在损失函数中加上$\lambda ||\hat w||_2^2$(其中$\lambda$为参数)时,模型损失函数为: $$ Loss(\hat w) = ||y - X\hat w||_2^2 +\lambda ||\hat w||_2^2 $$ 经过数学转化,上述矩阵表达式对$\hat w$求导后令其为零,则可解出: $$ (X^TX+\lambda I) \hat w = X^Ty $$ 其中**$I$为单位矩阵**。此时由于$(X^TX+\lambda I)$肯定是可逆矩阵,因此可以顺利求解出$\hat w$: $$ \hat w = (X^TX+\lambda I)^{-1}X^Ty $$

该过程也被称为岭回归。而类似的,如果是通过添加了$\hat w$的1-范数的某个表达式,从而构造损失函数如下: $$ Loss(\hat w) = ||y - X\hat w||_2^2 +\lambda ||\hat w||_1 $$ 则该过程被称为Lasso。而更进一步,如果构建的损失函数同时包含$\hat w$的1-范数和2-范数,形如如下形式: $$ Loss(\hat w) = \frac{1}{2n}||y - X\hat w||_2^2 + \lambda \alpha ||\hat w||_1 +\frac{\lambda(1-\alpha)}{2} ||\hat w||_2 ^ 2 $$ 则构建的是弹性网模型(Elastic-Net),其中$\lambda、\alpha$都是参数,n是样本个数。不难发现,岭回归和Lasso其实都是弹性网的一种特殊形式。更多关于线性模型的相关方法,我们将在后续逐渐介绍。

1-范数也被称为L1范数,将参数的1-范数添加入损失函数的做法,也被称为损失函数的L1正则化,L2正则化也类似。在大多数情况下,添加正则化项也可称为添加惩罚函数$p(w)$,核心作用是缓解模型过拟合倾向。

无偏估计:估计值的期望等于真实参数值。换句话说,如果我们使用相同的方法对许多不同的数据集进行估计,估计值的平均值应等于真实参数值。

有偏估计:估计值的期望与真实参数值之间存在偏差。

决定系数

对于线性回归模型来说,除了SSE以外,我们还可使用决定系数(R-square,也被称为拟合优度检验)作为其模型评估指标。决定系数的计算需要使用之前介绍的组间误差平方和和离差平方和的概念。在回归分析中,SSR表示聚类中类似的组间平方和概念,表意为Sum of squares of the regression,由预测数据与标签均值之间差值的平方和计算的出: $$ SSR =\sum^{n}{i=1}(\bar{y_i}-\hat{y_i})^2 $$ 而SST(Total sum of squares)则是实际值和均值之间的差值的平方和计算得到: $$ SST =\sum^{n}(\bar{y_i}-y_i)^2 $$ 并且,$SST$可由$SSR+SSE$计算得出。而决定系数,则由$SSR$和$SST$共同决定: $$ R-square=\frac{SSR}{SST}=\frac{SST-SSE}{SSE}=1-\frac{SSE}{SST} $$ 很明显,决定系数是一个鉴于[0,1]之间的值,并且约趋近于1,模型拟合效果越好。我们可以通过如下过程,进行决定系数的计算:

python
sst = np.power(labels - labels.mean(), 2).sum()
sse = SSELoss(features, w, labels)
r = 1-(sse/sst)

或使用sklearn的函数

python
from sklearn.metrics import r2_score

r2 = r2_score(y_true, y_pred)

Lesson 3.4 机器学习模型可信度理论与交叉验证基础

机器学习模型结果可信度基础理论

​ 模型评估指标是用于评估模型效果好坏的数值指标。但是否是评估指标好的模型就一定能用呢?其实并不一定。这里会涉及到一个关于、或者说了解模型真实性能的重要命题。

​ 但其实指标也只是我们了解模型性能的途径而不是模型性能本身。而要真实、深刻的评判模型性能,

​ 因此,在正式讲解模型优化方法之前,我们需要花些时间讨论机器学习算法的建模目标机器学习算法为了能够达到目标的一般思路,以及评估模型性能的手段,也就是模型评估指标。

  • 建模目标:机器学习和统计分析的建模目标都是探索数据规律,且机器学习和传统统计分析都依赖于从历史数据中学习。

  • 关键问题:如何证明从过去数据中提取的模型能够在未来未见过的数据上依然有效?

传统统计分析建模和机器学习建模的异同

目标相同,但在具体的实现方法上,传统的数理统计分析建模和机器学习采用了不同的解决方案

  • 传统统计分析建模
    • 样本与总体的一致性假设
      • 传统统计分析假设样本数据和总体数据之间存在一定的一致性,即样本是从一个更大、未知的总体中抽取的,样本的规律可以推测总体的规律。
      • 统计分析通常采用先验的方法,先通过样本数据计算一些统计量(如均值、方差等),然后推测总体的分布规律。这一过程依赖于假设检验和参数估计。
    • 检验可信性
      • 一旦估计了总体的统计特征,接下来会使用各种检验方法来验证这些估计是否可靠。这包括假设检验、置信区间等,以判断推测的均值和方差是否合理。
    • 预测模型的构建
      • 如果检验结果表明推测是可信的,那么可以基于这些统计特征构建预测模型,进行未来数据的预测。
    • 误差来源
      • 不同样本之间可能存在个体差异,这些差异会影响模型的准确性。此外,模型本身无法完全捕获数据中的所有规律(即存在未捕获的变量或噪声),这些都会导致误差的产生。
image-20240921171202987
  • 机器学习建模

    • 无样本-总体理论

      • 机器学习不依赖于传统的“样本-总体”理论,而是更关注从数据中自动学习规律。它采用了一种数据驱动的方式来构建模型。
      • 机器学习通过后验的方法来评估模型的有效性。具体来说,它先构建模型,然后通过测试集来验证模型的预测能力,而不是在建模过程中假设总体特征。

      数据划分

      • 为了处理数据中的差异,机器学习通常将可用数据划分为训练集(trainSet)和测试集(testSet)。在训练集上,模型学习数据中的规律;在测试集上,则评估模型的预测性能。

      模拟预测情况

      • 测试集的作用是模拟未来数据的未知标签,模型在测试集上的表现可以视为其在未知数据集上的预测能力。

      预测效果的评估

      • 如果模型在测试集上表现良好,可以“简单粗暴”地假设它在真实的未来数据上也会有类似的表现。这种假设虽然简单,但在实践中经常使用,并且能在一定程度上反映模型的泛化能力。
image-20240921173044125

数据集切分方法

在进行数据划分的过程中,如果测试集划分数据过多,参与模型训练的数据就会相应减少,而训练数据不足则会导致模型无法正常训练、损失函数无法收敛、模型过拟合等问题。

但如果反过来测试集划分数据过少,则无法代表一般数据情况测试模型是否对未知数据也有很好的预测作用。

因此一般来说,训练集和测试集可以按照8:2或7:3比例进行划分。

python
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=2024)

测试集的“不可知”悖论

在机器学习中,模型的性能主要通过其在测试集上的表现来评估。测试集是独立于训练过程的数据集,用于验证模型的泛化能力。

但在训练过程中,无法直接验证训练的有效性。如果在模型训练后使用测试集结果进行调整,就等于在模型构建中引入了测试集的数据,这会影响模型的独立性和评估的准确性。简单说,就是模型已经见过测试集数据了,严格意义上,评估出来的模型效果就可信度下降了。

验证集用于评估模型在训练后是否需要调整。它不参与模型的参数训练,但在模型完成训练后,可以用来检测模型的性能。通过观察模型在验证集上的表现,可以决定是否需要调整超参数,从而优化模型的整体性能。

在机器学习中,通常将数据划分为三类:训练集、验证集和测试集。训练集用于模型的学习和参数优化,验证集用于模型调整,而测试集则用于最终的性能评估。测试集严格不能用于训练,以确保评估的客观性。

不过由于测试集定位特殊,在一些不需要太严谨的场景下,有时也会混用验证集和测试集的概念。

在某些场景下,测试集确实是严格不可知的,比如在线提交结果的数据竞赛。

交叉验证基本思想

除了训练集-测试集划分理论之外,和模型结果可信度相关的,还有一个基本理论——交叉验证。

image-20240921181302019

尽管通过训练集和测试集的划分,我们可以利用不参与建模的测试集结果来证明模型输出的可信度,但在许多实际场景中,数据集的随机切分本身也是影响模型泛化能力以及测试集结果可信度的重要因素。例如,如果将数据按 7:3 的比例划分,而质量高、规律明显的数据恰好被分到训练集中的 70% 部分,这时模型的输出结果可能会不佳,但这并不意味着模型本身的性能较差,而可能是由于输入数据的偏差导致的。

此时,我们可以采用一种名为交叉验证的技术手段来进一步提升模型最终输出结果的可信度。

假设仍然是此前我们创建的数据集并且仍然采用SSE作为模型评估指标,则在进行十折验证时可以计算出十组SSE取值,最终我们可以对这十组结果进行均值计算,求得这组参数最终所对应的模型评估指标结果。不过此时我们需要在所有的数据集上进行训练,然后再进行交叉验证。

假设仍然是此前我们创建的数据集并且仍然采用SSE作为模型评估指标,则在进行十折验证时可以计算出十组SSE取值,最终我们可以对这十组结果进行均值计算,求得这组参数最终所对应的模型评估指标结果。不过此时我们需要在所有的数据集上进行训练,然后再进行交叉验证。

不得不说,对于线性回归的交叉验证过程其实和训练集测试集划分理论略显冲突,如果缺少了测试集的后验过程,再训练集上再怎么训练,得出的结果都没有反馈调整的机会。

其实从更加根本的角度来说,在机器学习理论体系中,一个更加严谨的做法,是先划分训练集和测试集,然后再在训练集上划分测试集,此处由于我们尚未接触超参数相关概念,因此目前暂时先只介绍其基本思想。