😄 同分布问题是数据挖掘中的常见问题,也是ML中的一个重要假设。解决训练与测试数据不满足同分布问题,有助于提高模型的泛化性、稳定性!
文章目录
- 一、定义:训练与测试数据不满足同分布
- 定义:
- ❓疑问:为什么数据会出现不满足同分布
- 二、检测方法:检测训练与测试数据是否满足同分布
- 1、基于统计指标的方法
- 1、PSI检验
- 2、KS检验
- 3、Overlap Rate检验
- 4、KL散度检验
- 5、KDE核密度估计
- 2、基于异常点检测的方法
- 3、基于机器学习分类的方法
- 三、解决方法:解决训练与测试数据不满足同分布
- Reference:
一、定义:训练与测试数据不满足同分布
定义:
不满足同分布,也就是指训练与测试数据的数据集偏移问题。
数据集偏移用公式定义的话也就是说,训练集与测试集的联合概率分布不一致:
Ptrain(x, y) ≠ Ptese(x, y)
学过概率论的应该都记得,贝叶斯定理:
P(x, y) = P(y|x) * P(x) = P(x|y) * P(y)
- P(x):输入空间的边缘概率分布
- P(y):输出空间的标签分布
- P(y|x):条件概率分布
从贝叶斯定理来看,只要其中的一项有变动,那P(x, y)就会改变,也就是数据集偏移,造成数据不满足同分布。
所以呢,以上3种因素分别对应如下3种造成数据不满足同分布问题的情况:
⭐ 协变量偏移:输入空间的边缘概率分布P(x)的变化,即特征分布的变化造成的(协变量指特征)。如测试集中出现了训练集中没遇到过的特征。
⭐先验偏移:输出空间的标签分布P(y)的变化造成的。如线上预测是在某段时间内,某种类别的样本剧增。
⭐映射关系偏移:即P(y|x)的分布变化,x->y的映射关系变化造成。比如训练集中某类特征对应的是标签1,但线上测试时,同样的特征对应的标签却是标签2。
❓疑问:为什么数据会出现不满足同分布
这其实很正常。
(1)样本选择偏差:如我们收集数据时肯定是按照某种规则进行过滤筛选的,但和实际线上的一些数据可能是有差异的。
(2)不平稳环境:如信贷预测任务,在宏观经济景气时,某类用户是可以正常偿还的,但由于疫情等影响,这类用户无法偿还。
二、检测方法:检测训练与测试数据是否满足同分布
⭐ 有时候线上预测效果差了,你可能会认为你模型过度拟合了训练集了,但也有可能是因为待预测的数据的分布出现变化导致的。
具体地,可用如下几种常用方法:
1、基于统计指标的方法
1、PSI检验
- 我们通常用群体稳定性指标(Population Stability Index,PSI), 衡量未来的(测试集)样本及模型训练样本评分的分布比例是否保持一致,以评估模型的稳定性。同理,PSI也可以细化衡量特征值的分布差异,评估数据特征层面的稳定性。
- 其他的方法如 KS检验,KDE (核密度估计)
2、KS检验
⭐ KS是一种非参数检验方法,可以在不知道数据具体分布的情况下检验两个数据分布是否一致。当然这样方便的代价就是当检验的数据分布符合特定的分布时,KS检验的灵敏度没有相应的检验来的高。在样本量比较小的时候,KS检验作为非参数检验在分析两组数据之间是否不同时相当常用。
计算方式很简单,其实就是两组数据的累积分布图中曲线的最大垂直距离。
代码实现:
from scipy.stats import ks_2samp
ks_2samp(train[col],test[col]).pvalue
3、Overlap Rate检验
⭐ 上面的KS检验适用于连续型变量,而对于类别型变量也可先编码然后再KS检验。或者通过特征重合率来检验(Overlap Rate,这里我简称OR)。其实OR的思想就是检测训练集的特征在测试集中出现的比率。
如:
训练集特征:[猫,狗,狗,猫,狗,狗,狗,猫]
测试集特征:[猫,猫,鱼,猪,鱼,鱼,猪,猪]
重合率仅有1/4 (因为测试集中只有训练集中的猫,2/8=1/4)
即使该特征在训练集表现很好,但在测试集上的用处并不大,因为重合率仅有1/4,
反而会导致过拟合或者模型忽略到其他更有用的特征。
4、KL散度检验
⭐ 虽然特征重合率可以筛掉一些不好的特征,但是在下面这种情况下,特征重合率虽然是100%,但是特征的作用并不大:
训练集特征:[猫,猫,鱼,狗,鱼,鱼,猪,猪]
测试集特征:[猫,狗,狗,狗,狗,狗,狗,狗]
- 该特征在训练集可能有很大的作用,但在测试集无法有效的划分样本,因为在测试集大多是一样的取值。在这种情况下,可先用用Overlap Rate筛选过后,再计算测试集的信息熵(在决策树中我们提到过,信息熵更大代表着可以更好的对样本进行划分)。
- 但其实没必要这么麻烦,直接用KL散度即可一步到位。KL 散度是一种衡量两个概率分布的匹配程度的指标,两个分布差异越大,KL散度越大。注意如果要查看测试集特征是否与训练集相同,P代表训练集,Q代表测试集,这个公式对于P和Q并不是对称的。
5、KDE核密度估计
⭐ KDE核密度估计,看起来好像是统计学里面一个高端的非参数估计方法。我简单的理解下哈,大概就是通过一个核函数把一个频率分布直方图搞成平滑的了(如下图),然后把测试集和训练集的特征分别画出来,看看图像不像,不像的直接扔了就行/敷衍。大该知道是这个步骤就好。
代码实现:
import numpy as np
import seaborn as sns
sns.set(color_codes=True)
np.random.seed(10)
mean, cov = [0, 2], [(1, .5), (.5, 1)]
x, y = np.random.multivariate_normal(mean, cov, size=50).T
ax = sns.kdeplot(x)
2、基于异常点检测的方法
- 这类方法属于异常检测那块了,通过训练集训练一个模型,再利用这个模型来识别出测试集中哪些样本不同于训练集的分布。如可用one-class SVM只在训练集里训练(整个训练集作为一类)。
3、基于机器学习分类的方法
⭐听大佬说kaggle上更为牛x的方法就是这种基于机器学习来分类的方法。
-
如果测试数据可以拿到,那么可以将训练与测试数据分别标注为0和1,shuffle一下然后训练进行分类。若模型能够很好地区分开训练与测试数据,则说明训练与测试数据的特征值分布有较大差异,存在协变量偏移。
-
同时,对分类贡献度高的特征也就是分布偏差较大的特征。分类准确的样本也就是分布偏差较大的样本。
-
拓展小知识 - 竞赛tricks(代码链接请进入:https://www.kaggle.com/kevinbonnes/adversarial-validation):我们可用训练好的二分类模型对训练集进行预测,然后输出预测概率,根据这个概率为训练集设置权重(概率越接近1代表训练集分布更接近测试集),这样就可以强行过拟合到测试集上!对于非线上测试型的数据挖掘比赛应该会有比较大的提升!
三、解决方法:解决训练与测试数据不满足同分布
-
1、增加数据。增加数据是最暴力最有效的,数据量越大,模型学到的知识更加泛化,也就见多识广了。
-
2、数据增强。某些场景下可能比较难收集到大量数据。这时就可以通过数据增强来造出一些数据,从而提高原数据的质量,减少模型过拟合,提升泛化能力。
-
3、选择数据。也就是说用全量数据不一定比筛选出一批数据训练效果好,因为可以筛选出和待预测的样本分布较一致的数据进行训练,这样效果更好。一般的做法有:选出较优的随机种子进行划分;人工选出与待预测样本分布较一致的训练样本(如根据时间相近,业务类型等,也可训练的时候基于这部分样本较高的学习权重)。
-
4、半监督学习。通过半监督学习来捕捉数据整体的潜在分布。常见的做法是对无标注样本打上伪标签加入训练,看效果有无变好。对于伪标的方法:可根据业务含义或者模型来为无标注的样本打上伪标。
-
5、特征选择。对于协变量偏移,特征选择是个不错的办法。如可根据前面说的PSI指标来分析各个特征的分布稳定性,筛掉分布差异大的特征(注:这里适用的是筛掉特征重要性一般且稳定性差的特征)。如果重要特征的分布差距也很大,这就难搞了,还是回头搞搞数据或者整整其他的强特征。
-
6、均衡学习。均衡学习适用与标签分布差异(先验偏移)导致的数据集偏移。均衡学习的方法可以归结为:通过某种方法,使得不同类别的样本对于模型学习中的Loss(或梯度)贡献是比较均衡的,以消除模型对不同类别的偏向性,学习到更为本质的决策。还可通过采样型方法缓解,或者采用更合理的指标(如AUC),减少非均衡样本的影响造成判定结果不合理。
Reference:
[1] 机器学习数据不满足同分布,怎么整?
[2] 5种数据同分布的检测方法!