一、简介
在用机器学习训练模型的时候,会将数据集D划分成训练集和测试集,因为如果在相同的数据上训练并测试无法评估模型的效果,常用的划分方法有K折交叉验证、p次k折交叉验证、留出法、留一法、留P法、随机分配、自助法等。另外,在训练模型的时候,经常需要进行调参,当我们有一堆参数的时候,也可以用类似的较差验证的方式依次使用不同的参数建模,最后选择最好的一个参数。在sklearn中要实现主要用sklearn.model_selection包的各种类,下面进行详细介绍。
二、数据集交叉验证方法
1、留出法
留出法的方法很简单,将数据集D分为两个部分,一个作为训练集另一个作为测试集,一般会选择70%的数据作为训练集。
对应的方法:
sklearn.model_selection.train_test_split(*arrays, **options)
- *arrays:数组,可以传入多个,例如同时传入x,y或者传入x,y,z。传入的数据类型为lists,、numpy arrays、scipy-sparse matrices、pandas dataframes。
- test_size:如果是float数据,表示测试集的占比;如果是None则默认取占比0.25;如果是int数据,则表示测试集样本个数。
- train_size:如果是float数据,表示训练集的占比;如果是None则默认取占比0.25;如果是int数据,则表示训练集样本个数。
- random_state:随机数种子。
- shuffle:是否清洗数据,若false,则不清洗。
- stratify:数据是否按Y的class分层的方式来划分,若Ture则是。例如Y的class=[‘a’,'b'],其中a占0.9、b占0.1,则划分训练集与测试集之后,训练集与测试集中a、b的占比不变。
方法return:
一个包含分裂后训练集、测试集的列表,列表形式为[x_train,x_test,y_train,y_test,....]。
代码示例:
from sklearn.model_selection import train_test_split import numpy as np x = np.arange(10) # 创建一维属性x y = np.arange(10) # 创建一维属性y x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2) # 划分测试集与训练集 print('x_train:', x_train) print('x_test:', x_test) print('y_train:', y_train) print('y_test:', y_test) ''' 结果: x_train: [2 0 1 7 5 9 4 8] x_test: [3 6] y_train: [2 0 1 7 5 9 4 8] y_test: [3 6] '''
2、K折交叉验证
将数据集分为k等份,每次训练时,将其中k-1份用作训练集,单独的那一份用作测试集,依次训练K次,可以选择训练效果较好的那份或者以平均模型优度作为模型优度。
对应的类:
sklearn.model_selection.KFold(n_splits=3, shuffle=False, random_state=None)
-
n_splits:几折,划分为几等分。
-
shuffle:在每次划分时,是否进行洗牌,不洗牌的话则按顺序划分。
-
若为Falses时,其效果等同于random_state等于整数,每次划分的结果相同
-
若为True时,每次划分的结果都不一样,表示经过洗牌,随机取样的
-
-
random_state:随机种子数
类的方法:
- get_n_splits(X=None, y=None, groups=None):获取参数n_splits的值,返回交叉验证的train-test的个数。
- split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器(即每一份样本在数据集D中的位置)。
代码示例:
from sklearn.model_selection import KFold import numpy as np x = np.arange(12) #创建一维属性x fold = KFold(3) #创建3折交叉验证 for train_index, test_index in fold.split(x): print('训练集索引:', train_index) print('测试集索引:', test_index) print('-------------------------------') ''' 结果:训练集索引: [ 4 5 6 7 8 9 10 11] 测试集索引: [0 1 2 3] ------------------------------- 训练集索引: [ 0 1 2 3 8 9 10 11] 测试集索引: [4 5 6 7] ------------------------------- 训练集索引: [0 1 2 3 4 5 6 7] 测试集索引: [ 8 9 10 11] ------------------------------- '''
3、p次K折交差验证
有时候,依次K折交叉验证不能够满足训练要求,可以进行p次,经典的例如10次10折交叉验证。
对应的类:
sklearn.model_selection.RepeatedKFold(n_splits=5,n_repeats=2,random_state =0)
- n_splits:几折,划分为几等分。
- n_repeats:重复的次数,即p次K折的p。
- random_state :随机数种子。
类的方法:
- get_n_splits(X=None, y=None, groups=None):获取参数n_splits的值,即返回交叉验证的train-test的个数。
- split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器(即每一份样本在数据集D中的位置)。
注意:
RepeatedKFold在划分的时候,重复p次,每次重复会进行1次k折划分,每次划分都是随机的,这个与KFold默认方式是不同的。
代码示例:
from sklearn.model_selection import RepeatedKFold import numpy as np x = np.arange(12) #创建一维属性x fold = RepeatedKFold(n_splits=3,n_repeats=2) #创建3折交叉验证 for train_index, test_index in fold.split(x): print('训练集索引:', train_index) print('测试集索引:', test_index) print('-------------------------------') '''结果:训练集索引: [ 1 2 3 4 5 8 10 11] 测试集索引: [0 6 7 9] ------------------------------- 训练集索引: [ 0 3 4 6 7 9 10 11] 测试集索引: [1 2 5 8] ------------------------------- 训练集索引: [0 1 2 5 6 7 8 9] 测试集索引: [ 3 4 10 11] ------------------------------- 训练集索引: [0 2 3 5 6 7 8 9] 测试集索引: [ 1 4 10 11] ------------------------------- 训练集索引: [ 1 4 6 7 8 9 10 11] 测试集索引: [0 2 3 5] ------------------------------- 训练集索引: [ 0 1 2 3 4 5 10 11] 测试集索引: [6 7 8 9] ------------------------------- '''
4、留一较差验证
留一法就是Kflod的特殊形式k=1,即每次取1个样本作为测试集,其余做训练集。
对应的类:
sklearn.model_selection.train_test_split()
类的方法:
- get_n_splits(X=None, y=None, groups=None):返回较差验证的train-test数据对的个数。
- split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器(即每一份样本在数据集D中的位置)。
代码示例:
from sklearn.model_selection import LeaveOneOut import numpy as np x = np.arange(4) # 创建一维属性x leaveoneout=LeaveOneOut() for train,test in leaveoneout.split(x) : # 划分测试集与训练集 print('x_train:', train) print('x_test:', test) print('------------------------------------------------------') ''' 结果: x_train: [1 2 3] x_test: [0] ------------------------------------------------------ x_train: [0 2 3] x_test: [1] ------------------------------------------------------ x_train: [0 1 3] x_test: [2] ------------------------------------------------------ x_train: [0 1 2] x_test: [3] ------------------------------------------------------ '''
5、留P交叉验证
从数据集D中选P个样本作为测试集,其余作为训练集,直到选出所有的可能的P个组合为止。当P=1的时候就是留一交叉验证。
对应的类:
sklearn.model_selection.LeavePOut(p)
- p:测试集的样本数。
类的方法:
- get_n_splits(X=None, y=None, groups=None):返回较差验证的train-test数据对的个数。
- split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器(即每一份样本在数据集D中的位置)。
代码示例:
from sklearn.model_selection import LeavePOut import numpy as np x = np.arange(4) # 创建一维属性x leavePout=LeavePOut(2) for train,test in leavePout.split(x) : # 划分测试集与训练集 print('x_train:', train) print('x_test:', test) print('------------------------------------------------------') ''' 结果: x_train: [2 3] x_test: [0 1] ------------------------------------------------------ x_train: [1 3] x_test: [0 2] ------------------------------------------------------ x_train: [1 2] x_test: [0 3] ------------------------------------------------------ x_train: [0 3] x_test: [1 2] ------------------------------------------------------ x_train: [0 2] x_test: [1 3] ------------------------------------------------------ x_train: [0 1] x_test: [2 3] ------------------------------------------------------ '''
6、随机交叉验证
从数据集D中随机选择样本划分训练集与测试集,可以根据需要选择需要重复几次,重复n次能获得n个train-test样本对。
对应的类:
sklearn.model_selection.ShuffleSplit(n_splits=10, test_size=None, train_size=None, random_state=None)
-
n_splits:几折,划分为几等分。
- test_size:如果是float数据,表示测试集的占比;如果是None则自动设置;如果是int数据,则表示测试集样本个数。
- train_size:如果是float数据,表示训练集的占比;如果是None则自动设置;如果是int数据,则表示训练集样本个数。
-
random_state:随机种子数
类的方法:
- get_n_splits(X=None, y=None, groups=None):返回较差验证的train-test数据对的个数。
- split(X, y=None, groups=None):将数据集划分成训练集和测试集,返回索引生成器(即每一份样本在数据集D中的位置)。
代码示例:
from sklearn.model_selection import ShuffleSplit import numpy as np x = np.arange(10) # 创建一维属性x SS=ShuffleSplit(3,test_size=0.2) for train,test in SS.split(x) : # 划分测试集与训练集 print('x_train:', train) print('x_test:', test) print('------------------------------------------------------') ''' 结果: x_train: [5 3 2 9 6 8 1 7] x_test: [4 0] ------------------------------------------------------ x_train: [9 1 5 8 0 3 7 4] x_test: [6 2] ------------------------------------------------------ x_train: [4 9 3 7 5 6 2 8] x_test: [1 0] ------------------------------------------------------ '''
7、其它特殊情况的数据划分方法
1:对于分类数据来说,它们的target可能分配是不均匀的,比如在医疗数据当中得癌症的人比不得癌症的人少很多,这个时候,使用的数据划分方法有 StratifiedKFold ,StratifiedShuffleSplit
2:对于分组数据来说,它的划分方法是不一样的,主要的方法有 GroupKFold,LeaveOneGroupOut,LeavePGroupOut,GroupShuffleSplit
3:对于时间关联的数据,方法有TimeSeriesSplit
三、模型评估交叉验证
对数据集可以进行交叉验证从而建立交叉验证模型,也可以对模型的评估利用交叉验证的方法。sklearn的一些评估方法同样可以用于交叉验证。
1、模型准确度评分交叉验证
对应的方法:
sklearn.model_selection.cross_val_score(estimator, X, y=None, cv=’warn’,......)
- estimator:sklearn的estimator类,即各种模型。
- cv:几折验证,默认是3。
方法return:
一个包含所有交叉验证的score的列表。
代码示例:
from sklearn import datasets from sklearn import svm from sklearn.model_selection import cross_val_score iris = datasets.load_iris() clf = svm.SVC(kernel='linear', C=1) scores = cross_val_score(clf, iris.data, iris.target, cv=5) print(scores) ''' 结果: [0.96666667 1. 0.96666667 0.96666667 1. ]
2、其他评估方法交叉验证
对应方法:
sklearn.model_selection.cross_validate(estimator, X, y=None, scoring=None, cv=’warn’,......)
- estimator:sklearn的estimator类,即各种模型。
- scoring:sklearn的评估方法,可以用字典或列表方式传入。
- cv:几折验证,默认是3。
方法return:
一个字典,字典中每个