返回列表

45th Place (Silver Medal) : A Multi-LLM Ensemble Approach [LB-0.947]

673. MAP - Charting Student Math Misunderstandings | map-charting-student-math-misunderstandings

开始: 2025-07-10 结束: 2025-10-15 个性化学习 数据算法赛
```html 第 45 名(银牌):多 LLM 集成方法 - 解决方案
作者: Jatin Mehra_666
发布时间: 2025-10-16
比赛: MAP - Charting Student Math Misunderstandings
排名: 第 45 名 (银牌 🥈)

第 45 名(银牌):多 LLM 集成方法 [LB-0.947]

简单而有效

快速总结

🎯 比赛目标: 根据解释预测学生的数学误解
📊 最终得分: 0.947 MAP@3 (私有排行榜)
🏅 排名: 第 45 名 / 银牌
🤖 方法: 6 模型 LLM 集成与智能投票
关键创新: 基于家族的过滤 + 多因素评分

致谢 🙏

如果没有 Kaggle 社区的慷慨贡献,这次银牌成就将不可能实现。我深表感激:

比赛与平台:

  • Kaggle 提供这个令人难以置信的学习和竞赛平台
  • 比赛主办方 组织 MAP 比赛并创造如此有意义的现实世界挑战

社区贡献者:

  • Chris Deotte - 他的 Ettin-Encoder-1B 讨论和数据预处理方法为我的数据管道奠定了基础。
  • Kishan Vavdara - 他的集成笔记本对于开发我的多模型投票策略至关重要。
  • Raja Biswas - 他来自上一场比赛的预训练 Eedi CoT 14B 模型给了我一个强大的起点。

Kaggle 社区:

  • 所有在整个比赛过程中分享见解、笔记本和讨论的参与者
  • 使 Kaggle 成为一个特别的学习之地的协作和知识共享精神

这是我的第一枚银牌,它证明了站在巨人的肩膀上可以取得多大的成就。谢谢大家!🚀

比赛概述

MAP (Misconception Annotation Project) 比赛挑战参与者开发 NLP 模型,从学生的开放式解释中预测他们的数学误解。目标是帮助教师有效地识别和解决阻碍学生学习的错误思维模式。
评估指标:Mean Average Precision @ 3 (MAP@3)

最终结果:

  • 公开排行榜 (Public LB): 0.949
  • 私有排行榜 (Private LB): 0.947 (第 45 名,银牌 🥈)

解决方案架构

我的解决方案利用了 6 个不同 LLM 的集成,每个模型都为最终预测贡献了独特的优势。关键见解是不同的模型架构和训练配置捕捉到了数学误解模式的不同方面。

# 模型 公开 LB 训练方法 GPU 设置 LoRA 配置 学习率 Epochs 训练时间
1 Hunyuan 7B Instruct 0.945 LoRA 2×L4 R:64, α:128 2e-4 3 4h 34m
2 Qwen 3 4B 0.945 LoRA 2×L4 R:512, WD:0.3 2e-5 3 2h
3 Qwen 2 8B 0.945 QLoRA 4-bit 2×L4 R:64, α:32 2e-4 2 4h 23m
4 Qwen 3 14B 0.944 QLoRA 4-bit 4×L4 R:16, α:32 2e-4 3 11h 34m
5 Qwen 3 8B 0.943 全量微调 4×L4 N/A 2e-5 3 3h
6 DeepseekMath 7B 0.944 全量微调 4×L4 N/A 2e-5 3 3h 24m

数据预处理管道

所有模型的预处理保持一致以确保公平比较:

# 创建目标标签
train['target'] = train.Category + ":" + train.Misconception
train['label'] = le.fit_transform(train['target'])

# 识别正确答案
idx = train.apply(lambda row: row.Category.split('_')[0], axis=1) == 'True'
correct = train.loc[idx].copy()
correct['c'] = correct.groupby(['QuestionId', 'MC_Answer']).MC_Answer.transform('count')
correct = correct.sort_values('c', ascending=False)
correct = correct.drop_duplicates(['QuestionId'])
correct = correct[['QuestionId', 'MC_Answer']]
correct['is_correct'] = 1 # 标记这些为正确答案

# 将 'is_correct' 标志合并到主训练 DataFrame 中
train = train.merge(correct, on=['QuestionId', 'MC_Answer'], how='left')
train.is_correct = train.is_correct.fillna(0)

输入格式

每个训练示例的格式如下:

Question: {QuestionText}
Answer: {MC_Answer}
Is Correct Answer: {Yes/No}
Student Explanation: {StudentExplanation}

这种结构为模型提供了完整的上下文:问题、学生的答案选择、是否正确以及他们的推理。

训练策略

1. LoRA (Low-Rank Adaptation)

  • 用于:Hunyuan 7B, Qwen 3 4B
  • 优势: 内存效率高,训练速度快,防止灾难性遗忘
  • 配置变化: 尝试了从 64 到 512 的秩 (ranks)

2. QLoRA (Quantized LoRA)

  • 用于:Qwen 2 8B, Qwen 3 14B
  • 4-bit NF4 量化 配合 bfloat16 计算数据类型
  • 能够在有限的 GPU 资源上训练更大的模型
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

3. 全量微调 (Full Fine-tuning)

  • 用于:Qwen 3 8B, DeepseekMath 7B
  • 完整的参数更新以实现最大的模型适应
  • 需要更多 GPU 内存但实现了强劲的性能

关键训练超参数

# 所有模型的通用设置
num_train_epochs = 3
learning_rate = 2e-4 to 2e-5  # 因模型而异
lr_scheduler_type = "cosine"
warmup_ratio = 0.1
gradient_accumulation_steps = 16
fp16/bf16 = True

推理策略

概率提取
对于每个模型,我生成了所有类别的完整概率分布(不仅仅是前 3 名),这对于有效的集成至关重要:

# 生成概率
logits = trainer.predict(test_dataset).predictions
probs = softmax(logits, axis=1)

# 排序并保存前 K 个类别及其概率
top_indices = np.argsort(-probs, axis=1)
for i in range(num_classes):
    prob_dict[f"prob_{i}"] = probs[i, top_indices[i]]
    
# 保存用于集成
prob_df.to_csv(f"submission_{model_name}_prob.csv", index=False)

集成方法论

集成是将性能从单独的 0.943-0.945 分提升到公开排行榜 0.949 分的关键组件。

基于家族的过滤 (Family-Based Filtering)

一个关键见解是认识到预测必须尊重类别家族(True 与 False):

# 从正确答案构建家族映射
fam_map = test_df.merge(correct_answers, on=['QuestionId','MC_Answer'])
fam_map['family'] = fam_map['is_correct'].map({1: 'True_', 0: 'False_'})

带多因素评分的加权投票

集成结合了三个评分组件:

  1. 加权概率和 (34%): 聚合模型置信度
  2. 一致性奖励 (33%): 有多少模型同意这个类别
  3. 置信度奖励 (33%): 任何模型的最大置信度
for class_name in all_classes:
    base_score = class_total_prob[class_name]
    agreement_bonus = class_votes[class_name] / n_models
    confidence_bonus = class_max_prob[class_name]
    
    final_scores[class_name] = (
        base_score * 0.34 +
        agreement_bonus * 0.33 +
        confidence_bonus * 0.33
    )

家族过滤与回填

# 按家族过滤
final_scores = {k: v for k, v in final_scores.items() 
                if k.startswith(family_prefix)}

# 如果预测少于 3 个则回填
fillers = [f"{family}_Neither:NA"]
if family == "True_":
    fillers.append(f"{family}_Correct:NA")

模型权重

所有模型权重相等 (weight=1),因为它们表现相似:

weights = [1, 1, 1, 1, 1, 1]  # 等权重

关键洞察与收获

1. 多样性很重要

  • 结合不同的架构(Qwen, Hunyuan, DeepseekMath)捕捉到了互补的模式
  • 不同的训练策略(LoRA, QLoRA, 全量微调)提供了多样化的视角

2. 家族约束至关重要

  • 强制执行类别家族(True/False)一致性防止了无意义的预测
  • 简单的基于规则的过滤提供了巨大的收益

3. 概率校准

  • 保存完整的概率分布(不仅仅是前 3 名)实现了复杂的集成
  • 多因素评分(概率 + 一致性 + 置信度)优于简单的平均

4. 高效训练

  • LoRA 和 QLoRA 使得在可访问的硬件上训练大型模型(高达 14B 参数)成为可能
  • 4-bit 量化对最终性能的影响微乎其微

5. 迁移学习

  • 使用 Raja Biswas 来自上一届 Eedi 比赛的预训练 Qwen2 模型提供了一个强大的起点
  • 数学误解数据的领域特定预训练非常有价值

计算资源

  • GPU: 主要是 2×T4, 2×L4 和 4×L4 配置
  • 总训练时间: 所有模型约 30+ 小时
  • 推理时间: 所有 6 个模型对完整测试集约 6-7 小时

无效尝试

探索但未包含的模型:

  • OpenAI GPT 20B: 训练复杂性超过了收益
  • 生成式训练方法: 文本生成不如分类有效
  • 小模型 (smoLM2/3): 360M-3B 参数模型缺乏容量
  • 50+ 其他模型: 包括 Llama 3.1 8B, Phi 4 12B 等
  • Qwen 32B: 没有足够时间在 4-bit 量化下完成完整的推理管道

表现不佳的技术:

  • 重度提示工程: 结构化输入格式比复杂提示更有效
  • 不等权重集成: 等权重表现一样好或更好
  • 单模型方法: 没有一个能匹配集成的性能

改进空间

  1. 超参数优化: 更系统地调整 LoRA 秩、学习率和集成权重
  2. 数据增强: 合成误解生成以增加训练多样性
  3. 集成权重: 学习最佳权重而不是等权重
  4. 交叉验证: 更好的验证策略以检测过拟合

结论

这次比赛表明,集成多样性高效微调技术领域特定约束是在专用 NLP 任务中实现顶级性能的关键。6 个精心训练的 LLM 与智能集成的结合实现了 0.947 MAP@3 分数银牌 的成绩。


资源与致谢

感谢阅读!欢迎提问或讨论该方法。 🚀

```
同比赛其他方案