0%

Scikit-learn Cross-validation

为了评价模型在新数据上的泛化性能,我们一般除了训练集外,还需要测试集;有时为了评价不同参数下的模型性能,不能直接在测试集进行测评,而是在两者之间再加个验证集来先进行评估;如果比较成功的话,再在测试集上进行最后的评估

还有个更加好的选择:交叉验证(cross-validation,一种评估泛化性能的统计学方法),其优势在于:

  • 避免由于train_test_split造成的不恰当的随机划分,而交叉验证则可以将每个样本会都在测试集出现一次
  • 通过多次划分,提供我们模型对于训练集的敏感性信息(最坏/最好情况下的表现)
  • 数据的利用率更高(根据需求增加训练集的样本量)

主要调用sklearn.model_selection中的各种方法。。。

以最常见的K折交叉验证为例(输出平均得分和95%置信区间):

import numpy as np
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("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
>>Accuracy: 0.98 (+/- 0.03)

有时也可以使用cross_validate函数来指定多个评价指标

from sklearn.model_selection import cross_validate
scoring = ['precision_macro', 'recall_macro']
scores = cross_validate(clf, iris.data, iris.target, scoring=scoring, cv=5)
sorted(scores.keys())
print(scores)

如果想返回交叉验证的预测结果,则可以用cross_val_predict函数

其他交叉验证策略有:

分层K折交叉验证

有时,数据是不均衡的,那么常规的分类会导致分类的偏差,这时可以考虑用stratified(分层)的KFold

skf = StratifiedKFold(n_splits=3)

默认情况下,对于分类问题,scikit-learn使用分层K折交叉验证;对于回归问题,则使用标准K折交叉验证

如果想在分类问题使用标准K折交叉验证,则使用KFold分类器,如果想打乱数据则添加shuffle=True参数(别忘记设置random_state)

# 如2折,打乱
kf = KFold(n_splits=2, shuffle=True, random_state=12345)

有时,K折交叉验证不能够满足训练要求,则希望重复进行多次,这时可以考虑用RepeatedKFold类。经典的例如10次10折交叉验证

rkf = RepeatedKFold(n_splits=2, n_repeats=2, random_state=12345)

留一法交叉验证(leave-one-out)

从字面上即可理解,使用LeaveOneOut

loo = LeaveOneOut()
scores = cross_val_score(clf, iris.data, iris.target, cv=loo)

如果不想留一,而想留P个,则可以用LeavePOut

lpo = LeavePOut(p=2)

打乱划分交叉验证(shuffle-split)

使用ShuffkeSplit类可指定训练集和测试集各自数据集大小(即可不使用全部数据,比如在大型数据上)

ss = ShuffleSplit(n_splits=5, train_size=0.5, test_size=0.5, random_state=0)

如想增加分层形式,则用StratifiedSuffleSplit类,其相当于stratified和shuffle-split相结合

sss = StratifiedShuffleSplit(n_splits=5, train_size=0.5, test_size=0.5, random_state=0)

分组交叉验证

即将数据集中的某一类同组数据进行分组处理,其相当于增加一个分组向量,然后搭配以上的各个分类器使用,如(蛮好记的):

  • GroupKFold
  • LeaveOneGroupOut
  • LeavePGroupsOut
  • GroupShuffleSplit

时间序列分割

对于时序数据,常规的分割是在假设样本是独立的且分布相同的基础上的,因此需要使用TimeSeriesSplit类才行

tscv = TimeSeriesSplit(n_splits=5)

参考资料:
Cross-validation: evaluating estimator performance
《Python机器学习基础教程》

本文出自于http://www.bioinfo-scrounger.com转载请注明出处