【初中生讲机器学习】7. 交叉验证是什么?有哪些?怎么实现?来看!

创建时间:2024-02-10
最后编辑时间:2024-02-10
作者:Geeker_LStar

你好呀~这里是 Geeker_LStar 的人工智能学习专栏,很高兴遇见你~
我是 Geeker_LStar,一名初三学生,热爱计算机和数学,我们一起加油~!
⭐(●’◡’●) ⭐ 那就让我们开始吧!

文章目录

  • 一、训练集、验证集和测试集
    • 训练集 Training Set
    • 验证集 Validation Set
    • 测试集 Test Set
    • 三者关系 & 使用方法
  • 二、什么是交叉验证
  • 三、为什么需要交叉验证
  • 四、如何实现交叉验证
    • 1. Hold-out 交叉验证
      • 方式
      • 优点
      • 缺点
      • 代码实现
    • ⭐2. K 折(K-fold)交叉验证
      • 方式
      • 优点
      • 缺点
      • 代码实现
    • 3. 留一交叉验证
      • 方式
      • 优点
      • 缺点
      • 代码实现
    • 4. 蒙特卡罗交叉验证
      • 方式
      • 代码实现
    • 5. 时间序列交叉验证
      • 方式
      • 代码实现

一、训练集、验证集和测试集

emm,看了好几篇文章,貌似这三个概念很容易混淆(尤其是验证集和测试集),所以先在这里讲明白。
一句话:训练集用于训练模型,验证集用于调整模型超参数并选择合适模型,而测试集用于评估模型性能。验证集 ≠ 测试集!

训练集 Training Set

很明显,训练集就是用于训练模型的数据。
拿中考举例,参加中考之前我们要做无数的作业练习,我们就是模型,作业题就是训练集。
一般来讲,训练集在总数据集中占的比例应该在 70% 左右。过多会造成过拟合,过少会造成欠拟合,都不利于模型的泛化。

验证集 Validation Set

验证集是个易被忽视 or 错用的概念。
还是中考的例子,在正式中考之前,我们还要参加零模一模二模三模…这些考试就是在 “验证” 用测试集训练的成果,但是又不是真正的 “测试”。
和模拟考试一样,验证集的目的是在正式用测试集评估模型之前,大致了解模型的性能并调整模型的一些参数(超参数,后面会讲),最终获得(一定范围内)性能最优的模型,进行测试。

测试集 Test Set

中考就是测试集嘛,就是在用训练集训练 & 验证集调参后,对模型性能的最终评估。测试集并不用于调整任何参数或进行任何优化。

想起了一句特别形象的至理名言:除了中高考以外的所有考试都是检测性考试(验证集),寄了没大事,后面还能调整,而中高考是选拔性考试(测试集),寄了就真寄了((

三者关系 & 使用方法

一句话:训练集 -> 模型训练 -> 验证集 -> 超参数调整 -> 最终模型 -> 合并再训练 -> 测试集 -> 最终性能评估。

一般来讲,拿到一个数据集,要先把测试集分出来(大概 10%-20% 左右吧,看数据量有多少了),这部分数据不参与训练 & 验证的过程,从而保证测试数据全部都是未知数据,不会出现模型对某个测试数据特别熟悉的情况,更能看出模型的 “真实水平”(就像中考题永远找不到某某练习册或模拟的原题一样)。

划分完测试集,把剩下数据的 20% 左右(一样,看数据量)再分出来,作为验证集。训练之后先用验证集验证,如果效果不好,可以考虑调整模型的各种超参数。
这个 “调整超参数” 是怎么个事呢?就比如,对于支持向量机,我可以选择不同的核函数(也就是超参数),linear、poly、rbf 之类的,but 我事先并不知道哪种核函数效果最好,于是我可以先选一种,比如 linear,训练一下,再用验证集验证一下效果,发现效果不太好,于是我换一个核函数比如 poly 试试,诶发现效果还是不理想,那我再换用 rbf,发现这次效果好了,就说明最适合这个实例的核函数是径向基函数 rbf。
ok,然后超参数调整好了,找到最合适的模型了,再把训练集和验证集都合并为训练集,进行一次训练,最后用测试集进行测试,评价模型的性能。

概括为下图。

集合们

二、什么是交叉验证

一句话:交叉验证是一种评估并有利于提高机器学习模型性能的技术。
交叉验证通常把数据集分为多个子集,一部分用于训练模型(训练集),一部分用于验证 & 调参(验证集,在部分交叉验证方式中可能没有),另一部分用于(测试集)。训练+验证这个过程会重复多次,每次用于训练和验证的数据都不一样,从而得到多个独立的模型性能评估结果。通过这种方式可以优化模型参数,减少过拟合或欠拟合的发生,最终提高模型的泛化能力

三、为什么需要交叉验证

一句话:交叉验证是为了寻找最适合的超参数,检测并提高模型的泛化能力。

简单来讲,我们现在有很多的训练数据,在不断训练的过程中,模型为了在这些训练数据上获得好的表现,会逐步调整参数来靠近这些训练数据,但这就会导致过拟合的出现,如下图中 “过拟合”。
通过图也能看出来,过拟合并不是什么好事。因为即使模型在训练数据上达到了 100% 的正确,它在新数据上的表现也不会很好,也就是它的泛化能力不强

过拟合和欠拟合
同上 2

but,模型总归还是要用在未知数据上的,所以我们要防止过拟合的情况出现。也就是说,当我们用一批数据训练出了一个模型,必然要用另一批数据来检验一下这个模型的泛化能力,并且最好多次换用不同的数据进行训练 & 验证,最大限度地减少过拟合/欠拟合发生的可能

同时,很多模型是有超参数的,手动 “试” 这些超参数会非常麻烦,我们可以通过交叉验证的方式,看超参数的不同取值下的模型性能,进而确定超参数要取哪个值
这就是要进行交叉验证的原因,细节后面会详细讲。

四、如何实现交叉验证

1. Hold-out 交叉验证

方式

Hold-out 交叉验证是最简单的一种方式,它只是把原始数据集随机分成两部分,一般是训练集 70%(+),测试集 30%(-),在训练集上训练过后用测试集进行测试。
严格来讲,Hold-out 验证都不能被称为 “交叉验证”,因为它其实不涉及到数据的 “交叉使用”,它只进行一次训练和一次测试
下图第二行说明了 Hold-out 训练的形式。

holdout

优点

  • 训练成本低、速度快
    由于 Hold-out 验证只需要进行一次训练+测试,所以它用起来很简单、速度很快,适用于数据量很大的情况。

缺点

  • 不太适合用于正负样本不平衡的数据集中。
    原因:举一个极端的例子,一个数据集中有 80% 正样本,20% 负样本,如果在随机划分的时候训练集里全是正样本,测试集里全是负样本,这事就很难办了。
    这种问题可以通过多次随机划分数据集来解决,但 hold-out 划分只随机划分一次,偶然性高,有可能遇到这种情况。
  • 不太适合用于样本量小的数据集中。
    原因:样本量不大的时候,每一个样本都很重要。选取 30% 的数据作为测试集(即这部分数据没有被训练到)可能会让模型错过一些重要的特征,出现欠拟合

代码实现

以鸢尾花数据集和逻辑回归算法为例,实现 hold-out 验证。

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
iris = load_iris()
X = iris.data
Y = iris.target
print("Size of Dataset {}".format(len(X)))
logreg = LogisticRegression()
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=0.3, random_state=218)
logreg.fit(x_train, y_train)
predict = logreg.predict(x_test)
# 训练集准确率
print("Accuracy score on training set is {}".format(accuracy_score(logreg.predict(x_train),y_train)))
# 测试集准确率
print("Accuracy score on test set is {}".format(accuracy_score(predict,y_test)))

⭐2. K 折(K-fold)交叉验证

一句话:K 折交叉验证主要用于模型超参数的调整,即模型调优。

方式

K-fold 交叉验证首先分出测试集,再把剩下的数据随机平均分为 k 组,每一组都是一个 “折叠”(所以叫 K 折嘛)。
在进行训练 & 验证时,k 组中的每一组都会当一次验证集,剩下的 (k-1) 组当训练集,一共会进行 k 次训练 & 验证。k 轮过后再用测试集进行最终评估。
不过有一个要注意的小细节:第 n 折的训练不是在第 n-1 折训练的基础上进行的,相当于每一次训练前都会初始化模型参数

下图说明了 K-fold 交叉验证的方式。

K折交叉验证

在实际训练中,一般会分为 10 个折叠,也被称为 10 折交叉验证。

除了防止过拟合,K 折法另一大作用是选择最适合的超参数值(核函数的例子),提高模型性能,过程如下:
选取参数的第一个值 A,进行 k 次训练 & 验证,将 k 次验证的准确率(或其它指标)的平均值作为 A 参数下的模型性能。再取参数的第二个值 B,重复上述过程,得到 B 参数下的模型性能。以此类推,得到同一参数的不同取值(比如核函数中的 linear、poly、rbf)下的模型性能。哪个取值下模型表现好,就用哪个值作为该参数的最终值

优点

  • K 折交叉验证是最常用的交叉验证方式。它可以用于选择最合适的超参数
  • k 次中每次都用不同的数据进行训练 & 测试,可以避免过拟合或欠拟合,提高模型的泛化能力
  • 对于小规模数据,K 折交叉验证相当于反复给它提供不同的验证数据,从一定程度上缓解了样本量不够的问题。

缺点

  • 不太适合用于时间序列数据中。
    对于时间序列数据,样本顺序很重要,但 K 折交叉验证的样本是随机划分的。
  • 训练成本较高,时间较长
    很好理解,如果要选择某一个参数的最优值,要进行(取值数 * k)次训练。

代码实现

还是利用鸢尾花数据集 & 逻辑回归算法实现 K-fold 交叉验证。

from sklearn.datasets import load_iris
from sklearn.model_selection import cross_val_score, KFold
from sklearn.linear_model import LogisticRegression
iris = load_iris()
X = iris.data
y = iris.target
logreg = LogisticRegression()
kf = KFold(n_splits = 5)    # 划分 5 个折叠
# cross_val_score() 函数负责进行交叉验证并计算交叉验证(5 次)的得分
score = cross_val_score(logreg, X, y, cv=kf)
# 交叉验证准确率
print("Cross Validation Scores are {}".format(score))
# 平均准确率
print("Average Cross Validation score :{}".format(score.mean()))

结果是这样的:
kfold 结果

3. 留一交叉验证

一句话:留一法是验证集只有一个样本的 K 折法。

方式

emmm,其实留一法就是 K 折法的一个特例——让 k 值等于刨除测试集后的数据集中数据的个数,每次用一个样本作为测试集(留一),其它样本作为训练集。就像这样:

留一法

优点

  • 适合样本量小的数据集
    对于样本量小的数据集,每一个数据都很关键,使用留一法可以有效避免模型错过某些重要特征(之前在讲 Hold-out 的缺点时提到过)。

缺点

  • 训练成本较高,耗时较长

代码实现

利用鸢尾花数据集和随机森林算法实现留一交叉验证。

from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import LeaveOneOut, cross_val_score
iris = load_iris()
X = iris.data
y = iris.target
loo = LeaveOneOut()    # 留一法函数
tree = RandomForestClassifier(n_estimators=10, max_depth=5, n_jobs=-1)
score=cross_val_score(tree, X, y, cv=loo)
# 交叉验证准确率
print("Cross Validation Scores are {}".format(score))
# 交叉验证平均准确率
print("Average Cross Validation score :{}".format(score.mean()))

4. 蒙特卡罗交叉验证

emm 这貌似不太常用诶不过还是讲一下吧。

方式

和 K 折或留一法不同,蒙特卡罗交叉验证并不一定要 “随机平均分不同的折”,也不用 “一次一折” 地训练。它允许我们自由决定要用做训练集和验证集的百分比,自由决定训练次数,同时训练集和验证集的百分比加起来不需要是 100%。

比如,我们有 100 个样本,其中 60% 的样本用作训练集,20% 的样本用作验证集,那么剩下的 20% 将不被使用,这种形式重复 n 次。

蒙特卡罗交叉验证的方式如下图。
蒙特卡罗交叉验证

代码实现

利用鸢尾花数据集和逻辑回归算法实现蒙特卡罗交叉验证。

from sklearn.model_selection import ShuffleSplit,cross_val_score
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression()
shuffle_split = ShuffleSplit(test_size=0.3,train_size=0.5,n_splits=10)
scores=cross_val_score(logreg, iris.data, iris.target, cv=shuffle_split)
print("cross Validation scores:n {}".format(scores))
print("Average Cross Validation score :{}".format(scores.mean()))

5. 时间序列交叉验证

一句话:时间序列交叉验证专门用于处理在不同时间点(时间序列)收集的数据。

方式

“时间序列数据” 就是在不同时间点收集的数据。由于样本是在相邻时间段收集的,因此样本之间可能存在相关性。在这种情况下,我们不能随机选择样本并将它们分配给训练集或验证集,因为这会破坏样本之间(可能存在)的相关性,同时,使用未来数据的值去预测过去数据的值是没有意义的。

so,这种时候,我们需要根据时间顺序将数据拆分为训练集和验证集,也称为 “前向链” 方法或滚动交叉验证。先用一小部分样本作为训练集,预测稍后的样本的值,检查准确性。再将预测样本作为下一个训练数据集的一部分,对后续样本进行预测,以此类推。

大概是这样的:

在这里插入图片描述

代码实现

这个只能自造数据了((

import numpy as np
from sklearn.model_selection import TimeSeriesSplit
X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
y = np.array([1, 2, 3, 4, 5, 6])
time_series = TimeSeriesSplit()
print(time_series)    # 时间序列
for train_index, test_index in time_series.split(X):
    print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]

ok!!以上就是机器学习中的各种交叉验证方法,其中 K 折法最常用

这篇文章讲了机器学习中的各种交叉验证方法(方式+优缺点+代码实现),希望对你有所帮助!⭐
欢迎三连!!一起加油!🎇
——Geeker_LStar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/381742.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【深度学习:SegGPT】在上下文中分割所有内容 [解释]

【深度学习:SegGPT】在上下文中分割所有内容 [解释] SegGPT与以前的模型相比如何?SegGPT在实践中是如何工作的?SegGPT培训计划上下文着色上下文集成上下文调整SegGPT 训练参数 如何尝试 SegGPT?使用哪些数据集来训练 SegGPT&#…

Spring基础 - Spring简单例子引入Spring要点

Spring基础 - Spring简单例子引入Spring要点 设计一个Spring的Hello World 设计一个查询用户的案例的两个需求&#xff0c;来看Spring框架帮我们简化了什么开发工作 pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"htt…

vue.js基于springboot的实验室设备管理系统10345

(1)设备信息模块&#xff1a;记录设备的基本信息&#xff0c;如设备采购来源信息、设备需求量、当前数量、日期等。 (2) 用户模块&#xff1a;教师职工。实现对用户个人信息、消息管理和实验室设备的查询使用申请等。 (3) 管理员模块&#xff1a;实现对所有设备信息的增删改查&…

Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画,Kotlin(二)

Android用setRectToRect实现Bitmap基于Matrix矩阵scale缩放RectF动画&#xff0c;Kotlin&#xff08;二&#xff09; 文章 https://zhangphil.blog.csdn.net/article/details/135980821 实现了基于Matrix缩放Bitmap的动画&#xff0c;但是从左上角&#xff08;0,0&#xff09;位…

FPGA_简单工程_状态机

一 理论 fpga是并行执行的&#xff0c;当处理需要顺序解决的事时&#xff0c;就要引入状态机。 状态机&#xff1a; 简写FSM&#xff0c;也称同步有限状态机。 分为&#xff1a;more型状态机&#xff0c;mealy型状态机。 功能&#xff1a;执行该事件&#xff0c;然后跳转到下…

幻兽帕鲁服务器怎么更新?进入游戏显示:加入的比赛正在运行不兼容的版本,请尝试升级游戏版本(阿里云)

幻兽帕鲁服务器怎么更新&#xff1f;进入游戏显示&#xff1a;加入的比赛正在运行不兼容的版本&#xff0c;请尝试升级游戏版本。这是因为游戏客户端或者服务器上的游戏服务端&#xff0c;没有更新版本。导致两个版本不一致&#xff0c;所以无法进入游戏。 最近幻兽帕鲁 官方客…

统计数字出现次数的数位动态规划解法-数位统计DP

在处理数字问题时,我们经常遇到需要统计一定范围内各个数字出现次数的情况。这类问题虽然看起来简单,但当数字范围较大时,直接遍历统计的方法就变得不再高效。本文将介绍一种利用数位动态规划(DP)的方法来解决这一问题,具体来说,是统计两个整数a和b之间(包含a和b)所有…

CSS 2D转换 3D动画 3D转换

目录 2D转换(transform): 移动translate: 旋转rotate: 缩放scale&#xff1a; CSS3动画&#xff08;transform&#xff09;&#xff1a; 动画常用的属性&#xff1a; 将长图片利用盒子实现动画的效果&#xff1a; 3D转换&#xff1a; 透视perspective&#xff1a; 旋转r…

点云——噪声(代码)

本人硕士期间研究的方向就是三维目标点云跟踪&#xff0c;对点云和跟踪有着较为深入的理解&#xff0c;但一直忙于实习未进行梳理&#xff0c;今天趁着在家休息对点云的噪声进行梳理&#xff0c;因为预处理对于点云项目是至关重要的&#xff0c;所有代码都是近期重新复现过。 这…

【并发编程】锁-源码分析

1、ReentrantLock 1.1 加锁流程源码 1.1.1 加锁流程概述 1.1.2 lock源码分析 1.1.2.1 公平和非公平锁方式 // 非公平锁 final void lock() {// 上来就先基于CAS的方式,尝试将state从0改为1if (compareAndSetState(0, 1))// 获取锁资源成功,会将当前线程设置到exclusiveOwn…

前端JavaScript篇之call() 和 apply() 的区别?

目录 call() 和 apply() 的区别&#xff1f; call() 和 apply() 的区别&#xff1f; 在JavaScript中&#xff0c;call()和apply()都是用来改变函数中this指向的方法&#xff0c;它们的作用是一样的&#xff0c;只是传参的方式不同。 call()方法和apply()方法的第一个参数都是…

【Web】小白友好的Java内存马基础学习笔记

目录 简介 文件马与内存马的比较 文件马原理 内存马原理 内存马使用场景 内存马分类 内存马注入方式 这篇文章主要是概念性的&#xff0c;具体技术细节不做探究&#xff0c;重点在祛魅。 简介 内存马&#xff08;Memory Shellcode&#xff09;是一种恶意攻击技术&…

【GAMES101】Lecture 20 颜色

目录 光 颜色 加色系统 CIE RGB颜色匹配实验 颜色空间 CIE XYZ颜色空间 HSV颜色空间(Hue-Saturation-Value) CIELAB空间 减色系统&#xff1a;CMYK 光 光是由不同波长的光波组成的&#xff0c;其中可见光的波长范围在400nm到700nm 用谱功率密度&#xff08;Spectral…

相机图像质量研究(11)常见问题总结:光学结构对成像的影响--像差

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…

算法学习——LeetCode力扣字符串篇

算法学习——LeetCode力扣字符串篇 344. 反转字符串 344. 反转字符串 - 力扣&#xff08;LeetCode&#xff09; 描述 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间&#xff0c;你必须原地…

每日五道java面试题之java基础篇(四)

第一题. 访问修饰符 public、private、protected、以及不写&#xff08;默认&#xff09;时的区别&#xff1f; Java 中&#xff0c;可以使⽤访问控制符来保护对类、变量、⽅法和构造⽅法的访问。Java ⽀持 4 种不同的访问权限。 default (即默认&#xff0c;什么也不写&…

腾讯云4核8g10M轻量服务器能承受多少人在线访问?

腾讯云轻量4核8G12M轻量应用服务器支持多少人同时在线&#xff1f;通用型-4核8G-180G-2000G&#xff0c;2000GB月流量&#xff0c;系统盘为180GB SSD盘&#xff0c;12M公网带宽&#xff0c;下载速度峰值为1536KB/s&#xff0c;即1.5M/秒&#xff0c;假设网站内页平均大小为60KB…

七、滚动条操作——调整图像对比度

对比度调整&#xff1a;是在原来图像基础上进行相应的公式调整&#xff0c;是类似乘法操作&#xff0c;本身像数值越大&#xff0c;对比度增加之后其与低像素点值差距越大&#xff0c;导致对比增强 项目最终效果&#xff1a;通过滚动条trackbar来实现调整图片亮度的功能 我这里…

单片机与外设的交互

单片机与外设的交互是嵌入式系统中非常重要的一个基础知识点。单片机是一个集成在同一芯片上的中央处理器、存储器和输入/输出接口,它可以根据用户编写的程序与各种外部设备即外设进行交互。单片机与外设之间的交互主要通过单片机上的输入/输出口(I/O口)来实现。 I/O口的工作原…

(坑点!!!)给定n条过原点的直线和m条抛物线(y=ax^2+bx+c,a>0),对于每一条抛物线,是否存在一条直线与它没有交点,若有,输出直线斜率

题目 思路: 1、区间端点可能是小数的时候,不能直接利用加减1将 < 转化为 <=,例如,x < 1.5 不等价于 x <= 2.5 2、该题中k在(b - sqrt(4 * a * c), b + sqrt(4 * a * c) 中,注意是开区间,那么可以将左端点向上取整,右端点向下取整,即sqrt(4 * a * c)向下取…