交叉验证(Cross Validation)是常用的一种用来评估模型效果的方法。

当样本分布发生变化时,交叉验证无法准确评估模型在测试集上的效果,这导致模型在测试集上的效果远低于训练集。

通过本文,你将通过一个kaggle的比赛实例了解到,样本分布变化如何影响建模,如何通过对抗验证辨别样本的分布变化,以及有哪些应对方法。

本篇文章完整代码: https://github.com/Qiuyan918/Adversarial_Validation_Case_Study/blob/master/Adversarial_Validation.ipynb

1 什么是「样本分布变化」?

在真实的业务场景中,我们经常会遇到「样本分布变化」的问题。

主要体现在训练集和测试集的分布存在的差异。比如,在化妆品或者医美市场,男性的比例越来越多。基于过去的数据构建的模型,渐渐不适用于现在。

2 为什么「样本分布变化」的时候,交叉验证不适用?

当我们要做一个模型,来预测人们在超市的消费习惯。

我们的训练样本主要是18岁至25岁的年轻人构成,而测试样本主要是70岁以上的老人组成。这时样本分布就发生了变化。

这种情况下,使用交叉验证,无法准确评估模型的效果。原因是,交叉验证的验证集和测试集不够相似。

交叉验证中,每一折的验证集都是从训练集随机抽取的。随机抽取的验证集的分布和整体的训练集是相同的,也就意味着每一折的验证集都和测试集的分布存在较大的差异。

所以在样本分布变化时,通过交叉验证的方式构建的模型,在测试集上的表现,相较于训练集,通常会打折扣。稍后我们会通过一个实例来确认这一点。

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

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

它的本质是构造一个分类模型,来预测样本是训练集或测试集的概率。

如果这个模型的效果不错(通常来说AUC在0.7以上),那么可以说明我们的训练集和测试集存在较大的差异。

仍然以「预测人们在超市的消费习惯」为例。因为训练集主要是18岁-25岁的年轻人,测试集主要是70岁以上的老人,那么通过「年龄」,我们就能够很好的区分出训练集和测试集。

图2 分类器通过「年龄」可以轻松区分训练集和测试集

具体步骤:

  1. 定义y:样本是train还是test。
  2. 将 Train 和 Test 合成一个数据集
  3. 构造一个模型,拟合新定义的y
  4. 观察模型效果:如果模型的AUC超过0.7,说明了 Train 和 Test 的分布存在较大的差异
# 定义新的Y
df_train['Is_Test'] = 0
df_test['Is_Test'] = 1# 将 Train 和 Test 合成一个数据集。
df_adv = pd.concat([df_train, df_test])

4 分布变化时,有哪些优于交叉验证的方法?

4.1 人工划分验证集

人工划分验证集,需要我们对数据有充分的了解。

因为这次比赛的数据是根据时间划分的,所以我的验证集同样可以根据时间划分。

如果我们不清楚训练集和测试集如何划分,可以采用后面两种方法。

# 将样本根据时间排序
df_train = df_train.sort_values('Date').reset_index(drop=True)
df_train.drop(['Date'], axis=1, inplace=True)# 前80%的样本作为训练集,后20%的样本作为验证集
df_validation_1 = df_train.iloc[int(0.8 * len(df_train)):, ]
df_train_1 = df_train.iloc[:int(0.8 * len(df_train)), ]

4.2 和测试集最相似的样本作为验证集

如果对数据没有充分了解,如何找到训练集中,和测试集分布最相似的样本呢?

这就会用到我们做对抗验证时,模型预测样本是测试集的概率。概率越高,则说明和测试集越相似。

# 通过抗验证中的模型,得到各个样本属于测试集的概率
model_adv.fit(df_adv.drop('Is_Test', axis=1), df_adv.loc[:, 'Is_Test'])
preds_adv = model_adv.predict_proba(df_adv.drop('Is_Test', axis=1))[:, 1]# 只需要训练样本的概率
df_train_copy = df_train.copy()
df_train_copy['is_test_prob'] = preds_adv[:len(df_train)]# 根据概率排序
df_train_copy = df_train_copy.sort_values('is_test_prob').reset_index(drop=True)# 将概率最大的20%作为验证集
df_validation_2 = df_train_copy.iloc[int(0.8 * len(df_train)):, ]
df_train_2 = df_train_copy.iloc[:int(0.8 * len(df_train)), ]

4.3 有权重的交叉验证

不仅可以用对抗验证中,样本是测试集的概率来划分验证集,也可以将这个概率作为样本的权重。

概率越高,和测试集就越相似,权重就越高。这样,我们就可以做有权重的交叉验证。

# 生成lightgbm的数据格式,赋予各个样本权重
train_set = lgb.Dataset(df_train.drop('HasDetections', axis=1),label=df_train.loc[:, 'HasDetections'], weight=preds_adv[:len(df_train)])

5 实例

5.1 用到的数据

图3 微软恶意软件比赛

这里用到的数据来自Kaggle上的微软恶意软件比赛。

因为这次比赛的 Train 和 Test 是根据时间划分的,所以Train 和 Test 的分布非常不同,很具有代表性。

通过对该数据做对抗验证,我们发现模型的AUC达到了0.99。说明本次比赛的训练集和测试集的样本分布存在较大的差异。

5.2 对比各种方法的效果

分别使用上述提到的总共4种方法,我们来对比一下四种方法的效果,如下表:

使用交叉验证时,验证集AUC和测试集AUC的差值是最大的,远高于其他方式。说明在样本分布发生变化时,交叉验证不能够准确评估模型在测试集上的效果。

5.3 为什么评价方式是差值,而不是测试集AUC?

有人可能会提到,哪种方法在测试集上的AUC最高,哪种方法就更好,不是吗?

需要注意的是,本文讨论的不是“提升”模型效果的方法,而是“评估”模型效果的方法。

具体来说,虽然目前看来,比如交叉验证在测试集上的AUC,略高于有权重的交叉验证。

但是,当前的模型只是一个很基础的模型(Baseline Model),没有做任何的变量筛选,特征工程,以及模型调参。

由于所有的优化模型的决定,都将基于验证集,而交叉验证无法准确评估模型在测试集上的效果,这将导致很多优化模型的决定是错误的。

只有在有一个可靠的验证集的情况下,提升模型在验证集上效果的方法,我们才有信心认为,它也可以提升在测试集上的表现。

另外,从本次比赛的结果,我们也可以发现,最终排名很好的参赛者,都没有使用交叉验证。

6 结论

在样本分布发生变化时,交叉验证不能够准确评估模型在测试集上的效果。

这里建议采用其他方式:

  • 人工划分验证集
  • 和测试集最相似的样本作为验证集
  • 有权重的交叉验证

[机器学习]试试Kaggle大牛们常用的方法——对抗验证相关推荐

  1. Sklearn 损失函数如何应用到_机器学习大牛最常用的5个回归损失函数,你知道几个?...

    "损失函数"是机器学习优化中至关重要的一部分.L1.L2损失函数相信大多数人都早已不陌生.那你了解Huber损失.Log-Cosh损失.以及常用于计算预测区间的分位数损失么?这些可 ...

  2. ML之ME/LF:机器学习之风控业务中常用模型评估指标PSI(人群偏移度指标)的的简介、使用方法、案例应用之详细攻略

    ML之ME/LF:机器学习之风控业务中常用模型评估指标PSI(人群偏移度指标)的的简介.使用方法.案例应用之详细攻略 目录 PSI(稳定度指标)的简介 1.如何计算PSI? (1).PSI计算过程

  3. 机器学习之常用优化方法(GD、牛顿、拟牛顿、拉格朗日乘子)

    写在前面,本文只记录了个人认为的关键点,仅供参考.更多细节请参考链接中文章 参考1:机器学习之常用优化方法 参考2:拉格朗日乘数法 梯度下降法 梯度下降法是最早最简单,也是最为常用的最优化方法.梯度下 ...

  4. ML之ME/LF:机器学习之风控业务中常用模型监控指标CSI(特征稳定性指标)的简介、使用方法、案例应用之详细攻略

    ML之ME/LF:机器学习之风控业务中常用模型监控指标CSI(特征稳定性指标)的简介.使用方法.案例应用之详细攻略 目录 CSI(特征稳定性指标)的简介 1.如何计算CSI? 2.CSI值的意义 3. ...

  5. 提高机器学习模型性能的五个关键方法

    提高机器学习模型性能的五个关键方法 1. 数据预处理 2. 特征工程 3. 机器学习算法 4. 模型集成与融合 5. 数据增强 以下是各个方面的具体分析和方法: [ 说明:1.这里主要是各个关键方法的 ...

  6. 基于 Python 的 8 种常用抽样方法

    抽样是统计学.机器学习中非常重要,也是经常用到的方法,因为大多时候使用全量数据是不现实的,或者根本无法取到.所以我们需要抽样,比如在推断性统计中,我们会经常通过采样的样本数据来推断估计总体的样本. 上 ...

  7. 机器学习中用来防止过拟合的方法有哪些?

     机器学习中用来防止过拟合的方法有哪些? 雷锋网(公众号:雷锋网)按:本文作者 qqfly,上海交通大学机器人所博士生,本科毕业于清华大学机械工程系,主要研究方向机器视觉与运动规划,会写一些好玩的 ...

  8. 数据挖掘常用的方法(分类,回归、聚类、关联规则)

    原文出自:http://www.vsharing.com/k//2013-10/690272.html 在大数据时代,数据挖掘是最关键的工作.大数据的挖掘是从海量.不完全的.有噪声的.模糊的.随机的大 ...

  9. 机器学习中处理缺失值的7种方法

    机器学习中处理缺失值的7种方法 转载 |  https://cloud.tencent.com/developer/article/1680427 作者 | Satyam Kumar 编译 | VK ...

最新文章

  1. 第十六届全国大学生智能车竞赛比赛获奖证书格式说明以及下载链接
  2. 5.6 Spring与Struts 2整合应用
  3. XP登录时提示“无法加载配置文件,找不到指定文件”
  4. css --- 伸缩布局,让图片居中
  5. java.io.file()_JAVA基础知识之IO-File类
  6. 设一组初始记录关键字序列为(25,50,15,35,80,85,20,40,36,70)进行一趟归并后的结果为
  7. numpy统计分布显示
  8. IEDevToolBar - 一个分析网页的有用的工具
  9. 库克退休前将再推出一个新品类?可能是AR眼镜
  10. swift - scrollview 判断左右移动, 以及上下两个view联动
  11. 作死把mysql root用户的权限给去掉了或者忘记密码了怎么办
  12. 生物信息学——RNA的剪切过程
  13. idea uml图各符号含义_设计模式-UML类图的各符号含义(转)
  14. 管理新语:软件工作考评的设计思路
  15. vue项目element-ui中el-select回车键隐藏下拉框,实现按回车键查询
  16. 专利基本知识及撰写要求
  17. 【已解决】你遇到过windows更新之后,输入法突然不好用的情况吗?
  18. Maya vray 3S皮肤材质球设置与材质节点连接
  19. 蓝牙耳机型号有哪些?口碑最好的蓝牙耳机
  20. template波浪线

热门文章

  1. Python 旋风之旅——简介
  2. AI云边端算力调度智能分析网关算法模块细节优化介绍
  3. TypeError: Cannot use ‘in‘ operator to search for ‘message‘ in undefine
  4. [推荐]ubuntu下的精品软件[elain整理]
  5. 迭代深入搜索(Iterative Deepening)
  6. 金蝶eas应付单会自动生成成本调整单,调整单又有个开关控制是否自动生成凭证,如果整个开关没有关,而且又没有配置成本调整单到凭证得botop,则会导致应付单审核不通过
  7. Andorid手机从Type-C接口读取U盘数据
  8. python判断输入是否为数字、在输出_判断Python输入是否为数字、字符
  9. 如何利用大数据构建用户画像?
  10. [bzoj5308][二分][ST表]胖