机器学习 | 交叉验证

52 篇文章 6 订阅
15 篇文章 0 订阅

1 什么是交叉验证?

1.1 思想

基本思想:

  • 将原始数据(dataset)进行分组,一部分做为训练集来训练模型,另一部分做为测试集来评价模型。

交叉验证是一种模型选择的方法!(引自李航统计学习方法)可以分为以下三种:

  • 简单交叉验证。即将数据按照一定比例 比如73开,分为训练集和测试集。
  • S折交叉验证。将已给数据切分为S个互不相交、大小相同的子集,将S-1个子集的数据作为训练集来训练模型,剩余的一个测试模型,重复S次,选择S次中平均测试误差最小的模型。
  • 留一交叉验证。即S=n。往往在数据缺乏的时候使用。因为数据很少没法再分了!

注1:由于交叉验证是用来模型选择的,所以是将不同的模型,比如SVM,LR,GBDT等运用上述方法,然后比较误差大小,选择误差最小的模型!

注2:上述三种方法是针对数据量不充足的时候采用的交叉验证方法,如果数据量充足,一种简单的方法就是将数据分为3部分:

  • 训练集。用来训练模型
  • 验证集。用于模型选择
  • 测试集。用于最终对学习方法的评估

选择验证集上有最小预测误差的模型。

注3:如果数据量为bigdata,这时候可以不用7/3开了,照样分成训练集,验证集,测试集三份。比如100万的数据量,完全可以将数据分成98:1:1,即验证集只要1万即可,测试集也只要1万即可,更多的数据用在训练集来训练模型!

1.2 疑问

一旦使用交叉验证,模型还需要划分训练集和测试集吗?

回答:需要!保持测试集的纯净!对训练集进行简单或者K折交叉验证都ok!目的是评估模型在训练集上的效果,如果在训练集上都表现不好,那么这个问题就是一个不容易学习的问题,进而测试集上大概率也会表现得不好。但核心还是看模型在测试集上的表现效果,并根据测试集结果来评估模型的优劣!所以用简单或者K折交叉验证都ok,甚至不做也行,主要看测试集!

回答2:如果是kaggle等比赛,由于测试集没有标签,只提供了训练集,这时候当然也有两种方式:即普通的划分以及K折交叉验证。但建议K折交叉验证,然后取每一折上测试集评估效果的均值来衡量模型的预测效果!因为这时候我们仅仅只有这个数据,所以希望尽可能多的利用数据的信息

2 为什么要交叉验证?

  • 交叉验证用于评估模型的预测性能,尤其是训练好的模型在新数据上的表现,可以在一定程度上减小过拟合。
  • 完整的利用数据信息!而不是简单的分成7 3 开!

3 Python实现交叉验证

3.1 简单交叉验证

from sklearn.model_selection import train_test_split
import pandas as pd
df = pd.read_csv('data/telecom_churn.csv')
print(df.shape)
df.head()
(3463, 20)
subscriberIDchurngenderAGEedu_classincomeCodedurationfetonpeakMinAvpeakMinDiffposTrendnegTrendnrPrompromcurPlanavgplanplanChangeposPlanChangenegPlanChangecall_10000
0191649581020212160113.666667-8.00100110000
139244924112002150274.000000-371.00121322101
239578413101114730392.000000-784.00100330001
34099226510430412031.000000-76.00121330001
443061957116009140129.333333-334.00100330000
X = df.drop(['subscriberID', 'churn'], axis=1)
y = df['churn'].values
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.3, random_state = 23)
print(X_train.shape, X_test.shape, y_train.shape, y_test.shape)
(2424, 18) (1039, 18) (2424,) (1039,)

通过训练集来训练模型,然后看测试集表现来评估该模型!如何评估呢?看之前的博客:机器学习 | 评价指标

3.2 S折交叉验证

import warnings
warnings.filterwarnings('ignore')
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import GradientBoostingClassifier
clf = LogisticRegression()
gbdt = GradientBoostingClassifier()
scores1 = cross_val_score(clf, X, y, cv=10, scoring='roc_auc')
scores2 = cross_val_score(gbdt, X, y, cv=10, scoring='roc_auc')
print('逻辑回归 10折交叉验证 平均AUC结果为: %.2f ' % scores1.mean())
print('GBDT 10折交叉验证 平均AUC结果为: %.2f ' % scores2.mean())
逻辑回归 10折交叉验证 平均AUC结果为: 0.92 
GBDT 10折交叉验证 平均AUC结果为: 0.95 

所以初步来看,在这个数据集上,通过10折交叉验证来看,GBDT的预测效果比LR要好!

3.3 留一交叉验证

print(df.shape)
(3463, 20)
from sklearn.model_selection import LeaveOneOut
loo = LeaveOneOut()
for train, test in loo.split(X, y):
    print('%s - %s' % (train.shape, test.shape))
(3462,) - (1,)
(3462,) - (1,)
(3462,) - (1,)
(3462,) - (1,)
(3462,) - (1,)
......
(3462,) - (1,)
(3462,) - (1,)
(3462,) - (1,)
(3462,) - (1,)

可以看到留一交叉验证,每一次把n-1的作为训练集,1作为验证集!即训练集样本量为n-1,测试集为1

# 取训练集
df.iloc[train, :].head()
subscriberIDchurngenderAGEedu_classincomeCodedurationfetonpeakMinAvpeakMinDiffposTrendnegTrendnrPrompromcurPlanavgplanplanChangeposPlanChangenegPlanChangecall_10000
0191649581020212160113.666667-8.00100110000
139244924112002150274.000000-371.00121322101
239578413101114730392.000000-784.00100330001
34099226510430412031.000000-76.00121330001
443061957116009140129.333333-334.00100330000
# 取测试集
df.iloc[test, :].head()
subscriberIDchurngenderAGEedu_classincomeCodedurationfetonpeakMinAvpeakMinDiffposTrendnegTrendnrPrompromcurPlanavgplanplanChangeposPlanChangenegPlanChangecall_10000
346277861800002404671321.333333-4.00100220000

4 参考

  • 6
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值