在实际应用中,一般会选择将数据集划分为训练集(training set)、验证集(validation set)和测试集(testing set)。其中,训练集用于训练模型,验证集用于调参、算法选择等,而测试集则在最后用于模型的整体性能评估。
1. 留出法 (Hold-out)
将数据集D划分为2个互斥子集,其中一个作为训练集S,另一个作为测试集T,即有:
D = S ∪ T, S ∩ T = ∅
用训练集S训练模型,再用测试集T评估误差,作为泛化误差估计。
特点:单次使用留出法得到的估计结果往往不够稳定可靠,故如果要使用留出法,一般采用若干次随机划分,重复进行实验评估后,取平均值作为最终评估结果。
比例:S = 2/3 ~ 4/5 D,T = 1/3 ~ 1/5 D
2. 交叉验证法 (Cross validation)
将数据集D划分为k个大小相似的互斥子集,即:
D = D1 ∪ D2 ∪ D3 ∪ ...... ∪ Dk
有:Di ∩ Dj=∅,每个子集Dr都尽可能保持数据分布的一致性,即:从D中通过分层采样得到,每次使用k-1个子集的并集作为训练集S,余下的一个作为测试集T,最终返回的是k个测试结果的均值。因其稳定性与保真性取决于k值,故又称为k折交叉验证 (K-fold cross validation),其中k最常用取值为10,又称10折交叉验证。
当k等于样本数量时,得到k折交叉验证的特例:留一法 (Leave-One-Out, LOO)。
特点:当数据集D中数据量较大时,训练m个模型的开销过大。
1 #!/usr/bin/env python3 2 3 # 使用10折交叉验证来划分Iris数据集的训练集、测试集 4 from sklearn.cross_validation import KFold 5 6 # 参数n_splits决定了k值,即折数 7 kf = KFold(len(iris.y), n_splits = 10, shuffle = True) 8 9 for train_index, test_index in kf: 10 x_train, x_test = iris.x[train_index], iris.x[test_index] 11 y_train, y_test = iris.y[train_index], iris.y[test_index] 12 13 x_train.shape, x_test.shape, y_train.shape, y_test.shape
输出结果: ((135, 4), (15, 4), (135, ), (15, ))
或者,其实自己用的更多的是下面一种:
1 #! /usr/bin/env python3 2 3 from sklearn.cross_validation import train_test_split 4 import numpy as np 5 6 filename = '文件路径' 7 8 # 参数delimiter是数据集中属性间的分隔符 9 data_set = np.loadtxt(filename, delimiter = ';') 10 11 # 假定该数据集中的属性数目为11,标记label位于数据集的最后一列 12 x = data_set[:, 0:11] 13 y = data_set[: 11] 14 15 # 划分比例为8:2 16 x_train, y_train, x_test, y_test = train_test_split(x, y, test_size = 0.2) 17 18 x_train.shape, y_train.shape, x_test.shape, y_test.shape
输出结果: ((16497, 11), (16497,), (4125, 11), (4125,))
3. 自助法 (Bootstrapping)
以自助采样为基础 (Boostrap sampling),给定包含m个样本的数据集D,对D进行采样,产生数据集D':每次随机从D中挑选一个样本,拷贝后放入D',再讲该样本放回D中,使得该样本在下次采样时仍然有可能被采集到。重复该过程m次,即可得到包含m个样本的数据集D',这就是自助采样的结果。显然,部分样本会多次出现,而另一部分则不会,在m次采样中,始终不被采集到的概率为 (1-1/m)m,即:
故D中有约36.8%的样本不会出现在D'中,所以将D'用作训练集S,D\D'用作测试集T,这样仍有约36.8%的数据样本不在训练集内,可以用作测试集进行测试。
特点:适用于数据集D中数据量较小时,难以划分训练集、测试集时使用。