机器学习简单流程:使用大量和任务相关的数据集来训练模型;

通过模型在数据集上的误差不断迭代训练模型,得到对数据集拟合合理的模型;

将训练好调整好的模型应用到真实的场景中;

我们最终的目的是将训练好的模型部署到真实的环境中,希望训练好的模型能够在真实的数据上得到好的预测效果,换句话说就是希望模型在真实数据上预测的结果误差越小越好。我们把模型在真实环境中的误差叫做泛化误差,最终的目的是希望训练好的模型泛化误差越低越好。

我们希望通过某个信号来了解模型的泛化误差,这样就可以指导我们得到泛化能力更强的模型:使用泛化误差本身。这是很自然的想法,我们训练模型的最终目的就是希望模型的泛化误差最低,当然可以使用泛化误差本身来作为检测信号。如果泛化误差小的话还可以接受,但是通常情况下没有那么幸运,泛化误差可能很大,这个时候你肯定会将部署的模型撤回,重新训练,你可能需要部署和训练之间往复很多次,这种方式虽然能够更好的指导我们的模型,但是成本和效率非常的差;

使用模型在数据集上训练的拟合程度来作为评估模型的信号。但是往往我们获取的数据集并不是完全的干净以及有代表性,通常我们获取到的数据集可能很少、数据的代表性不够、包含太多的噪声或者是被一些无关特征污染,我们获取到的数据集或多或少都会有这些问题,那么模型对训练数据集的拟合程度不能指导泛化误差,也就是说训练的时候拟合的好并不代表模型的泛化误差就小,你甚至可以将模型在数据集上的误差减小到0,但是因为对模型训练时候的数据集往往不干净,所以这样的模型并不代表泛化能力就强。

1.训练集与测试集

前面说到我们既不能通过直接将泛化误差作为了解模型泛化能力的信号,因为在部署环境和训练模型之间往复,代价很高,也不能使用模型对训练数据集的拟合程度来作为了解模型泛化能力的信号,因为我们获得的数据往往不干净。

更好的方式就是将数据分割成两部分:训练集和测试集。我们可以使用训练集的数据来训练模型,然后用测试集上的误差作为最终模型在应对现实场景中的泛化误差。有了测试集,我们想要验证模型的最终效果,只需将训练好的模型在测试集上计算误差,即可认为此误差即为泛化误差的近似,我们只需让我们训练好的模型在测试集上的误差最小即可。

这里有几点需要注意:通常将数据集的80%作为训练集,20%作为测试集;

通常需要在开始构建模型之前把数据集进行划分,防止数据窥探偏误,也就是说我们避免了解太多关于测试集中的样本特点,防止我们认为的挑选有助于测试集数据的模型,这样的结果会过于乐观,但是实际上并没有预期的那样优秀;

通常我们在构建模型的时候需要将数据进行处理,包括一些数据的清洗,数据的特征缩放(标准化或者归一化),此时我们只需要在训练集上进行这些操作,然后将其在训练集上得到的参数应用到测试集中,也就是说,在工作流程中,你不能使用在测试数据集上计算的得到的任何结果。比如:我们得到的属性中可能有缺失值,因为在这些操作之前,我们已经把数据集分成了训练集和测试集,通常的做法是通过计算属性值的中位数来填充缺失值,注意此时计算属性值的中位数是通过训练集上的数据进行计算的,当我们得到一个模型的时候,如果想要测试模型的测试误差来近似泛化误差的时候,可能此时的测试集也会有一些缺失值,此时对应属性的缺失值是通过训练集计算的中位数来进行填充的;

由于测试集作为对泛化误差的近似,所以训练好模型,最后在测试集上近似估计模型的泛化能力。此时假设有两个不同的机器学习模型,犹豫不决的时候,可以通过训练两个模型,然后对比他们在测试数据上的泛化误差,选择泛化能力强的模型。

前面说了这么多,那如何划分数据集为训练集和测试集呢?其实很简单,可以自己编写程序,也可以使用sklearn提供的模块:

通过简单代码实现:

import numpy as np

def split_train_test(data,test_ratio):

#设置随机数种子,保证每次生成的结果都是一样的

np.random.seed(42)

#permutation随机生成0-len(data)随机序列

shuffled_indices = np.random.permutation(len(data))

#test_ratio为测试集所占的百分比

test_set_size = int(len(data) * test_ratio)

test_indices = shuffled_indices[:test_set_size]

train_indices = shuffled_indices[test_set_size:]

#iloc选择参数序列中所对应的行

return data.iloc[train_indices],data.iloc[test_indices]

#测试

train_set,test_set = split_train_test(data,0.2)

print(len(train_set), "train +", len(test_set), "test")

通过sklearn实现:

from sklearn.model_selection import train_test_split

#data:需要进行分割的数据集

#random_state:设置随机种子,保证每次运行生成相同的随机数

#test_size:将数据分割成训练集的比例

train_set, test_set = train_test_split(data, test_size=0.2, random_state=42)

前面介绍的两种分割数据集的方式都是采用纯随机的采样方式,这种方式对于大量数据集以及对于目标值分布均匀的情况是可行的。比如对于分类任务,我们训练一个二值分类器,可能数据中包含大量的正例样本,仅仅包含10%的反例样本,此时的标签分布很不均匀,如果我们通过随机采样的方式,极端情况下可能将正例样本都划分到训练集上,而反例样本恰好都分到测试集,这样训练出来的模型,效果一定不会太好,所以我们需要采用分层采样的方式进行划分数据集,也就是说保证训练集中既包含一定比例的正例样本又要包含一定比例的负例样本。

幸运的是sklearn提供了我们分层抽样的函数,在这之前先看看官方提供的例子:

from sklearn.model_selection import StratifiedShuffleSplit

X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])

y = np.array([0, 0, 1, 1])

split = StratifiedShuffleSplit(n_splits=3, test_size=0.5, random_state=0)

print(split ) # doctest: +ELLIPSIS

# StratifiedShuffleSplit(n_splits=3, random_state=0, ...)

for train_index, test_index in split.split(X, y):

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]

"""StratifiedShuffleSplit(n_splits=3, random_state=0, test_size=0.5,train_size=None)TRAIN: [1 2] TEST: [3 0]TRAIN: [0 2] TEST: [1 3]TRAIN: [0 2] TEST: [3 1]"""

通过上面的例子我们可以了解使用分层进行划分数据集的大概流程,以及各个参数的含义:n_splits:分割迭代的次数,如果我们要划分训练集和测试集的话,将其设置为1即可;

test_size:分割测试集的比例;

random_state:设置随机种子;

下面通过两种方式对原始的mnist数据集进行划分,首先要准备数据集:

from sklearn.datasets import fetch_mldata

#我将最原始的mnist数据集下载到当前路径下,指定data_home

mnist = fetch_mldata('MNIST original',data_home=r"./")

x_data = mnist["data"].reshape((mnist["data"].shape[0],-1))

y_data = mnist["target"].reshape((mnist["target"].shape[0],-1))

print(x_data.shape) #(70000, 784)

print(y_data.shape) #(70000, 1)使用随机采样的方式分割数据集:

#使用随机采样方式划分数据集

from sklearn.model_selection import train_test_split

import numpy as np

data = np.hstack((x_data,y_data))

#先将数据集进行拼接,要不然我们只针对样本进行采样的话,会找不到对应的标签的

train_set,test_set = train_test_split(data,test_size = 0.2,random_state = 42)

print(len(train_set),len(test_set))

"""56000 14000"""使用分层采样的方式分割数据集:

from sklearn.model_selection import StratifiedShuffleSplit

split = StratifiedShuffleSplit(n_splits = 1,test_size = 0.2,random_state = 42)

#根据mnist["target"]来进行分层采样

for train_index,test_index in split.split(data[:,:-1],data[:,-1]):

train_set = data[train_index,:]

test_set = data[test_index,:]

print(len(train_set),len(test_set))

"""56000 14000"""

如果想要知道抽取的各个样本的比例,你可以将数据转换成DataFrame对象(当然在处理数据的开始你也可以将数据转换为DataFrame方便操作):

#将分割后的训练数据转换为DataFrame

#这里的参数data可以是分割之后的训练集或者测试集

train_data = pd.DataFrame(train_set)

#快速查看对数据的描述

train_data.info()

#查看各个类别的比例

print(train_data[784].value_counts() / len(train_data))

下面各图分别是:原始数据10个类别所占的比例、随机采样训练集中10个类别所占比例以及分层采样训练集中10个类别所占的比例(当然也可以对测试集进行统计)。

统计对比

通过上面的分析可以看出,分层采样出的10个类别所占的比例和原数据中的10个类别所占的比例很接近。

2.验证集

前面说到我们将数据集划分为训练集和测试集,我们让模型在训练集上进行训练,然后在测试集上来近似模型的泛化能力。我们如果想要挑选不同的模型的话,可以让两个模型分别在训练集上训练,然后将两个训练好的模型分别在测试集上进行测试,由于我们把测试集上的误差近似近似为泛化误差,所以我们自然可以选择在测试集上误差小的模型作为最终我们要选择的泛化能力强的模型。

但是我们要做的不仅是不同的模型与模型之间的对比,很多时候我们需要对模型本身进行选择,假如我们有两个模型,线性模型和神经网络模型,我们知道神经网络的泛化能力要比线性模型要强,我们选择了神经网络模型,但是神经网络中还有很多的需要人工进行选择的参数,比如神经网络的层数和每层神经网络的神经元个数以及正则化的一些参数等等,我们将这些参数称为超参数。这些参数不同选择对模型最终的效果也很重要,我们在开发模型的时候总是需要调节这些超参数。

现在我们需要调节这些超参数来使得模型泛化能力最强。我们使用测试集来作为泛化误差估计,而我们最终的目的就是选择泛化能力强的模型,那么我们可以直接通过模型在测试集上的误差来调节这些参数不就可以了。可能模型在测试集上的误差为0,但是你拿着这样的模型去部署到真实场景中去使用的话,效果可能会非常差。

这一现象叫做信息泄露。我们使用测试集作为泛化误差的近似,所以不到最后是不能将测试集的信息泄露出去的,就好比考试一样,我们平时做的题相当于训练集,测试集相当于最终的考试,我们通过最终的考试来检验我们最终的学习能力,将测试集信息泄露出去,相当于学生提前知道了考试题目,那最后再考这些提前知道的考试题目,当然代表不了什么,你在最后的考试中得再高的分数,也不能代表你学习能力强。而如果通过测试集来调节模型,相当于不仅知道了考试的题目,学生还都学会怎么做这些题了(因为我们肯定会人为的让模型在测试集上的误差最小,因为这是你调整超参数的目的),那再拿这些题考试的话,人人都有可能考满分,但是并没有起到检测学生学习能力的作用。原来我们通过测试集来近似泛化误差,也就是通过考试来检验学生的学习能力,但是由于信息泄露,此时的测试集即考试无任何意义,现实中可能学生的能力很差。所以,我们在学习的时候,老师会准备一些小测试来帮助我们查缺补漏,这些小测试也就是要说的验证集。我们通过验证集来作为调整模型的依据,这样不至于将测试集中的信息泄露。

也就是说我们将数据划分训练集、验证集和测试集。在训练集上训练模型,在验证集上评估模型,一旦找到的最佳的参数,就在测试集上最后测试一次,测试集上的误差作为泛化误差的近似。关于验证集的划分可以参考测试集的划分,其实都是一样的,这里不再赘述。

吴恩达老师的视频中,如果当数据量不是很大的时候(万级别以下)的时候将训练集、验证集以及测试集划分为6:2:2;若是数据很大,可以将训练集、验证集、测试集比例调整为98:1:1;但是当可用的数据很少的情况下也可以使用一些高级的方法,比如留出方,K折交叉验证等。

参考:

1.《Hands-On Machine Learning with Scikit-Learn and TensorFlow》

matlab划分训练集验证和测试集代码_训练集、验证集和测试集相关推荐

  1. mock测试使用断言_使用自定义断言丰富测试代码

    mock测试使用断言 受GeeCON会议期间@tkaczanowski演讲的启发,我决定仔细研究AssertJ库的自定义断言. 在我的"骰子"游戏中,我创建了一个"机会& ...

  2. 互联网测试岗位分类_【科普】互联网测试岗位的工作日常

    近期公司新来了一批实习生,公司也组织了大量的人力物力对实习生的进行培训.不得不说,公司的确在朝"大公司"的方向发展,各项制度福利也在逐步完善.以前别说是实习生了,不管是社招还是校招 ...

  3. python怎么测试c代码_如何正确测试python中的C-API,C-API返回错误代码

    我的设置 我正在使用Python中的pytest和ctypes测试C库中的函数.C库中的每个函数调用一个嵌入式linux PCI板上的函数,然后C库函数返回一个整数,该整数映射到一组返回代码.如果函数 ...

  4. 龙果学院mysql分布式集群代码_龙果学院-MySQL大型分布式集群解决方案

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 1 课程概述 2 课程背景 3 纵观大型网站架构发展,总结持久化部分需要应对的问题 4 操作系统安装以及配置 5 在CentOS上通过yum安装mysql ...

  5. mysql启动集群报连接本地失败_启动本地安装的pxc集群失败,前面的步骤都检查没错了...

    在真是的华为云linux centos7.4 上执行 systemctl start mysql@bootstrap.service 启动失败了 ● mysql@bootstrap.service - ...

  6. java测试性能代码_关于性能:Java代码内部的基准测试

    我最近一直在研究基准测试,我一直对记录程序数据等感兴趣.我想知道我们是否可以在程序中有效地实现自己的内存使用代码和实现自己的时间消耗代码.我知道如何检查代码运行所需的时间: public static ...

  7. 开发转测试好转吗_月薪15K+的高级测试开发工程师基础面试题,你要来试试吗?...

    小编准备了三道测试开发题, 答对即有机会获得本期精选图书! 快来挑战吧!@所有人 本期图书介绍 本书从测试的角度,针对性地讲述了软件测试人员在软件测试和测试开发过程中需要掌握的知识点,以及需要达到的技 ...

  8. jset编写测试vue代码_详解使用jest对vue项目进行单元测试

    最近领导对前端提出了新的要求,要进行单元测试.之前使用vue做了一个快报名小程序的pc端页面,既然要做单元测试,就准备用这个项目了,之前有些react的经验,vue还是第一遭 vue-cli3.0单元 ...

  9. jset编写测试vue代码_使用 Jest 进行 Vue 单元测试

    本文介绍: 1.vue-cli3下jest环境的搭建 2.vue组件基本的测试方法 环境配置 vue-cli3 的插件使安装流程变得格外简单,通过 vue ui 启动可视化管理系统,在插件栏,点击 ' ...

  10. postman可以测试websocket吗_小海塔罗娱乐测试2021年可以脱单吗?

    默念问题 选择喜欢的牌 测试仅供娱乐 如需专业咨询 详细询问助理 A 权杖ace逆 2021年的你还是很努力的一年,努力的向下扎根,和爱情相比,你还是更想要面包.爱情对于现阶段的你来讲,是一个奢侈品. ...

最新文章

  1. wamp配置虚拟域名
  2. JAVA线程池的简单实现及优先级设置
  3. linux下rpm包和命令使用简介
  4. 不能在 UTF8 和 UCS2 之间转换: failUTF8Conv
  5. Android手机使用命令行增加/删除/修改密码(password/pin/pattern)
  6. js中浮点型运算 加减乘除
  7. char强制类型转换为int_C语言学习第5篇---类型转换概念理解
  8. HTTP/2 学习笔记
  9. 带你一起学软件工程的专业英语!(IT行业、四六级党快记起来)《软件工程专业英语》第一单元:启动软件项目——单词、短语、名词缩写、难句、备忘录的基本格式样本(必备技能)
  10. 用触发器实现主从表关系(主表更改从表更改 )
  11. JAVA中几种循环结构的表示_本文通过实例讲解给大家介绍Java中for、while、do while三种循环语句的区别,具体详情如下所示:第一种:for循环 循环结构for语句的格式...
  12. linux 环境变量和shell变量
  13. 软件的卡顿与卡死,意思是不同的
  14. Linux chmod命令:修改文件或目录的权限
  15. 酒店抖音小程序开发方案
  16. 现在俏皮话越来越多了
  17. 互联网摸鱼日报(2022-12-25)
  18. 四天搞懂生成对抗网络(二)——风格迁移的“精神始祖”Conditional GAN
  19. 音响为什么要做CCC认证以及流程有哪些
  20. 无聊的游戏 Beta 0.1

热门文章

  1. 使用VMware创建一个虚拟机,并安装乌班图系统
  2. vivo应用商店服务器,vivo应用商店
  3. 第二次作业:软件分析之网易云音乐
  4. [工具] Mac下一键APK逆向环境
  5. 20190216-Java 教程(菜鸟教程)
  6. 邻接矩阵实现(有向邻接矩阵)、(无向邻接矩阵) 基于C++
  7. Java面试知识点概览(持续更新)
  8. 图像处理与机器学习-第一章(概述)
  9. 计算机安装软件没有管理员权限设置,实用技巧:如何在win10中安装没有管理员权限的软件...
  10. eclipse使用git提交代码步骤