交叉验证总结

在机器学习中,交叉验证是模型选择的常用方法。如果给定的样本数据充足,进行模型选择的一种简单方法是随机的降数据集分成:训练集(training set)、验证集(validation set)、测试集(test set)。训练集用来训练模型,验证集用来选择模型,测试集用于最终对学习方法的评估。在学习到的不同复杂度的模型中,选择对验证集有最小预测误差的模型。由于验证集有足够多的数据,用它对模型进行选择也是有效的。

但是在实际应用中数据时不充足的。为了选择好的模型,可以采用交叉验证方法。交叉验证的基本思想:重复的使用数据;把给定的数据进行切分,将切分的数据集组合为训练集与测试集,在此基础上反复的进行训练、测试及模型选择。

1 交叉验证的原理

简单交叉验证

方法:首先随机的将已给数据分为两部分,一部分作为训练集,另一部分作为测试集(例如70%作为训练,30%作为测试),然后用训练集在各种条件下(不同的参数个数)训练模型,从而得到不同的模型;在训练集上评价各个模型的测试误差,选出测试误差最小的模型。

S折交叉验证
方法:首先随机的将已给数据切分为S个互不相交的大小相同的自己;然后利用S-1个自己的数据训练模型,利用余下的子集测试模型;将这一过程对可能的S种选择重复进行;最后选出S次评测中平均测试误差最小的模型。

留一交叉验证

\(S\)折交叉验证的特殊情形是\(S=N\),称为留一交叉验证(leave-one-out cross validation),往往在数据缺乏的情况下使用。这里,\(N\)是给定数据集的容量。

2 交叉验证代码实现

2.1 简单交叉验证

简单交叉验证就是对训练集进行train_test_split,划分成train 和test 两部分,其中train用来训练模型,test用来评估模型,模型通过fit方法从t训练数据集中学习,然后调用score方法在测试集上进行评估。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = train_test_split(cancer.data,cancer.target,random_state=0)
logreg = LogisticRegression().fit(X_train,y_train)
print("Test set score:{:.2f}".format(logreg.score(X_test,y_test)))  #Test set score:0.96

这种方式数据集只拆分一次,默认比例是3:1,即75%的样本数据被作为训练集,25%的样本被作为测试集,这种默认带有偶然性,训练的模型不稳定。

2.2 S折交叉验证

交叉验证就是对数据集进行多次train_test_split划分,每次划分,在不同数据集上进行训练、测试和评估。如5折交叉验证,就是对原数据集进行5次划分,然后每次划分进行一次训练、评估,得到5次划分的评估结果,最后对5次评估结果取平均。

from sklearn.model_selection import cross_val_score

logreg = LogisticRegression()
scores = cross_val_score(logreg,cancer.data,cancer.target)  #默认是3折交叉验证
print("Cross validation scores:{}".format(scores))      #Cross validation scores:[ 0.93684211  0.96842105  0.94179894]
print("Mean cross validation score:{:2f}".format(scores.mean()))    #Mean cross validation score:0.949021

交叉验证每次拆分是对数据进行均分,如果数据集是按类别存放的,那么划分时会出现每一折全是同一类数据,这样训练得到的模型泛化能力极差。

2.3 分层交叉验证

为了解决S折交叉验证存在的问题,分层交叉验证的思想是在每一折中都保持着原始数据中各个类别的比例关系,比如说:原始数据有3类,比例为1:2:1,采用3折分层交叉验证,那么划分的3折中,每一折中的数据类别保持着1:2:1的比例,这样的验证结果更加可信。

from sklearn.datasets import load_iris
from sklearn.model_selection import StratifiedKFold,cross_val_score
from sklearn.linear_model import LogisticRegression

iris = load_iris()
#print('Iris labels:\n{}'.format(iris.target))
logreg = LogisticRegression()
strKFold = StratifiedKFold(n_splits=3,shuffle=False,random_state=0)
scores = cross_val_score(logreg,iris.data,iris.target,cv=strKFold)
print("straitified cross validation scores:{}".format(scores))  #straitified cross validation scores:[ 0.96078431  0.92156863  0.95833333]
print("Mean score of straitified cross validation:{:.2f}".format(scores.mean()))    #Mean score of straitified cross validation:0.95

2.4 留一法

留一法是一种特殊的交叉验证方式。如果样本容量为n,则k=n,进行n折交叉验证,每次留下一个样本进行验证。主要针对小样本数据。

from sklearn.datasets import load_iris
from sklearn.model_selection import LeaveOneOut,cross_val_score
from sklearn.linear_model import LogisticRegression

iris = load_iris()
#print('Iris labels:\n{}'.format(iris.target))
logreg = LogisticRegression()
loout = LeaveOneOut()
scores = cross_val_score(logreg,iris.data,iris.target,cv=loout)
#print("leave-one-out cross validation scores:{}".format(scores))
print("Mean score of leave-one-out cross validation:{:.2f}".format(scores.mean()))  #Mean score of leave-one-out cross validation:0.95

参考:统计学习方法 几种交叉验证比较

posted @ 2019-09-24 22:03  Christine_7  阅读(2048)  评论(1编辑  收藏  举报