公开的训练代码在这里(可利用双 T4 约 90% 算力,模型收束很快): https://www.kaggle.com/code/fishbyshark/minimind
项目的开始
我个人本地只有一张 AMD 显卡,而 GitHub 上的高星大模型开源项目(如这次复现的 MiniMind)几乎全系绑定 CUDA 生态。我想到了白嫖 Kaggle 免费的双 T4 GPU 算力。
原项目没有 Kaggle 部署教程,整个过程踩了不少坑。以下是四个关键问题和对应的解决思路。是我从零跑通分布式大模型预训练的问题和反思总结:
一、Kaggle 容器与本地 IDE 的路径不同
开源项目的路径逻辑基本都是按本地工作站设计的,直接搬到 Kaggle 容器里大概率会出问题。比如在尝试从断点恢复权重时,程序死活报 FileNotFoundError。
反思
最开始我顺着 AI 的思路去暴力修改 --from_weight 传入的绝对路径,结果越改越错。停下来深入学习 train_pretrain.py 源码后,我发现了作者好心办坏事的问题:代码固定了基于本地的数据传入格式,Kaggle 的数据集挂载在只读的 /kaggle/input,而有效输出区在 /kaggle/working。传入绝对路径会被源码强行拼接路。
最终方案
定位到问题本质后,将相关代码交给 AI 针对 Kaggle 目录结构做适配,一次解决。关键在于先自己把问题定义清楚,再让 AI 来写方案——给一个模糊的报错,AI 只会跟着你瞎猜。
二、如何确定模型训练的最优路径
两张 T4 显卡各15GB 显存,对于 25.8M 参数的模型来说看似充裕,但在实际预训练中,激活值和优化器状态会瞬间吃满显存。
现象
按照默认参数跑,要么 GPU 利用率极低,要么盲目拉大 Batch Size 直接引发显存溢出。同时,盲目开启 torch.compile 会因为编译图缓存带来额外 1-2GB 的显存开销,直接成为压死骆驼的最后一根稻草。
反思方案
- 寻找最优方式:经过二分测试,将单卡
batch_size锁定在 96。此时单卡显存占用达到 14GB,完美贴合 15GB 的物理极限。 - 时间换空间:引入梯度累加
--accumulation_steps 6。 - 算力账本:此时我的实际有效全局批次大小(Global Batch Size)达到了
96 * 6 * 2 = 1152。这不仅拉满了 100% 的 GPU 计算负荷,还确保了梯度下降方向的绝对平稳。
三、读档的问题:只加载权重不等于"续训"
在训练中断后,我尝试通过 --from_weight 重新拉起训练,却发现 Loss 会经历剧烈的震荡反弹,几乎是从头开始收敛。
原因
大语言模型预训练使用的是 AdamW 优化器,它内部维护着关键的"动量"和"方差"状态。只加载模型权重,模型需要从头再训。
再次回归源码排查,发现真正的续训代码其实是 --from_resume 1 参数。只有激活它,代码才会去读取 ckp_data 中的 optimizer 和 scaler 状态,并准确跳过已训练的步数,实现真正的无损接续。
四、如何高效优雅训练好:后台默认训练就行了
现象
预训练需要连续运行 3个小时,而 Kaggle 的前端会有休眠机制,一旦浏览器休眠或网络波动,直接白干。
架构
在前端通过小规模 Step 验证了 Loss 正常下降且无报错后,我彻底摒弃了"盯着进度条"的新手习惯。利用 Kaggle 的 Save & Run All 功能,将代码打包推送到云端后台,生成独立且不受本地网络干扰的虚拟机静默执行。这才是利用云端算力最严谨的工程姿态。
总结
整个过程最大的体会:遇到问题先读源码定位根因,再借助工具解决——顺序反了效率会断崖式下降。希望这份踩坑记录对同样想在 Kaggle 上训模型的同学有帮助。
训练成果展示

MiniMind 模型训练 Loss 收敛曲线