第15名解决方案
第15名解决方案
作者: Fatih Öztürk (Grandmaster)
比赛排名: 第15名
首先,我要感谢 Kaggle 和 IEEE 让我们参加这次挑战。对我来说,这是一个相当累人但也很有教育意义的过程。
我已经阅读了所有排名靠前的解决方案,我知道我的技巧和他们并没有太大的不同。我只是想告诉那些好奇的人,我在比赛过程中的思路是如何形成的。
让我们开始吧。
我的最终提交主要有以下几点:
- 使用未打乱的 KFold 生成预测结果。由于测试集是按时间分割的,而我使用的是未打乱的 KFold,因此我在本地验证方案中模拟了所有这些情况。我将最后 20% 的数据作为留出集,并通过对前 80% 的训练数据设置另一个未打乱的 KFold 来获得其预测结果。使用此策略测试了特征生成、参数调整、后处理等所有操作。
- 只使用了 LightGBM。我既没能生成足够好的 CatBoost 预测,也没能生成 NN(神经网络)预测。最终提交的是 4-5 个不同 LightGBM 模型的加权融合结果。
- 我无法进行任何特征选择,因为我尝试的所有方法都降低了我的 CV(交叉验证)分数。
- 基于不同的特征组合找到了不同的 userid(用户ID)。并通过在训练数据中将 isFraud(欺诈标记)移动 1 位后计算目标均值来测试它们的质量。
示例:
train['ReferenceDate'] = train.DayNumber - train.D1
key_cols = ['TransactionAmt','ProductCD','card1','card2','card3', 'card4','card5','card6','addr1','addr2','ReferenceDate','P_emaildomain']
train['key'] = train[key_cols].apply(tuple,1)
train['previous_isfraud'] = train.groupby(['key'])['isFraud'].shift(1)
print(train.groupby('previous_isfraud')['isFraud'].mean())
>previous_isfraud
>0.0 0.000528
>1.0 0.991961
- 将同一 userid 的 isFraud 信息从训练集转移到测试集行并进行后处理当然是主要的提升手段。注意:后处理并不是直接将 isFraud 信息从训练集转移到测试集。而是将预测值乘以一个我通过验证数据集找到的常数。由于我有多个不同的 userid,我也有多个后处理步骤。
- 基于 userid 创建了许多聚合特征。
- 将预测的平均值分配给某个 userid 的所有交易。这确实带来了显著的提升。(仅对准确率高的 userid 应用此操作)
- 对于融合,我发现使用 'dart' 方法加速的 lgbm 非常有用。
- 最终融合仅针对测试集中的新用户进行。
我的里程碑是什么?
- 在 Excel 中按 TransactionAmt 和 card 信息排序来分析数据集。看到排序后的数据集中移动后的 isFraud 与真实的 isFraud 之间存在高度相关性。(我发现大多数时候在 Excel 中查看数据非常有用。)
- 意识到 D1 和 D3 的真正含义。然后通过简单计算 data['DayNumber'] - data['D1'] 创建了 'ReferenceDate' 特征。
- 开始使用不同的特征组合创建 userid,并使用移动后的 isFraud 信息对最终预测进行后处理。
- 在训练期间,将具有来自最高准确率 userid 的移动后 isFraud 信息的测试行作为伪数据集添加。
- 基于 userid 创建聚合特征。
- 意识到我们的模型实际上是通过过拟合来学习的。numleaves >= 200 表现得很好,这难道不奇怪吗?这是因为模型实际上在测试集中找到了相同的用户。所以我们面临真正的问题是在仅存在于测试集中的新用户上。你也可以为你的模型检查这一点。将最后 20% 的训练数据作为留出集并进行预测。如果它的 AUC 大约为 0.940,现在也检查一下同时存在于训练集中的用户的 AUC,以及仅存在于留出集中的用户的 AUC。你会发现老用户的 AUC 大约为 0.977,而新用户的 AUC 大约为 0.900。
- 最后一周我也专注于改进测试集中的新用户,因为 Private LB(私有排行榜)中的新用户比 Public LB(公共排行榜)多得多。发现我生成的一些特征虽然在提高老用户的预测,但降低了新用户的预测。同样