LLM基础学习03:Qwen2.5-1.5B-Instruct指令微调全流程实践——LLaMA Factor ...

王柳  金牌会员 | 2025-3-10 22:48:24 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 993|帖子 993|积分 2979

盼望尽大概将自己学习过程中参考过的资料进行系统的整理,方便后面的初学者更快的找到自己想要的资料!
  笔记持续更新中…
LLM基础学习01:LLM解码计谋和显存占用计算
LLM基础学习02:分布式训练核心架构与多级并行计谋详解——DDP/FSDP/ZeRO实战代码、显存优化方案及技术资源全景索引
本文的所有代码都放在了仓库Basic-LLM-Learning中,欢迎star!!!
简介

LLM的训练中大抵可以分为六个任务:data preparation(数据准备), pre-training(预训练), fine-tuning(微调), instruction-tuning(指令调优), preference alignment(偏好对齐), and applications(卑鄙应用)。关于数据准备和预训练阶段,通常需要进行大量的准备工作和充足的显卡资源,作者作为个人爱勤学习者现在是打仗不到的;而微调和指令微调的区别在于:微调盼望模型顺应特定任务(比如分类,翻译等)通常是针对单一任务优化,而指令微调则盼望模型可以理解并依照自然语言表现的指令,可以完成多种任务;偏好对齐则是训练模型使其生成更符合人类偏好的答案。
这篇笔记主要是对指令微调进行学习和代码实现。
LLM数据集中的JSON

训练过程中数据集和数据集信息文件都会涉及到JSON文件,以是这里对用到的JSON的语法进行简要的记录,更具体的先容和各种数据集的用途可以依据LLaMA Factory的文档先容,附上相关数据处理的链接:数据集格式。下面只对数据集中用到的相关语法进行先容,主要参考资料是菜鸟教程。
JSON中的对象用 {}表现,具体应用类似于python中的字典(一个对象中可以有多个键值对,数据由英文逗号进行分隔),比如数据集中的一个样本就是一个对象,可以表现为:
  1. {
  2.     "instruction": "你是一个AI助手,请准确回答下面的问题:",
  3.     "input": "在Mygo中最后睦给soyo送的礼物是什么?",
  4.     "output": "在《BanG Dream! It's MyGO!!!!!》中,最后睦送给Soyo的礼物是自己亲手种的小黄瓜。"
  5. }
复制代码
在这里,相当于一个训练的样本里有3个键值对:instruction,input和output,分别代表人类指令、人类输出和模型回答(如今只针对JSON的格式进行先容,更具体的表明会放在后面)。别的,JSON中没有缩进要求,但是为了可读性还是只管在config类的里面保持缩进比较好。
而JSON中的数组则用 []表现,中心可以包罗多个对象,比如:
  1. [
  2.   {
  3.     "instruction": "你是一个AI助手,请准确回答下面的问题:",
  4.     "input": "在Mygo中最后睦给soyo送的礼物是什么?",
  5.     "output": "在《BanG Dream! It's MyGO!!!!!》中,最后睦送给Soyo的礼物是自己亲手种的小黄瓜。"
  6.         },
  7.   {
  8.     "instruction": "你是一个番剧高手,请准确回答下面的问题:",
  9.     "input": "ave mujica的op是什么?",
  10.     "output": "《BanG Dream! Ave Mujica》的OP(片头曲)是《KiLLKiSS》。"
  11.         }
  12. ]
复制代码
这个例子里面一个数组包罗了两个样本,每个样本里都是雷同的格式即包罗3个键值对。
模型微调

下面将使用LLaMA Factory作为微调框架,选取Qwen/Qwen2.5-1.5B-Instruct作为base model进行微调,选取GSM8K作为微调数据集。
数据集先容及下载

GSM8K数据集是一个包罗了8.5K道小学数学题的数据集,其中办理方案以自然语言的推理过程和终极答案构成。
这里数据使用使用huggingface进行下载,假如毗连不到huggingface可以像下面的代码一样设置镜像站:
  1. import  os
  2. os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
  3. from datasets import load_dataset
  4. cache_dir = r'your_path'    # 后续所有your_path需要转换为自己的路径
  5. ds = load_dataset("openai/gsm8k", "main",cache_dir=cache_dir)
复制代码
起首输出观察数据集的结构和其中的键值对如下,可以看到是一个DatasetDict中包罗了train和test两个字典,一个样本中对应的两个键:question即为是模型的输入,answer即为盼望得到的模型输出。

那么按照前文引用过的数据集格式先容,需要新建一个dataset_info.json来对数据集信息进行形貌,而且需要放置在gsm8k-train.arrow文件所在的同一文件夹下(和gsm8k-test.arrow也是同一个文件夹):
  1. {
  2.   "gsm8k_math_train": {
  3.     "file_name": "gsm8k-train.arrow",
  4.     "formatting": "alpaca",
  5.     "columns": {
  6.       "query": "question",
  7.       "response": "answer"
  8.     }
  9.   },
  10.   
  11.   "gsm8k_math_test": {
  12.     "file_name": "gsm8k-test.arrow",
  13.     "formatting": "alpaca",
  14.     "columns": {
  15.       "query": "question",
  16.       "response": "answer"
  17.     }
  18.   }
  19. }
复制代码
进一步输出训练集中前三个样本观察如下,###符号后接的即为终极答案。

模型先容及下载

Qwen/Qwen2.5-1.5B-Instruct是Qwen2.5系列中的一个参数比较小的decoder-only模型(从名字知道只有1.5B),可以在作者的笔记本上使用LoRA微调(8G显存)。
这里提供两种下载方法,由于huggingface下载速率比较慢,以是保举安装ModelScope进行下载,以是这里在命令行中使用命令
  1. modelscope download --model Qwen/Qwen2.5-1.5B-Instruct --local_dir your_path/Qwen2.5-1.5B-Instruct
复制代码
  1. huggingface-cli download --resume-download Qwen/Qwen2.5-1.5B-Instruct --local-dir your_path/Qwen2.5-1.5B-Instruct
复制代码
下载模型权重到指定文件夹(特别指出,官方的示例代码在cmd中运行会报错,需要把单引号去掉才气运行成功!!!)

LLaMA-Factory微调

起首按照LLaMA-Factory安装中的流程完成微调框架的安装,然后将新建一个文件llama_train.yaml并把下面的训练相关参数复制进去。然后就可以在该文件同一起径下或者指定绝对路径来使用命令进行模型训练了。
  1. llamafactory-cli train llama_train.yaml     
复制代码
下面是具体的训练参数配置文件内容,需要把里面所有的文件路径设置为自己的文件路径(作者这里在AutoDL上租了一张4090进行学习,以是后面路径中出现的都是作者自己的文件路径,需要进行设置)。
  1. # ------------------- 基础模型配置 -------------------
  2. model_name_or_path: /root/autodl-tmp/model/Qwen2.5-1.5B-Instruct  # 使用Qwen2.5-1.5B基座模型
  3. # ------------------- 训练阶段配置 -------------------
  4. stage: sft
  5. do_train: true
  6. report_to: tensorboard    # Tensorboard设置
  7. logging_dir: ./log_output/qwen1.5b_instruct_gsm8k_full_llamafactory
  8. finetuning_type: lora  # lora微调
  9. lora_target: all
  10. lora_rank: 16
  11. flash_attn: fa2
  12. # ------------------- 数据集配置 -------------------
  13. dataset_dir: /root/autodl-tmp/dataset/openai___gsm8k/main/0.0.0/e53f048856ff4f594e959d75785d2c2d37b678ee
  14. dataset: gsm8k_math_train               # 对应JSON中定义的数据集名称
  15. max_samples: null  # null表示使用全部数据,如需部分调试可设为具体数值
  16. template: qwen  # 必须使用Qwen对应的模板格式
  17. cutoff_len: 1024  # 上下文最大长度(GSM8K数学题通常不超过此长度)
  18. overwrite_cache: true  # 重新预处理数据时强制刷新缓存
  19. preprocessing_num_workers: 16  # 数据预处理并行进程数(根据CPU核数调整)
  20. # ------------------- 训练输出相关 -------------------
  21. output_dir: ./output/qwen1.5b_instruct_gsm8k_lora_llamafactory  # 输出目录需要存在可写权限
  22. logging_steps: 10  # 每10步输出一次日志
  23. save_steps: 100  # 每500步保存一次检查点
  24. plot_loss: true  # 绘制训练损失曲线
  25. # ------------------- 训练超参数 -------------------
  26. per_device_train_batch_size: 8  
  27. gradient_accumulation_steps: 4              # 梯度累积步数(等效总batch_size=2*4=8)
  28. learning_rate: 3.0e-5                       # 1.5B模型SFT建议学习率(高于7B但低于large模型)
  29. num_train_epochs: 6                         # GSM8K需更多epoch学习推理逻辑
  30. max_grad_norm: 0.5                          # 梯度裁剪阈值
  31. lr_scheduler_type: cosine                  
  32. warmup_ratio: 0.15                          # warmup阶段占训练总步数的比例
  33. weight_decay: 0.05                          # 新增权重衰减,防止过拟合
  34. # ------------------- 验证与评估 -------------------
  35. val_size: 0.1  # 10%数据作为验证集
  36. per_device_eval_batch_size: 16  # 评估时batch_size可以更大
  37. eval_strategy: steps  # 按步数评估
  38. eval_steps: 100  # 每200步验证一次(GSM8K需要及时评估推理能力)
  39. # ------------------- 显存优化 -------------------
  40. gradient_checkpointing: true  # 激活梯度检查点节省显存
  41. optim: adamw_torch  # 推荐使用AdamW优化器
复制代码
可以使用tensorboard查看训练效果,根据上述文件配置的文件记录路径,可以使用以下命令:
  1. tensorboard --port 6007 --logdir /root/autodl-tmp/llm03/log_output/qwen1.5b_instruct_gsm8k_full_llamafactory
复制代码

可以看到,大概在迭代600step后模型就会在训练集上过拟合(验证集损失明显上升),同时由于上面的训练命令中设置每200步生存一次模型参数,以是我们选取过拟合前的模型参数(即600step时生存的参数,具体生存参数的列表可以看下图)作为终极测试的参数。

微调竣事后,由于使用的是LoRA训练,以是需要对模型参数进行合并导出,根据官方导出教程,合并命令和配置文件merge_config.yaml如下:
  1. llamafactory-cli export merge_config.yaml
复制代码
  1. ### model
  2. ### 选取eval loss最小的checkpoint进行合并
  3. model_name_or_path: /root/autodl-tmp/model/Qwen2.5-1.5B-Instruct
  4. adapter_name_or_path: /root/autodl-tmp/llm03/output/qwen1.5b_instruct_gsm8k_lora_llamafactory/checkpoint-600
  5. template: qwen
  6. finetuning_type: lora
  7. ### export
  8. export_dir: /root/autodl-tmp/model/Qwen2.5-1.5B-Instruct-lora-sft
  9. export_size: 1
  10. export_device: cpu
  11. export_legacy_format: false
复制代码
模型评估

评估工具

如今使用一个评估工具:Language Model Evaluation Harness来对模型的效果进行评价,有一个先容的比较好的安装和使用教程。
使用下面的命令对指定路径下的模型权重文件进行一次测试
  1. lm_eval --model hf --model_args pretrained="/root/autodl-tmp/model/Qwen2.5-1.5B-Instruct" --tasks gsm8k --device cuda:0 --batch_size 8 --output_path ./eval_results --num_fewshot 0
复制代码
其中指定了num_fewshot参数为每个问题提供指定个数的示例(可以理解为做题前可以查看例题的解题格式,由于训练时模型是没有例题的,以是这里设置为0)。
假如要使用多卡进行评估,则需要使用accelerate launch,具体的命令如下(该命令会在所有的可用GPU上进行推理)
  1. accelerate launch -m lm_eval --model hf --model_args pretrained="/root/autodl-tmp/model/Qwen2.5-1.5B-Instruct" --tasks gsm8k --batch_size 8 --output_path ./eval_results --num_fewshot 0
复制代码
本地数据集

假如要使用本地模型和调用本地数据集,则在对应的库(这里是\lm-evaluation-harness\lm_eval\tasks\gsm8k)下找到文件gsm8k.yaml后复制其中的内容得到gsm8k-local.yaml文件在雷同的文件夹,然后在里面根据官方教程进行了修改,修改的内容如下所示(实际上不规范啊,不能验证集和测试集是同一个的,这里是图方便没在训练集里面划分验证集直接做个示范):

作者在自己电脑基于这个配置文件使用下面的命令进行了测试,是可以运行成功的。
  1. lm_eval --model hf --model_args pretrained="D:\04.Code\model\Qwen2.5-1.5B-Instruct" --tasks gsm8k-local --device cuda:0 --batch_size 1 --output_path ./eval_results --trust_remote_code
复制代码
评估效果

起首使用未经训练的模型进行评估,测试完之后可以得到以下效果。可以看到,这个模型的能力还是挺菜的(n-shot为5表现了每道题会提供0个例题,flexible-extract表现从输出中灵活提取数字答案,strict-match表现必须严格匹配答案格式,可以看出模型的规范输出能力很差,但基本还是能得到一些精确效果)。
TasksVersionFiltern-shotMetricValueStderrgsm8k3flexible-extract0exact_match↑0.1494±0.0098strict-match0exact_match↑0.0000±0.0000 下面是微调后的效果,可以看到微调对模型的提升是很大的,而且严格匹配答案格式,但是现在还没搞清晰为什么宽松模式的得分会比严格模式的低那么多。
TasksVersionFiltern-shotMetricValueStderrgsm8k3flexible-extract0exact_match↑0.3806±0.0134strict-match0exact_match↑0.4723±0.0138 Base Model评估

基于Qwen2.5-1.5B又进行了一次测试,效果比Instruct的还好,推测是base model中有相关的知识,但是Instruct之后破坏了这些知识,有点在训练集上过拟合的意思。
训练前
TasksVersionFiltern-shotMetricValueStderrgsm8k3flexible-extract0exact_match↑0.0902±0.0079strict-match0exact_match↑0.0000±0.0000 训练后:
TasksVersionFiltern-shotMetricValueStderrgsm8k3flexible-extract0exact_match↑0.5474±0.0137strict-match0exact_match↑0.5747±0.0136
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王柳

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表