普通人从0开始训练LLM大语言模型

普通人从0开始训练LLM大语言模型

  • 首先声明。本项目基于开源项目:MiniMind,基于个人的理解和踩坑。做了个人的理解和注释。完成从小白开始,从0训练一个LLM大语言模型。项目源地址:https://github.com/jingyaogong/minimind
  • MiniMind极其轻量,力求做到最普通的个人GPU也可快速推理甚至训练。
  • MiniMind发布了大模型极简结构,数据集清洗和预处理、监督预训练(Pretrain)、有监督指令微调(SFT)、低秩自适应(LoRA) 微调,无奖励强化学习直接偏好对齐(DPO)的全阶段代码,也包含拓展共享混合专家(MoE) 的稀疏模型。
  • 这不仅是一个开源模型的实现,也是入门大语言模型(LLM)的教程。希望此项目能为研究者提供一个抛砖引玉的入门示例,帮助大家快速上手并对LLM领域产生更多的探索与创新。

前言

大语言模型(LLM)领域,如 GPT、LLaMA、GLM 等,虽然它们效果惊艳, 但动辄10 Bilion庞大的模型参数个人设备显存远不够训练,甚至推理困难。 几乎所有人都不会只满足于用Lora等方案fine-tuing大模型学会一些新的指令, 这约等于在教牛顿玩21世纪的智能手机,然而,这远远脱离了学习物理本身的奥妙。 此外,卖课付费订阅的营销号漏洞百出的一知半解讲解AI的教程遍地, 让理解LLM的优质内容雪上加霜,严重阻碍了学习者。

因此,本项目的目标是把上手LLM的门槛无限降低, 直接从0开始训练一个极其轻量的语言模型。

Tip

(截至2025-2-8)MiniMind系列已完成了1个型号微小模型的预训练,最小仅需26M(0.02B),即可具备流畅的对话能力!

模型 (大小)tokenizer长度推理占用release主观评分(/100)
minimind-v1-small (26M)64000.5 GB2025.02.0850’

该分析在具有Torch 2.1.2、CUDA 12.6 和 NVIDIA GeForce RTX 4060 Laptop GPU上进行。没错,是在本人的笔记本上进行的。

项目包含:

  • 公开MiniMind模型代码(包含Dense和MoE模型)、Pretrain、SFT指令微调、LoRA微调、DPO偏好优化的全过程代码、数据集和来源。
  • 兼容transformersacceleratetrlpeft等流行框架。
  • 训练支持单机单卡、单机多卡(DDP、DeepSpeed)训练,使用wandb可视化训练流程。支持在任意位置停止,及在任意位置继续训练。
  • 在Ceval数据集上进行模型测试的代码。
  • 实现Openai-Api基本的chat接口,便于集成到第三方ChatUI使用(FastGPT、Open-WebUI等)。

希望此开源项目可以帮助LLM初学者快速入门!

基础环境

仅是我个人的软硬件环境配置,自行推理或训练,请自行酌情更改:

CPU: Intel(R) Core(TM) i7-13620H
内存:32 GB
显卡:NVIDIA GeForce RTX 4060 Laptop GPU
环境:python 3.10 + Torch 2.1.2 + DDP单机多卡训练
系统:win11专业工作站版本 + Anaconda3-2024.02-1-Windows-x86_64

初始化环境安装

本次推理和训练,均采用Anaconda3部署环境,环境要求:

# 初始化虚拟环境
conda create -n minimind-v1 python=3.10

# 激活环境
conda activate minimind-v1

# 配置conda环境为国内源,可自行更改
# 设置清华源
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/

# 部署torch
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu126

# 测试torch是否可用cuda
# python解释器下进行
import torch
print(torch.cuda.is_available())

cuda、python和操作系统是有严格的关联关系。torch如果不可用,请自行去https://pytorch.org/get-started/locally/ 下载对应的版本。

启动训练

1、克隆项目代码

git clone https://gitee.com/zhu-wanming/minimind-v1-small.git

2、环境安装

pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 注意torch请根据自身设备情况,安装对应版本

3、下载数据集

对应下载的数据集信息如下:

【tokenizer训练集】	tokenizer_train.jsonl 大概980M
【Pretrain数据】	pretrain_data.csv 大概4.33G
【SFT数据】	sft_data_zh.jsonl 大概16G
【DPO数据】	./dpo/* 所有文件大概72M

数据集下载完成后,我们可以开始训练任务了!

注意:关于训练模型的大小和精度,请在./model/LMConfig.py 中调整model的参数配置
这里仅需调整dim和n_layers和use_moe参数,分别是(512+8)或(768+16),对应于minimind-v1-small和minimind-v1

4、处理数据集

抽取sft_data_zh.jsonl sft数据集抽离qa到csv文件(例如pretrain数据提前进行token-encoder、sft数据集抽离qa到csv文件)

# 处理数据集
python data_process.py 

# 抽取数据时间大概5分钟左右。在./dataset 目录下生成 sft_data_single.csv 文件。

5、预训练

对Pretrain数据 pretrain_data.csv 执行预训练,得到 pretrain_*.pth 作为预训练的输出权重

python 1-pretrain.py

# 因为本地显卡是笔记本型号,显存占用高且训练时间长,预训练时间大概9小时左右。训练完成会在./out 目录下生成pretrain_*.pth权重模型。

在这里插入图片描述
在这里插入图片描述

6、指令微调

执行指令微调,得到 full_sft_*.pth 作为指令微调的输出权重

python 3-full_sft.py 

# 因为本地显卡是笔记本型号,显存占用高且微调时间长,微调时间大概9小时左右。微调完成会在./out 目录下生成full_sft_*.pth作为指令微调的输出权重。

在这里插入图片描述
在这里插入图片描述

7、执行lora微调(非必须)

python 4-lora_sft.py 

# 本次训练旨在快速训练一个LLM大语言小模型,此步骤可不做。后续完全熟悉后可自行调整处理。

8、执行DPO人类偏好强化学习对齐(非必须)

python 5-dpo_train.py 

# 本次训练旨在快速训练一个LLM大语言小模型,此步骤可不做。后续完全熟悉后可自行调整处理。

以上除了非必须步骤都完成后,专属于个人的LLM大语言小模型就已经训练完成了。接下来可以开始运行测试。

测试LLM训练模型

1、测试预训练模型的接龙效果

python 0-eval_pretrain.py

# 本次训练的LLM模型较小,执行推理测试时候,显存占用较低且速度极快。

在这里插入图片描述
在这里插入图片描述

2、连续对话测试

python 2-eval.py

在这里插入图片描述

3、启动网页聊天界面

# 需要python>=3.10,安装 pip install streamlit==1.27.2
streamlit run fast_inference.py

在这里插入图片描述
在这里插入图片描述

推理与导出

1、导出模型

python ./export_model.py
# 可以导出模型到transformers格式,推送到huggingface

2、API推理

python my_openai_api.py
# 完成了openai_api的聊天接口,方便将自己的模型接入第三方UI 例如fastgpt、OpenWebUI等
  • 模型可用自己的训练模型,也可从Huggingface下载已经训练好了的模型权重文件

    minimind (root dir)
    ├─minimind
    |  ├── config.json
    |  ├── generation_config.json
    |  ├── LMConfig.py
    |  ├── model.py
    |  ├── pytorch_model.bin
    |  ├── special_tokens_map.json
    |  ├── tokenizer_config.json
    |  ├── tokenizer.json
    
  • 启动聊天服务端

    python my_openai_api.py
    
  • 测试服务接口

    python chat_openai_api.py
    
  • API接口示例,兼容openai api格式

    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": -1,
        "stream": true
    }'
    

评测

C-Eval评测代码见:./eval_ceval.py

小模型的测评通常为了避免回复格式的难以固定的特点, 而直接判断A,B,C,D四个字母对应token预测概率,取最大的作为回答答案,与标准答案计算正确率。 minimind模型本身没有使用较大的数据集训练,也没有针对回答选择题的指令做微调,测评结果可以当个参考。

例如minimind-small的结果细项:

Type12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
Dataprobability_and_statisticslawmiddle_school_biologyhigh_school_chemistryhigh_school_physicslegal_professionalhigh_school_chinesehigh_school_historytax_accountantmodern_chinese_historymiddle_school_physicsmiddle_school_historybasic_medicineoperating_systemlogicelectrical_engineercivil_servantchinese_language_and_literaturecollege_programmingaccountantplant_protectionmiddle_school_chemistrymetrology_engineerveterinary_medicinemarxismadvanced_mathematicshigh_school_mathematicsbusiness_administrationmao_zedong_thoughtideological_and_moral_cultivationcollege_economicsprofessional_tour_guideenvironmental_impact_assessment_engineercomputer_architectureurban_and_rural_plannercollege_physicsmiddle_school_mathematicshigh_school_politicsphysiciancollege_chemistryhigh_school_biologyhigh_school_geographymiddle_school_politicsclinical_medicinecomputer_networksports_scienceart_studiesteacher_qualificationdiscrete_mathematicseducation_sciencefire_engineermiddle_school_geography
Type12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
T/A3/185/244/217/195/192/234/196/2010/494/234/194/221/193/194/227/3711/475/2310/379/497/224/203/246/235/195/194/188/338/245/1917/5510/297/316/2111/465/193/194/1913/493/245/194/196/216/222/192/1914/3312/446/167/299/311/12
Accuracy16.67%20.83%19.05%36.84%26.32%8.70%21.05%30.00%20.41%17.39%21.05%18.18%5.26%15.79%18.18%18.92%23.40%21.74%27.03%18.37%31.82%20.00%12.50%26.09%26.32%26.32%22.22%24.24%33.33%26.32%30.91%34.48%22.58%28.57%23.91%26.32%15.79%21.05%26.53%12.50%26.32%21.05%28.57%27.27%10.53%10.53%42.42%27.27%37.50%24.14%29.03%8.33%
总题数: 1346  
总正确数: 316  
总正确率: 23.48%

结果汇总:

categorycorrectquestion_countaccuracy
minimind-v1-small344134625.56%
minimind-v1351134626.08%

验证

Model Nameparamslen_vocabbatch_sizepretrain_timesft_single_timesft_multi_time
minimind-v1-small26M640064≈2 hour (1 epoch)≈2 hour (1 epoch)≈0.5 hour (1 epoch)
minimind-v1-moe4×26M640040≈6 hour (1 epoch)≈5 hour (1 epoch)≈1 hour (1 epoch)
minimind-v1108M640016≈6 hour (1 epoch)≈4 hour (1 epoch)≈1 hour (1 epoch)

  1. 预训练(Text-to-Text):

    • LLM首先要学习的并非直接与人交流,而是让肚子中充满知识的墨水,至于墨水理论上喝的越饱越好,产生大量的对世界的认知积累。
    • 预训练就是让Model先埋头苦学大量基本的知识,例如从维基百科、新闻、常识、书籍等。
    • 它无监督的从大量的文本数据中压缩知识到自己模型的权重,目的是:学会词语接龙。例如我们输入“秦始皇是”四个字,它在大量学习后能预测出下一句话大概率是“中国的第一位皇帝”。

    pretrain的学习率设置为1e-4到1e-5的动态学习率,预训练epoch数设为5。

    torchrun --nproc_per_node 2 1-pretrain.py
    
  2. 单轮次对话有监督微调(Single dialog Fine-tuning):

    • 经过预训练,半成品LLM此时已经掌握了几乎所有的语言知识和百科常识。此时它还不会与人聊天,相反它只会无脑地进行输入词语的接龙,生成下一个词。
    • 此时需要对半成品LLM做限制在聊天模板中进行微调,例如当它遇到这样的模板“<聊天开始>秦始皇是<聊天终止> ”后不再无脑接龙,而是意识到这是一段完整的对话结束。
    • 我们称这个过程为指令微调,就如同让学富五车的「牛顿」先生适应21世纪的聊天习惯,学习屏幕左侧是对方消息,右侧是本人消息这个规律。
    • 在训练时,MiniMind的指令和回答长度被截断在512,是为了节省显存空间。就像我们学习时,会先从短的文章开始,当学会阅读200字作文后,800字长文章就不需要再单独学习。

    在推理时通过调整RoPE线性差值,实现长度外推到1024或2048及以上很方便。学习率设置为1e-5到1e-6的动态学习率,微调epoch数为6。

    # 3-full_sft.py中设置数据集为sft_data_single.csv
    torchrun --nproc_per_node 2 3-full_sft.py
    
  3. 多轮对话微调(Multi dialog Fine-tuning):

    • 在2的基础上,LLM已经学会一个问题->一个回答的聊天模板。此时仅需在具备历史问答的更长聊天模板上进一步微调即可。
    • 我们仅需使用数据集的history_chat 字段,即历史对话,以及history_chat_response字段,即历史对话的回答。
    • 构建【问题->回答,问题->回答,问题->】的新聊天模板,然后使用这个数据集进行微调。
    • 学习完成的模型不仅仅只能回答当前问题,还能根据历史对话进行连贯的对话。
    • 这一步 并非必须 ,因为小模型长上文对话能力很弱,强行对齐多轮问答模板会损失一定程度的单轮SFT效果。

    学习率设置为1e-5到1e-6的动态学习率,微调epoch数为5。

    # 3-full_sft.py中设置数据集为sft_data.csv
    torchrun --nproc_per_node 2 3-full_sft.py
    
  4. 人类反馈强化学习(RLHF)之-直接偏好优化(Direct Preference Optimization, DPO):

    • 在前面的训练中,GPT已经具备了基本的对话能力,但是这样的能力完全基于单词接龙,缺少正例反例的激励。
    • GPT尚且未知什么回答是好的,什么是差的。我们希望它能够更符合人的偏好,给出更让人满意的回答。
    • 这个过程就像是让GPT参加工作培训,从优秀员工的作为例子,消极员工作为反例,学习如何更好地服务客户。
    • RLHF系列中,与PPO(Proximal Policy Optimization)这种需要奖励模型、价值模型的RL算法不同;
    • DPO通过推导PPO奖励模型的显式解,把在线奖励模型换成离线数据,ref输出可以提前保存。
    • DPO性能几乎不变,只用跑 actor 和 ref 2 个模型,大大节省显存开销和增加训练稳定性。
    • 同样的,LLM的RL步骤也 并非必须,有利也有弊。

    活字三元组(q,chose,reject)数据集,学习率le-5,半精度fp16,共1个epoch,耗时1h。

    python 5-dpo_train.py
    

📋关于LLM的参数配置,有一篇很有意思的论文MobileLLM做了详细的研究和实验。 scaling law在小模型中有自己独特的规律。 引起Transformer参数成规模变化的参数几乎只取决于d_modeln_layers

  • d_model↑+n_layers↓->矮胖子

  • d_model↓+n_layers↑->瘦高个

    2020年提出Scaling Law的论文认为,训练数据量、参数量以及训练迭代次数才是决定性能的关键因素,而模型架构的影响几乎可以忽视。 然而似乎这个定律对小模型并不完全适用。 MobileLLM提出架构的深度比宽度更重要,「深而窄」的「瘦长」模型可以学习到比「宽而浅」模型更多的抽象概念。 例如当模型参数固定在125M或者350M时,30~42层的「狭长」模型明显比12层左右的「矮胖」模型有更优越的性能, 在常识推理、问答、阅读理解等8个基准测试上都有类似的趋势。 这其实是非常有趣的发现,因为以往为100M左右量级的小模型设计架构时,几乎没人尝试过叠加超过12层。 这与MiniMind在训练过程中,模型参数量在d_modeln_layers之间进行调整实验观察到的效果是一致的。 然而「深而窄」的「窄」也是有维度极限的,当d_model<512时,词嵌入维度坍塌的劣势非常明显, 增加的layers并不能弥补词嵌入在固定q_head带来d_head不足的劣势。 当d_model>1536时,layers的增加似乎比d_model的优先级更高,更能带来具有“性价比”的参数->效果增益。 因此MiniMind设定small模型的d_model=512,n_layers=8来获取的「极小体积<->更好效果」的平衡。 设定d_model=768,n_layers=16来获取效果的更大收益,更加符合小模型scaling-law的变化曲线。

作为参考,GPT3的参数设定见下表:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值