你还在用交叉验证吗? 大神都开始用对抗验证(Adversarial validation)了

你还在用交叉验证吗?之前我是这么想的,交叉验证可以保证训练集和测试集都是随机选举,但是是否考虑过这样划分的数据集有可能特征分布不均匀?这样怎么能训练出高效的模型呢?
今天忽然发现了对抗验证,分享一下:

1、传统方法

在机器学习里,通常来说我们不能将全部用于数据训练模型,否则我们将没有数据集对该模型进行验证,从而评估我们的模型的预测效果。为了解决这一问题,有如下常用的方法:

1.1 直接划分

第一种是最简单的,也是很容易就想到的。我们可以把整个数据集分成两部分,一部分用于训练,一部分用于验证,这也就是我们经常提到的训练集(training set)和测试集(test set)。
在这里插入图片描述
如下图所示,我们将数据按序号排好,然后按我们所需的比例直接划分,我们可以将蓝色部分的数据作为训练集(包含7、22、13等数据),将右侧的数据作为测试集(包含91等),这样通过在蓝色的训练集上训练模型,在测试集上观察不同模型不同参数对应的MSE的大小,就可以合适选择模型和参数了,训练出我们所需模型。

存在弊端:
不确定因素较多,如果这样排序,以时间序列为例,很有可能在某个时刻发生一些不确定情况,这样如果这些样本全部分在一起,就会是训练样本和测试样本分布不均。

右边是十种不同的训练集和测试集划分方法得到的test MSE,可以看到,在不同的划分方法下,test MSE的变动是很大的,而且对应的最优degree也不一样。所以如果我们的训练集和测试集的划分方法不够好,很有可能无法选择到最好的模型与参数。在这里插入图片描述

1.2 LOOCV

首先,我们先介绍LOOCV方法,即(Leave-one-out cross-validation)。像Test set approach一样,LOOCV方法也包含将数据集分为训练集和测试集这一步骤。但是不同的是,我们现在只用一个数据作为测试集,其他的数据都作为训练集,并将此步骤重复N次(N为数据集的数据数量)。
在这里插入图片描述
如上图所示,假设我们现在有n个数据组成的数据集,那么LOOCV的方法就是每次取出一个数据作为测试集的唯一元素,而其他n-1个数据都作为训练集用于训练模型和调参。结果就是我们最终训练了n个模型,每次都能得到一个MSE。而计算最终test MSE则就是将这n个MSE取平均。
在这里插入图片描述
缺点:计算量太大,是test set approach耗时的n-1倍。

1.3 k折交叉验证

另外一种折中的办法叫做K折交叉验证,和LOOCV的不同在于,我们每次的测试集将不再只包含一个数据,而是多个,具体数目将根据K的选取决定。比如,如果K=5,那么我们就是将数据分为5分,4分用于训练,1分用为验证,之后再选取其他份作为验证。利用五折交叉验证的步骤就是:

  • 1.将所有数据集分成5份

  • 2.不重复地每次取其中一份做测试集,用其他四份做训练集训练模型,之后计算该模型在测试集上的MSE

  • 3.将5次的[公式]取平均得到最后的MSE
    在这里插入图片描述

在这里插入图片描述
每一幅图种蓝色表示的真实的test MSE,而黑色虚线和橙线则分贝表示的是LOOCV方法和10-fold CV方法得到的test MSE。我们可以看到事实上LOOCV和10-fold CV对test MSE的估计是很相似的,但是相比LOOCV,10-fold CV的计算成本却小了很多,耗时更少。

2 对抗验证

2.1 样本分布不均匀

相信参加过kaggle等一些数据比赛的小伙伴们都有类似的体会,我在线下测试指标挺高的,但是提交之后,用没有公开的测试集,分数并没有那么高,这是为什么呢?

很重要的一个原因就是样本分布不均,我们超市购物为例,在周内,很多年轻人都要上班,没时间逛超市,所以去超市的老年人居多,而周末,很多上班族就是趁着这个时候去超市囤货。如果我们基于超市做预测,吧周一到周五的数据作为训练集,周六和周日的数据作为测试集,这显然存在不均匀的现象。

2.2 何时样本分布均匀?

刚才说了很多时候都有可能存在不均匀的情况,那么什么情况可以证明样本分布均匀呢?

这时候可以将训练样本和测试样本标记好好,合成一个数据集,训练一个分类器来区分训练/测试样本

  • 如果分类模型无法分辨样本(AUC接近0.5),则说明训练集和测试集数据分布比较一致;
  • 如果分类模型可以很好分辨样本(AUC接近1),则说明训练集和测试集数据分布不太一致;
# 设置train数据集合test数据集的类别:
train = pd.read_csv( 'data/train.csv' )
test = pd.read_csv( 'data/test.csv' )
train['TARGET'] = 1
test['TARGET'] = 0

# 将train数据和test数据合并成一个数据
data = pd.concat(( train, test ))
data = data.iloc[ np.random.permutation(len( data )) ]
data.reset_index( drop = True, inplace = True )
x = data.drop( [ 'TARGET', 'ID' ], axis = 1 )
y = data.TARGET

# 重新划分一个新的train和test数据:
from sklearn.cross_validation import train_test_split
x_train, x_test, y_train, y_test = train_test_split( x, y, train_size = train_examples)

训练一个lr和rf分类器,训练结果如下:

logistic regression / AUC: 49.82%
random forest, 10 trees / AUC: 50.05%
random forest, 100 trees / AUC: 49.95%

在valid数据集上的结果如下:

logistic regression / AUC: 58.30%
random forest / AUC: 75.32%

在test数据集上的结果如下:

 logistic regression / AUC: 61.47%
random forest / AUC: 74.37%

看样子,valid数据跟test数据结果类似。

2.3 什么是对抗验证(Adversarial Validation)?

对抗验证(Adversarial Validation),并不是一种评估模型效果的方法,而是一种用来确认训练集和测试集的分布是否变化的方法。

对抗验证,通常是发现在训练集上模型表现得非常好,AUC非常高,此时如果采用k-fold交叉验证,模型在验证集上却表现非常糟糕。一种可能性就是训练集与测试集相差非常大。就如同许多数据科学竞赛都面临着测试集与训练集明显不同的问题(这违反了“相同分布”的假设)。因此很难建立一个具有代表性的验证集。对抗验证,选择与测试样本最相似的训练样本,并将其作为验证集,然而问题是,如何才能找到与测试集最相似的训练样本呢?这个方法的核心思想是:

  • 划分数据集方面:训练一个分类器来区分训练/测试样本,之后用这个模型应用于训练集中,在训练集中,选取被预测为测试样本的前n%数据作为验证集,这些数据在分布上是最像真正测试集的数据。

  • 选择特征方面:如何在这个模型中一个特征的重要性越高,那么这个特征在原本训练集和测试集的分布就越不相同,这种特征就需要被剔除。使用对抗验证,尽可能除去在训练集和测试集中分布差异太大的特征

2.4 步骤

  • 1.建立一个分类器来区分train数据集和test数据集
    将train数据和test数据合并成一个数据中。并新增一个类别变量isTest,其中train数据中isTest为0,test数据中isTest为1。然后需要构建一个二元分类器(可以是任意分类器,比如RF,xgboost或lr等)来区分train数据和test数据。

  • 2.将train数据的预测概率按递减顺序排序
    一旦训练完模型之后,接下来使用训练好的模型对train数据进行预测。得到一个拟合概率,对概率按递减顺序排序,那么,top的数据可以理解为很大的概率预测为test数据。

  • 3.取train数据的top n%数据作为valid数据集
    比如取30%作为验证集,剩下的数据作为train数据来训练模型。

通过上述方法,得到valid数据集上的准确性度量应该与test数据上的相似。如果模型能够很好地预测valid数据,那么它应该也能够很好地预测test数据。

2.5 实战

具体来说,我们将使用交叉验证训练一个分类器,从而获得所有train数据的预测概率。然后我们将看到哪些train数据被错误地预测为test数据,并将它们当做valid数据。这意味着它们看起来像test数据,但实际上是trian数据。

i = predictions.argsort()
train['p'] = predictions
train_sorted = train.iloc[i]

按照概率排序结果,选取训练集前面一定样本量作为验证集。

val_size = 5000
train = data.iloc[:-val_size]
val = data.iloc[-val_size:]

这里只是大概写一下思路,没有具体举例,如果想看例子参照:
Adversarial validation
Adversarial validation, part one
Adversarial validation, part two
Adversarial_Validation_Case_Study

参考及扩展阅读:
《An Introduction to Statistical Learning with Applications in R》

  • 6
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力改掉拖延症的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值