1. 概念
- 对抗验证(Adversarial Validation)是一种用于检测训练集和测试集之间分布差异的技术。
- 构建二分类器对将训练集和测试集进行区分,即将训练集和测试集的样本分别标记为0和1,从而判断它们之间的相似性。
- 如果这个二分类器的性能很好,说明训练集和测试集之间的分布差异很大。
2. 代码示例(挑选特征)
- 每个特征依次单独作为训练特征预测adv,进行k折交叉验证,只要在交叉验证中出现了score超过阈值,则说明该特征能很好的区分训练集和测试集,相应的也说明该特征在测试集和训练集上分布差距过大,如果训练模型时加入会导致在训练集上过拟合该特征,影响泛化能力,应该剔除。
def get_adv_feats(df_train, df_test, feats):
'''
adv新特征标识训练集测试集
训练集测试集合并,供后面交叉验证
'''
df_train['adv'] = 1
df_test['adv'] = 0
df = pd.concat([df_train, df_test]).reset_index(drop=True)
params = {
'learning_rate': 0.1,
'boosting_type': 'gbdt',
'objective': 'binary',
'metric': 'auc',
'seed': 2222,
'n_jobs': 4,
'verbose': -1,
}
fold_num = 5
seeds = [2222]
new_feats = []
'''
每个特征依次单独作为训练特征预测adv,
进行k折交叉验证,
只要在交叉验证中出现了score超过阈值,
则说明该特征能很好的区分训练集和测试集,相应的也说明该特征在测试集和训练集上分布差距过大,
如果训练模型时加入会导致在训练集上过拟合该特征,影响泛化能力,应该剔除。
'''
for f in feats:
oof = np.zeros(len(df))
for seed in seeds:
kf = StratifiedKFold(n_splits=fold_num, shuffle=True, random_state=seed)
for fold, (train_idx, val_idx) in enumerate(kf.split(df[[f]], df['adv'])):
train = lgb.Dataset(df.loc[train_idx, [f]],
df.loc[train_idx, 'adv'])
val = lgb.Dataset(df.loc[val_idx, [f]],
df.loc[val_idx, 'adv'])
model = lgb.train(params, train, valid_sets=[val], num_boost_round=10000,
callbacks=[lgb.early_stopping(100), lgb.log_evaluation(-1)])
oof[val_idx] += model.predict(df.loc[val_idx, [f]]) / len(seeds)
score = auc(df.loc[val_idx, 'adv'], oof[val_idx])
if score > 0.85:
print('--------------------------------------', f, score)
else:
new_feats.append(f)
break
return new_feats
feats = get_adv_feats(df_train, df_test, feats)