Lesson 3. 线性回归的手动实现(3.3 线性回归手动实现与模型局限 & 3.4 机器学习模型结果可信度理论与交叉验证基础)

本文涉及的产品
交互式建模 PAI-DSW,5000CU*H 3个月
模型训练 PAI-DLC,5000CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
简介: Lesson 3. 线性回归的手动实现(3.3 线性回归手动实现与模型局限 & 3.4 机器学习模型结果可信度理论与交叉验证基础)

文章目录

一、线性回归手动实现与模型局限

1. 线性回归的手动实现

2. 线性回归模型局限

3. 线性回归的决定系数

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

1. 机器学习模型结果可信度理论基础与数据集划分

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

1.2 数据集切分方法

1.3 线性回归手动实现

1.4 测试集的不可知悖论

2. 交叉验证基本思想


一、线性回归手动实现与模型局限

  • 在创建好了数据生成器之后,接下来即可进行手动线性回归建模实验。
# 科学计算模块
import numpy as np
import pandas as pd
# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt
# 自定义模块
from ML_basic_function import *


1. 线性回归的手动实现


  • 接下来,我们尝试进行线性回归模型的手动建模实验。建模过程将遵照机器学习的一般建模流程,并且借助 NumPy 所提供的相关工具来进行实现。
  • 根据机器学习建模流程构建线性回归模型,可分为以下几步。
  • (1) 数据准备
  • 我们利用数据生成器创建一个扰动项不太大的数据集:
# 设置随机数种子
np.random.seed(24)   
# 扰动项取值为0.01
features, labels = arrayGenReg(delta=0.01)
features
#array([[ 1.76405235,  0.40015721,  1.        ],
#       [ 0.97873798,  2.2408932 ,  1.        ],
#       [ 1.86755799, -0.97727788,  1.        ],
#       ...,
#       [ 0.19782817,  0.0977508 ,  1.        ],
#       [ 1.40152342,  0.15843385,  1.        ],
#       [-1.14190142, -1.31097037,  1.        ]])
labels

labels 得到如下数据。

037e74c86aa9453084ae1962ce1ee2ca.png


  • (2) 模型选取
  • 选取模型对上述回归类问题数据进行建模。此处我们选取带有截距项的多元线性回归方程进行建模,基本模型为:

36.png

np.random.seed(24)
w = np.random.randn(3).reshape(-1, 1)
w
#array([[ 1.32921217],
#       [-0.77003345],
#       [-0.31628036]])


  • 此时模型输出结果为:
y_hat = features.dot(w)
y_hat[:10]
#array([[ 2.04347616],
#       [ 0.02627308],
#       [-0.63176501],
#       [ 0.20623364],
#       [-2.64718921],
#       [-0.86880796],
#       [ 0.88171608],
#       [-1.61055557],
#       [ 0.80113619],
#       [-0.49279524]])


37.png

(labels - y_hat).T.dot(labels - y_hat)
#array([[2093.52940481]])
# 计算MSE
(labels - y_hat).T.dot(labels - y_hat) / len(labels)
#array([[2.0935294]])
labels[:10]
#array([[ 4.43811826],
#       [ 1.375912  ],
#       [ 0.30286597],
#       [ 1.81970897],
#       [-2.47783626],
#       [ 0.47374318],
#       [ 2.83085905],
#       [-0.83695165],
#       [ 2.84344069],
#       [ 0.8176895 ]])


  • 能够看出,在当前参数取值下,模型输出结果和真实结果相距甚远。
  • 不过,为了后续快速计算 SSE,我们可以将上述 SSE 计算过程封装为一个函数,令其在输入特征矩阵、标签数组和真实参数情况下即可输出 SSE 计算结果:
def SSELoss(X, w, y):
    """
    SSE计算函数
    :param X:输入数据的特征矩阵
    :param w:线性方程参数
    :param y:输入数据的标签数组
    :return SSE:返回对应数据集预测结果和真实结果的误差平方和 
    """
    y_hat = X.dot(w)
    SSE = (y - y_hat).T.dot(y - y_hat)
    return SSE


# 简单测试函数性能
SSELoss(features, w, labels)
#array([[2093.52940481]])


实验结束后,需要将上述 SSELoss 函数写入 ML_basic_function.py 中。

(4) 利用最小二乘法求解损失函数。

我们需要在 SSELoss 中找到一组最佳的参数取值,另模型预测结果和真实结果尽可能接近。此处我们利用最小二乘法来进行求解,最小二乘法求解模型参数公式为:


38.png

np.linalg.det(features.T.dot(features))
#967456500.1798325

行列式不为 0,因此 XtX逆矩阵存在,可以通过最小二乘法求解。具体求解方法分为两种,其一是使用 NumPy 中线性代数基本方法,根据上述公式进行求解,其二是直接使用 lstsq 函数进行求解。

  • 基础方法求解
w = np.linalg.inv(features.T.dot(features)).dot(features.T).dot(labels)
w
#array([[ 1.99961892],
#       [-0.99985281],
#       [ 0.99970541]])


  • 即可算出模型最优参数 w。所谓模型最优参数,指的是参数取得任何其他数值,模型评估结果都不如该组参数时计算结果更好。首先,我们也可以计算此时模型 SSE 指标:
SSELoss(features, w, labels)
array([[0.09300731]])



  • 明显小于此前所采用的随机 w 取值时 SSE 结果。此外,我们还可以计算模型 MSE
SSELoss(features, w, labels) / len(y)
array([[9.30073138e-05]])


模型评估指标中 SSE、MSE、RMSE 三者反应的是一个事实,我们根据 SSE 构建损失函数只是因为 SSE 计算函数能够非常方便的进行最小值推导,SSE 取得最小值时 MSE、RMSE 也取得最小值。

lstsq 函数求解

当然,我们也可以利用 lstsq 函数进行最小二乘法结果求解。二者结果一致。


np.linalg.lstsq(features, labels, rcond=-1)
#(array([[ 1.99961892],
#        [-0.99985281],
#        [ 0.99970541]]),
# array([0.09300731]),
# 3,
# array([32.70582436, 31.3166949 , 30.3678959 ]))


  • 最终 w 参数取值为:
np.linalg.lstsq(features, labels, rcond=-1)[0]
#array([[ 1.99961892],
#       [-0.99985281],
#       [ 0.99970541]])


2. 线性回归模型局限


尽管上述建模过程能够发现,面对白噪声不是很大、并且线性相关性非常明显的数据集,模型整体表现较好,但在实际应用中,大多数数据集可能都不具备明显的线性相关性,并且存在一定的白噪声(数据误差)。此时多元线性回归模型效果会受到极大影响。

plt.plot(features[:, 0], labels, 'o')

ea572ed20d5847068b93c82bf8647c87.png


  • 非线性相关规律
  • 例如,此处创建一个满足y=x3+1基本规律,并且白噪声很小的数据集进行建模测试。
# 设置随机数种子
np.random.seed(24)   
# 扰动项取值为0.01
features, labels = arrayGenReg(w=[2,1], deg=3, delta=0.01)
features
#array([[ 1.32921217,  1.        ],
#       [-0.77003345,  1.        ],
#       [-0.31628036,  1.        ],
#       ...,
#       [ 0.84682091,  1.        ],
#       [ 1.73889649,  1.        ],
#       [ 1.93991673,  1.        ]])
plt.plot(features[:, 0], labels, 'o')

7155c70d28214fb7bc1823c7aed3fba5.png


  • 进行最小二乘法模型参数求解。
np.linalg.lstsq(features, labels, rcond=-1)
#(array([[5.91925985],
#        [0.96963333]]),
# array([28466.58711077]),
# 2,
# array([32.13187164, 31.53261742]))
w = np.linalg.lstsq(features, labels, rcond=-1)[0]
w
#array([[5.91925985],
#       [0.96963333]])
SSELoss(features, w, labels)
#array([[28466.58711077]])
y_hat = features.dot(w)
y_hat
plt.plot(features[:, 0], labels, 'o')
plt.plot(features[:, 0], y_hat, 'r-')


e7395e5967564029a705742e26b48e5e.png

  • 从模型结果能够看出,模型和数据集分布规律相差较大。
  • 噪声增加
  • 我们稍微增加模型白噪声,测试线性回归模型效果。
# 设置随机数种子
np.random.seed(24)   
# 扰动项取值为2
features, labels = arrayGenReg(w=[2,1], delta=2)
features
#array([[ 1.32921217,  1.        ],
#       [-0.77003345,  1.        ],
#       [-0.31628036,  1.        ],
#       ...,
#       [ 0.84682091,  1.        ],
#       [ 1.73889649,  1.        ],
#       [ 1.93991673,  1.        ]])
plt.plot(features[:, 0], labels, 'o')

1a09b67006464a83a484ddeca610ad37.png

np.linalg.lstsq(features, labels, rcond=-1)
#(array([[1.91605821],
#        [0.90602215]]),
# array([3767.12804359]),
# 2,
# array([32.13187164, 31.53261742]))
w = np.linalg.lstsq(features, labels, rcond=-1)[0]
w
#array([[1.91605821],
#       [0.90602215]])
SSELoss(features, w, labels)
#array([[3767.12804359]])
X = np.linspace(-5, 5, 1000)
y = w[0] * X + w[1]
plt.plot(features[:, 0], labels, 'o')
plt.plot(X, y, 'r-')

ea2385a5f02d4abfb9df3215c62121f8.png


  • 能够发现,模型误差较大。
  • 最小二乘法条件限制
  • 除此之外,线性回归模型还面临这一个重大问题就是,如果特征矩阵的交叉乘积不可逆,则最小二乘法求解过程就不成立了。


40.png

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

(1) 对数据进行降维处理

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

(2) 修改求解损失函数的方法

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

(3) 修改损失函数


修改原损失函数,令其满足最小二乘法求解条件即可。如果 X T X XTXXTX 不可逆,那么我们可以通过试图在损失函数中加入一个正则化项,从而令损失函数可解。根据SSE所构建的损失函数如下


41.png


42.png


3. 线性回归的决定系数


对于线性回归模型来说,除了 SSE 以外,我们还可使用决定系数(R-square,也被称为拟合优度检验)作为其模型评估指标。

决定系数的计算需要使用之前介绍的组间误差平方和和离差平方和的概念。在回归分析中,SSR 表示聚类中类似的组间平方和概念,由预测数据与标签均值之间差值的平方和计算的出:

43.png


  • 很明显,决定系数是一个鉴于 [0,1] 之间的值,并且越趋近于 1,模型拟合效果越好。我们可以通过如下过程,进行决定系数的计算:
sst = np.power(labels - labels.mean(), 2).sum()
sse = SSELoss(features, w, labels)
r = 1-(sse/sst)
r
#array([[0.99998114]])



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

# 科学计算模块
import numpy as np
import pandas as pd
# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt
# 自定义模块
from ML_basic_function import *


1. 机器学习模型结果可信度理论基础与数据集划分

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


模型评估指标是用于评估模型效果好坏的数值指标,例如 SSE 就是评估回归类模型拟合效果的指标。但是否是评估指标好的模型就一定能用呢?其实并不一定。这里会涉及到一个关于评估指标可信度、或者说了解模型真实性能的重要命题。


其实,要了解模型的性能其实并不简单,固然我们会使用某些指标去进行模型评估,但其实指标也只是我们了解模型性能的途径而不是模型性能本身。


而要真实、深刻的评判模型性能,就必须首先了解机器学习的建模目标,并在此基础之上熟悉我们判断模型是否能够完成目标的一些方法,当然,只有真实了解的模型性能,我们才能进一步考虑如何提升模型性能。


无论是机器学习还是传统的统计分析模型,核心使命就是探索数字规律,而有监督学习则是希望在探索数字规律的基础上进一步对未来进行预测。


当然,在数字的世界,这个预测未来,也就是预测未来某项事件的某项数值指标,如某地区未来患病人次、具备某种数字特征的图片上的动物是哪一类,此处的未来也并非指绝对意义上的以后的时间,而是在模型训练阶段暂时未接触到的数据。


正是因为模型有了在未知标签情况下进行预判的能力,有监督学习才有了存在的价值,

但我们知道,基本上所有的模型,都只能从以往的历史经验当中进行学习,也就是在以往的、已经知道的数据集上进行训练(如上述利用已知数据集进行模型训练,如利用过往股票数据训练时间序列模型)。


这里的核心矛盾在于,在以往的数据中提取出来的经验(也就是模型),怎么证明能够在接下来的数据中也具备一定的预测能力呢?或者说,要怎么训练模型,才能让模型在未知的数据集上也拥有良好的表现呢?


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


在统计分析领域,我们会假设现在的数据和未来的数据其实都属于某个存在但不可获得的总体,也就是说,现在和未来的数据都是从某个总体中抽样而来的,都是这个总体的样本。而正式因为这些数据属于同一个总体,因此具备某些相同的规律,而现在挖掘到的数据规律也就在某些程度上可以应用到未来的数据当中去,不过呢,不同抽样的样本之间也会有个体之间的区别,另外模型本身也无法完全捕获规律,而这些就是误差的来源。


虽然样本和总体的概念是统计学概念,但样本和总体的概念所假设的前后数据的局部规律一致性,却是所有机器学习建模的基础。如果获取到的数据前后描绘的不是一件事情,那么模型训练也就毫无价值(比如拿着 A 股走势预测的时间序列预测某地区下个季度患病人次)。


因此,无论是机器学习所强调的从业务角度出发,要确保前后数据描述的一致性,还是统计分析所强调的样本和总体的概念,都是建模的基础。


在有了假设基础之后,统计分析就会利用一系列的数学方法和数理统计工具去推导总体的基本规律,也就是变量的分布规律和一些统计量的取值,由于这个过程是通过已知的样本去推断未知的总体,因此会有大量的估计和检验,在确定了总体的基本分布规律之后,才能够进一步使用统计分析模型构建模型(这也就是为什么在数理统计分析领域,构建线性回归模型需要先进行一系列的检验和变换的原因)。


当然,这些模型都是在总体规律基础之上、根据样本具体的数值进行的建模,我们自然有理由相信这些模型对接下来仍然是从总体中抽样而来的样本还是会具备一定的预测能力,这也就是我们对统计分析模型信心的来源。


简单来说,就是我们通过样本推断总体的规律,然后结合总体的规律和样本的数值构建模型,由于模型也描绘了总体规律,所以模型对接下来从总体当中抽样而来的数据也会有不错的预测效果,这个过程我们可以通过下图来进行表示。

b5f8c387bb7b407f8afb5a014e59e9af.png

对于机器学习来说,并没有借助样本 - 总体的基本理论,而是简单的采用了一种后验的方法来判别模型有效性。

我们假设前后获取的数据拥有规律一致性,但数据彼此之间又略有不同,为了能够在捕捉规律的同时又能考虑到略有不同所带来的误差。

机器学习会把当前能获取到的数据划分成训练集(trainSet)和测试集(testSet),在训练集上构建模型,然后带入测试集的数据,观测在测试集上模型预测结果和真实结果之间的差异。

这个过程其实就是在模拟获取到真实数据之后模型预测的情况,模型能够在未知标签的数据集上进行预测,就是模型的核心价值,此时的测试集就是用于模拟未来的未知标签的数据集。

如果模型能够在测试集上有不错的预测效果,我们就简单粗暴的认为模型可以在真实的未来获取的未知数据集上有不错的表现。其一般过程可以由下图表示。


baf07655438842b181d6b4439fbd14d7.png

因此,我们称模型在训练集上误差称为训练误差,在测试集上的误差称为泛化误差,不过毕竟在测试集上进行测试还只是模拟演习,我们采用模型的泛化能力来描述模型在未知数据上的判别能力。

当然泛化能力无法准确衡量(未知的数据还未到来,到来的数据都变成了已知数据),我们只能通过模型在训练集和测试集上的表现,判别模型泛化能力,当然,最基本的,我们会通过模型在测试集上的表现来判断模型的泛化能力。


1.2 数据集切分方法


接下来,我们就尝试通过数据集切分来执行更加可信的机器学习建模流程。首先是对数据集进行切分。一般来说,为了避免数据集上下顺序对数据规律的影响,我们会考虑对数据集进行随机切分,其中 70%-80% 作为训练集、20%-30% 作为测试集。此处我们先考虑构建一个数据切分函数,用于训练集和测试集的切分:


np.random.shuffle 函数

在 NumPy 中,我们可以非常便捷的通过调用 np.random.shuffle 函数来进行二维数组按行重排的相关操作,而二维数组也就是结构化数据的一般表示形式,因此我们可以使用该函数进行数据集乱序排列。

并且我们可以通过设置随机数种子,来复现这个乱序的过程,这将极大程度有助于当需要对多个序列进行乱序排列时的代码简化。

A = np.arange(10).reshape(5, 2)
A
#array([[0, 1],
#       [2, 3],
#       [4, 5],
#       [6, 7],
#       [8, 9]])
B = np.arange(0, 10, 2).reshape(-1, 1) #(-1, 1)表示为设定行数,1列
B
#array([[0],
#       [2],
#       [4],
#       [6],
#       [8]])
np.random.seed(24)
np.random.shuffle(A) #shuffle表示打乱
A
#array([[8, 9],
#       [2, 3],
#       [0, 1],
#       [6, 7],
#       [4, 5]])
B
#array([[0],
#       [2],
#       [4],
#       [6],
#       [8]])
np.random.seed(24)
np.random.shuffle(B)
B
#array([[8],
#       [2],
#       [0],
#       [6],
#       [4]])
  • np.vsplit 切分函数
  • 此外,我们可以通过 vsplit 函数进行数组的按行切分,也就相当于 split(axis=0)。
A
#array([[8, 9],
#       [2, 3],
#       [0, 1],
#       [6, 7],
#       [4, 5]])
# 从行索引的第二、三元素之间切开
np.vsplit(A,[2, ])
#[array([[8, 9],
#        [2, 3]]),
# array([[0, 1],
#        [6, 7],
#        [4, 5]])]


  • 数据集切分函数
  • 基于上述函数,我们可以非常简单的构建一个数据集切分函数:
def array_split(features, labels, rate=0.7, random_state=24):
    """
    训练集和测试集切分函数
    :param features: 输入的特征张量
    :param labels:输入的标签张量
    :param rate:训练集占所有数据的比例
    :random_state:随机数种子值
    :return Xtrain, Xtest, ytrain, ytest:返回特征张量的训练集、测试集,以及标签张量的训练集、测试集 
    """
    np.random.seed(random_state)                           
    np.random.shuffle(features)                             # 对特征进行切分
    np.random.seed(random_state)
    np.random.shuffle(labels)                               # 按照相同方式对标签进行切分
    num_input = len(labels)                                 # 总数据量
    split_indices = int(num_input * rate)                   # 数据集划分的标记指标
    Xtrain, Xtest = np.vsplit(features, [split_indices, ])  
    ytrain, ytest = np.vsplit(labels, [split_indices, ])
    return Xtrain, Xtest, ytrain, ytest


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

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

如果测试集划分数据过少,则无法代表一般数据情况测试模型是否对未知数据也有很好的预测作用。因此,根据经验,我们一般来说会按照 8:2 或 7:3 比例进行划分。

测试函数性能

f = np.arange(10).reshape(-1, 1)                 # 创建特征0-9
f
#array([[0],
#       [1],
#       [2],
#       [3],
#       [4],
#       [5],
#       [6],
#       [7],
#       [8],
#       [9]])
l = np.arange(1, 11).reshape(-1, 1)             # 创建标签1-10,保持和特征+1的关系
l
#array([[ 1],
#       [ 2],
#       [ 3],
#       [ 4],
#       [ 5],
#       [ 6],
#       [ 7],
#       [ 8],
#       [ 9],
#       [10]])
array_split(f, l)
#(array([[9],
#        [4],
#        [8],
#        [7],
#        [5],
#        [6],
#        [1]]),
# array([[0],
#        [3],
#        [2]]),
# array([[10],
#        [ 5],
#        [ 9],
#        [ 8],
#        [ 6],
#        [ 7],
#        [ 2]]),
# array([[1],
#        [4],
#        [3]]))

1.3 线性回归手动实现


  • 根据机器学习结果可信度理论,我们构建一个在训练集上训练、在测试集上测试的完整的线性回归实现流程。
  • 数据准备
# 设置随机数种子
np.random.seed(24)   
# 扰动项取值为0.01
features, labels = arrayGenReg(delta=0.01)
# 数据切分
Xtrain, Xtest, ytrain, ytest = array_split(features, labels)


在训练集上训练

最小二乘法求解公式:




44.png

w = np.linalg.inv(Xtrain.T.dot(Xtrain)).dot(Xtrain.T).dot(ytrain)
w
#array([[ 1.99976073],
#       [-0.99986178],
#       [ 0.99934303]])
  • 在大多数情况下,所谓训练模型,都是训练得出模型的一组参数。
  • 在测试集上测试
  • 然后即可在测试集上计算模型评估指标:
SSELoss(Xtest, w, ytest)
array([[0.02725208]])


至此,我们即完成了模型在训练集上训练得出参数,然后运行测试集观察结果的全过程。由于数据情况较为简单,因此模型效果较好。

但如果测试集效果不好,我们能否因此对模型进行调整的呢?如果测试集真的完全不参与建模,那么根据测试集反馈结果调整模型是否算测试集间接参与建模?如果测试集不能间接参与建模,那测试集的提供的模型结果反馈又有什么作用呢?这就是所谓的,测试集悖论。


1.4 测试集的不可知悖论


我们已经知道,机器学习模型主要通过模型在测试集上的运行效果来判断模型好坏,测试集相当于是高考,而此前的模型训练都相当于是在练习,但怎么样的练习才能有效的提高高考成绩?

这里就存在一个悖论,那就是练习是为了高考,而在高考前我们永远不知道练习是否有效,那高考对于练习的核心指导意义何在?

在机器学习领域,严格意义上的测试集是不能参与建模的,此处不能参与建模,不仅是指在训练模型时不能带入测试集进行训练,更是指当模型训练完成之后、观察模型在测试集上的运行结果后,也不能据此再进行模型修改(比如增加神经网络层数)。

把数据带入模型训练是影响模型参数,而根据模型运行结果再进行模型结构调整,实际上是修改了模型超参数,不管是修改参数还是超参数,都是影响了模型建模过程,都相当于是带入进行了建模。

如果通过观察测试集结果再调整模型结构,也相当于是带入测试集数据进行训练,而严格意义上的测试集,是不能带入模型训练的。

但是,学习建模的核心目标就是提升模型的泛化能力。而泛化能力指的是在模型未知数据集(没带入进行训练的数据集)上的表现,虽然测试集只能测一次,但我们还是希望有机会能把模型带入未知数据集进行测试,此时我们就需要一类新的数据集——验证集。

验证集在模型训练阶段不会带入模型进行训练,但当模型训练结束之后,我们会把模型带入验证集进行计算,通过观测验证集上模型运行结果,判断模型是否要进行调整,验证集也会模型训练,只不过验证集训练的不是模型参数,而是模型超参数。

因此,我们也可以把验证集看成是应对高考的模拟考试,通过“模拟考试”的考试结果来调整复习策略,从而更好的应对高考。

总的来说,测试集是严格不能带入训练的数据集,在实际建模过程中我们可以先把测试集切分出来,然后假装这个数据集不存在,在剩余的数据集中划分训练集和验证集,把训练集带入模型进行运算,再把验证集放在训练好的模型中进行运行,观测运行结果,再进行模型调整。

因此,在模型训练和观测模型运行结果的过程总共涉及三类数据集,分别是训练集、验证集和测试集。不过由于测试集定位特殊,在一些不需要太严谨的场景下,有时也会混用验证集和测试集的概念。

在不区分验证集和测试集的情况下,当数据集切分完成后,对于一个模型来说,我们能够获得两套模型运行结果,一个是训练集上模型效果,一个是测试集上模型效果,而这组结果,就将是整个模型优化的基础数据。


2. 交叉验证基本思想


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


尽管通过训练集和测试集的划分,我们可以以不参与建模的测试集的结论来证明模型结果的可信度,但在很多实际场景中,数据集的随机切分本身也是影响模型泛化能力、影响测试集结果可信度的重要因素。


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


交叉验证的基本思想非常简单,在我们不严格区分测试集的情况下,我们可以将数据集整体按照某个比例切分,然后进行循环验证。


在所有的切分方法中,最基础也最常用的一种就是所谓的 K-fold(K折)验证,也就是将数据集进行 K 份等比例划分,然后依次取出其中一份进行验证(测试)、剩下几份进行训练。


例如,当我们使用 10 折验证时,数据集划分情况如下所示:


faa0d2b8916c4d38ad20ff61bfd947a9.png

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

  • 不过此时我们需要在所有的数据集上进行训练,然后再进行交叉验证。





































相关文章
|
1天前
|
机器学习/深度学习 Python
验证集的划分方法:确保机器学习模型泛化能力的关键
本文详细介绍了机器学习中验证集的作用及其划分方法。验证集主要用于评估模型性能和调整超参数,不同于仅用于最终评估的测试集。文中描述了几种常见的划分方法,包括简单划分、交叉验证、时间序列数据划分及分层抽样划分,并提供了Python示例代码。此外,还强调了在划分数据集时应注意随机性、数据分布和多次实验的重要性。合理划分验证集有助于更准确地评估模型性能并进行有效调优。
|
2天前
|
机器学习/深度学习 人工智能 自然语言处理
机器学习模型之深度神经网络的特点
深度神经网络(Deep Neural Networks, DNNs)是一类机器学习模型,通过多个层级(层)的神经元来模拟人脑的工作方式,从而实现复杂的数据处理和模式识别任务。
8 1
|
7天前
|
机器学习/深度学习 人工智能 自然语言处理
探索机器学习:从线性回归到深度学习
【9月更文挑战第4天】在这篇文章中,我们将深入探讨机器学习的世界,从基础的线性回归模型开始,逐步深入到复杂的深度学习网络。我们将通过实际的代码示例,揭示这些模型背后的数学原理,以及如何在现实世界的问题中应用它们。无论你是初学者还是有经验的数据科学家,这篇文章都将为你提供新的视角和深入的理解。
|
10天前
|
机器学习/深度学习 算法 前端开发
R语言基础机器学习模型:深入探索决策树与随机森林
【9月更文挑战第2天】决策树和随机森林作为R语言中基础且强大的机器学习模型,各有其独特的优势和适用范围。了解并熟练掌握这两种模型,对于数据科学家和机器学习爱好者来说,无疑是一个重要的里程碑。希望本文能够帮助您更好地理解这两种模型,并在实际项目中灵活应用。
|
9天前
|
机器学习/深度学习 数据采集 存储
一文读懂蒙特卡洛算法:从概率模拟到机器学习模型优化的全方位解析
蒙特卡洛方法起源于1945年科学家斯坦尼斯劳·乌拉姆对纸牌游戏中概率问题的思考,与约翰·冯·诺依曼共同奠定了该方法的理论基础。该方法通过模拟大量随机场景来近似复杂问题的解,因命名灵感源自蒙特卡洛赌场。如今,蒙特卡洛方法广泛应用于机器学习领域,尤其在超参数调优、贝叶斯滤波等方面表现出色。通过随机采样超参数空间,蒙特卡洛方法能够高效地找到优质组合,适用于处理高维度、非线性问题。本文通过实例展示了蒙特卡洛方法在估算圆周率π和优化机器学习模型中的应用,并对比了其与网格搜索方法的性能。
81 1
|
11天前
|
机器学习/深度学习 存储 前端开发
实战揭秘:如何借助TensorFlow.js的强大力量,轻松将高效能的机器学习模型无缝集成到Web浏览器中,从而打造智能化的前端应用并优化用户体验
【8月更文挑战第31天】将机器学习模型集成到Web应用中,可让用户在浏览器内体验智能化功能。TensorFlow.js作为在客户端浏览器中运行的库,提供了强大支持。本文通过问答形式详细介绍如何使用TensorFlow.js将机器学习模型带入Web浏览器,并通过具体示例代码展示最佳实践。首先,需在HTML文件中引入TensorFlow.js库;接着,可通过加载预训练模型如MobileNet实现图像分类;然后,编写代码处理图像识别并显示结果;此外,还介绍了如何训练自定义模型及优化模型性能的方法,包括模型量化、剪枝和压缩等。
22 1
|
11天前
|
API UED 开发者
如何在Uno Platform中轻松实现流畅动画效果——从基础到优化,全方位打造用户友好的动态交互体验!
【8月更文挑战第31天】在开发跨平台应用时,确保用户界面流畅且具吸引力至关重要。Uno Platform 作为多端统一的开发框架,不仅支持跨系统应用开发,还能通过优化实现流畅动画,增强用户体验。本文探讨了Uno Platform中实现流畅动画的多个方面,包括动画基础、性能优化、实践技巧及问题排查,帮助开发者掌握具体优化策略,提升应用质量与用户满意度。通过合理利用故事板、减少布局复杂性、使用硬件加速等技术,结合异步方法与预设缓存技巧,开发者能够创建美观且流畅的动画效果。
34 0
|
11天前
|
开发者 算法 虚拟化
惊爆!Uno Platform 调试与性能分析终极攻略,从工具运用到代码优化,带你攻克开发难题成就完美应用
【8月更文挑战第31天】在 Uno Platform 中,调试可通过 Visual Studio 设置断点和逐步执行代码实现,同时浏览器开发者工具有助于 Web 版本调试。性能分析则利用 Visual Studio 的性能分析器检查 CPU 和内存使用情况,还可通过记录时间戳进行简单分析。优化性能涉及代码逻辑优化、资源管理和用户界面简化,综合利用平台提供的工具和技术,确保应用高效稳定运行。
25 0
|
11天前
|
前端开发 开发者 设计模式
揭秘Uno Platform状态管理之道:INotifyPropertyChanged、依赖注入、MVVM大对决,帮你找到最佳策略!
【8月更文挑战第31天】本文对比分析了 Uno Platform 中的关键状态管理策略,包括内置的 INotifyPropertyChanged、依赖注入及 MVVM 框架。INotifyPropertyChanged 方案简单易用,适合小型项目;依赖注入则更灵活,支持状态共享与持久化,适用于复杂场景;MVVM 框架通过分离视图、视图模型和模型,使状态管理更清晰,适合大型项目。开发者可根据项目需求和技术栈选择合适的状态管理方案,以实现高效管理。
23 0
|
11天前
|
机器学习/深度学习 人工智能 自动驾驶
探索AI的魔法:用Python构建你的第一个机器学习模型
【8月更文挑战第31天】在这个数字时代,人工智能(AI)已经渗透到我们生活的方方面面。从智能助手到自动驾驶汽车,AI正在改变世界。本文将带你走进AI的世界,通过Python编程语言,一步步教你如何构建第一个机器学习模型。无论你是编程新手还是有经验的开发者,这篇文章都将为你打开新世界的大门,让你体验到创造智能程序的乐趣和成就感。所以,让我们一起开始这段激动人心的旅程吧!

相关产品

  • 人工智能平台 PAI