【机器学习】交叉验证(cross-validation)

1、什么是交叉验证 
交叉验证(Cross validation),交叉验证用于防止模型过于复杂而引起的过拟合。有时亦称循环估计, 是一种统计学上将数据样本切割成较小子集的实用方法。于是可以先在一个子集上做分析, 而其它子集则用来做后续对此分析的确认及验证。 一开始的子集被称为训练集。而其它的子集则被称为验证集或测试集。交叉验证是一种评估统计分析、机器学习算法对独立于训练数据的数据集的泛化能力(generalize)。

交叉验证一般要尽量满足: 
1)训练集的比例要足够多,一般大于一半 
2)训练集和测试集要均匀抽样

2、交叉验证的几大方法

a、留出法 (holdout cross validation)

在机器学习任务中,拿到数据后,我们首先会将原始数据集分为三部分:训练集、验证集和测试集。 
训练集用于训练模型,验证集用于模型的参数选择配置,测试集对于模型来说是未知数据,用于评估模型的泛化能力。对于留出法,这个方法操作简单,只需随机把原始数据分为三组即可;一般如果只做一次分割,它对训练集、验证集和测试集的样本数比例,还有分割后数据的分布是否和原始数据集的分布相同等因素比较敏感,不同的划分会得到不同的最优模型,而且分成三个集合后,用于训练的数据更少了。一般留出法的验证集和测试集等同,以下实例说明:

#导入函数包
import numpy as np
#导入留出法的函数:train_test_split
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svmwa
#导入数据集 
iris = datasets.load_iris()
iris.data.shape, iris.target.shape
#根据留出法将数据集分为训练(60%)、测试集(40%)
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target,test_size=0.4, random_state=0) #test_size=0.4就是测试集的比例
1
2
3
4
5
6
7
8
9
10
11
b、k 折交叉验证(k-fold cross validation)

k个子集,每个子集均做一次测试集,其余的作为训练集。交叉验证重复k次,每次选择一个子集作为测试集,并将k次的平均交叉验证识别正确率作为结果。 
优点:所有的样本都被作为了训练集和测试集,每个样本都被验证一次。10-folder通常被使用。k 折交叉验证通过对 k 个不同分组训练的结果进行平均来减少方差,因此模型的性能对数据的划分就不那么敏感。

PS:之所以选择将数据集分为10份,是因为通过利用大量数据集、使用不同学习技术进行的大量试验,表明10折是获得最好误差估计的恰当选择,而且也有一些理论根据可以证明这一点。但这并非最终诊断,争议仍然存在。而且似乎5折或者20折与10折所得出的结果也相差无几。

具体步骤如下: 
第一步,不重复抽样将原始数据随机分为 k 份。 
第二步,每一次挑选其中 1 份作为测试集,剩余 k-1 份作为训练集用于模型训练。 
第三步,重复第二步 k 次,这样每个子集都有一次机会作为测试集,其余机会作为训练集。 
在每个训练集上训练后得到一个模型,用这个模型在相应的测试集上测试,计算并保存模型的评估指标; 
第四步,计算 k 组测试结果的平均值作为模型精度的估计,并作为当前 k 折交叉验证下模型的性能指标。

k 一般取 10, 数据量小的时候,k 可以设大一点,这样训练集占整体比例就比较大,不过同时训练的模型个数也增多。 数据量大的时候,k 可以设小一点。

#最简单的方法是直接调用 cross_val_score
#导入函数包
import numpy as np
#导入留出法的函数:train_test_split
from sklearn.model_selection import train_test_split
from sklearn import datasets
from sklearn import svm
from sklearn.model_selection import cross_val_score
clf = svm.SVC(kernel='linear', C=1)
iris = datasets.load_iris()
#用 5 折交叉验证,设定参数 cv = 5,另外cross_val_score(分类器,X,y,交叉验证次数)
scores = cross_val_score(clf, iris.data, iris.target, cv=5)
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
1
2
3
4
5
6
7
8
9
10
11
12
13
亦可以通过KFold来划分数据

import numpy as np
#导入KFold
from sklearn.model_selection import KFold
X = ["a", "b", "c", "d"]
#生成KFold数据划分器
kf = KFold(n_splits=2)
for train, test in kf.split(X):
    #获取训练和测试数据
    print("%s %s" % (train, test))
1
2
3
4
5
6
7
8
9
但是上述KFold方法得到分开的数据后,还需要进一步通过分类器进行测试评估分数才行,因此没有直接调用cross_val_score直接。

c、留一法(Leave one out cross validation)

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

同样的数据 X,我们看 LeaveOneOut 后是什么样子, 那就是把它分成 4 折, 结果中最后一个集合是测试集,只有一个元素,前面的是训练集, 每一行为 1 折:

from sklearn.model_selection import LeaveOneOut
X = [1, 2, 3, 4]
loo = LeaveOneOut()
for train, test in loo.split(X):
    print("%s %s" % (train, test))
--------------------- 

https://blog.csdn.net/brucewong0516/article/details/78731076 

猜你喜欢

转载自blog.csdn.net/weixin_38208741/article/details/84205273