jingyaogong/minimind
"大道至简"
中文 | English
- 此开源项目旨在完全从0开始,仅用3块钱成本 + 2小时!即可训练出仅为25.8M的超小语言模型MiniMind。
- MiniMind系列极其轻量,最小版本体积是 GPT-3 的 $\frac{1}{7000}$,力求做到最普通的个人GPU也可快速训练。
- 项目同时开源了大模型的极简结构-包含拓展共享混合专家(MoE)、数据集清洗、预训练(Pretrain)、监督微调(SFT)、LoRA微调, 直接偏好强化学习(DPO)算法、模型蒸馏算法等全过程代码。
- MiniMind同时拓展了视觉多模态的VLM: MiniMind-V。
- 项目所有核心算法代码均从0使用PyTorch原生重构!不依赖第三方库提供的抽象接口。
- 这不仅是大语言模型的全阶段开源复现,也是一个入门LLM的教程。
- 希望此项目能为所有人提供一个抛砖引玉的示例,一起感受创造的乐趣!推动更广泛AI社区的进步!
为防止误解,“2小时” 基于NVIDIA 3090硬件设备(单卡)测试,“3块钱” 指GPU服务器租用成本,具体规格详情见下文。
📌 Introduction
大语言模型(Large Language Model, LLM)的出现引发了全世界对AI的空前关注。 无论是ChatGPT、DeepSeek还是Qwen,都以其惊艳的效果令人叹为观止。 然而,动辄数百亿参数的庞大规模,使得它们对个人设备而言不仅难以训练,甚至连部署都显得遥不可及。 打开大模型的“黑盒子”,探索其内部运作机制,多么令人心潮澎湃! 遗憾的是,99%的探索只能止步于使用LoRA等技术对现有大模型进行少量微调,学习一些新指令或任务。 这就好比教牛顿如何使用21世纪的智能手机——虽然有趣,却完全偏离了理解物理本质的初衷。 与此同时,第三方的大模型框架和工具库,如transformers+trl,几乎只暴露了高度抽象的接口。 通过短短10行代码,就能完成“加载模型+加载数据集+推理+强化学习”的全流程训练。 这种高效的封装固然便利,但也像一架高速飞船,将我们与底层实现隔离开来,阻碍了深入探究LLM核心代码的机会。 然而,“用乐高拼出一架飞机,远比坐在头等舱里飞行更让人兴奋!”。 更糟糕的是,互联网上充斥着大量付费课程和营销号,以漏洞百出、一知半解的内容推销AI教程。 正因如此,本项目初衷是拉低LLM的学习门槛,让每个人都能从理解每一行代码开始, 从零开始亲手训练一个极小的语言模型。是的,从零开始训练,而不是仅仅进行推理! 最低只需3块钱不到的服务器成本,就能亲身体验从0到1构建一个语言模型的全过程。 一起感受创造的乐趣吧!
[!NOTE] (截至2025-02-07)MiniMind系列已完成多个型号模型的预训练,最小仅需25.8M(0.02B),即可具备流畅对话能力!
Models List
模型 (大小) | 推理占用 (约) | Release |
---|---|---|
MiniMind2-small (26M) | 0.5 GB | 2025.04.26 |
MiniMind2-MoE (145M) | 1.0 GB | 2025.04.26 |
MiniMind2 (104M) | 1.0 GB | 2025.04.26 |
minimind-v1-small (26M) | 0.5 GB | 2024.08.28 |
minimind-v1-moe (4×26M) | 1.0 GB | 2024.09.17 |
minimind-v1 (108M) | 1.0 GB | 2024.09.01 |
项目包含
- MiniMind-LLM结构的全部代码(Dense+MoE模型)。
- 包含Tokenizer分词器详细训练代码。
- 包含Pretrain、SFT、LoRA、RLHF-DPO、模型蒸馏的全过程训练代码。
- 收集、蒸馏、整理并清洗去重所有阶段的高质量数据集,且全部开源。
- 从0实现预训练、指令微调、LoRA、DPO强化学习,白盒模型蒸馏。关键算法几乎不依赖第三方封装的框架,且全部开源。
- 同时兼容
transformers
、trl
、peft
等第三方主流框架。 - 训练支持单机单卡、单机多卡(DDP、DeepSpeed)训练,支持wandb可视化训练流程。支持动态启停训练。
- 在第三方测评榜(C-Eval、C-MMLU、OpenBookQA等)进行模型测试。
- 实现Openai-Api协议的极简服务端,便于集成到第三方ChatUI使用(FastGPT、Open-WebUI等)。
- 基于streamlit实现最简聊天WebUI前端。
- 全面兼容社区热门
llama.cpp
、vllm
、ollama
推理引擎或Llama-Factory
训练框架。 - 复现(蒸馏/RL)大型推理模型DeepSeek-R1的MiniMind-Reason模型,数据+模型全部开源!
希望此开源项目可以帮助LLM初学者快速入门!
👉更新日志
2025-04-26 (newest 🎉🎉🎉)
- 重要更新
- 如有兼容性需要,可访问🔗旧仓库内容🔗。
- MiniMind模型参数完全改名,对齐Transformers库模型(统一命名)。
- generate方式重构,继承自GenerationMixin类。
- 🔥支持llama.cpp、vllm、ollama等热门三方生态。
- 规范代码和目录结构。
- 改动词表
<s></s>
-><|im_start|><|im_end|>
|
|
2025-02-09
- 迎来发布以来重大更新,Release MiniMind2 Series。
- 代码几乎全部重构,使用更简洁明了的统一结构。 如有旧代码的兼容性需要,可访问🔗旧仓库内容🔗。
- 免去数据预处理步骤。统一数据集格式,更换为
jsonl
格式杜绝数据集下载混乱的问题。 - MiniMind2系列效果相比MiniMind-V1显著提升。
- 小问题:{kv-cache写法更标准、MoE的负载均衡loss被考虑等等}
- 提供模型迁移到私有数据集的训练方案(医疗模型、自我认知样例)。
- 精简预训练数据集,并大幅提升预训练数据质量,大幅缩短个人快速训练所需时间,单卡3090即可2小时复现!
- 更新:LoRA微调脱离peft包装,从0实现LoRA过程;DPO算法从0使用PyTorch原生实现;模型白盒蒸馏原生实现。
- MiniMind2-DeepSeek-R1系列蒸馏模型诞生!
- MiniMind2具备一定的英文能力!
- 更新MiniMind2与第三方模型的基于更多大模型榜单测试性能的结果。
2024-10-05
- 为MiniMind拓展了多模态能力之—视觉
- 移步孪生项目minimind-v查看详情!
2024-09-27
- 09-27更新pretrain数据集的预处理方式,为了保证文本完整性,放弃预处理成.bin训练的形式(轻微牺牲训练速度)。
- 目前pretrain预处理后的文件命名为:pretrain_data.csv。
- 删除了一些冗余的代码。
2024-09-17
- 更新minimind-v1-moe模型
- 为了防止歧义,不再使用mistral_tokenizer分词,全部采用自定义的minimind_tokenizer作为分词器。
2024-09-01
- 更新minimind-v1 (108M)模型,采用minimind_tokenizer,预训练轮次3 + SFT轮次10,更充分训练,性能更强。
- 项目已部署至ModelScope创空间,可以在此网站上体验:
- 🔗ModelScope在线体验🔗
2024-08-27
- 项目首次开源
📌 快速开始
分享本人的软硬件配置(仅供参考)
- CPU: Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz
- RAM: 128 GB
- GPU: NVIDIA GeForce RTX 3090(24GB) * 8
- Ubuntu==20.04
- CUDA==12.2
- Python==3.10.16
- requirements.txt
第0步
|
|
Ⅰ 测试已有模型效果
1.环境准备
|
|
2.下载模型
到项目根目录
|
|
(可选)命令行问答
|
|
(可选)启动WebUI
|
|
(可选)第三方推理框架
|
|
Ⅱ 从0开始自己训练
1.环境准备
|
|
注:提前测试Torch是否可用cuda
|
|
如果不可用,请自行去torch_stable 下载whl文件安装。参考链接
2.数据下载
从下文提供的数据集下载链接
下载需要的数据文件(创建./dataset
目录)并放到./dataset
下
注:数据集须知
默认推荐下载pretrain_hq.jsonl
+ sft_mini_512.jsonl
最快速度复现Zero聊天模型。
数据文件可自由选择,下文提供了多种搭配方案,可根据自己手头的训练需求和GPU资源进行适当组合。
3.开始训练
目录位于trainer
3.1 预训练(学知识)
|
|
执行预训练,得到
pretrain_*.pth
作为预训练的输出权重(其中*为模型的dimension,默认为512)
3.2 监督微调(学对话方式)
|
|
执行监督微调,得到
full_sft_*.pth
作为指令微调的输出权重(其中full
即为全参数微调)
注:训练须知
所有训练过程默认每隔100步保存1次参数到文件./out/***.pth
(每次会覆盖掉旧权重文件)。
简单起见,此处只写明两个阶段训练过程。如需其它训练 (LoRA, 蒸馏, 强化学习, 微调推理等) 可参考下文【实验】小节的详细说明。
4.测试模型效果
确保需要测试的模型*.pth
文件位于./out/
目录下。
也可以直接去此处下载使用我训练的*.pth
文件。
|
|
注:测试须知
如需详情,查看eval_model.py
脚本代码即可。model_mode分为 0: 预训练模型,1: SFT-Chat模型,2: RLHF-Chat模型,3: Reason模型
[!TIP] 所有训练脚本均为Pytorch原生框架,均支持多卡加速,假设你的设备有N (N>1) 张显卡:
单机N卡启动训练方式 (DDP, 支持多机多卡集群)
|
|
注:其它须知
单机N卡启动训练 (DeepSpeed)
|
|
可根据需要开启wandb记录训练过程
|
|
通过添加--use_wandb
参数,可以记录训练过程,训练完成后,可以在wandb网站上查看训练过程。通过修改wandb_project
和wandb_run_name
参数,可以指定项目名称和运行名称。
📌 数据介绍
Ⅰ Tokenizer
分词器将单词从自然语言通过“词典”映射到0, 1, 36
这样的数字,可以理解为数字就代表了单词在“词典”中的页码。
可以选择自己构造词表训练一个“词典”,代码可见./scripts/train_tokenizer.py
(仅供学习参考,若非必要无需再自行训练,MiniMind已自带tokenizer)。
或者选择比较出名的开源大模型分词器,
正如同直接用新华/牛津词典的优点是token编码压缩率很好,缺点是页数太多,动辄数十万个词汇短语;
自己训练的分词器,优点是词表长度和内容随意控制,缺点是压缩率很低(例如"hello"也许会被拆分为"h e l l o"
五个独立的token),且生僻词难以覆盖。
“词典”的选择固然很重要,LLM的输出本质上是SoftMax到词典N个词的多分类问题,然后通过“词典”解码到自然语言。
因为MiniMind体积需要严格控制,为了避免模型头重脚轻(词嵌入embedding层参数在LLM占比太高),所以词表长度短短益善。
Tokenizer介绍
第三方强大的开源模型例如Yi、qwen、chatglm、mistral、Llama3的tokenizer词表长度如下:
Tokenizer模型 | 词表大小 | 来源 |
---|---|---|
yi tokenizer | 64,000 | 01万物(中国) |
qwen2 tokenizer | 151,643 | 阿里云(中国) |
glm tokenizer | 151,329 | 智谱AI(中国) |
mistral tokenizer | 32,000 | Mistral AI(法国) |
llama3 tokenizer | 128,000 | Meta(美国) |
minimind tokenizer | 6,400 | 自定义 |
👉2024-09-17更新:为了防止过去的版本歧义&控制体积,minimind所有模型均使用minimind_tokenizer分词,废弃所有mistral_tokenizer版本。
|
|
Ⅱ Pretrain数据
经历了MiniMind-V1的低质量预训练数据,导致模型胡言乱语的教训,2025-02-05
之后决定不再采用大规模无监督的数据集做预训练。
进而尝试把匠数大模型数据集的中文部分提取出来,
清洗出字符<512
长度的大约1.6GB的语料直接拼接成预训练数据 pretrain_hq.jsonl
,hq即为high
quality(当然也还不算high,提升数据质量无止尽)。
文件pretrain_hq.jsonl
数据格式为
|
|
Ⅲ SFT数据
匠数大模型SFT数据集
“是一个完整、格式统一、安全的大模型训练和研究资源。
从网络上的公开数据源收集并整理了大量开源数据集,对其进行了格式统一,数据清洗,
包含10M条数据的中文数据集和包含2M条数据的英文数据集。”
以上是官方介绍,下载文件后的数据总量大约在4B tokens,肯定是适合作为中文大语言模型的SFT数据的。
但是官方提供的数据格式很乱,全部用来sft代价太大。
我将把官方数据集进行了二次清洗,把含有符号污染和噪声的条目去除;另外依然只保留了总长度<512
的内容,此阶段希望通过大量对话补充预训练阶段欠缺的知识。
导出文件为sft_512.jsonl
(~7.5GB)。
Magpie-SFT数据集
收集了~1M条来自Qwen2/2.5的高质量对话,我将这部分数据进一步清洗,把总长度<2048
的部分导出为sft_2048.jsonl
(~9GB)。
长度<1024
的部分导出为sft_1024.jsonl
(~5.5GB),用大模型对话数据直接进行sft就属于“黑盒蒸馏”的范畴。
进一步清洗前两步sft的数据(只保留中文字符占比高的内容),筛选长度<512
的对话,得到sft_mini_512.jsonl
(~1.2GB)。
所有sft文件 sft_X.jsonl
数据格式均为
|
|
Ⅳ RLHF数据
来自Magpie-DPO数据集
大约200k条偏好数据(均是英文)生成自Llama3.1-70B/8B,可以用于训练奖励模型,优化模型回复质量,使其更加符合人类偏好。
这里将数据总长度<3000
的内容重组为dpo.jsonl
(~0.9GB),包含chosen
和rejected
两个字段,chosen
为偏好的回复,rejected
为拒绝的回复。
文件 dpo.jsonl
数据格式为
|
|
Ⅴ Reason数据集:
不得不说2025年2月谁能火的过DeepSeek…
也激发了我对RL引导的推理模型的浓厚兴趣,目前已经用Qwen2.5复现了R1-Zero。
如果有时间+效果work(但99%基模能力不足)我会在之后更新MiniMind基于RL训练的推理模型而不是蒸馏模型。
时间有限,最快的低成本方案依然是直接蒸馏(黑盒方式)。
耐不住R1太火,短短几天就已经存在一些R1的蒸馏数据集R1-Llama-70B、R1-Distill-SFT、
Alpaca-Distill-R1、
deepseek_r1_zh等等,纯中文的数据可能比较少。
最终整合它们,导出文件为r1_mix_1024.jsonl
,数据格式和sft_X.jsonl
一致。
Ⅵ 更多数据集
目前已经有HqWu-HITCS/Awesome-Chinese-LLM 在收集和梳理中文LLM相关的开源模型、应用、数据集及教程等资料,并持续更新这方面的最新进展。全面且专业,Respect!
Ⅷ MiniMind训练数据集
[!NOTE] 2025-02-05后,开源MiniMind最终训练所用的所有数据集,因此无需再自行预处理大规模数据集,避免重复性的数据处理工作。
MiniMind训练数据集下载地址: ModelScope | HuggingFace
无需全部clone,可单独下载所需的文件
将下载的数据集文件放到./dataset/
目录下(✨为推荐的必须项)
|
|
注:各数据集简介
dpo.jsonl
–RLHF阶段数据集lora_identity.jsonl
–自我认知数据集(例如:你是谁?我是minimind…),推荐用于lora训练(亦可用于全参SFT,勿被名字局限)lora_medical.jsonl
–医疗问答数据集,推荐用于lora训练(亦可用于全参SFT,勿被名字局限)pretrain_hq.jsonl
✨ –预训练数据集,整合自jiangshu科技r1_mix_1024.jsonl
–DeepSeek-R1-1.5B蒸馏数据,每条数据字符最大长度为1024(因此训练时设置max_seq_len=1024)sft_1024.jsonl
–整合自Qwen2.5蒸馏数据(是sft_2048的子集),每条数据字符最大长度为1024(因此训练时设置max_seq_len=1024)sft_2048.jsonl
–整合自Qwen2.5蒸馏数据,每条数据字符最大长度为2048(因此训练时设置max_seq_len=2048)sft_512.jsonl
–整合自匠数科技SFT数据,每条数据字符最大长度为512(因此训练时设置max_seq_len=512)sft_mini_512.jsonl
✨ –极简整合自匠数科技SFT数据+Qwen2.5蒸馏数据(用于快速训练Zero模型),每条数据字符最大长度为512(因此训练时设置max_seq_len=512)tokenizer_train.jsonl
–均来自于匠数大模型数据集
,这部分数据相对次要,(不推荐自己重复训练tokenizer,理由如上)如需自己训练tokenizer可以自由选择数据集。
说明 & 推荐训练方案
-
MiniMind2 Series均经过共约20GB语料训练,大约4B tokens,即对应上面的数据组合训练结果(开销:💰💰💰💰💰💰💰💰,效果:😊😊😊😊😊😊)
-
想要最快速度从0实现Zero模型,推荐使用
pretrain_hq.jsonl
+sft_mini_512.jsonl
的数据组合,具体花销和效果可查看下文表格(开销:💰,效果:😊😊) -
推荐具备一定算力资源或更在意效果的朋友可以考虑前者完整复现MiniMind2;仅有单卡GPU或在乎短时间快速复现的朋友强烈推荐后者;
-
【折中方案】亦可选择例如
sft_mini_512.jsonl
、sft_1024.jsonl
中等规模数据进行自由组合训练(开销:💰💰💰,效果:😊😊😊😊)。
📌 Model Structure
MiniMind-Dense(和Llama3.1一样)使用了Transformer的Decoder-Only结构,跟GPT-3的区别在于:
- 采用了GPT-3的预标准化方法,也就是在每个Transformer子层的输入上进行归一化,而不是在输出上。具体来说,使用的是RMSNorm归一化函数。
- 用SwiGLU激活函数替代了ReLU,这样做是为了提高性能。
- 像GPT-Neo一样,去掉了绝对位置嵌入,改用了旋转位置嵌入(RoPE),这样在处理超出训练长度的推理时效果更好。
MiniMind-MoE模型,它的结构基于Llama3和Deepseek-V2/3中的MixFFN混合专家模块。
- DeepSeek-V2在前馈网络(FFN)方面,采用了更细粒度的专家分割和共享的专家隔离技术,以提高Experts的效果。
MiniMind的整体结构一致,只是在RoPE计算、推理函数和FFN层的代码上做了一些小调整。 其结构如下图(重绘版):
修改模型配置见./model/LMConfig.py。 参考模型参数版本见下表:
Model Name | params | len_vocab | rope_theta | n_layers | d_model | kv_heads | q_heads | share+route |
---|---|---|---|---|---|---|---|---|
MiniMind2-Small | 26M | 6400 | 1e6 | 8 | 512 | 2 | 8 | - |
MiniMind2-MoE | 145M | 6400 | 1e6 | 8 | 640 | 2 | 8 | 1+4 |
MiniMind2 | 104M | 6400 | 1e6 | 16 | 768 | 2 | 8 | - |
minimind-v1-small | 26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | - |
minimind-v1-moe | 4×26M | 6400 | 1e4 | 8 | 512 | 8 | 16 | 1+4 |
minimind-v1 | 108M | 6400 | 1e4 | 16 | 768 | 8 | 16 | - |
📌 Experiment
Ⅰ 训练开销
- 时间单位:小时 (h)。
- 成本单位:人民币 (¥);7¥ ≈ 1美元。
- 3090 租卡单价:≈1.3¥/h(可自行参考实时市价)。
- 参考标准:表格仅实测
pretrain
和sft_mini_512
两个数据集的训练时间,其它耗时根据数据集大小估算(可能存在些许出入)。
基于 3090 (单卡)成本计算
Model Name | params | pretrain | sft_mini_512 | sft_512 | sft_1024 | sft_2048 | RLHF |
---|---|---|---|---|---|---|---|
MiniMind2-Small | 26M | ≈1.1h ≈1.43¥ |
≈1h ≈1.3¥ |
≈6h ≈7.8¥ |
≈4.58h ≈5.95¥ |
≈7.5h ≈9.75¥ |
≈1h ≈1.3¥ |
MiniMind2 | 104M | ≈3.9h ≈5.07¥ |
≈3.3h ≈4.29¥ |
≈20h ≈26¥ |
≈15h ≈19.5¥ |
≈25h ≈32.5¥ |
≈3h ≈3.9¥ |
训练开销总结&预测
MiniMind2-Small参数
pretrain_hq
+sft_mini_512
数据集
单卡3090 (1 epoch) + 2.1小时 + 花费2.73元人民币
即可从0训练出MiniMind-Zero-0.025B模型!!!
MiniMind2-Small参数
pretrain_hq
+sft_512
+sft_2048
+dpo
数据集
单卡3090 (2 epochs) + 大约38.16小时 + 花费49.61元人民币
即可从0训练出MiniMind2-Small-0.025B模型!!!
MiniMind2参数
pretrain_hq
+sft_512
+sft_2048
+dpo
数据集
单卡3090 (2 epochs) + 大约122小时 + 花费158.6元人民币
即可从0训练出MiniMind2-0.1B模型!!!
✨基于单卡NVIDIA 3090的MiniMind-Zero
从0训练仅需2小时
+ 3块钱
,实现ChatBot效果!
✨PS:若采用8卡4090训练,总用时甚至可以压缩到10分钟以内!(由于时间更短,花费同样3元左右,与单卡成本相当)
✨以极低极低的门槛,实现人人可玩的大模型自由!这正是MiniMind系列的诞生初衷!
✨仅价值3块钱
成本的MiniMind-Zero
并不是噱头!Chat测试:
|
|
极速且初具效果,甚至仍然可以进一步压缩获取更小更优质的训练数据。
Zero模型权重保存为 full_sft_512_zero.pth
(见下文MiniMind模型文件链接),如有兴趣可下载检验此模型效果。
Ⅱ 主要训练步骤
所有训练脚本均
cd ./trainer
目录执行
1. 预训练(Pretrain):
LLM首先要学习的并非直接与人交流,而是让网络参数中充满知识的墨水,“墨水” 理论上喝的越饱越好,产生大量的对世界的知识积累。 预训练就是让Model先埋头苦学大量基本的知识,例如从Wiki百科、新闻、书籍整理大规模的高质量训练数据。 这个过程是“无监督”的,即人类不需要在过程中做任何“有监督”的校正,而是由模型自己从大量文本中总结规律学习知识点。 模型此阶段目的只有一个:学会词语接龙。例如我们输入“秦始皇”四个字,它可以接龙“是中国的第一位皇帝”。
|
|
训练后的模型权重文件默认每隔
100步
保存为:pretrain_*.pth
(* 为模型具体dimension,每次保存时新文件会覆盖旧文件)
2. 有监督微调(Supervised Fine-Tuning):
经过预训练,LLM此时已经掌握了大量知识,然而此时它只会无脑地词语接龙,还不会与人聊天。 SFT阶段就需要把半成品LLM施加一个自定义的聊天模板进行微调。 例如模型遇到这样的模板【问题->回答,问题->回答】后不再无脑接龙,而是意识到这是一段完整的对话结束。 称这个过程为指令微调,就如同让已经学富五车的「牛顿」先生适应21世纪智能手机的聊天习惯,学习屏幕左侧是对方消息,右侧是本人消息这个规律。 在训练时,MiniMind的指令和回答长度被截断在512,是为了节省显存空间。就像我们学习时,会先从短的文章开始,当学会写作200字作文后,800字文章也可以手到擒来。 在需要长度拓展时,只需要准备少量的2k/4k/8k长度对话数据进行进一步微调即可(此时最好配合RoPE-NTK的基准差值)。
在推理时通过调整RoPE线性差值,实现免训练长度外推到2048及以上将会很方便。
|
|
训练后的模型权重文件默认每隔
100步
保存为:full_sft_*.pth
(* 为模型具体dimension,每次保存时新文件会覆盖旧文件)
Ⅲ 其它训练步骤
所有训练脚本均
cd ./trainer
目录执行
3. 人类反馈强化学习(Reinforcement Learning from Human Feedback, RLHF)
在前面的训练步骤中,模型已经具备了基本的对话能力,但是这样的能力完全基于单词接龙,缺少正反样例的激励。 模型此时尚未知什么回答是好的,什么是差的。我们希望它能够更符合人的偏好,降低让人类不满意答案的产生概率。 这个过程就像是让模型参加新的培训,从优秀员工的作为例子,消极员工作为反例,学习如何更好地回复。 此处使用的是RLHF系列之-直接偏好优化(Direct Preference Optimization, DPO)。 与PPO(Proximal Policy Optimization)这种需要奖励模型、价值模型的RL算法不同; DPO通过推导PPO奖励模型的显式解,把在线奖励模型换成离线数据,Ref模型输出可以提前保存。 DPO性能几乎不变,只用跑 actor_model 和 ref_model 两个模型,大大节省显存开销和增加训练稳定性。
注:RLHF训练步骤并非必须,此步骤难以提升模型“智力”而通常仅用于提升模型的“礼貌”,有利(符合偏好、减少有害内容)也有弊(样本收集昂贵、反馈偏差、多样性损失)。
|
|
训练后的模型权重文件默认每隔
100步
保存为:rlhf_*.pth
(* 为模型具体dimension,每次保存时新文件会覆盖旧文件)
4. 知识蒸馏(Knowledge Distillation, KD)
在前面的所有训练步骤中,模型已经完全具备了基本能力,通常可以学成出师了。
而知识蒸馏可以进一步优化模型的性能和效率,所谓知识蒸馏,即学生模型面向教师模型学习。
教师模型通常是经过充分训练的大模型,具有较高的准确性和泛化能力。
学生模型是一个较小的模型,目标是学习教师模型的行为,而不是直接从原始数据中学习。
在SFT学习中,模型的目标是拟合词Token分类硬标签(hard labels),即真实的类别标签(如 0 或 6400)。
在知识蒸馏中,教师模型的softmax概率分布被用作软标签(soft labels)。小模型仅学习软标签,并使用KL-Loss来优化模型的参数。
通俗地说,SFT直接学习老师给的解题答案。而KD过程相当于“打开”老师聪明的大脑,尽可能地模仿老师“大脑”思考问题的神经元状态。
例如,当老师模型计算1+1=2
这个问题的时候,最后一层神经元a状态为0,神经元b状态为100,神经元c状态为-99…
学生模型通过大量数据,学习教师模型大脑内部的运转规律。这个过程即称之为:知识蒸馏。
知识蒸馏的目的只有一个:让小模型体积更小的同时效果更好。
然而随着LLM诞生和发展,模型蒸馏一词被广泛滥用,从而产生了“白盒/黑盒”知识蒸馏两个派别。
GPT-4这种闭源模型,由于无法获取其内部结构,因此只能面向它所输出的数据学习,这个过程称之为黑盒蒸馏,也是大模型时代最普遍的做法。
黑盒蒸馏与SFT过程完全一致,只不过数据是从大模型的输出收集,因此只需要准备数据并且进一步FT即可。
注意更改被加载的基础模型为full_sft_*.pth
,即基于微调模型做进一步的蒸馏学习。
./dataset/sft_1024.jsonl
与./dataset/sft_2048.jsonl
均收集自qwen2.5-7/72B-Instruct大模型,可直接用于SFT以获取Qwen的部分行为。
|
|
训练后的模型权重文件默认每隔
100步
同样保存为:full_sft_*.pth
(*为模型具体dimension,每次保存时新文件会覆盖旧文件)
此处应当着重介绍MiniMind实现的白盒蒸馏代码train_distillation.py
,由于MiniMind同系列本身并不存在强大的教师模型,因此白盒蒸馏代码仅作为学习参考。
|
|
5. LoRA (Low-Rank Adaptation)
LoRA是一种高效的参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)方法,旨在通过低秩分解的方式对预训练模型进行微调。
相比于全参数微调(Full Fine-Tuning),LoRA 只需要更新少量的参数。
LoRA 的核心思想是:在模型的权重矩阵中引入低秩分解,仅对低秩部分进行更新,而保持原始预训练权重不变。
代码可见./model/model_lora.py
和train_lora.py
,完全从0实现LoRA流程,不依赖第三方库的封装。
|
|
训练后的模型权重文件默认每隔
100步
保存为:lora_xxx_*.pth
(* 为模型具体dimension,每次保存时新文件会覆盖旧文件)
非常多的人困惑,如何使模型学会自己私有领域的知识?如何准备数据集?如何迁移通用领域模型打造垂域模型?
这里举几个例子,对于通用模型,医学领域知识欠缺,可以尝试在原有模型基础上加入领域知识,以获得更好的性能。
同时,我们通常不希望学会领域知识的同时损失原有基础模型的其它能力,此时LoRA可以很好的改善这个问题。
只需要准备如下格式的对话数据集放置到./dataset/lora_xxx.jsonl
,启动 python train_lora.py
训练即可得到./out/lora/lora_xxx.pth
新模型权重。
医疗场景
|
|
自我认知场景
|
|
此时【基础模型+LoRA模型】即可获得医疗场景模型增强的能力,相当于为基础模型增加了LoRA外挂,这个过程并不损失基础模型的本身能力。
我们可以通过eval_model.py
进行模型评估测试。
|
|
小测试
|
|
PS:只要有所需要的数据集,也可以full_sft全参微调(需要进行通用知识的混合配比,否则过拟合领域数据会让模型变傻,损失通用性)
6. 训练推理模型 (Reasoning Model)
DeepSeek-R1实在太火了,几乎重新指明了未来LLM的新范式。
论文指出>3B
的模型经历多次反复的冷启动和RL奖励训练才能获得肉眼可见的推理能力提升。
最快最稳妥最经济的做法,以及最近爆发的各种各样所谓的推理模型几乎都是直接面向数据进行蒸馏训练,
但由于缺乏技术含量,蒸馏派被RL派瞧不起(hhhh)。
本人迅速已经在Qwen系列1.5B小模型上进行了尝试,很快复现了Zero过程的数学推理能力。
然而一个遗憾的共识是:参数太小的模型直接通过冷启动SFT+GRPO几乎不可能获得任何推理效果。
MiniMind2第一时间只能坚定不移的选择做蒸馏派,日后基于0.1B模型的RL如果同样取得小小进展会更新此部分的训练方案。
做蒸馏需要准备的依然是和SFT阶段同样格式的数据即可,数据集来源已如上文介绍。数据格式例如:
|
|
推理模型R1的回复模板是:
|
|
这在GRPO中通过设置规则奖励函数约束模型符合思考标签和回复标签(在冷启动靠前的阶段奖励值设置应该提高一些)
另一个问题是蒸馏过程虽然和SFT一样,但实验结果是模型难以每次都符合模板规范的回复,即脱离思考和回复标签约束。
这里的小技巧是增加标记位置token的损失惩罚,详见train_distill_reason.py
:
|
|
另另一个tips是由于推理数据由于只筛选了<1024
长度的数据,其中多轮对话和英文数据偏少,
因此r1_mix_1024.jsonl
进行了大约10k条多轮对话+英文数据的混合,防止模型遗忘严重。
脚本默认基于rlhf后的基模型做推理能力的蒸馏微调,下面直接启动训练即可:
|
|
训练后的模型权重文件默认每隔
100步
保存为:reason_*.pth
(*为模型具体dimension,每次保存时新文件会覆盖旧文件)
测试一下:
|
|
Ⅳ 模型参数设定
📋关于LLM的参数配置,有一篇很有意思的论文MobileLLM做了详细的研究和实验。
Scaling Law在小模型中有自己独特的规律。
引起Transformer参数成规模变化的参数几乎只取决于d_model
和n_layers
。
d_model
↑ +n_layers
↓ -> 矮胖子d_model
↓ +n_layers
↑ -> 瘦高个
2020年提出Scaling Law的论文认为,训练数据量、参数量以及训练迭代次数才是决定性能的关键因素,而模型架构的影响几乎可以忽视。
然而似乎这个定律对小模型并不完全适用。
MobileLLM提出架构的深度比宽度更重要,「深而窄」的「瘦长」模型可以学习到比「宽而浅」模型更多的抽象概念。
例如当模型参数固定在125M或者350M时,30~42层的「狭长」模型明显比12层左右的「矮胖」模型有更优越的性能,
在常识推理、问答、阅读理解等8个基准测试上都有类似的趋势。
这其实是非常有趣的发现,因为以往为100M左右量级的小模型设计架构时,几乎没人尝试过叠加超过12层。
这与MiniMind在训练过程中,模型参数量在d_model
和n_layers
之间进行调整实验观察到的效果是一致的。
然而「深而窄」的「窄」也是有维度极限的,当d_model<512时,词嵌入维度坍塌的劣势非常明显,
增加的layers并不能弥补词嵌入在固定q_head带来d_head不足的劣势。
当d_model>1536时,layers的增加似乎比d_model的优先级更高,更能带来具有“性价比”的参数->效果增益。
- 因此MiniMind设定small模型dim=512,n_layers=8来获取的「极小体积<->更好效果」的平衡。
- 设定dim=768,n_layers=16来获取效果的更大收益,更加符合小模型Scaling-Law的变化曲线。
作为参考,GPT3的参数设定见下表:
Ⅴ 训练结果
MiniMind2 模型训练损失走势(由于数据集在训练后又更新清洗多次,因此Loss仅供参考)
models | pretrain (length-512) | sft (length-512) |
---|---|---|
MiniMind2-Small | ![]() |
![]() |
MiniMind2 | ![]() |
![]() |
训练完成-模型合集
考虑到多人反应百度网盘速度慢,MiniMind2及以后全部使用ModelScope/HuggingFace托管。
① PyTorch原生模型
MiniMind2模型权重 (ModelScope | HuggingFace)
MiniMind-V1模型权重 (百度网盘)
Torch文件命名对照
Model Name | params | pretrain_model | sft_model | rl_model | reason_model | lora_model |
---|---|---|---|---|---|---|
MiniMind2-small | 26M | pretrain_512.pth |
full_sft_512.pth |
rlhf_512.pth |
reason_512.pth |
lora_xxx_512.pth |
MiniMind2-MoE | 145M | pretrain_640_moe.pth |
full_sft_640_moe.pth |
rlhf_640_moe.pth |
- | - |
MiniMind2 | 104M | pretrain_768.pth |
full_sft_768.pth |
rlhf_768.pth |
reason_768.pth |
lora_xxx_768.pth |
Model Name | params | pretrain_model | 单轮对话sft | 多轮对话sft | rl_model |
---|---|---|---|---|---|
minimind-v1-small | 26M | pretrain_512.pth |
single_chat/full_sft_512.pth |
multi_chat/full_sft_512.pth |
rl_512.pth |
minimind-v1-moe | 4×26M | pretrain_512_moe.pth |
single_chat/full_sft_512_moe.pth |
multi_chat/full_sft_512_moe.pth |
- |
minimind-v1 | 108M | pretrain_768.pth |
single_chat/full_sft_768.pth |
multi_chat/full_sft_768.pth |
rl_768.pth |
② Transformers模型
MiniMind系列 (ModelScope | HuggingFace)
📌 Eval
Ⅰ RLHF对比SFT篇
测试基于full_sft
和rlhf
的MiniMind2系列
模型对比,测试随机种子均固定
问答实测
[A0] MiniMind2:full_sft_640
[A1] MiniMind2:rlhf_640
|
|
👉效果总结
full_sft模型在简洁性和信息准确性方面表现更好;rlhf模型在回答中倾向于提供更多的背景信息,但信息准确性有待改进。 总的来说RLHF后的模型倾向于学习:说更多有礼貌但无用的废话讨好“对话”本身,而对信息准确性则有轻微损失。 天下没有免费的午餐,还需要继续提升RLHF数据集的质量,也要接受模型能力无法避免的损失(程度有轻重)。 DPO和在线PPO的区别在于reject和chosen都是离线准备的,和minimind模型本身的输出必然存在很大的分布差异。 通俗地说DPO算法使模型观看乒乓球世界冠军的打法「录像」进行RL,而不是像PPO一样请reward模型做「教练」纠正自己的打法进行RL。
Ⅱ 主观样例测评
🏃以下测试于2025-02-09完成,此日期后发布的新模型,无特殊需要时将不加入测试。
[A] MiniMind2 (0.1B)
[B] MiniMind2-MoE (0.15B)
[C] MiniMind2-Small (0.02B)
[D] minimind-v1-small(0.02B)
[E] minimind-v1-moe(0.1B)
[F] minimind-v1(0.1B)
[G] baby-llama2-chinese(0.2B)
[H] chatlm-mini-chinese(0.2B)
|
|
🙋直接把以上所有问题和模型的回答丢给DeepSeek-R1,让它帮忙点评和排名打分:
具体点评
评分标准:
- 准确性:回答是否正确且无明显错误。
- 完整性:回答是否涵盖了问题的核心要点。
- 逻辑性:回答是否有条理,是否符合逻辑。
- 代码质量:代码是否能正常运行,逻辑是否清晰。
点评:
-
A模型:
- 优点:回答非常全面,信息量大,逻辑清晰,尤其在长江、大熊猫、海水咸味等问题上表现优异。代码虽然有小瑕疵,但整体思路正确。
- 缺点:部分回答稍显冗长,但不影响整体质量。
- 总评:综合表现最佳,得分最高。
-
H模型:
- 优点:回答较为准确,尤其在珠穆朗玛峰、万有引力等问题上表现出色。代码虽未完全展示,但解释较为详细。
- 缺点:部分回答略显啰嗦,但逻辑性较强。
- 总评:仅次于A模型,表现稳定。
-
C模型:
- 优点:回答简洁明了,尤其在大熊猫、快速排序代码等问题上表现较好。
- 缺点:部分回答略显简短,缺乏深入解释。
- 总评:整体表现不错,但细节上略逊于A和H。
-
F模型:
- 优点:回答较为准确,尤其在长江、万有引力等问题上表现尚可。代码部分有一定逻辑性。
- 缺点:部分回答不够深入,代码存在一些小问题。
- 总评:表现中规中矩,仍有提升空间。
-
D模型:
- 优点:回答基本准确,尤其在万有引力、长江等问题上表现尚可。
- 缺点:部分回答过于简略,代码存在明显错误。
- 总评:表现一般,需改进代码部分。
-
B模型:
- 优点:回答较为准确,尤其在长江、海水咸味等问题上表现尚可。
- 缺点:部分回答逻辑性较差,代码存在较大问题。
- 总评:表现平平,需进一步优化。
-
E模型:
- 优点:部分回答较为准确,尤其在海水咸味、大熊猫等问题上表现尚可。
- 缺点:回答过于简略,代码部分几乎无法运行。
- 总评:表现不佳,需大幅提升。
-
G模型:
- 优点:几乎没有明显的优点。
- 缺点:回答严重偏离主题,代码部分完全无法运行。
- 总评:表现最差,需大幅改进。
总结:
- A模型在各方面表现最为出色,尤其在复杂问题的回答上展现了极高的准确性与逻辑性。
- H模型紧随其后,表现稳定,但在某些细节上略显不足。
- G模型表现最差,回答偏离主题且代码无法运行,需大幅改进。
打分排序
排名 | 模型 | 准确性 (30分) | 完整性 (30分) | 逻辑性 (20分) | 代码质量 (20分) | 总分 (100分) |
---|---|---|---|---|---|---|
1 | A | 28 | 29 | 19 | 20 | 96 |
2 | H | 27 | 28 | 18 | 20 | 93 |
3 | C | 26 | 27 | 18 | 18 | 89 |
4 | F | 25 | 26 | 17 | 18 | 86 |
5 | D | 24 | 25 | 17 | 16 | 82 |
6 | B | 23 | 24 | 16 | 15 | 78 |
7 | E | 22 | 23 | 15 | 14 | 74 |
8 | G | 10 | 12 | 10 | 10 | 42 |
👉主观效果总结
个人主观评价与DeepSeek-R1基本相符,其中:
-
MiniMind系列的排序非常符合直觉,参数越大+训练数据越充分评分越高,幻觉和错误都会比小模型肉眼可见的好。
-
H模型的回答肉眼看起来是不错的,尽管存在些许幻觉瞎编的情况。
-
G模型可能训练数据不够完备,给出的权重经过测试效果不佳。
-
再复诵一遍经久不衰的Scaling Law: 参数越大,训练数据越多模型的性能越强。
Ⅲ Objective Benchmark
下面就到喜闻乐见的benchmark刷榜测试环节,就不找乐子和qwen、glm级别的中文模型做对比了。 这里选取了一些<1B的微型模型进行横评比较, 测试集选择C-Eval、CMMLU、A-CLUE、TMMLU+这几个纯中文语言榜单。
测评框架
测评框架选择lm-evaluation, 安装后启动测试非常方便:
|
|
PS: 在这种全是选择题的测评集中,为了避免回复格式的难以固定的特点,
所以常用做法是直接把A
,B
,C
,D
四个字母对应token的预测概率取出来,将其中概率最大的字母与标准答案计算正确率。
选择题1/4乱选的正确率是25%,然而这个量级的所有模型都集中在25附近,甚至很多时候不如瞎选,是不是像极了高中完形填空的滑铁卢正确率…
MiniMind模型本身预训练数据集小的可怜,也没有针对性的对测试集做刷榜微调,因此结果图一乐即可:
models | from | params↓ | ceval↑ | cm mlu↑ | aclue↑ | tmmlu+↑ |
---|---|---|---|---|---|---|
MiniMind2 | JingyaoGong | 104M | 26.52 | 24.42 | 24.97 | 25.27 |
MiniMind2-Small | JingyaoGong | 26M | 26.37 | 24.97 | 25.39 | 24.63 |
MiniMind2-MoE | JingyaoGong | 145M | 26.6 | 25.01 | 24.83 | 25.01 |
Steel-LLM | ZhanShiJin | 1121M | 24.81 | 25.32 | 26 | 24.39 |
GPT2-medium | OpenAI | 360M | 23.18 | 25 | 18.6 | 25.19 |
TinyLlama-1.1B-Chat-V1.0 | TinyLlama | 1100M | 25.48 | 25 | 25.4 | 25.13 |
SmolLM2 | HuggingFaceTB | 135M | 24.37 | 25.02 | 25.37 | 25.06 |
Aquila-Instruct | BAAI | 135M | 25.11 | 25.1 | 24.43 | 25.05 |
📌 其它 (Others)
模型转换
- ./scripts/convert_model.py可以实现
torch模型/transformers
模型之间的转换
基于MiniMind-API服务接口
-
./scripts/serve_openai_api.py完成了兼容openai-api的最简聊天接口,方便将自己的模型接入第三方UI 例如FastGPT、OpenWebUI、Dify等等。
-
从Huggingface下载模型权重文件,文件树:
1 2 3 4 5 6 7 8 9 10
<MiniMind-Model-Name> (root dir) ├─<MiniMind-Model-Name> | ├── config.json | ├── generation_config.json | ├── LMConfig.py | ├── model.py | ├── pytorch_model.bin | ├── special_tokens_map.json | ├── tokenizer_config.json | ├── tokenizer.json
-
启动聊天服务端
1
python serve_openai_api.py
-
测试服务接口
1
python chat_openai_api.py
-
API接口示例,兼容openai api格式
1 2 3 4 5 6 7 8 9 10 11
curl http://ip:port/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "model-identifier", "messages": [ { "role": "user", "content": "世界上最高的山是什么?" } ], "temperature": 0.7, "max_tokens": 512, "stream": true }'
VLLM模型推理(服务)
vLLM是极其流行的高效推理框架,支持大模型快速部署,优化显存利用与吞吐量。
|
|
服务将以openai api协议启动,端口默认为8000。
更多用法请参考官方说明~
llama.cpp
llama.cpp是一个C++库, 可以在命令行下直接使用,支持多线程推理,支持GPU加速。
参考官方仓库安装后,在convert_hf_to_gguf.py
~760行插入
|
|
转换自定义训练的minimind模型 -> gguf
|
|
量化模型
|
|
命令行推理
|
|
更多用法请参考官方说明~
ollama
ollama是本地运行大模型的工具,支持多种开源LLM,简单易用。
通过ollama加载自定义的gguf模型,新建minimind.modelfile:
|
|
加载模型并命名为minimind2
|
|
启动推理
|
|
更多用法请参考官方说明~
📌 Acknowledge
[!NOTE] 如果觉得
MiniMind系列
对您有所帮助,可以在 GitHub 上加一个⭐
篇幅超长水平有限难免纰漏,欢迎在Issues交流指正或提交PR改进项目
您的小小支持就是持续改进此项目的动力!
🤝贡献者
😊鸣谢
参考链接 & 感谢以下优秀的论文或项目
- 排名不分任何先后顺序
- https://github.com/meta-llama/llama3
- https://github.com/karpathy/llama2.c
- https://github.com/DLLXW/baby-llama2-chinese
- (DeepSeek-V2)https://arxiv.org/abs/2405.04434
- https://github.com/charent/ChatLM-mini-Chinese
- https://github.com/wdndev/tiny-llm-zh
- (Mistral-MoE)https://arxiv.org/pdf/2401.04088
- https://github.com/Tongjilibo/build_MiniLLM_from_scratch
- https://github.com/jzhang38/TinyLlama
- https://github.com/AI-Study-Han/Zero-Chatgpt
- https://github.com/xusenlinzy/api-for-open-llm
- https://github.com/HqWu-HITCS/Awesome-Chinese-LLM
🫶支持者
License
This repository is licensed under the Apache-2.0 License.