sklearn中的交叉验证的实现(Cross-Validation)


Posted in Python onFebruary 22, 2021

sklearn是利用python进行机器学习中一个非常全面和好用的第三方库,用过的都说好。今天主要记录一下sklearn中关于交叉验证的各种用法,主要是对sklearn官方文档 Cross-validation: evaluating estimator performance进行讲解,英文水平好的建议读官方文档,里面的知识点很详细。

先导入需要的库及数据集

In [1]: import numpy as np

In [2]: from sklearn.model_selection import train_test_split

In [3]: from sklearn.datasets import load_iris

In [4]: from sklearn import svm

In [5]: iris = load_iris()

In [6]: iris.data.shape, iris.target.shape
Out[6]: ((150, 4), (150,))

1.train_test_split

对数据集进行快速打乱(分为训练集和测试集)

这里相当于对数据集进行了shuffle后按照给定的test_size 进行数据集划分。

In [7]: X_train, X_test, y_train, y_test = train_test_split(
  ...:     iris.data, iris.target, test_size=.4, random_state=0)
  #这里是按照6:4对训练集测试集进行划分

In [8]: X_train.shape, y_train.shape
Out[8]: ((90, 4), (90,))

In [9]: X_test.shape, y_test.shape
Out[9]: ((60, 4), (60,))

In [10]: iris.data[:5]
Out[10]: 
array([[ 5.1, 3.5, 1.4, 0.2],
    [ 4.9, 3. , 1.4, 0.2],
    [ 4.7, 3.2, 1.3, 0.2],
    [ 4.6, 3.1, 1.5, 0.2],
    [ 5. , 3.6, 1.4, 0.2]])

In [11]: X_train[:5]
Out[11]: 
array([[ 6. , 3.4, 4.5, 1.6],
    [ 4.8, 3.1, 1.6, 0.2],
    [ 5.8, 2.7, 5.1, 1.9],
    [ 5.6, 2.7, 4.2, 1.3],
    [ 5.6, 2.9, 3.6, 1.3]])

In [12]: clf = svm.SVC(kernel='linear', C=1).fit(X_train, y_train)

In [13]: clf.score(X_test, y_test)
Out[13]: 0.96666666666666667

2.cross_val_score

对数据集进行指定次数的交叉验证并为每次验证效果评测

其中,score 默认是以 scoring='f1_macro'进行评测的,余外针对分类或回归还有:

sklearn中的交叉验证的实现(Cross-Validation)

这需要from sklearn import metrics ,通过在cross_val_score 指定参数来设定评测标准;
cv 指定为int 类型时,默认使用KFoldStratifiedKFold 进行数据集打乱,下面会对KFoldStratifiedKFold 进行介绍。

In [15]: from sklearn.model_selection import cross_val_score

In [16]: clf = svm.SVC(kernel='linear', C=1)

In [17]: scores = cross_val_score(clf, iris.data, iris.target, cv=5)

In [18]: scores
Out[18]: array([ 0.96666667, 1.    , 0.96666667, 0.96666667, 1.    ])

In [19]: scores.mean()
Out[19]: 0.98000000000000009

除使用默认交叉验证方式外,可以对交叉验证方式进行指定,如验证次数,训练集测试集划分比例等

In [20]: from sklearn.model_selection import ShuffleSplit

In [21]: n_samples = iris.data.shape[0]

In [22]: cv = ShuffleSplit(n_splits=3, test_size=.3, random_state=0)

In [23]: cross_val_score(clf, iris.data, iris.target, cv=cv)
Out[23]: array([ 0.97777778, 0.97777778, 1.    ])

cross_val_score 中同样可使用pipeline 进行流水线操作

In [24]: from sklearn import preprocessing

In [25]: from sklearn.pipeline import make_pipeline

In [26]: clf = make_pipeline(preprocessing.StandardScaler(), svm.SVC(C=1))

In [27]: cross_val_score(clf, iris.data, iris.target, cv=cv)
Out[27]: array([ 0.97777778, 0.93333333, 0.95555556])

3.cross_val_predict

cross_val_predictcross_val_score 很相像,不过不同于返回的是评测效果,cross_val_predict 返回的是estimator 的分类结果(或回归值),这个对于后期模型的改善很重要,可以通过该预测输出对比实际目标值,准确定位到预测出错的地方,为我们参数优化及问题排查十分的重要。

In [28]: from sklearn.model_selection import cross_val_predict

In [29]: from sklearn import metrics

In [30]: predicted = cross_val_predict(clf, iris.data, iris.target, cv=10)

In [31]: predicted
Out[31]: 
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
    1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2,
    2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2,
    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

In [32]: metrics.accuracy_score(iris.target, predicted)
Out[32]: 0.96666666666666667

4.KFold

K折交叉验证,这是将数据集分成K份的官方给定方案,所谓K折就是将数据集通过K次分割,使得所有数据既在训练集出现过,又在测试集出现过,当然,每次分割中不会有重叠。相当于无放回抽样。

In [33]: from sklearn.model_selection import KFold

In [34]: X = ['a','b','c','d']

In [35]: kf = KFold(n_splits=2)

In [36]: for train, test in kf.split(X):
  ...:   print train, test
  ...:   print np.array(X)[train], np.array(X)[test]
  ...:   print '\n'
  ...:   
[2 3] [0 1]
['c' 'd'] ['a' 'b']


[0 1] [2 3]
['a' 'b'] ['c' 'd']

5.LeaveOneOut

LeaveOneOut 其实就是KFold 的一个特例,因为使用次数比较多,因此独立的定义出来,完全可以通过KFold 实现。

In [37]: from sklearn.model_selection import LeaveOneOut

In [38]: X = [1,2,3,4]

In [39]: loo = LeaveOneOut()

In [41]: for train, test in loo.split(X):
  ...:   print train, test
  ...:   
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]


#使用KFold实现LeaveOneOtut
In [42]: kf = KFold(n_splits=len(X))

In [43]: for train, test in kf.split(X):
  ...:   print train, test
  ...:   
[1 2 3] [0]
[0 2 3] [1]
[0 1 3] [2]
[0 1 2] [3]

6.LeavePOut

这个也是KFold 的一个特例,用KFold 实现起来稍麻烦些,跟LeaveOneOut 也很像。

In [44]: from sklearn.model_selection import LeavePOut

In [45]: X = np.ones(4)

In [46]: lpo = LeavePOut(p=2)

In [47]: for train, test in lpo.split(X):
  ...:   print train, test
  ...:   
[2 3] [0 1]
[1 3] [0 2]
[1 2] [0 3]
[0 3] [1 2]
[0 2] [1 3]
[0 1] [2 3]

7.ShuffleSplit

ShuffleSplit 咋一看用法跟LeavePOut 很像,其实两者完全不一样,LeavePOut 是使得数据集经过数次分割后,所有的测试集出现的元素的集合即是完整的数据集,即无放回的抽样,而ShuffleSplit 则是有放回的抽样,只能说经过一个足够大的抽样次数后,保证测试集出现了完成的数据集的倍数。

In [48]: from sklearn.model_selection import ShuffleSplit

In [49]: X = np.arange(5)

In [50]: ss = ShuffleSplit(n_splits=3, test_size=.25, random_state=0)

In [51]: for train_index, test_index in ss.split(X):
  ...:   print train_index, test_index
  ...:   
[1 3 4] [2 0]
[1 4 3] [0 2]
[4 0 2] [1 3]

8.StratifiedKFold

这个就比较好玩了,通过指定分组,对测试集进行无放回抽样。

In [52]: from sklearn.model_selection import StratifiedKFold

In [53]: X = np.ones(10)

In [54]: y = [0,0,0,0,1,1,1,1,1,1]

In [55]: skf = StratifiedKFold(n_splits=3)

In [56]: for train, test in skf.split(X,y):
  ...:   print train, test
  ...:   
[2 3 6 7 8 9] [0 1 4 5]
[0 1 3 4 5 8 9] [2 6 7]
[0 1 2 4 5 6 7] [3 8 9]

9.GroupKFold

这个跟StratifiedKFold 比较像,不过测试集是按照一定分组进行打乱的,即先分堆,然后把这些堆打乱,每个堆里的顺序还是固定不变的。

In [57]: from sklearn.model_selection import GroupKFold

In [58]: X = [.1, .2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]

In [59]: y = ['a','b','b','b','c','c','c','d','d','d']

In [60]: groups = [1,1,1,2,2,2,3,3,3,3]

In [61]: gkf = GroupKFold(n_splits=3)

In [62]: for train, test in gkf.split(X,y,groups=groups):
  ...:   print 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]

10.LeaveOneGroupOut

这个是在GroupKFold 上的基础上混乱度又减小了,按照给定的分组方式将测试集分割下来。

In [63]: from sklearn.model_selection import LeaveOneGroupOut

In [64]: X = [1, 5, 10, 50, 60, 70, 80]

In [65]: y = [0, 1, 1, 2, 2, 2, 2]

In [66]: groups = [1, 1, 2, 2, 3, 3, 3]

In [67]: logo = LeaveOneGroupOut()

In [68]: for train, test in logo.split(X, y, groups=groups):
  ...:   print train, test
  ...:   
[2 3 4 5 6] [0 1]
[0 1 4 5 6] [2 3]
[0 1 2 3] [4 5 6]

11.LeavePGroupsOut

这个没啥可说的,跟上面那个一样,只是一个是单组,一个是多组

from sklearn.model_selection import LeavePGroupsOut

X = np.arange(6)

y = [1, 1, 1, 2, 2, 2]

groups = [1, 1, 2, 2, 3, 3]

lpgo = LeavePGroupsOut(n_groups=2)

for train, test in lpgo.split(X, y, groups=groups):
  print train, test
  
[4 5] [0 1 2 3]
[2 3] [0 1 4 5]
[0 1] [2 3 4 5]

12.GroupShuffleSplit

这个是有放回抽样

In [75]: from sklearn.model_selection import GroupShuffleSplit

In [76]: X = [.1, .2, 2.2, 2.4, 2.3, 4.55, 5.8, .001]

In [77]: y = ['a', 'b','b', 'b', 'c','c', 'c', 'a']

In [78]: groups = [1,1,2,2,3,3,4,4]

In [79]: gss = GroupShuffleSplit(n_splits=4, test_size=.5, random_state=0)

In [80]: for train, test in gss.split(X, y, groups=groups):
  ...:   print train, test
  ...:   
[0 1 2 3] [4 5 6 7]
[2 3 6 7] [0 1 4 5]
[2 3 4 5] [0 1 6 7]
[4 5 6 7] [0 1 2 3]

13.TimeSeriesSplit

针对时间序列的处理,防止未来数据的使用,分割时是将数据进行从前到后切割(这个说法其实不太恰当,因为切割是延续性的。。)

In [81]: from sklearn.model_selection import TimeSeriesSplit

In [82]: X = np.array([[1,2],[3,4],[1,2],[3,4],[1,2],[3,4]])

In [83]: tscv = TimeSeriesSplit(n_splits=3)

In [84]: for train, test in tscv.split(X):
  ...:   print train, test
  ...:   
[0 1 2] [3]
[0 1 2 3] [4]
[0 1 2 3 4] [5]

这个repo 用来记录一些python技巧、书籍、学习链接等,欢迎star github地址

Python 相关文章推荐
python和flask中返回JSON数据的方法
Mar 26 Python
Python使用MD5加密算法对字符串进行加密操作示例
Mar 30 Python
python获取文件路径、文件名、后缀名的实例
Apr 23 Python
python利用smtplib实现QQ邮箱发送邮件
May 20 Python
python 爬虫一键爬取 淘宝天猫宝贝页面主图颜色图和详情图的教程
May 22 Python
python实现从pdf文件中提取文本,并自动翻译的方法
Nov 28 Python
python处理DICOM并计算三维模型体积
Feb 26 Python
为什么从Python 3.6开始字典有序并效率更高
Jul 15 Python
python多进程并发demo实例解析
Dec 13 Python
使用keras实现BiLSTM+CNN+CRF文字标记NER
Jun 29 Python
python RSA加密的示例
Dec 09 Python
pytho matplotlib工具栏源码探析一之禁用工具栏、默认工具栏和工具栏管理器三种模式的差异
Feb 25 Python
Python爬虫分析微博热搜关键词的实现代码
Feb 22 #Python
anaconda升级sklearn版本的实现方法
Feb 22 #Python
详解Python 中的 defaultdict 数据类型
Feb 22 #Python
python快速安装OpenCV的步骤记录
Feb 22 #Python
Python中生成ndarray实例讲解
Feb 22 #Python
python爬虫利用代理池更换IP的方法步骤
Feb 21 #Python
Python用requests库爬取返回为空的解决办法
Feb 21 #Python
You might like
DOM基础及php读取xml内容操作的方法
2015/01/23 PHP
php控制文件下载速度的方法
2015/03/24 PHP
php里array_work用法实例分析
2015/07/13 PHP
php代码检查代理ip的有效性
2016/08/19 PHP
php微信高级接口调用方法(自定义菜单接口、客服接口、二维码)
2016/11/28 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
Yii框架视图、视图布局、视图数据块操作示例
2019/10/14 PHP
thinkphp 框架数据库切换实现方法分析
2020/05/18 PHP
javascript中类的定义及其方式(《javascript高级程序设计》学习笔记)
2011/07/04 Javascript
js贪吃蛇网页版游戏特效代码分享(挑战十关)
2015/08/24 Javascript
为何JS操作的href都是javascript:void(0);呢
2015/11/12 Javascript
jQuery UI制作选项卡(tabs)
2016/12/13 Javascript
JavaScript常见的五种数组去重的方式
2016/12/15 Javascript
解决Nodejs全局安装模块后找不到命令的问题
2018/05/15 NodeJs
vue动画之点击按钮往上渐渐显示出来的实例
2018/09/29 Javascript
小程序富文本提取图片可放大缩小
2020/05/26 Javascript
[53:15]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS TNC
2018/03/30 DOTA
[03:04]2018年度DOTA2玩家最喜爱的主播-完美盛典
2018/12/16 DOTA
python 装饰器功能以及函数参数使用介绍
2012/01/27 Python
深入理解Python变量与常量
2016/06/02 Python
Python中对象迭代与反迭代的技巧总结
2016/09/17 Python
python解决Fedora解压zip时中文乱码的方法
2016/09/18 Python
Python使用django框架实现多人在线匿名聊天的小程序
2017/11/29 Python
VSCode基础使用与VSCode调试python程序入门的图文教程
2020/03/30 Python
记一次Django响应超慢的解决过程
2020/09/17 Python
美国孕妇装购物网站:Motherhood Maternity
2019/09/22 全球购物
Gretna Green中文官网:苏格兰格林小镇
2019/10/16 全球购物
华硕新加坡官方网上商店:ASUS Singapore
2020/07/09 全球购物
办理信用卡工作证明
2014/01/11 职场文书
新闻编辑求职信
2014/07/13 职场文书
市场营销毕业求职信
2014/08/07 职场文书
初中成绩单评语
2014/12/29 职场文书
2015年医院工作总结范文
2015/04/09 职场文书
企业法律事务工作总结
2015/08/11 职场文书
缅怀先烈主题班会
2015/08/14 职场文书
MySQL数据库如何使用Shell进行连接
2022/04/12 MySQL