573. Kaggle - LLM Science Exam | kaggle-llm-science-exam
感谢Kaggle举办LLM竞赛——它既充满挑战又组织有序。向我们的社区致以诚挚的感谢,感谢你们富有洞察力的讨论,并展示了在有限GPU资源下所能实现的一切。祝贺获胜的团队,我们从解决方案报告中学习了很多。非常感谢我超级有才华的队友们@ubamba98、@nbroad、@trushk和@abhishek,感谢他们惊人的协作和完美的团队合作!
从最初开始,我们就采用了检索器-阅读器的框架来回答STEM选择题。
注意:我们在流水线中使用了platypus2-70b-instruct,我们不确定该模型与比赛规则的兼容性。
我们采用了标准的检索和重排序流水线,从自定义的STEM维基百科语料库中查找与选择题相关的文本块。
为了解决现有维基百科语料库中常见的渲染问题(数字、方程和符号)并过滤掉不相关的文章,我们创建了一个自定义的STEM维基百科语料库,具体步骤如下:
分块:我们首先根据每个文章的不同部分拆分完整文本。较长的部分进一步拆分为包含约300个标记的较小块。我们为每个块维护两种表示形式:
使用预训练嵌入模型(如thenlper/gte-base、BAAI/bge-base-en-v1.5)检索文本块,为下游选择题模型提供了强大的性能提升。在我们的流水线中,通过微调嵌入模型,我们观察到了进一步的性能改进。我们将生成的合成选择题重新用于检索任务,如下图所示:

检索器使用NCE损失 + 动态计算的同批次困难负样本进行微调。具体来说,我们采用了这个解决方案帖子中的批处理策略。在我们的流水线中,我们使用了微调后的thenlper/gte-base和BAAI/bge-base-en-v1.5模型检索到的前10个文本块的并集。
为了减少提供给下游选择题模型的上下文中的噪声,我们使用交叉编码器(deberta-v3-base)对前10个检索到的候选进行重排序。我们根据重排序器计算的相关性分数的动态阈值选择前2到4个重排序后的上下文。
我们探索了几种使用检索到的上下文解答选择题的策略。

在比赛接近尾声时,我们明显感到DeBERTa模型的性能遇到了瓶颈。因此,我们决定探索微调LLM。尽管我们尝试了多种模型(例如flan-t5-xl (3b)、flan-t5-xxl (11b)、llama-7b、mistral-7b、llama-30b和llama-70b),但我们的最终流水线只包含1个使用LoRA微调的mistral-7b模型。LoRA设置如下:
在LLM微调过程中,我们采用了选项间设置,即在给定所有选项的情况下预测正确答案。我们没有探索在二分类设置中训练模型。
非常感谢@simjeg展示了在Kaggle GPU上使用70b LLM的潜力!!
在比赛结束前5天左右,我们开始尝试70b模型。我们意识到我们无法通过这么大的模型运行每个样本,但我们也知道我们的deberta模型在90-95%的问题上表现良好。因此,我们选择最不自信的预测并传递给70b模型,使用@simjeg的代码。在最后几天里,我们进行了一些提示工程,发现使用两个标记(yes/no或true/false)之间的差异会带来稍好的结果。最终,我们同时使用了platypus 70b和sheep-duck-llama-70b。我们根据公开笔记本调整了提示以匹配其训练方式。我们最后的几次提交都是实验,传递5-10%的样本,与其他模型融合,或者直接使用70b预测作为最终预测。我们的运气不错,因为最好的分数出现在最后一天。
在我们的自定义数据集上的交叉验证显示,一次性传递所有选项的性能略好,但我们无法在Kaggle上实现这一点。
使用Sheep-duck-llama的本地验证结果:
我们确实尝试过使用QLoRA微调70b模型,但在时间耗尽之前无法解决遇到的问题。