尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

大模型微调实战:用LLaMA-Factory跑通LoRA全流程

大模型微调实战:用LLaMA-Factory跑通LoRA全流程 不废话直接说正题。如果你最近正在把目光从“用大模型聊天”转向“训练自己的大模型”那这篇内容就是给你准备的。大模型微调这个词现在已经被聊滥了但真上手跑通一条完整链路的人其实没那么多更多人是卡在“理论都懂、环境装不上、第一次训练就报错”这三座大山前面。我写这篇入门实战会把大模型微调最核心的认知、环境部署的硬性要求以及 LLaMA-Factory 这个当前最流行的微调工具的完整操作流程一次性讲透目标是让你跟着走一遍之后自己也敢动手跑一个最小规模的微调任务。这篇内容适合两类人一是刚接触大模型、想搞清楚“微调到底在调什么”的人二是已经扒过不少教程但还没有真正在本地环境里跑通一个训练任务的人。我的主张很简单——先建立正确的理论直觉再用 LLaMA-Factory 把全流程过一遍在这个过程中把坑提前踩一遍给你看。1. 理论认知模型从“通才”到“专才”微调到底改了什么1.1 预训练与微调一张白纸到一名专业员工理解大模型微调之前得先分清两个阶段预训练和微调。预训练是模型用海量文本“自学成才”的阶段。它读了几万亿个token目的只有一个——学会预测下一个词。你给它前半句话它能把后半句接下去并且接得很有逻辑、语感通顺。这个阶段训练出来的模型知识面极广上知天文下知地理但它的“表达能力”停留在“续写”层面你问它一个问题它并不一定知道应该用“回答”的方式输出它只是凭着概率继续写文本。而微调更准确地说监督微调 SFT是让模型学会“做任务”的阶段。你给它一批人工标注好的数据比如“问题-答案”对让它在你的监督下学习“用户提问时我该怎么回应”。这个阶段不需要几万亿token几百、几千、几万条高质量数据就足够让模型的行为风格发生明显变化。我常用一个类比来理解这两者预训练相当于读完大学通识课的高材生什么都懂一点但没受过职业训练微调相当于岗前培训让他掌握岗位上的具体工作规范。你要打造一个律师助理模型微调数据就是真实的法律文书和问答案例你要做一个客服模型微调数据就是真实的客服对话记录。模型底子还是原来那个底子但它学会了在你指定的场景里该怎么说话。1.2 全参微调与参数高效微调为什么现在都在谈 LoRA搞清楚“微调在做什么”之后下一个绕不开的问题是怎么“调”最原始粗暴的方案是全参微调。也就是把预训练模型的全部权重都作为可训练参数用你的数据集重新更新一遍。这种方式效果通常最好因为它给模型的“自由度”最大。但代价极其昂贵一个 7B 参数的模型光把权重以 FP16 精度加载到显存里就需要大约 14GB而训练过程中的梯度、优化器状态、中间激活值会让显存需求轻松翻到 3 到 4 倍。也就是说微调一个 7B 全参模型没有 60GB 以上的单卡显存会非常痛苦13B 以上基本就要上多卡并行或者 A100/H100 这类专业卡了。于是参数高效微调PEFT成了绝大多数人的选择。它的核心思想是冻结原有模型的绝大部分参数不动只额外训练一小部分新增参数。目前最主流的是 LoRALow-Rank Adaptation。LoRA 的数学直觉其实并不难在原始权重矩阵 (W) 旁边增加一个低秩的增量矩阵 (\Delta W)而 (\Delta W) 被分解成两个小矩阵 (A) 和 (B) 的乘积(\Delta W A \times B)。训练时只更新 A 和 B原始参数 (W) 保持冻结。这个 (A \times B) 的维度由一个叫 rank 的超参数控制rank 设成 8、16、32就代表这个增量矩阵的“秩”。理解成大白话就是全参微调相当于把整本词典重写一遍LoRA 则是在原词典里贴批注、做索引只动少量内容但已经能让模型在特定领域表现大变样。推理和部署时LoRA 还带来一个额外好处所有微调任务可以共享同一个基础模型。你在几个不同的数据集上各训练一个 LoRA 适配器应用中按需加载即可不需要为每个任务各存一份完整的几十GB模型文件。顺带提一个概念——Adapter。它属于另一种参数高效微调思路是在 Transformer 层中插入小型前馈网络同样只训练新增部分。目前社区里 LoRA 的应用量远大于 Adapter但有时间的话可以了解思路互为补充。1.3 基座模型与对话模型别把选择题做成填空题如果你去 Hugging Face 或 ModelScope 上搜索模型会发现同一个系列通常有好几个版本。以 Qwen 为例有Qwen/Qwen2.5-7B这种基座版本也有Qwen/Qwen2.5-7B-Instruct这种对话对齐版本。这两者的差别非常大。基座模型base只做过大规模预训练它擅长文本续写你输入“请解释什么是Transformer”它可能回复的是“Transformer是一种……的结构它在2017年被提出……”看起来像模像样但它本质上还是在做下一词预测只是碰巧接得很好。而对话模型Instruct/Chat通常经过了监督微调和更复杂的对齐训练学会了“用户提问-模型回答”这种交互格式。入门阶段我强烈建议一个策略直接用官方已经对齐好的 Instruct/Chat 版本作为底座在你的业务数据上做二次微调。不要选 base 版本。原因很简单Instruct 版已经能用“对话”的形式和用户交流你微调时只需要把业务知识、回答风格“注入”进去工作量小得多而训练 base 版做对话任务你需要准备海量且高质量的对话数据相当于同时教它两件事——对话格式和业务知识对新手来说提升了不少难度。另一个原因是训练输出格式。对话模型在预训练后已经见过统一的对话模板微调时训练框架会把你的数据套进模板再喂给模型LLaMA-Factory 里叫 template模型学习起来非常轻松。所以除非你有特殊需求否则首选定型对话模型。2. 环境部署先别急着跑代码把“舞台”搭稳2.1 硬件怎么选一张显卡能跑多大模型心里要有数微调是吃显存的活儿选硬件之前先学会估算。一个经验法则以 FP16 精度加载模型模型的大小约等于参数量 × 2 字节。7B 模型就是约 14GB。如果用 LoRA 微调训练时除了模型权重还需要存储梯度、优化器状态和中间激活值。好在 LoRA 只更新少量参数优化器状态压力很小真正的大头是激活值和 KV Cache。我自己实测下来用一张 24GB 显存的显卡RTX 3090/4090微调 7B 模型把 batch size 控制在 2 到 4、max length 控制在 1024 左右是比较舒服的配置。用 48GB 的 A6000/6000 Ada微调 13B 模型 LoRA 也能较从容。如果只有 12GB 或 16GB 显存也并非完全没希望——配合 4bit 量化加载bitsandbytes可以把 7B 模型压到 6GB 左右权重再加上 LoRA 训练勉强能跑但要做好频繁 OOM、反复调参的心理准备。这里给出一个粗略参考表是我基于实际操作整理的硬件参数不同结论会有浮动但大方向靠谱模型规模推荐训练方式最低舒适显存推荐卡型1.5B ~ 4BLoRA / QLoRA12GBRTX 3060 12G / 4060Ti 16G7B ~ 8BLoRA / QLoRA24GBRTX 3090 / 409013B ~ 14BQLoRA / LoRA48GBA6000 / 双409070B基本不用想单卡多卡并行A100 80G 集群有了这张表你就知道自己手头的卡能做什么事。个人买不起大显卡的话租云 GPU 实例是目前很成熟的做法按小时计费用完即走适合学习和验证阶段反复折腾。2.2 软件栈Python、CUDA、PyTorch 的版本组合硬件确认之后软件环境是让新手最容易心态崩的一环。我推荐在 Linux 环境下操作Windows 不是不行但 DeepSpeed、bitsandbytes 这类库在 Windows 上兼容性经常出幺蛾子。有条件的话优先用 WSL2Windows Subsystem for Linux或者在云服务器上直接开一台 Ubuntu 系统的实例。版本组合我直接给一套稳妥的组合Python 3.10 或 3.11CUDA 11.8 或 12.1取决于显卡驱动PyTorch 2.1 及以上配合对应 CUDA 版本的预编译 wheeltransformers、accelerate、peft、trl 等依赖交给 LLaMA-Factory 装即可安装 PyTorch 时我建议去官网用对应的pip install torchxxx命令选择cu121或cu118版本。这一步容易踩的坑是直接pip install torch装到 CPU 版然后训练时发现速度慢到怀疑人生或者干脆不识别 GPU。装完一定要验证一下python -c import torch; print(torch.__version__, torch.cuda.is_available())输出2.1.0cu121 True才算环境正常。如果输出False先回去检查 CUDA 版本和 PyTorch 是否匹配这是最常见的错配问题。Conda 用户可以在新建环境时安装cudatoolkit但考虑到 PyTorch 预编译包其实已经自带 CUDA 运行时系统层面不需要额外装完整的 CUDA Toolkit除非你要用 DeepSpeed 编译算子。这条经验能省不少事。2.3 安装 LLaMA-Factory源码方式装一遍心里有底LLaMA-Factory 是目前社区里非常活跃的大模型微调工具它把数据准备、训练、推理、导出整条链路都封装好了同时支持 LoRA、QLoRA、全参微调等多种方式并且对国内外主流模型Qwen、Llama、DeepSeek、Baichuan 等都有良好的适配。安装方式我推荐用源码安装。这样做的好处是出问题容易定位也能拿到最新的功能更新。操作如下git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory pip install -e .[metrics][metrics]是可选扩展装上会多几个评估相关的依赖建议一次到位。安装完成后验证llamafactory-cli version能看到版本号就说明核心工具已经就绪。从 Hugging Face 下载模型时如果因为网络原因速度不理想可以改用国内的 ModelScope 平台下载LLaMA-Factory 也支持直接读取 ModelScope 上的模型路径方式是在模型名前面加modelscope://前缀。我自己的使用习惯是模型权重用 ModelScope 下载到本地目录训练时直接指定本地路径这样速度稳定、也方便多个实验复用同一份模型文件。另外提醒一句不要直接在项目目录里存模型文件单独建一个models/文件夹统一管理数据集也单独放目录结构干净了后面你会省很多心。3. LLaMA-Factory 全流程速览从一份数据集到第一个微调任务3.1 数据集长什么样Alpaca 格式是绕不开的起点任何微调项目数据都是灵魂。LLaMA-Factory 默认支持的数据格式很多但新手最先接触到的往往是 Alpaca 格式。Alpaca 格式的核心是三个字段instruction指令、input输入、output输出。其中instruction是必填的任务指令input是可选的外部输入output是期望模型给出的标准答案。举个例子你做一个“润色中文句子”的微调任务数据是这样的[ { instruction: 请将下面的句子润色得更正式一些。, input: 老板的这个计划我觉得不太行但是我不知道该怎么说。, output: 我对老板提出的这项计划有所顾虑但目前尚未确定合适的表达方式。 } ]如果是纯问答类数据没有额外的外部输入那就把input字段留空字符串即可LLaMA-Factory 处理起来没有问题。如果你手里已有的数据是 CSV 或者 Excel 表格只有问题和答案两列那就需要写个小脚本转成 Alpaca 格式。处理方法很简单逐行读取把问题填进instruction答案填进outputinput填空。我习惯用 pandas 做转换几百行数据也就几秒的事。转换完成后把 JSON 文件放到 LLaMA-Factory 项目里的data目录下然后在data/dataset_info.json文件里注册一下数据集信息给它起个名字并指定文件路径。这个注册步骤是很多人忽略的不注册的话你在配置里写数据集名会直接报找不到。3.2 图形界面还是命令行两种开局方式各有什么讲究LLaMA-Factory 提供了两种使用入口图形界面和命令行YAML 配置。如果你想直观地看到界面、通过下拉框配置参数可以用llamafactory-cli webui启动后在浏览器里打开对应地址选模型、选数据集、填参数点“开始”就能跑。图形界面适合第一次上手时快速试错毕竟所有字段旁边都有中文提示鼠标点一点就能完成配置。但图形界面的问题也很明显参数不好复用。你调好一组参数下次开一个新实验还得重新点一遍。当我跑通的第一个任务之后就彻底转向了命令行 YAML 配置的方式。把一次训练的所有参数写到一个.yaml文件里相当于给自己的每个实验做了一份“配方”。下次想复现实验一条命令就能启动。如果想调参数复制一份 YAML 改几个值即可。而且 YAML 方式更容易配合自动化脚本做不同参数组合的批量跑批实验。我建议你的学习路径是先用 webui 界面跑通第一个任务感受一下参数变化对训练的影响之后切换到 YAML 方式把配置管理起来这样你的实验会越来越规范。3.3 关键参数解读让新手少纠结的几组数字YAML 配置第一次看会有点懵我挑几个关键参数逐个说明你就知道绝大部分字段该怎么填了。以下是一份最小可跑的 LoRA 微调配置以 Qwen2.5-7B-Instruct 为例model_name_or_path: /data/models/Qwen2.5-7B-Instruct template: qwen stage: sft finetuning_type: lora dataset: my_dataset cutoff_len: 1024 learning_rate: 2.0e-4 num_train_epochs: 3.0 per_device_train_batch_size: 2 gradient_accumulation_steps: 8 lr_scheduler_type: cosine warmup_ratio: 0.1 bf16: true output_dir: outputs/qwen25-7b-lora-my_dataset logging_steps: 10 save_steps: 500逐个解释重点template训练时模型会用哪个对话模板。这个必须跟你的底座模型匹配Qwen 系就填qwenLlama 系填llama或llama3。填错了训练出来的模型输出格式会错乱回答内容看着像乱码一样。finetuning_type训练方式lora是 LoRAfull是全参。新手默认选lora。cutoff_len训练时序列最大长度。它决定单条数据里能塞进多少 token。调高能处理长文本但显存占用呈线性增长新手先从 1024 开始等你的卡有余力再往上加。learning_rateLoRA 训练一般用 1e-4 到 2e-4 这个区间。太小了学不动太大了 loss 会震荡甚至爆掉训练出来变“复读机”。2e-4 是一个很中庸的起点。per_device_train_batch_size单张卡上的批次大小。24GB 显存跑 7B 模型batch size 从 2 开始试不行就降。gradient_accumulation_steps梯度累积步数。它和 batch size 的乘积近似等于“等效 batch size”在微调里常用 8、16、32。显存不够、想让训练更稳定的时候就调大它。num_train_epochs训练轮数。数据集质量高、数量少时 2 到 3 轮就够了轮数太多容易过拟合模型只背答案不学“能力”。参数不是越多越好重点先把以上几项弄明白其余的配置项完全可以先保持默认等有具体问题再针对性地看。4. 训练、导出与推理验证跑通链路才是真本事4.1 启动训练前台跑还是静默跑配置写好之后启动训练非常简单llamafactory-cli train train_qwen.yaml训练日志会实时打印在终端里。你需要盯着几个关键信息一是loss值它应该整体呈下降趋势如果出现剧烈反弹或者长时间不降大概率是学习率设置有问题或者数据格式有问题二是显存占用是否 OOM如果爆了结合前面说的调整 batch size、cutoff_len 或开启gradient_checkpointing。这里多说一句gradient_checkpointing。它是一个经典的“用时间换显存”技术开启后训练过程中不再保留所有中间激活值而是反向传播时重新计算显存占用能省下约一半代价是训练时间增加约 20%-30%。在我的 24GB 显存配置上如果per_device_train_batch_size想从 2 升到 4这个开关几乎是必开的。训练实际耗时要看数据量和模型规模。一个 7B 模型跑 1 万条数据、3 个 epoch在单张 4090 上大约需要几十分钟到两三小时不等。中途想观察模型效果也完全不用等全部跑完可以在另一个终端里读output_dir里保存的 checkpoint 继续做推理LLaMA-Factory 支持随时加载训练过程中的 checkpoints。长任务建议用nohup或tmux放到后台跑防止终端断开导致训练中断。我自己习惯开一个 tmux session把日志重定向到文件里再定时看一眼tmux new -s train llamafactory-cli train train_qwen.yaml 21 | tee train.log这样既能看到实时输出日志也留了底出现报错还能回溯找原因。4.2 导出与合并LoRA 适配器不能直接用于部署LoRA 训练完成之后你得到的不再是一个完整模型而是一个“狭义”的适配器文件——它记录的只是前面提到的 (A \times B) 增量权重体积通常只有几十到几百 MB而不是原始模型的十几 GB。这个适配器必须和基础模型配合才能使用直接拿去部署是不行的。如果你想让最终产物变成一个可以直接用 vLLM、SGLang 等推理框架加载的标准模型目录需要做一步权重合并导出。导出的配置同样是一个 YAML 文件重点字段如下model_name_or_path: /data/models/Qwen2.5-7B-Instruct adapter_name_or_path: outputs/qwen25-7b-lora-my_dataset template: qwen finetuning_type: lora export_dir: outputs/qwen25-7b-lora-merged export_size: 5 export_legacy_format: false执行llamafactory-cli export export_qwen.yaml之后outputs/qwen25-7b-lora-merged目录下就是一个完整的合并模型包含了基础模型和 LoRA 微调的效果可以直接用AutoModelForCausalLM.from_pretrained加载或者直接在推理框架里部署。这里有一个重要的经验如果你的模型是通过 4bit 量化加载训练的即训练时用了quantization_bit: 4配置导出前要改成原模型路径重新加载否则会把量化模型权重合并进去导出的模型质量有损失。另外建议导出时用 FP16 精度部署端如果需要 INT8/INT4 量化的模型等导出来之后再用专门工具二次量化不要直接在训练链路里混着做。4.3 推理验证跟自己的模型聊一聊模型导出完成后验证是必不可少的一步。有两个渠道命令行对话或者启动 API 服务。如果你只是简单看看效果可以直接用llamafactory-cli chat outputs/qwen25-7b-lora-merged进入交互界面之后输入你在训练数据类似的问题观察模型回答的风格、知识、语气是否符合你的预期。这里我会额外准备一些“泛化测试题”比如你微调的数据是金融领域的训练数据里可能没出现过的新问题模型会不会给出合理回答。如果只在训练集上表现好、换个问法就崩说明过拟合了需要回炉调整数据或训练参数。如果你想验证部署链路可以用llamafactory-cli api \ --model_name_or_path outputs/qwen25-7b-lora-merged \ --template qwen默认会启动一个 OpenAI 兼容风格的 API 服务用任何 HTTP 客户端发请求就能调用。这一步的意义在于它和真实的线上部署结构一致能提前发现推理服务启动时的问题比如 tokenizer 配置不对、模板不匹配、显存占用过高需要换量化等等。5. 常见问题与排查技巧实录5.1 显存不足、OOM新手的第一个客服是 torch.cuda.OutOfMemoryErrorOOM 基本是每个入坑微调的人都必遇的现象。不用慌按下面的优先级排查降低per_device_train_batch_size这是最直接有效的调整。从 2 降到 1显存压力立刻下去一半。降低cutoff_len从 2048 降到 1024长文本数据的显存开销会显著下降。开启gradient_checkpointing常见能省 30%-50% 显存。使用quantization_bit: 4开启 QLoRA用 4bit 量化加载模型7B 模型权重只有约 6GB。检查是否无意中用了全参微调finetuning_type: full它的显存需求比 LoRA 高一个数量级。还要注意一个细节当显存用尽报错之后PyTorch 的显存缓存不会立刻释放后续训练即使调小参数也可能继续报同类型错误。稳妥做法是调整配置后重启训练进程而不是在同一个进程里硬着头皮继续跑。5.2 Loss 不降、模型变“复读机”先检查数据再检查参数Loss 训练几轮之后不降或者模型输出变成一句话反复重复最常见的有三个原因。第一学习率过大了。LoRA 微调的学习率超过 1e-3 很容易把 loss 直接搞震荡模型参数被改得面目全非。把学习率降到 1e-4 到 2e-4 区间再试试。第二数据集格式问题。如果output字段写的是指令本身或者你训练的数据是“错误的参考答案”模型自然会学到错误行为。检查一下数据有没有明显的噪声比如空答案、重复串行。第三训练轮数太多导致严重过拟合。模型把训练数据“背”下来了遇到稍微偏离训练分布的问题就只会复读。适当减少 epoch或者把学习率稍降一档通常能缓解。我曾经遇到过最典型的案例数据集里几百条数据全是同一个模板训练 5 轮之后模型回答问题几乎每一句都是“根据您的需求我为您准备了以下方案”看起来像模像样实际上完全没学到内在逻辑。这类问题靠调参数是无解的必须回到数据处理环节增加多样性。5.3 模型输出格式混乱大概率是 template 选错了训练完模型技术指标一切正常但一问一答的格式完全不对——比如没有|im_start|这种对话标记或者回答开头直接带上user字样。这种情况几乎可以肯定是template没有配好。template指定的是将你的训练数据格式化为模型所需格式的方法每个系列模型都有自己特殊的模板规则。Qwen 填qwenLlama 3 填llama3如果你用的是和模型不匹配的模板训练时模型学到的是毫无意义的内容自然无法输出规范的对话格式。检查这项比检查任何其他参数都优先。排查时我还有个技巧训练前先不看 loss直接跑两三个 step 然后导出 checkpoint用未合并的 adapter 做一次快速对话看模型能不能按标准模板回复。这样能在早期就发现问题避免跑完一个完整训练任务后才发现模板错了白白烧掉几个小时。最后分享一点个人体会我自己跑通第一个大模型微调任务时实际上是第五次尝试才完整跑完的。前四次分别栽在 Python 环境反复冲突、torch 装了 CPU 版、数据集未注册、显存不足且不知道梯度累积怎么用这四个经典问题上。回头看最大的教训是跑通一个最小规模的微调任务并不需要等你把理论全都弄明白更不需要一步到位追求最佳效果而是应该尽早把“数据 → 训练 → 导出 → 推理”这条链路完整走通一次。链路通了你就有了一块可以反复折腾的地基后面的优化都有得放矢。这条路接下来还能往不少方向走比如数据清洗与配比、LoRA 参数寻优、多轮对话数据处理、训练后的自动评估、量化部署等等。这篇先帮你把大门推开后续的系列内容里我会把每一块单独展开用同样“手把手 踩坑实录”的方式写下去。如果你想动手了就从准备一份自己的小数据集开始吧。
返回列表