我的团队解决方案部分 (Punch Cards Are All You Need, LB 排名 24)
我的团队解决方案部分 (Punch Cards Are All You Need, LB 排名 24)
作者: Cabbage972 | 发布时间: 2022-08-12
大家好,
我参加这次比赛的经历非常棒,感谢组织者、Kaggle 工作人员、所有在讨论区和公开 Notebook 中分享见解的人,最重要的是——感谢我出色的队友们。
背景
由于夏天没有空闲时间,我原本不打算认真参加这次比赛。然而,到了 7 月下旬,我想到了一个方向,由于其在开发时间、训练时间和推理时间方面都很轻量,看起来很有吸引力。因此,我决定尝试一下,看看会发生什么。当我看到结果有希望时,我与几位其他参赛者组成了团队。组队后,我主要负责团队的模型集成工作。我在下面介绍了一些关于我的单模型、我的集成方法、团队解决方案、我使用的工具以及我的一些工作流程的信息。
单模型
我实现了一个 Bi-encoder(双向编码器)模型,给定一个 markdown 单元格和一个文本单元格,根据编码单元格的余弦相似度预测它们是否相邻。以下是一些细节。
- 损失函数: 多重负样本排序损失,并从与正样本相同的 notebook 中采样额外的困难负样本。
- 主要建模技巧: 我添加了伪代码单元格来代表 notebook 的开头和结尾,以便更好地预测介绍和总结部分的 markdown 单元格(LB 提升 0.01)。
- 推理时间优化: 以 50 个 notebook 为一组加载输入数据,按文本长度对单元格进行排序,以最大限度地减少编码填充 token 所花费的时间。以 128 的批量大小运行编码。
- 数据集: 8 万个 notebook,90/10 的训练/测试分割。
- 序列长度: 每个单元格 256 个 token,即 256 个 markdown 和 256 个代码。
- 数据预处理: 无!
- 训练轮数: 3 轮。
- 训练时长: 在 A6000 上耗时 17 小时。
- 推理时长: 1 小时 20 分钟。
- 单模型性能: 使用 GraphCodeBert 骨干网络,Public 和 Private LB 均为 0.8555。
集成
首先,我发现结合分数预测而不是提交文件中出现的排名很有帮助,因为量化为整数排名会引入偏差。为了计算模型权重,我使用 Nelder-Mead 方法优化最大 Kendall Tau 值。在此基础上,我还实现了一种自适应方案,其中每个单独预测进一步由置信度分数加权,该分数基于其 logit 分布的尖锐程度。这种自适应加权方案相对于简单线性组合的提升是 0.0037。
团队解决方案
我们最好的解决方案(LB 0.8824)是我的两个 bi-encoder 模型(CodeBert, GraphCodeBert)与我队友开发的一个单点 Deberta-v3-base 模型的集成。
工具
- 使用 W&B 进行实验跟踪
- 使用 Hydra 进行配置管理
- 通过 Discord 进行团队沟通
- 使用 Github 进行代码版本管理
- 使用 PyCharm 进行开发
- 在 Kaggle、Colab 以及最后的 JarvisLabs 上进行模型训练
工作方法
通过以下方式实现了训练和推理之间数据预处理的一致性:
- 将我的 GitHub 项目打包为 Pip Wheel 文件,将其保存为数据集,然后使用它来运行推理。推理 notebook 中没有任何 Python 代码,它只调用包中的脚本。
- 训练脚本将超参数与模型权重一起保存。在推理中,此超参数文件被应用于配置。
- 训练脚本和推理代码打包脚本都保存了一个 git commit hash,这使我可以确保版本一致。
测试新想法的流程:
- 在功能分支中进行原型设计,以避免将问题引入主代码。在 Git 中,撤销日志中较靠后的错误提交可能很难。
- 在 IDE 中逐行运行以进行调试。
- 首先在小型数据集上进行训练,看看结果是否在合理范围内。
- 运行预测分析 notebook,通过以下方面检查预测误差:语言、notebook 长度、单元格的真实排名分位数、单元格文本长度等。
感谢阅读,祝所有参与者在即将到来的重赛中好运!