常见交叉验证方法汇总


交叉验证(Cross Validation,简称CV)是机器学习模型的重要环节之一,它可以用于检验机器学习模型对问题解释的能力。

通常我们将数据集分为两部分,即训练集和测试集;训练集数据是用于模型训练和开发,测试集是用于验证模型的性能。交叉验证是重复多次选取训练集,并将全部数据遍历验证的过程。

五重交叉验证的机器学习模型如何应用于测试集 多重交叉验证_python


交叉验证方法对于机器学习至关重要,通过选择合适的评判指标,我们就可以评价模型的学习能力。常见的交叉验证方法包括:

1)KFold

在这种 K 折交叉验证技术中,整个数据集被划分为 K 个相等大小的部分;每个分区称为一个“折叠”。因此,因为我们有 K 个部分,所以我们称之为 K 折叠。其中1折用作验证集,其余 K-1 折用作训练集。该技术重复 K 次,直到每个折叠用作验证集,其余折叠用作训练集。模型的最终精度是通过取 k-models 验证数据的平均精度来计算的。这种方法是最常见的交叉验证方法。

五重交叉验证的机器学习模型如何应用于测试集 多重交叉验证_python_02


上图就是4折交叉验证,红色代表验证集,蓝色代表训练集;class代表数据的label有三类,group代表不同数据属于第几组。

特点:整个数据集既用作训练集又可以用作验证集;但是不适用于数据集不均衡和时间序列问题

>>> import numpy as np
>>> from sklearn.model_selection import KFold

>>> X = ["a", "b", "c", "d"]
>>> kf = KFold(n_splits=2)
>>> for train, test in kf.split(X):
...     print("%s %s" % (train, test))
[2 3] [0 1]
[0 1] [2 3]

2)Stratified KFold

KFold方法不适用于不平衡的数据集,所以Stratified KFold交叉验证来解决这个问题。在分层k倍交叉验证中,数据集被划分为k个组或折叠,以使验证数据具有相等数量的目标类标签实例。 这样可以确保在验证或训练数据中不会出现一个特定的类,尤其是在数据集不平衡的时候。
特点:可以解决数据不均衡的问题,不适用于时间序列问题

>>> from sklearn.model_selection import StratifiedKFold, KFold
>>> import numpy as np
>>> X, y = np.ones((50, 1)), np.hstack(([0] * 45, [1] * 5))
>>> skf = StratifiedKFold(n_splits=3)
>>> for train, test in skf.split(X, y):
...     print('train -  {}   |   test -  {}'.format(
...         np.bincount(y[train]), np.bincount(y[test])))
train -  [30  3]   |   test -  [15  2]
train -  [30  3]   |   test -  [15  2]
train -  [30  4]   |   test -  [15  1]

3)Group KFold

GroupKFold是KFold一个变体,目的在于将group严格分开,以减少过拟合现象。

五重交叉验证的机器学习模型如何应用于测试集 多重交叉验证_数据_03

特点:可以将数据的group完全分开,避免样本高度相似出现重复

>>> from sklearn.model_selection import GroupKFold

>>> X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
>>> y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
>>> groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]

>>> gkf = GroupKFold(n_splits=3)
>>> for train, test in gkf.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[0 1 2 3 4 5] [6 7 8 9]
[0 1 2 6 7 8 9] [3 4 5]
[3 4 5 6 7 8 9] [0 1 2]

##4)Stratified Group KFold

类似于Group KFold和KFold的关系,Stratified Group KFold是Group KFold专门处理分层问题而设计的。

五重交叉验证的机器学习模型如何应用于测试集 多重交叉验证_数据集_04

特点:可以将数据的group和标签的class完全分层划开,避免出现样本高度相似和标签分布不均的问题

>>> from sklearn.model_selection import StratifiedGroupKFold
>>> X = list(range(18))
>>> y = [1] * 6 + [0] * 12
>>> groups = [1, 2, 3, 3, 4, 4, 1, 1, 2, 2, 3, 4, 5, 5, 5, 6, 6, 6]
>>> sgkf = StratifiedGroupKFold(n_splits=3)
>>> for train, test in sgkf.split(X, y, groups=groups):
...     print("%s %s" % (train, test))
[ 0  2  3  4  5  6  7 10 11 15 16 17] [ 1  8  9 12 13 14]
[ 0  1  4  5  6  7  8  9 11 12 13 14] [ 2  3 10 15 16 17]
[ 1  2  3  8  9 10 12 13 14 15 16 17] [ 0  4  5  6  7 11]

5)Time Series Split

数据的顺序对于与时间序列相关的问题非常重要。 对于与时间相关的数据集,将数据随机拆分或k倍拆分为训练和验证可能不会产生良好的结果。对于时间序列数据集,根据时间将数据分为训练和验证,也称为前向链接方法或滚动交叉验证。

五重交叉验证的机器学习模型如何应用于测试集 多重交叉验证_sklearn_05

特点:专门设计用于解决时间序列问题的数据切分方法。

>>> from sklearn.model_selection import TimeSeriesSplit
>>> X = np.array([[1, 2], [3, 4], [1, 2], [3, 4], [1, 2], [3, 4]])
>>> y = np.array([1, 2, 3, 4, 5, 6])
>>> tscv = TimeSeriesSplit(n_splits=3)
>>> print(tscv)
TimeSeriesSplit(gap=0, max_train_size=None, n_splits=3, test_size=None)
>>> for train, test in tscv.split(X):
...     print("%s %s" % (train, test))
[0 1 2] [3]
[0 1 2 3] [4]
[0 1 2 3 4] [5]

实际数据分析时,交叉验证用的十分频繁。如果想快速检验模型的学习能力,可以仅训练一次模型;如果想更全面的检验模型的学习能力,建议训练K次模型。另外,预测的时候可以把K次模型的结果进行平均,也能取得更好的预测效果。