一、留出法
1. 概念
- 直接将数据集D划分为两个互斥的集合,其中一个集合作为训练集S,另一个作为测试集T
- 即 D = S ∪ T, S ∩ T = ∅
- 在S上训练出模型后,用T来评估其测试误差,作为对泛化误差的估计
- 泛化能力:训练好的模型对于未知数据和未知场景下的表现能力;
- 泛化误差:模型在未知数据上的误差,一般可以使用测试误差来近似泛化误差;
2. 代码实现
from sklearn.model_selection import train_test_split
# 使用train_test_split划分训练集和测试集
train_X , test_X, train_Y ,test_Y = train_test_split(X, Y, test_size=0.2,random_state=0)
3. 留一法
- 在留出法中,有一个特例,叫: 留一法(Leave-One-Out,简称LOO),即每次抽取一个样本做为测试集。
- 代码实现
from sklearn.model_selection import LeaveOneOut data = [1, 2, 3, 4] loo = LeaveOneOut() for train, test in loo.split(data): print("%s %s" % (train, test)) # 结果 [1 2 3] [0] [0 2 3] [1] [0 1 3] [2] [0 1 2] [3]
- 优缺点
- 优点:留一法的评估结果往往被认为比较准确
- 缺点:在数据集比较大时,训练m个模型的计算开销可能是难以忍受的
二、交叉验证法
1. 概念
- 先将数据集D划分为k个大小相似的互斥子集
- 即 D = D1 ∪ D2 ∪ D3 …… ∪ Dk , Di ∩ Dj = ∅ (i!=j)
- 每个子集Di都尽可能保持数据分布的一致性,即从D中通过分层抽样得到。
- 然后,每次用k-1个子集的并集作为训练集,余下的那个子集作为测试集;
- 这样就可获得k组训练/测试集,从而可进行k次训练和测试,最终返回的是这k个测试结果的均值。
2. API
- KFold
- 随机采样,不能保证各样本比例一致;
- StratifiedKFold
- 分层采样,确保训练集,测试集中,各类别样本的比例是和原始数据集中的一致。
3. 代码
import numpy as np
from sklearn.model_selection import KFold,StratifiedKFold
X = np.array([[1,2,3,4], [11,12,13,14], [21,22,23,24], [31,32,33,34], [41,42,43,44], [51,52,53,54], [61,62,63,64], [71,72,73,74]])
y = np.array([1,1,0,0,1,1,0,0])
folder = KFold(n_splits = 4, random_state=0, shuffle = False)
sfolder = StratifiedKFold(n_splits = 4, random_state = 0, shuffle = False)
for train, test in folder.split(X, y):
print('train:%s | test:%s' %(train, test))
print("")
for train, test in sfolder.split(X, y):
print('train:%s | test:%s'%(train, test))
print("")
三、自助法
1. 概念
2. 优缺点
- 优点:
- 自助法在数据集较小、难以有效划分训练/测试集时很有用;
- 此外,自助法能从初始数据集中产生多个不同的训练集,这对集成学习等方法有很大的好处。
- 缺点:
- 自助法产生的数据集改变了初始数据集的分布,这会引入估计偏差。因此,在初始数据量足够时,留出法和交叉验证法更常用一些。
四、总结
- 当我们数据量足够时,选择留出法简单省时,在牺牲很小的准确度的情况下,换取计算的简便;
- 当我们的数据量较小时,我们应该选择交叉验证法,因为此时划分样本集将会使训练数据过少;
- 当我们的数据量特别少的时候,我们可以考虑留一法。