当前位置:首页 » 服务存储 » 多折交叉验证模型的存储与调用
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

多折交叉验证模型的存储与调用

发布时间: 2022-11-16 22:57:46

㈠ 如何进行变量筛选和特征选择(三)交叉验证

交叉验证是机器学习中常用的一种验证和选择模型的方法,常用的交叉验证方法是K折交叉验证。将原始数据分成K组(一般是均分),将每个子集分别作一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,k个模型的验证误差的均值即作为模型的总体验证误差,取多次验证的平均值作为验证结果,误差小的模型则为最优模型。k一般大于等于2,一般而言 k=10 (作为一个经验参数)算是相当足够了。

采用的R包是bestglm,主要函数是bestglm()。
结合一个二元Logistic回归的例子,分享如何运用R软件实现10折交叉验证。

搭建完模型,运用predict()得到预测概率,保存测试集的预测概率。

函数中IC = "CV"表示采用交叉验证,CVArgs 表示交叉验证的参数,k=10表示分成10份,REP=1是每次一份作为测试集,family=binomial 表示因变量为二项分布。该函数是利用最优子集回归的原理,对于不同数量的特征,都用k折交叉验证法求一个验证误差,最后比较验证误差与特征数量的关系,选取最优变量。

将返回结果的cv列作图,可以看到在模型变量个数为3的时候,验证误差变得很小,之后随着变量个数增加,误差变化不大。利用coef()函数可查看最优变量。

根据筛选的最优变量,搭建模型,运用predict()得到预测概率。

根据ROC曲线面积对比两个模型在测试集上的预测性能,检验P值>0.05,且AUC均接近于1,说明两模型预测性能一致且很好,但交叉验证得到的模型变量为3个,模型简洁,在实际运用中效率更高,因此可选择交叉验证的模型作为最优模型。

在构建模型做变量筛选方法比较多,在前面推文中给大家介绍了2个,可以翻看一下
如何进行高维变量筛选和特征选择(一)?Lasso回归
如何进行变量筛选和特征选择(二)?最优子集回归
以上就是本次跟大家分享的内容,觉得有用的话点赞、转发哦~

㈡ 5折交叉验证与10折区别

5折交叉验证与10折区别:5折交叉验证就是把样本分为5份,其中4份用来做训练建立模型,留剩下的一份来验证,交叉验证重复5次,每个子样本验证一次。10折交叉验证将数据集分成十份,轮流将其中9份做训练1份做验证,10次的结果的均值作为对算法精度的估计,一般还需要进行多次10折交叉验证求均值。交叉验证也称作循环估计(RotationEstimation),是一种统计学上将数据样本切割成较小子集的实用方法,该理论是由SeymourGeisser提出的。

㈢ 什么是交叉检验

交叉验证(Cross Validation)是用来验证分类器的性能一种统计分析方法,基本思想是把在某种意义下将原始数据(dataset)进行分组,一部分做为训练集(training set),另一部分做为验证集(validation set),首先用训练集对分类器进行训练,在利用验证集来测试训练得到的模型(model),以此来做为评价分类器的性能指标。常见的交叉验证方法如下:1、Hold-Out Method
将原始数据随机分为两组,一组做为训练集,一组做为验证集,利用训练集训练分类器,然后利用验证集验证模型,记录最后的分类准确率为此分类器的性能指标。此种方法的好处的处理简单,只需随机把原始数据分为两组即可,其实严格意义来说Hold-Out Method并不能算是CV,因为这种方法没有达到交叉的思想,由于是随机的将原始数据分组,所以最后验证集分类准确率的高低与原始数据的分组有很大的关系,所以这种方法得到的结果其实并不具有说服性。
2、Double Cross Validation(2-fold Cross Validation,记为2-CV)
做法是将数据集分成两个相等大小的子集,进行两回合的分类器训练。在第一回合中,一个子集作为training set,另一个便作为testing set;在第二回合中,则将training set与testing set对换后,再次训练分类器,而其中我们比较关心的是两次testing sets的辨识率。不过在实务上2-CV并不常用,主要原因是training set样本数太少,通常不足以代表母体样本的分布,导致testing阶段辨识率容易出现明显落差。此外,2-CV中分子集的变异度大,往往无法达到“实验过程必须可以被复制”的要求。
3、K-fold Cross Validation(K-折交叉验证,记为K-CV) 将原始数据分成K组(一般是均分),将每个子集数据分别做一次验证集,其余的K-1组子集数据作为训练集,这样会得到K个模型,用这K个模型最终的验证集的分类准确率的平均数作为此K-CV下分类器的性能指标。K一般大于等于2,实际操作时一般从3开始取,只有在原始数据集合数据量小的时候才会尝试取2。K-CV可以有效的避免过学习以及欠学习状态的发生,最后得到的结果也比较具有说服性。
4、Leave-One-Out Cross Validation(记为LOO-CV) 如果设原始数据有N个样本,那么LOO-CV就是N-CV,即每个样本单独作为验证集,其余的N-1个样本作为训练集,所以LOO-CV会得到N个模型,用这N个模型最终的验证集的分类准确率的平均数作为此下LOO-CV分类器的性能指标。相比于前面的K-CV,LOO-CV有两个明显的优点:
(1)每一回合中几乎所有的样本皆用于训练模型,因此最接近原始样本的分布,这样评估所得的结果比较可靠。
(2)实验过程中没有随机因素会影响实验数据,确保实验过程是可以被复制的。
但LOO-CV的缺点则是计算成本高,因为需要建立的模型数量与原始数据样本数量相同,当原始数据样本数量相当多时,LOO-CV在实作上便有困难几乎就是不显示,除非每次训练分类器得到模型的速度很快,或是可以用并行化计算减少计算所需的时间。

㈣ 一文看懂 AI 训练集、验证集、测试集(附:分割方法+交叉验证)

先用一个不恰当的比喻来说明3种数据集之间的关系:

训练集(Training Dataset)是用来训练模型使用的。

在《 一文看懂机器学习 》里我们介绍了机器学习的7个步骤,训练集(Training Dataset)主要在训练阶段使用。

当我们的模型训练好之后,我们并不知道他的表现如何。这个时候就可以使用验证集(Validation Dataset)来看看模型在新数据(验证集和测试集是不同的数据)上的表现如何。 同时通过调整超参数,让模型处于最好的状态

验证集有2个主要的作用:

说明:

当我们调好超参数后,就要开始“最终考试”了。我们通过测试集(Test Dataset)来做最终的评估。

通过测试集的评估,我们会得到一些最终的评估指标,例如:准确率、精确率、召回率、F1等。

扩展阅读:《 分类模型评估指标——准确率、精准率、召回率、F1、ROC曲线、AUC曲线 》

下面的数据集划分方式主要针对“留出法”的验证方式,除此之外还有其他的交叉验证法,详情见下文——交叉验证法。

数据划分的方法并没有明确的规定,不过可以参考3个原则:

假如我们教小朋友学加法:1个苹果+1个苹果=2个苹果

当我们再测试的时候,会问:1个香蕉+1个香蕉=几个香蕉?

如果小朋友知道“2个香蕉”,并且换成其他东西也没有问题,那么我们认为小朋友学习会了“1+1=2”这个知识点。

如果小朋友只知道“1个苹果+1个苹果=2个苹果”,但是换成其他东西就不会了,那么我们就不能说小朋友学会了“1+1=2”这个知识点。

评估模型是否学会了“某项技能”时,也需要用新的数据来评估,而不是用训练集里的数据来评估。这种“训练集”和“测试集”完全不同的验证方法就是交叉验证法。

留出法(Holdout cross validation)

上文提到的,按照固定比例将数据集 静态的 划分为训练集、验证集、测试集。的方式就是留出法。

留一法(Leave one out cross validation)

每次的测试集都只有一个样本,要进行 m 次训练和预测。
这个方法用于训练的数据只比整体数据集少了一个样本,因此最接近原始样本的分布。但是训练复杂度增加了,因为模型的数量与原始数据样本数量相同。
一般在数据缺乏时使用。

k 折交叉验证(k-fold cross validation)

静态的“留出法”对数据的划分方式比较敏感,有可能不同的划分方式得到了不同的模型。“k 折交叉验证”是一种动态验证的方式,这种方式可以降低数据划分带来的影响。具体步骤如下:

k 一般取 10
数据量小的时候,k 可以设大一点,这样训练集占整体比例就比较大,不过同时训练的模型个数也增多。
数据量大的时候,k 可以设小一点。
本文首发自 产品经理的 AI 学习库 easyai.tech

㈤ R语言之决策树和随机森林

R语言之决策树和随机森林
总结决策树之前先总结一下特征的生成和选择,因为决策树就是一种内嵌型的特征选择过程,它的特征选择和算法是融合在一起的,不需要额外的特征选择。
一、特征生成:
特征生成是指在收集数据之时原始数据就具有的数据特征,这些数据特征由收集的数据决定(其实也就是在产品定型时设定的需要收集的数据特征),当然,在数据预处理时,也可以在此基础上构造一些新的数据特征,这些特征越多越好,表示你考虑问题比较周全,具体那些变量有用或没用,这要交给下一步特征选择来决定。
二、特征选择
特征选择是指在原有数据特征的基础上,去除重要性比较低的特征变量,过滤出有用的特征变量。这里比较困难的是搞清楚什么样的特征比较重要?这需要根据具体的问题具体分析,有些变量的选择可以很直观的看出来,但这种直觉也不一定正确。对于常用特征选择方法主要有:过滤型、包装型、内嵌型。
过滤型:是指你可以根据某个统计量的大小排序来选择特征变量,如相关系数、p值、R值等
包装型:是指在一个特征集合中选取最优的特征子集。具体需要考虑:用什么样的算法来选取?选取的最优的标准是什么?
常用的算法是分步回归包括向前搜索、向后删除、双向搜索
向前搜索:每次选取一个能使模型预测或分类效果最好的特征变量进来,进来后不退出,直到模型改善效果不再明显;
向后删除:是指每次从特征全集中每次删除一个特征变量能使模型预测或分类效果最好,退出后不进来,直到模型改善效果不再明显;
双向搜索:是指每次每次删除一个特征变量或加入一个特征变量能使模型预测或分类效果最好,退出的不进来,进来的不退出,直到模型改善效果不再明显;
这里再提一下特征变量选择的几个标准:p值、R值、AIC(越小效果越好)、BIC(越小效果越好)、熵(越小效果越好)
内嵌型:这里应该主要就是像决策树这样的情况,算法内部完成特征变量的选取。
三、决策树
决策的几个要点:1、如何决策?(也就是如何树如何分叉)------熵和信息增益---这里面包含的就是特征的选择?哪个特征变量包含的信息量大,就排在前面,至于最后树的深度就决定特征变量的个数。
当然不同的算法使用的衡量的标准不同,还有:信息增益比、基尼不纯系数
2、如何剪枝?-----一般是事后剪枝
3、连续性变量如何离散化?-----阈值的选择
熵:是指信息的混合程度(混乱程度),熵【0-1】越大表示该集合中混合的信息越多,也就表明这次的分叉效果不好还是有很多不同类的信息混在一起
信息增益:熵值的减少量,越大越好
决策树模型特点:模型易于解释;存储空间较小,以树的形式存储,决策树是一个弱分类器,不能完全分类,需要把多个弱分类器通过多数投票法组合在一起。
四、R包实现决策树
library(rpart)
library(rpart.plot)
## rpart.control对树进行一些设置
## xval是10折交叉验证
## minsplit是最小分支节点数,这里指大于等于20,那么该节点会继续分划下去,否则停止
## minbucket:叶子节点最小样本数
## maxdepth:树的深度
## cp全称为complexity parameter,指某个点的复杂度,对每一步拆分,模型的拟合优度必须提高的程度
ct <- rpart.control(xval=10, minsplit=20, cp=0.1)
## kyphosis是rpart这个包自带的数据集
## na.action:缺失数据的处理办法,默认为删除因变量缺失的观测而保留自变量缺失的观测。
## method:树的末端数据类型选择相应的变量分割方法:
## 连续性method=“anova”,离散型method=“class”,计数型method=“poisson”,生存分析型method=“exp”
## parms用来设置三个参数:先验概率、损失矩阵、分类纯度的度量方法(gini和information)
## cost是损失矩阵,在剪枝的时候,叶子节点的加权误差与父节点的误差进行比较,考虑损失矩阵的时候,从将“减少-误差”调整为“减少-损失”
data("Kyphosis")
fit <- rpart(Kyphosis~Age + Number + Start,data=kyphosis, method="class",control=ct,parms = list(prior = c(0.65,0.35), split = "information"));
## 作图有2种方法
## 第一种:
par(mfrow=c(1,3));plot(fit); text(fit,use.n=T,all=T,cex=0.9)
## 第二种,这种会更漂亮一些:
rpart.plot(fit, branch=1, branch.type=2, type=1, extra=102,
shadow.col="gray", box.col="green",
border.col="blue", split.col="red",
split.cex=1.2, main="Kyphosis决策树");
## rpart包提供了复杂度损失修剪的修剪方法,printcp会告诉分裂到每一层,cp是多少,平均相对误差是多少
## 交叉验证的估计误差(“xerror”列),以及标准误差(“xstd”列),平均相对误差=xerror±xstd
printcp(fit)
## 通过上面的分析来确定cp的值
##调用CP(complexity parameter)与xerror的相关图,一种方法是寻找最小xerror点所对应
#的CP值,并由此CP值决定树的大小,另一种方法是利用1SE方法,寻找xerror+SE的最小点对应的CP值。
plotcp(fit)
##利用以下方法进行修剪:
## prune(fit, cp= fit$cptable[which.min(fit$cptable[,"xerror"]),"CP"])
fit2 <- prune(fit, cp=0.01)
#利用模型预测
ndata=data.frame(...)
predict(fit,newdata=ndata)

#案例
str(iris)
set.seed(1234)#设置随机数种子--使每次运行时产生的一组随机数相同,便于结果的重现
#抽样:从iris数据集中随机抽70%定义为训练数据集,30%为测试数据集(常用)
#这里是对行抽样,ind是一个只含1和2的向量
ind <- sample(2, nrow(iris), replace=TRUE, prob=c(0.7, 0.3))
trainData <- iris[ind==1,]
testData <- iris[ind==2,]
f<-Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width
#训练数据
fit<-rpart(f,trainData)
#预测
re<-predict(fit,testData)
#******************或者用其他包********************
library(party)
#建立决策树模型预测花的种类
myFormula <- Species ~ Sepal.Length + Sepal.Width + Petal.Length + Petal.Width
iris_ctree <- ctree(myFormula, data=trainData)
# 查看预测的结果
z<-table(predict(iris_ctree), trainData$Species)
#可以根据以上列联表求出预测的正确率---评估模型
#计算准确度
q<-sum(diag(z))/sum(z)
五、机器集成与随机森林法则
前面说过,决策树的一个特点是:弱分类器,分类不完全,需要利用集成投票的方式来增加精确度和稳健性。
机器集成算法:对于数据集训练多个模型,对于分类问题,可以采用投票的方法,选择票数最多的类别作为最终的类别,而对于回归问题,可以采用取均值的方法,取得的均值作为最终的结果。主要的集成算法有bagging和adaboost算法。
随机森林:随机森林就是利用机器集成多个决策树,主要有两个参数,一个是决策树的个数,一个是每棵树的特征变量个数。
随机森林特点:精确度高、稳健性好,但可解释性差。(可以知道各个变量的重要性)
R包实现机器集成算法:
#adabag包均有函数实现bagging和adaboost的分类建模
#利用全部数据建模
library(adabag)
a<-boosting(Species~.,data=iris)
z0<-table(iris[,5],predict(a,iris)$class)
#计算误差率
E0<-(sum(z0)-sum(diag(z0)))/sum(z0)
barplot(a$importance)
b<-errorevol(a,iris)#计算全体的误差演变
plot(b$error,type="l",main="AdaBoost error vs number of trees") #对误差演变进行画图

a<-bagging(Species~.,data=iris)
z0<-table(iris[,5],predict(a,iris)$class)
#计算误差率
E0<-(sum(z0)-sum(diag(z0)))/sum(z0)
barplot(a$importance)
b<-errorevol(a,iris)#计算全体的误差演变
plot(b$error,type="l",main="AdaBoost error vs number of trees") #对误差演变进行画图

#5折交叉验证
set.seed(1044) #设定随机种子
samp=c(sample(1:50,25),sample(51:100,25),sample(101:150,25)) #进行随机抽样
a=boosting(Species~.,data=iris[samp,]) #利用训练集建立adaboost分类模
z0<-table(iris[samp,5],predict(a,iris[samp,])$class)#训练集结果
z1<-table(iris[-samp,5],predict(a,iris[-samp,])$class)#测试集结果
E0<-(sum(z0)-sum(diag(z0)))/sum(z0)
E1<-(sum(z0)-sum(diag(z0)))/sum(z1)

a=bagging(Species~.,data=iris[samp,]) #利用训练集建立adaboost分类模
z0<-table(iris[samp,5],predict(a,iris[samp,])$class)#训练集结果
z1<-table(iris[-samp,5],predict(a,iris[-samp,])$class)#测试集结果
E0<-(sum(z0)-sum(diag(z0)))/sum(z0)
E1<-(sum(z0)-sum(diag(z0)))/sum(z1)
R包实现随机森林:
#随机森林法则
library(randomForest)
library(foreign)
data("iris")
#抽样数据
ind<-sample(2,nrow(iris),replace = TRUE,prob=c(0.7,0.3))
traning<-iris[ind==1,]
testing<-iris[ind==2,]
#训练数据
rf <- randomForest(Species ~ ., data=traning, ntree=100, proximity=TRUE)
#预测
table(predict(rf),traning$Species)
table(predict(rf,testing),testing$Species)
#查看预测的效果
print(rf)
plot(rf)
#查看重要性
importance(rf)
varImpPlot(rf)

㈥ 交叉验证,K折交叉验证的偏差和方差分析

交叉验证是一种通过估计模型的泛化误差,从而进行模型选择的方法。没有任何假定前提,具有应用的普遍性,操作简便, 是一种行之有效的模型选择方法。

人们发现用同一数据集,既进行训练,又进行模型误差估计,对误差估计的很不准确,这就是所说的模型误差估计的乐观性。为了克服这个问题,提出了交叉验证。基本思想是将数据分为两部分,一部分数据用来模型的训练,称为训练集;另外一部分用于测试模型的误差,称为验证集。由于两部分数据不同,估计得到的泛化误差更接近真实的模型表现。数据量足够的情况下,可以很好的估计真实的泛化误差。但是实际中,往往只有有限的数据可用,需要对数据进行重用,从而对数据进行多次切分,得到好的估计。

以上两种方法基于数据完全切分,重复次数多,计算量大。因此提出几种基于数据部分切分的方法减轻计算负担。

衡量一个模型评估方法的好坏,往往从偏差和方差两方面进行。

3.再来个射箭问题:假设你在射箭,红星是你的目标,以下是你的射箭结果

分析:

综合起来看,我们需要的模型最好是两个L,又准确又稳定,妥妥的,但是,这个在现实模型中是不会存在的。你只能权衡着来

一句话,过拟合会出现高方差问题

一句话,欠拟合会出现高偏差问题

避免欠拟合(刻画不够)

避免过拟合(刻画太细,泛化太差)

1. 交叉验证,这是仅使用训练集衡量模型性能的一个方便技术,不用建模最后才使用测试集

2. Cross-validation 是为了有效的估测 generalization error(泛化误差) 所设计的实验方法,而generalization error=bias+variance

可以发现,怎么来平衡Bias和Variance则成了我们最大的任务了,也就是怎么合理的评估自己模型呢?我们由此提出了交叉验证的思想,以K-fold Cross Validation(记为K-CV)为例,基本思想如下:(其他更多方法请看 @bigdataage --交叉验证(Cross-Validation) )

看不清上面的就来一幅更简单的

每次的training_set 红色, validation_set白色 ,也就是说k=5的情况了

注意:交叉验证使用的仅仅是训练集!!根本没测试集什么事!很多博客都在误导!

这也就解决了上面刚开始说的Variance(不同训练集产生的差异),Bias(所有data训练结果的平均值)这两大问题了!因为交叉验证思想集合了这两大痛点,能够更好的评估模型好坏!

说白了,就是你需要用下交叉验证去试下你的算法是否精度够好,够稳定!你不能说你在某个数据集上表现好就可以,你做的模型是要放在整个数据集上来看的!毕竟泛化能力才是机器学习解决的核心

@知乎--机器学习中的Bias(偏差),Error(误差),和Variance(方差)有什么区别和联系?
@知乎--方差和偏差
@bigdataage --交叉验证(Cross-Validation)
@一只鸟的天空--机器学习中防止过拟合的处理方法

㈦ 训练集、验证集、测试集(交叉验证)

模型参数分为 训练参数 超参数 ,其中前者是在训练集上训练得到的,而后者是在训练之前由用户指定的,比如学习率、迭代次数等。
机器学习中,样本集通常会被分为 训练集 验证集 测试集 ,其中训练集和测试集是必须有的。

对于一个训练好的模型,需要了解它的泛化性能(在新样本上的准确率),真正的泛化性能应该在除原样本集之外的所有潜在样本上进行计算,但实际中没法得到这些潜在样本,于是退而求其次,在原样本集上划分出了一个测试集作为近似,并将在该测试集上的泛化性能近似作为在所有样本上的泛化性能。
注意: 测试集中的样本与训练集、验证集不能有任何交集;测试集只能用于检验最终模型的泛化性能,不能用于更新模型参数。换句话说,只有最终模型才需要经过测试集检验泛化性能,或者说模型经过测试集检验泛化性能后就不能再进行任何训练或修改参数了 。如果将在测试集上得到的准确率(也就是误差)反过来作为模型进一步训练的依据,实际上是将测试集也作为训练集对待了,也就没有了测试集。
实际中,有人会这么做,当碰到最终模型在测试集上的准确率不高时,又反过来重新调整超参数或利用测试集上的误差进一步训练模型,如此重复直到模型在测试集上表现很好,但上线后发现模型的准确率很低。出现上线后准确率低的其中一种原因就是误用了测试集,上述过程实际上就没有测试集,而是将整个样本集都作为了训练集,并且调整模型使其在测试集上获得高准确率的做法还会导致模型过拟合,上线后准确率自然会很低。
理论上,如果最终模型在测试集上的表现非常差,则应该从样本数据量、样本分布、训练集和测试集划分情况、模型选择等一系列因素入手查找原因,而不是回去继续调整模型参数(虽然也有可能就是模型参数还不不够好)。
值得注意的是, 测试集上的准确率不一定越高越好 。如果样本集本身的分布就很有局限性(无法有效表征所有潜在样本的基本特征),那么测试集的分布就更有局限性,此时测试集上的高准确率就意味着严重的过拟合,模型投入实际应用后准确率一定差。因此对于不太理想的样本集而言,测试集上的准确率相对低一些,模型的真正泛化性能反而更好。如果样本集的分布足够好,能足够表征所有潜在样本的特征,那么模型在测试集上的准确率越高越好。

验证集是训练集和测试集之间的一个中间件。根据前面的定义,我们发现了一个问题,如果只有训练集和测试集,是无法在测试集之前对模型进行评价的。实际上我们更希望在最终模型确定之前,可以先对模型进行一定的评价,然后根据评价结果调整模型参数(特别是超参数),直到我们认为模型已经不错了,最后再用测试集进行测试,测试就只为了查看模型的近似泛化性能,不再继续更新模型参数。正是为了这个目的,才划分出了一个验证集。可见, 验证集一定程度上还是训练集,因为会根据验证集的结果调整模型参数
有了验证集,整个过程就变成了下面这样:先确定一组超参数,然后在训练集上训练,再用验证集进行检验,如果效果不好,则继续调整超参数,重新在训练集上训练,如此循环,直到模型在验证集上表现良好。 到这一步,相当于我们已经基本找到了最优的超参数,接下去可以将这组超参数对应的模型参数作为最终模型参数,也可以利用这组超参数在“训练集+验证集”上重新训练一遍,得到的结果作为最终模型参数 。最后用测试集检验最终模型参数的泛化效果,好与不好都不再单纯地调整模型参数了。

最简单的样本集划分就是只有训练集和测试集,而没有验证集。这种情况实际上前面已经说过,他无法利用验证集反过来对模型参数进行调整。只能确定一组超参数,然后训练得到训练参数,这个就算是最终结果了,然后利用测试集检验一下泛化效果就算结束了。或者更复杂点的做法,先确定几组超参数,然后分别在训练集上训练得到不同训练参数,最后利用测试集分别进行测试,最后根据测试结果选择认为最好的那组作为最终模型参数。如下图所示:

当然,不地道的做法,也可以一定程度上利用测试集的结果反过来调整模型参数,但不能过度,否则极容易过拟合。

将样本集划分为训练集、验证集和测试集,比例通常为8:1:1或6:2:2。这种情况比第一种要好,他多了一个验证集,至少让你可以根据验证集来不断调整模型参数了。
先确定一组超参数,在训练集上得到训练参数,然后在验证集上得到验证结果,根据验证结果反过来修改超参数,继续在训练集上训练,然后再验证……如此循环直到你认为训练结果在验证集上表现良好为止。到这一步,我们仅仅只是找到了相对最优的超参数,其对应的训练参数通常还不能作为最后参数。 还需要根据获得的最优超参数在“训练集+验证集”上整体做训练得到最终结果 ,最后将该“最优超参数+最终训练参数”在测试集上做测试(不再训练),结束整个过程。如下图所示,其中曲线图展示了不断尝试不同的超参数,最终确定最优超参数C0的过程(注意,这里的最优超参数C0只是当前训练集和验证集划分情况下的最优,但这并不代表它是整个样本集真正的最优超参数,详见“单一划分的缺陷”章节):

上述两种方式都有一个问题。
我们知道把一个样本集划分成训练集、(验证集)、测试集,由于每个样本可能不同,即使划分子集的样本数每次相同,最终的划分结果也不同。
事实证明, 在样本集规模较小的情况下,对于不同的子集划分,即使是完全相同的超参数,其最终的训练和测试结果也会出现很大波动 。如下图所示,同一个样本集,训练集和验证集划分不同(测试集用同一个),得到的最优超参数就不同,对应的误差曲线差异也很大。

出现上述情况的本质原因是样本集分布不够充分,导致划分后的子集更不充分,每一种划分都出现较大波动,自然训练和测试的结果也会波动较大;如果样本集足够大足够充分(足够表征全局特征),那么无论划分情况怎么变化,子集很大程度上也都足够充分,训练和测试出来的结果也就是全局结果,最优超参数和误差曲线也不会变化太大

前面已经说过,对于样本数量不大,样本分布不充分的样本集而言,单一验证方法会因为样本集分割变化而导致最终的训练和测试结果出现比较严重的动荡。
针对这种情况,很自然地想到,可以对训练集做K次分割(K折交叉验证),然后用同一组超参数对应训练K个模型,并在同一组测试集上测试,取最终的平均准确率作为该组超参数的最终测试结果;
然后选下一组超参数重复上述过程,这样我们就获得了不同超参数各自的平均准确率;
选择平均准确率最高的超参数作为最终超参数;
将最终超参数在“原训练集+验证集”上整体做训练得到最终结果;
最后将该“最终超参数+最终训练参数”在测试集上做测试(不再训练),结束整个过程。
上述过程可以用下图表示:

交叉验证使最终在测试集上的准确率更加可信,一定程度上摆脱了因为单一样本划分带来的分布不均衡问题;
交叉验证使训练集样本既做了训练集又做了验证集,因此,一定程度上利用了更多的样本信息;
用于调节超参数;用于选择不同模型;用于选择不同样本参数。

K折交叉验证的过程就是上图所示,不再赘述。
关于K的选择需要说明:
K=1 时,即所有训练样本都作为训练样本,这种情况相当于没有交叉验证,跟只有训练集和测试集的情况一样;
K=N 时(N是训练集的样本总数,不包括测试集),即每次只留1个样本作为验证集,N-1个作为训练集,这种方法称为留一法(LOOCV,Leave-one-out cross-validation);
LOOCV的优点:首先它不受训训练集和验证集划分(这里指将大训练集划分为训练集和验证集)的影响,因为每一个样本都单独的做过验证集,同时,其用了N-1个样本训练模型,几乎用到了所有样本信息。
LOOCV优点:计算量过大。
1<K<N 时,K选取实际上是偏差(bias)和方差(variance)的一个折中(trade off)。K越大,每次投入的训练样本越多,模型的Bias越小。但K越大,也意味着每次选取的训练样本的相关性越大(或者重叠性越大)(考虑最极端的例子,当K=N,也就是在LOOCV里,每次的训练样本几乎是一样的),而这种大相关性会导致最终的test error具有更大的Variance;K越小,偏差越大,方差越小。
一般来说,根据经验我们一般选择K=5或10。

下图展示了LOOCV和10折交叉验证的对比结果:
蓝色线表示真实的测试误差曲线;
黑色线表示LOOCV方法测试误差曲线;
橙色线表示10折交叉验证测试误差曲线;
可见LOOCV和10折交叉验证结果是很相似的,但是相比LOOCV,10折交叉验证的计算成本却小了很多

1.需要注意的是,交叉验证只是对训练集的进一步有效利用,最终还是要通过未使用过的数据(单独划分出测试集)来检验它的泛化能力;
2.我们首先要在样本集上留出一直不变的测试集,然后将剩余部分作为大测试集,然后在该的测试集上做K折交叉验证;
3.当训练集样本只有几十、几百或几千时,最好用交叉验证来保证利用尽量多的样本信息;
4.其他交叉验证方法:多次K折交叉验证(Repeated K-Fold Cross Validation)、蒙特卡洛交叉验证(Monte Carlo Cross Validation)

https://zhuanlan.hu.com/p/257808534
https://zhuanlan.hu.com/p/32627500
https://blog.csdn.net/yawei_liu1688/article/details/79138202
https://blog.csdn.net/qq_39751437/article/details/85071395
https://zhuanlan.hu.com/p/24825503?refer=rdatamining
https://www.cnblogs.com/wangkundentisy/p/8968316.html
https://blog.csdn.net/sysstc/article/details/103567520?utm_medium=distribute.pc_relevant.none-task-blog-2 default js_landingword~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3
https://tanxg.blog.csdn.net/article/details/109280753?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2 default BlogCommendFromBai Rate-6.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2 default BlogCommendFromBai Rate-6.pc_relevant_default&utm_relevant_index=11

㈧ 交叉验证

        交叉验证是在机器学习建立模型和验证模型参数时常用的办法。交叉验证就是重复使用数据,把得到的样本数据进行切分,组合为不同的训练集和测试集,用训练集来训练模型,用测试集来评估模型预测的好坏。在此基础上可以得到多组不同的训练和测试集,某次训练集中的某样本在下次可能成为测试集中的样本,即所谓“交叉”。
        交叉验证用在数据不是很充足的时候。比如,在日常项目中,对于普通适中问题,如果数据样本量小于一万条,我们就会采用交叉验证来训练优化选择模型。如果样本大于一万条的话,一般随机的把数据分成三份,一份为训练集(Training Set),一份为验证集(Validation Set),最后一份为测试集(Test Set)。用训练集来训练模型,用验证集来评估模型预测的好坏和选择模型及其对应的参数。把最终得到的模型再用于测试集,最终决定使用哪个模型以及对应参数。
         根据切分的方法不同,交叉验证分为下面三种:
        第一种,简单交叉验证。首先,随机的将样本数据分为两部分(比如:70%的训练集,30%的测试集),然后用训练集来训练模型,在测试集上验证模型及参数。接着,我们再把样本打乱,重新选择训练集合测试集,继续训练数据和检验模型。最后我们选择损失函数评估最优的模型和参数。
        第二种是S折交叉验证(S-Folder Cross Validation)。和第一种方法不同,S折交叉验证会把样本数据随机的分成S份,每次随机的选择S-1份作为训练集,剩下的1份做测试集。当这一轮完成后,重新随机选择S-1份来训练数据。若干轮(小于S)之后,选择损失函数评估最优的模型和参数。
        留一交叉验证(Leave-one-out Cross Validation),它是第二种情况的特例,此时S等于样本数N,这样对于N个样本,每次选择N-1个样本来训练数据,留一个样本来验证模型预测的好坏。此方法主要用于样本量非常少的情况,比如对于普通适中问题,N小于50时,一般采用留一交叉验证。
        通过反复的交叉验证,用损失函数来度量得到的模型的好坏,最终可以得到一个较好的模型。
        此外还有一种比较特殊的交叉验证方式,也是用于样本量少的时候,叫做自助法啊(bootstrapping)。比如有m个样本(m较小),每次在这m个样本中随机采集一个样本,放入训练集,采样完后把样本放回。这样重复采集n次,我们得到m个样本组成的训练集。当然,这m个样本中很有可能有重复的样本数据。同时,用没有被采样到的样本做测试集,这样接着进行交叉验证。由于我们的训练集有重复数据,这会改变数据的分布,因而训练结果会有估计偏差,因此,此种方法不是很常用,除非数据量很少,比如小于20个。

        将拿到的数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果,又称5折交叉验证。

㈨ Pytorch_循环神经网络RNN

RNN是Recurrent Neural Networks的缩写,即循环神经网络,它常用于解决序列问题。RNN有记忆功能,除了当前输入,还把上下文环境作为预测的依据。它常用于语音识别、翻译等场景之中。

RNN是序列模型的基础,尽管能够直接调用现成的RNN算法,但后续的复杂网络很多构建在RNN网络的基础之上,如Attention方法需要使用RNN的隐藏层数据。RNN的原理并不复杂,但由于其中包括循环,很难用语言或者画图来描述,最好的方法是自己手动编写一个RNN网络。本篇将介绍RNN网络的原理及具体实现。

在学习循环神经网络之前,先看看什么是序列。序列sequence简称seq,是有先后顺序的一组数据。自然语言处理是最为典型的序列问题,比如将一句话翻译成另一句话时,其中某个词汇的含义不仅取决于它本身,还与它前后的多个单词相关。类似的,如果想预测电影的情节发展,不仅与当前的画面有关,还与当前的一系列前情有关。在使用序列模型预测的过程中,输入是序列,而输出是一个或多个预测值。

在使用深度学习模型解决序列问题时, 最容易混淆的是,序列与序列中的元素 。在不同的场景中,定义序列的方式不同,当分析单词的感情色彩时,一个单词是一个序列seq;当分析句子感情色彩时,一个句子是一个seq,其中的每个单词是序列中的元素;当分析文章感情色彩时,一篇文章是一个seq。简单地说,seq是最终使用模型时的输入数据,由一系列元素组成。

当分析句子的感情色彩时,以句为seq,而句中包含的各个单词的含义,以及单词间的关系是具体分析的对象,此时,单词是序列中的元素,每一个单词又可有多维特征。从单词中提取特征的方法将在后面的自然语言处理中介绍。

RNN有很多种形式,单个输入单个输入;多个输入多个输出,单个输入多个输出等等。

举个最简单的例子:用模型预测一个四字短语的感情色彩,它的输入为四个元素X={x1,x2,x3,x4},它的输出为单个值Y={y1}。字的排列顺序至关重要,比如“从好变坏”和“从坏变好”,表达的意思完全相反。之所以输入输出的个数不需要一一对应,是因为中间的隐藏层,变向存储中间信息。

如果把模型设想成黑盒,如下图所示:

如果模型使用全连接网络,在每次迭代时,模型将计算各个元素x1,x2...中各个特征f1,f2...代入网络,求它们对结果y的贡献度。

RNN网络则要复杂一些,在模型内部,它不是将序列中所有元素的特征一次性输入模型,而是每一次将序列中单个元素的特征输入模型,下图描述了RNN的数据处理过程,左图为分步展示,右图将所有时序步骤抽象成单一模块。

第一步:将第一个元素x1的特征f1,f2...输入模型,模型根据输入计算出隐藏层h。

第二步:将第二个元素x2的特征输入模型,模型根据输入和上一步产生的h再计算隐藏层h,其它元素以此类推。

第三步:将最后一个元素xn的特征输入模型,模型根据输入和上一步产生的h计算隐藏层h和预测值y。

隐藏层h可视为将序列中前面元素的特征和位置通过编码向前传递,从而对输出y发生作用,隐藏层的大小决定了模型携带信息量的多少。隐藏层也可以作为模型的输入从外部传入,以及作为模型的输出返回给外部调用。

本例仍使用上篇中的航空乘客序列数据,分别用两种方法实现RNN:自己编写程序实现RNN模型,以及调用Pytorch提供的RNN模型。前一种方法主要用于剖析原理,后一种用于展示常用的调用方法。

首先导入头文件,读取乘客数据,做归一化处理,并将数据切分为测试集和训练集,与之前不同的是加入了create_dataset函数,用于生成序列数据,序列的输入部分,每个元素中包括两个特征:前一个月的乘客量prev和月份值mon,这里的月份值并不是关键特征,主要用于在例程中展示如何使用多个特征。

第一步:实现模型类,此例中的RNN模型除了全连接层,还生成了一个隐藏层,并在下一次前向传播时将隐藏层输出的数据与输入数据组合后再代入模型运算。

第二步,训练模型,使用全部数据训练500次,在每次训练时,内部for循环将序列中的每个元素代入模型,并将模型输出的隐藏层和下一个元素一起送入下一次迭代。

第三步:预测和作图,预测的过程与训练一样,把全部数据拆分成元素代入模型,并将每一次预测结果存储在数组中,并作图显示。

需要注意的是,在训练和预测过程中,每一次开始输入新序列之前,都重置了隐藏层,这是由于隐藏层的内容只与当前序列相关,序列之间并无连续性。

程序输出结果如下图所示:

经过500次迭代,使用RNN的效果明显优于上一篇中使用全连接网络的拟合效果,还可以通过调整超参数以及选择不同特征,进一步优化。

使用Pytorch提供的RNN模型,torch.nn.RNN类可直接使用,是循环网络最常用的解决方案。RNN,LSTM,GRU等循环网络都实现在同一源码文件torch/nn/moles/rnn.py中。

第一步:创建模型,模型包含两部分,第一部分是Pytorch提供的RNN层,第二部分是一个全连接层,用于将RNN的输出转换成输出目标的维度。

Pytorch的RNN前向传播允许将隐藏层数据h作为参数传入模型,并将模型产生的h和y作为函数返回值。形如: pred, h_state = model(x, h_state)

什么情况下需要接收隐藏层的状态h_state,并转入下一次迭代呢?当处理单个seq时,h在内部前向传递;当序列与序列之间也存在前后依赖关系时,可以接收h_state并传入下一步迭代。另外,当模型比较复杂如LSTM模型包含众多参数,传递会增加模型的复杂度,使训练过程变慢。本例未将隐藏层转到模型外部,这是由于模型内部实现了对整个序列的处理,而非处理单个元素,而每次代入的序列之间又没有连续性。

第二步:训练模型,与上例中把序列中的元素逐个代入模型不同,本例一次性把整个序列代入了模型,因此,只有一个for循环。

Pythorch支持批量处理,前向传递时输入数据格式是[seq_len, batch_size, input_dim),本例中输入数据的维度是[100, 1, 2],input_dim是每个元素的特征数,batch_size是训练的序列个数,seq_len是序列的长度,这里使用70%作为训练数据,seq_len为100。如果数据维度的顺序与要求不一致,一般使用transpose转换。

第三步:预测和作图,将全部数据作为序列代入模型,并用预测值作图。

程序输出结果如下图所示:

可以看到,经过500次迭代,在前100个元素的训练集上拟合得很好,但在测试集效果较差,可能存在过拟合。

㈩ 什么是交叉检验

交叉验证(Cross-validation)主要用于建模应用中,例如PCR 、PLS 回归建模中。在给定的建模样本中,拿出大部分样本进行建模型,留小部分样本用刚建立的模型进行预报,并求这小部分样本的预报误差,记录它们的平方加和。这个过程一直进行,直到所有的样本都被预报了一次而且仅被预报一次。把每个样本的预报误差平方加和,称为PRESS(predicted Error Sum of Squares)
用交叉验证的目的是为了得到可靠稳定的模型。在建立PCR 或PLS 模型时,一个很重要的因素是取多少个主成分的问题。用cross validation 校验每个主成分下的PRESS值,选择PRESS值小的主成分数。或PRESS值不再变小时的主成分数。
常用的精度测试方法主要是交叉验证,例如10折交叉验证(10-fold cross validation),将数据集分成十份,轮流将其中9份做训练1份做测试,10次的结果的均值作为对算法精度的估计,一般还需要进行多次10折交叉验证求均值,例如:10次10折交叉验证,以求更精确一点