
🧨 使用LLaMA-Factory微调Qwen3
本文很长,点击目录跳转至想看的地方
什么是微调大模型?
大模型微调(Fine-tuning Large Models) 是一种机器学习技术,指的是在一个已经预先训练好的大型模型(Pre-trained Large Model)的基础上,利用你自己的、通常规模更小且更具针对性的数据集,对模型进行进一步的训练,以使其更好地适应特定任务、领域或风格。
- 预训练的大模型(基础模型,如Qwen3-8B-Base): 通过在海量的通用数据(比如整个互联网的文本和代码)上进行学习,掌握了广泛的语言理解、知识推理和内容生成能力。它能理解语法、常识,甚至能进行一定程度的创作。
- 微调(专门化训练,如Qwen3-8B): 为了让基础模型能够更好地理解并响应人类的指令,或者以更自然、更有帮助的方式进行对话,需要对其进行进一步的训练,这个过程就是微调。
- 指令微调 (Instruction Tuning): 这种微调方法使用包含指令和对应期望输出的数据集来训练模型。这使得模型学会遵循指示,而不仅仅是续写文本。
- 对话微调: 为了创建专门的聊天模型,微调数据通常会包含大量的对话样本(例如,用户提问和助手回答的对话记录)。通过在这些对话数据上进行训练,模型学会了理解对话的上下文、保持对话连贯性、并以类似聊天的风格进行回应。
- 从人类反馈中强化学习 (Reinforcement Learning from Human Feedback - RLHF): 这是一种常用于进一步提升聊天模型质量的技术。首先,人工标注者会对模型生成的不同回复进行排序和打分,然后用这些反馈来训练一个奖励模型。最后,通过强化学习算法,根据奖励模型来优化聊天模型的行为,使其更倾向于生成人类偏好的、更有帮助、更无害的回复。
核心思想和目的
- 迁移学习(Transfer Learning): 微调是迁移学习的一种形式。它把从大规模通用数据中学到的知识(模型的参数和结构)“迁移”到新的、特定的任务上,而不是从零开始训练一个模型。
- 适应性与定制化: 目的是让模型能够更好地理解和处理特定领域的数据,生成更符合特定要求的输出,或者执行特定的功能。
- 效率与效果: 相比于从头训练一个大模型(这需要巨大的数据量和计算资源),微调通常更高效,并且能在特定任务上取得更好的效果,因为它站在了“巨人”(预训练模型)的肩膀上。
- 知识的特化: 通过微调,模型可以将它广泛的知识进行特化,学习新的术语、风格、事实,或者调整其回应的模式以匹配特定应用场景。
微调的关键点
- 基于预训练模型: 微调不是从随机参数开始的,而是从一个已经具备强大基础能力的模型开始,这个模型可以是基础模型(Base模型),也可以是聊天模型(instruct)。
- 特定数据集: 微调需要一个与目标任务紧密相关的、高质量的数据集。
- 参数调整: 在微调过程中,模型的权重(参数)会被更新,以最小化在特定数据集上的预测错误。根据微调策略的不同,可能调整模型的所有参数(全参数微调),也可能只调整一部分参数或附加一些小模块(参数高效微调,如LoRA)。
什么时候该微调模型?
提升特定任务的性能
- 专业领域知识: 应用场景需要特定领域的专业知识,而通用大模型无法提供足够深度或准确度的信息时(例如医疗、法律、金融、特定科学领域等)。通过在相关专业数据集上微调,模型可以学习该领域的术语、概念和细微差别。
- 特定任务优化: 需要模型执行非常具体的任务,如特定风格的文本生成、特定格式的问答、特定类型信息提取、代码生成或专门的对话系统(如模仿特定角色或品牌的语气),微调可以显著提高其在该任务上的表现。
- 数据稀缺但性能要求高:拥有一个相对较小(几百到几千个样本)但高质量的特定任务数据集,并且希望模型在该任务上达到较高性能时,微调是一个好选择。
定制化和个性化需求
- 语气和风格调整:这部分实际上也可以通过Prompt实现,但如果需要的语气比较特殊,需要模型输出符合特定的品牌声音、写作风格或对话语气(例如,更正式、更口语化、幽默或富有同情心),则可以微调可以帮助实现这一点。
- 个性化体验: 在某些应用中,微调有助于根据个体用户或特定组织的需求和偏好来个性化模型的响应或预测。
解决通用模型的局限性
- 减少“幻觉”或不相关输出: 由于网络上的通用知识不一定和实际知识对齐或网络通用知识被污染,通用大模型有时会产生不准确或偏离主题的回答。通过在特定、高质量的数据集上微调,可以引导模型更专注于相关信息,减少幻觉。(如下,虽然是梗图,但也说明了通用数据被污染)
- 提升对特定指令的理解: 微调可以使模型更准确地理解和遵循针对特定任务的复杂或细致的指令,有时甚至可以用更短的提示词达到更好的效果,如工具调用能力的实现。
- 语言本地化: 当需要将主要以某种语言(如英语)训练的模型调整以适应另一种语言或特定地区的方言时,微调可以帮助模型学习新的语言模式和文化背景,如早期llama官方开源模型不支持中文,就有很多用进行中文微调。
控制专有数据的使用
- 整合独特知识: 这可能是大多数情况下选择微调的理由,企业拥有与基础模型训练数据显著不同的专有或高度专业化的数据,并且希望将这些独特知识融入模型内部时,微调是一个有效途径。
什么情况下可能不需要微调,或应考虑其他方案?
- 通用任务且性能可接受: 如果通用大模型+合适的Prompt已经能很好地处理您的任务,且性能符合要求,则无需进行微调。
- 缺乏高质量的微调数据: 微调的效果高度依赖于数据的质量和相关性。如果缺乏足够的高质量、干净且与目标任务一致的数据,微调可能效果不佳,甚至损害模型原有能力(灾难性遗忘)。
- 计算资源和成本限制: 全参数微调(Full Fine-Tuning)计算成本较高。虽然有参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)如LoRA、QLoRA等方法可以降低资源需求,但仍需一定的投入。
- 任务需要实时更新最新信息: 如果任务高度依赖实时变化的最新信息,RAG通常是更合适的选择,因为它能动态检索最新数据。微调后的模型知识是静态的,直到下一次重新微调。
- 数据量非常庞大: 如果您拥有海量的高质量数据,从头开始训练一个模型可能也是一个选项,尽管这通常比微调成本更高。
进行微调前需要考虑的关键因素
- 明确定义任务和目标: 清晰地了解您希望通过微调解决什么问题,以及如何衡量成功(重中之重)。
- 选择合适的预训练模型: 选择与您的任务和数据特性尽可能接近的预训练模型作为基础。
- 高质量的数据准备: 这是微调成功的基石。数据需要清洗、标注(如果是有监督微调),并与模型输入格式对齐。
- 选择合适的微调策略和技术: 全参数微调还是PEFT方法(如LoRA, QLoRA, DPO等)?不同的方法在效果、资源消耗和训练时间上有所不同。
- 合理的超参数设置: 如学习率、训练轮次(epochs)、批处理大小(batch size)等,需要仔细调整和实验。
- 评估和迭代: 建立有效的评估机制,在验证集上监控模型性能,并根据结果进行迭代优化。
微调
微调技术发展路径
- 起点:全参数微调 (Full Fine-Tuning)
- 做法: 对预训练模型的所有参数进行重新训练,以适应新任务。
- 关键: 早期LLM的主要适配方法,能充分利用模型潜力。
- 瓶颈: 随着模型参数量剧增,计算和存储成本变得难以承受。
- 转折点:参数高效微调 (PEFT) 的兴起
- 核心驱动: 解决全参数微调的成本问题。
- 核心思想: 冻结预训练模型绝大部分参数,仅微调一小部分参数或添加少量可训练模块。
- 关键技术演进代表: ▪ 早期尝试: Freeze部分层、Adapter Tuning (在层间插入小型可训练模块)。 ▪ 输入端创新: Prompt Tuning、Prefix Tuning (学习添加到输入的“软提示”或“前缀”)。 ▪ 重大突破与普及:LoRA (低秩适应) 及其变种 (如 QLoRA 结合量化技术)。LoRA通过训练低秩矩阵来近似权重更新,效果好且效率高,成为主流。
- 能力升级:指令遵循与人类对齐
- 核心驱动: 使模型不仅能完成特定任务,更能理解复杂指令并生成有用、诚实、无害的回答。
- 关键技术: ▪ 指令微调 (Supervised Fine-Tuning, SFT): 使用大量“(指令, 理想输出)”格式的数据进行微调(可配合全参数或PEFT方法),让模型学会“听懂话、好好说话”。 ▪ 对齐技术 (RLHF / DPO 等): 在SFT基础上,通过人类反馈的强化学习 (RLHF) 或直接偏好优化 (DPO) 等方法,进一步使模型的输出与人类的偏好和价值观对齐。
微调技术对比
技术 | 核心机制 | 典型可训练参数百分比(范围) | 主要优势 | 主要局限性 | 主要解决的问题 |
---|---|---|---|---|---|
全量微调 (FFT) | 更新预训练模型的所有权重 。 | 100% | 潜在最高性能,全面适应新任务 。 | 计算成本高,灾难性遗忘,过拟合风险,存储开销大。 | 任务适配 |
LoRA | 冻结预训练权重,注入可训练的低秩分解矩阵(∆W = BA)到特定层 。 | 0.01% - 0.5% | 高效,减少显存,训练快,无额外推理延迟(可合并),易于任务切换,减轻灾难性遗忘。 | 性能依赖秩'r'的选择,超参数敏感。 | 计算成本,显存占用,灾难性遗忘,存储/部署多个模型 |
QLoRA | 将预训练模型权重化为低精度(如4-bit NF4),然后应用LoRA适配器 。 | 同LoRA(作用于量化模型) | 极大降低显存占用,可在消费级GPU上微调超大模型,成本效益高。 | 可能增加推理时间,对某些任务可能不如FFT,超参数敏感。 | 极端显存限制下的LLM微调 |
Adapter Tuning | 在预训练模型的层内插入小型、可训练的适配器模块,冻结原模型权重 。 | 0.1% - 6% | 资源高效,模块化(易于多任务切换),灵活性高。 | 可能引入推理延迟(若未合并),适配器设计和位置影响性能。 | 计算成本,多任务管理 |
Prompt Tuning | 在输入嵌入前添加可训练的连续向量(软提示),冻结LLM参数。 | < 0.1% | 参数效率极高,尤其对大模型有效,每个任务存储开销小。 | 性能对初始化和提示长度敏感,可能收敛慢,增加有效输入长度导致计算增加。 | 最小化可训练参数,多任务轻量级适配 |
Prefix Tuning | 在每个Transformer层的隐藏状态前添加可训练的连续向量(前缀),冻结LLM参数。 | 0.1% - 4.0% (26) | 比Prompt Tuning更具表达力,低数据场景和生成任务效果好,参数高效。 | 比Prompt Tuning参数多,前缀长度是超参数 。 | 复杂任务适配,生成任务 |
P-Tuning | 使用小型可训练提示编码器(如BiLSTM)生成软提示(虚拟token)并插入输入序列。 | 少量(编码器+虚拟token) | 比简单提示方法更稳定有效,参数高效,克服手动少样本提示的token预算限制。 | 提示编码器设计可能复杂。 | 提升软提示生成质量和稳定性 |
BitFit | 仅微调预训练模型中的偏置项(bias terms),冻结所有其他权重 。 | 0.05% - 0.1% | 实现简单,极大减少计算开销和优化器状态显存,良好保持预训练知识。 | 效果可能因模型架构和任务而异。 | 极简参数微调,保持模型权重不变 |
DiffPruning | 微调预训练模型权重的稀疏子集,并仅存储微调后权重与原始权重之间的差值(delta)。 | 少量(训练子集),存储差值 | 显著减少任务特定变更的存储需求,可能加快微调,有助于减轻灾难性遗忘。 | 性能依赖关键权重子集的识别,可能略微降低性能。 | 存储效率,稀疏更新 |
Freeze(冻结微调) | 选择性地“冻结”模型的一部分层,使其权重在新的训练过程中保持不变,而只训练模型的其余部分层 | 根据任务调整,从远低于1%(只训练头部)到50%以上 | 减少计算资源消耗,有效防止过拟合,易于实现 | 任务适应性差,冻结层选择困难,不如LoRA等 | 计算成本 |
微调工具
开源微调工具的涌现极大地推动了LLM定制化的普及和发展。降低了技术门槛,使得更广泛的用户和组织能够根据自身需求调整和优化强大的预训练模型,从而催生了大量的创新应用 。这一领域发展极为迅速,新的工具和技术层出不穷,不断提升微调的效率和效果 。
在众多开源LLM微调工具中,一些框架因其功能全面、社区活跃或性能卓越而备受关注。下面将重点分析以下几款具有代表性的工具:LLaMA-Factory、Hugging Face AutoTrain Advanced、Axolotl、Unsloth、LitGPT (Lightning AI)、Torchtune (PyTorch) 以及 XTuner (InternLM)。
截至写稿时间2025年5月9日
工具名称 | 主要维护者/组织 | GitHub星标数 (约) | 最近重要更新 (版本/日期) | 核心优势/关注点 |
---|---|---|---|---|
LLaMA-Factory | hiyouga (个人,社区支持) | 48.4k 9 | 2025年5月7日 | 易用性强,模型/方法支持广泛,提供UI界面 |
Hugging Face AutoTrain Adv. | Hugging Face | 4.4k 8 | 2025年1月 | 无代码/低代码,操作简便,与HF生态深度集成 |
Axolotl | axolotl-ai-cloud, OpenAccess-AI-Collective | 9.3k 11 | v0.9.1,2025年5月8日 | 灵活性高,社区驱动,YAML配置,多GPU支持良好 |
Unsloth | unslothai | 38.2k 12 | Qwen3支持, 2025年5月1日 | 单GPU速度与显存效率领先,易于上手 |
LitGPT (Lightning AI) | Lightning AI | 12.1k 13 | v0.5.8, 2025年5月 13日 | 代码可定制性强,性能优越,Lightning生态,透明度高 |
Torchtune (PyTorch) | PyTorch (Meta) | 5.2k 14 | v0.6.1, 2025年4月 14日 | PyTorch原生,扩展性好,控制力强,支持PyTorch高级特性 |
XTuner (InternLM) | InternLM (上海人工智能实验室) | 4.5k 15 | v0.2.0rc0, 2025年2月 15日 | InternLM生态,全栈工具链,亚洲LLM支持,高效率 |
主流微调框架详细特性矩阵
工具名称 | 核心PEFT方法 | 量化细节 | 分布式训练 | 主要语言/框架 | 易用性 (主观) | 性能亮点 | 许可证 | Github地址 |
---|---|---|---|---|---|---|---|---|
LLaMA-Factory | LoRA, QLoRA, Freeze, GaLore, DoRA, LoRA+ | 2-8bit (AQLM, AWQ, GPTQ, LLM.int8, etc.) | 支持 (DeepSpeed/Accelerate implied) | Python / PyTorch | 高 (GUI) | Unsloth集成加速, Flash Attention | Apache 2.0 | https://github.com/hiyouga/LLaMA-Factory |
AutoTrain Advanced | LoRA (PEFT) | 4-bit (int4) | 未明确 (单机/Spaces为主) | Python / PyTorch (implied) | 高 (No-code UI) | 依赖HF Spaces后端 | Apache 2.0 | https://github.com/huggingface/autotrain-advanced |
Axolotl | Full-tune, LoRA, QLoRA, ReLoRA | GPTQ, QLoRA | FSDP, DeepSpeed, Multi-node | Python / PyTorch | 高 (YAML, Cookbooks) | 长上下文高效 10, torch_compile | Apache 2.0 | https://github.com/axolotl-ai-cloud/axolotl |
Unsloth | LoRA, QLoRA (4/8bit), Full-tune, RSLORA, LoftQ | 4-bit, 8-bit QLoRA, Dynamic Quant. | Pro/Enterprise for Multi-GPU | Python / PyTorch (Triton kernels) | 高 (API, Notebooks) | 单GPU速度/显存领先 | Apache 2.0 | https://github.com/unslothai/unsloth |
LitGPT(Lightning AI) | LoRA, QLoRA, Adapter, Adapter v2 | 4-bit float, 8-bit int, Double Quant | FSDP, TPU, 1-1000+ GPUs/TPUs | Python / PyTorch (Lightning Fabric) | 中 (Dev-friendly, less abstraction) | 优化实现, Flash Attention v2 | Apache 2.0 | https://github.com/Lightning-AI/litgpt |
Torchtune (PyTorch) | LoRA, QLoRA, SFT, DPO, PPO, etc. | QAT, torchao | FSDP2, Multi-node | Python / PyTorch | 中 (PyTorch native, more control) | PyTorch 2.x特性, torch.compile | BSD-3-Clause | https://github.com/pytorch/torchtune |
XTuner (InternLM) | LoRA, QLoRA, Full-tune, DPO, ORPO | QLoRA, LMDeploy for 4-bit inference | DeepSpeed, Multi-GPU, SLURM, Seq. Parallel | Python / PyTorch | 中 (CLI, Config files) | 高效算子, 7B on 8GB GPU, DeepSeek V2 2x faster | Apache 2.0 (implied) | https://github.com/InternLM/xtuner |
基于场景的工具选择指南
- 场景1:初学者,GPU资源有限,希望尝试微调。
- 推荐:LLaMA-Factory (提供GUI,并集成了Unsloth优化 )或Unsloth (提供Colab Notebooks,单GPU性能优异 ) 或。对于完全无代码的需求,可以看看AutoTrain,不过已经很久没更新了(相对其他项目),慎选 。
- 场景2:研究人员,需要高度灵活性以实验新方法和多样化模型。
- 推荐:Axolotl (模型支持广泛,社区驱动,能快速采纳新技术 ) 或 LitGPT (代码可定制性强,便于修改和实验 )。
- 场景3:身处PyTorch生态的机器学习工程师,需要为大型模型进行稳健的分布式扩展。
- 推荐:Torchtune (PyTorch原生,支持FSDP2和多节点训练 )。
- 场景4:开发者希望最大限度地控制和理解训练过程的每一个细节。
- 推荐:LitGPT (几乎无抽象层,代码透明 ) 或 Torchtune (抽象层最少,接近PyTorch底层 )
量化
量化(Quantization)可以被视为大模型微调生态系统中的一个重要组成部分,或者是一个与微调紧密配合的关键技术,尤其是在追求极致效率和在资源受限环境下部署模型时。
但是严格来说,量化本身是一种模型压缩技术,旨在降低模型权重和/或激活值的数值精度(例如,从32位浮点数FP32转换为8位整数INT8、4位整数INT4或更低位数)。
量化的基本原理
- 将高精度浮点数(如FP32)映射到低精度定点数(如INT8, INT4)或低精度浮点数(如FP8, BF16)。
- 这涉及到确定一个缩放因子 (scale) 和一个可选的 零点 (zero-point),用于在高精度和低精度之间进行转换。
主要的量化方法类型
-
训练后量化 (Post-Training Quantization, PTQ):
在模型已经训练或微调完成后进行量化,不需要重新训练。
- GPTQ (Generative Pre-trained Transformer Quantization): 一种精确的、逐层进行的PTQ方法,通过解决权重矩阵的量化重建误差来获得较好的精度,常用于将LLM量化到INT4/INT3。
- AWQ (Activation-aware Weight Quantization): 认为并非所有权重都同等重要,保护那些对激活值影响大的权重,从而在量化时损失更少性能。
- SmoothQuant: 通过平滑激活值的分布,使得权重和激活值都更容易被量化。
-
量化感知训练 (Quantization-Aware Training, QAT):
- 在训练或微调过程中引入伪量化节点 (fake quantization nodes),模拟量化操作对前向传播和反向传播的影响。
- 模型在训练时就学习适应量化带来的精度损失,因此通常能达到比PTQ更高的准确率,尤其是在需要量化到非常低的比特数(如INT4甚至更低)时。
- 缺点是需要重新训练或完整微调,计算成本较高。
GGUF
GGUF (GPT-Generated Unified Format) 是一种常见的格式,由 llama.cpp
项目推广和广泛使用。但GGUF本身不是一种全新的、独立的量化算法,而是一个文件格式,它被设计用来存储和分发经过量化(或其他转换)的大语言模型。
- 通常是微调后的步骤: 一般情况下,开发者会首先在较高精度(如FP16或BF16)下完成模型的微调(无论是全参数微调还是PEFT如LoRA)。
- 转换与量化: 微调完成后,模型需要以GGUF格式分发和在本地运行,可以使用
llama.cpp
提供的转换脚本,将微调后的模型(如果是LoRA,则通常先合并LoRA权重到基础模型)转换为GGUF格式,并在此过程中选择一种llama.cpp
支持的量化类型进行量化。 - 部署与推理: 最终用户下载GGUF格式的模型文件,使用
llama.cpp
或其他兼容的推理引擎在本地加载并运行。 - 高效推理: 经过
llama.cpp
优化的量化方法,可以在CPU上实现惊人的推理速度,并有效利用GPU。 - 低资源占用: 大幅减小模型文件大小和运行时内存占用。
- 易于分发和使用: 单个文件,方便共享和加载。
构建数据集
💡 高质量且与任务高度相关的数据是确保微调模型达到预期性能、准确性和特定行为模式的基石。数据质量直接决定了模型学习的细微差别、可能继承或减轻的偏见,以及其泛化能力。业界普遍认同“输入垃圾,输出垃圾”的原则,这在LLM微调中尤为突出。
💡 微调数据集的质量对模型性能的影响,往往比预训练语料库的绝对规模更为显著。
💡 小规模**、高质量、任务针对性强的微调数据集能够带来显著的性能提升。
低质量的微调数据甚至可能导致性能下降,例如灾难性遗忘或偏见放大**。
微调数据集的构建是一个多阶段的生命周期,涵盖了从初始规划、数据搜集、清洗与预处理、格式化,到可能的数据增强与标注,以及严格的质量评估。这些阶段环环相扣,每一个环节都对最终数据集的效能至关重要。
数据
初始规划
任务的性质直接决定了所需数据的类型、范围、格式和标注要求。例如,对于问答任务,需要收集问答对或能够从中提取答案的文档。对于情感分析,则需要收集带有情感标签(如积极、消极、中性)的文本。代码生成任务则需要包含代码片段及其对应的自然语言描述的数据集。
数据搜集
LLM微调数据一般有四种来源
- 公共数据集:是LLM微调数据的重要来源之一。常见的平台包括Hugging Face Datasets Hub、Kaggle、GitHub项目、Google Dataset Search以及UCI机器学习知识库等。
- **网络抓取数据:**网络抓取是通过爬虫和抓取器系统性地从网站上提取公开信息的过程。
- **专有数据:组织内部的专有数据是另一个极具价值的数据来源,包括内部文档、客户交互记录(如聊天记录、支持工单、电子邮件)、数据库内容以及内部知识库(wiki)**等。(真正能帮我们解决问题的数据)
- **合成数据:**当真实世界数据有限(例如,罕见病症数据、边缘案例)、需要解决隐私问题、平衡非均衡数据集或为全新任务创建数据时,合成数据便有了用武之地。
数据清洗
原始数据通常充满噪声、不一致性,并包含大量不相关信息。数据清洗和预处理是将原始数据转化为结构化、高质量、适合模型训练的格式的关键步骤,下面介绍一些常见的清洗技术。
技术 | 描述 | 对LLM的重要性 | 常用工具/Python库 (代码片段示例思路) | 潜在陷阱 |
---|---|---|---|---|
去重 (Deduplication) | 移除重复或高度相似的数据项 | 防止模型偏向常见样本,提高训练效率,改善泛化能力 | Pandas (df.drop_duplicates()), MinHash (e.g., datasketch library), 语义相似性模型 (e.g., Sentence Transformers) | 模糊去重阈值设置不当可能误删有用数据或保留过多冗余 |
PII匿名化 (PII Anonymization) | 识别并移除或遮蔽个人身份信息 (如姓名、地址、身份证号) | 保护用户隐私,符合GDPR、CCPA等法规要求 | spaCy (NER), Presidio, 自定义正则表达式, Faker (生成假数据替换), cryptography (加密) | 过度匿名化可能损失数据效用,匿名化不彻底导致隐私泄露,可能引入新偏见 |
文本规范化 - 大小写转换 | 将所有文本统一转换为小写 (或大写) | 减少词汇表大小,确保一致性 | Python str.lower() | 可能丢失某些特定含义 (如专有名词首字母大写) |
文本规范化 - 标点符号处理 | 移除或标准化标点符号 | 减少噪声,聚焦核心文本内容 | Python string.punctuation, re.sub() | 某些标点符号可能承载语义信息 (如问号、感叹号) |
文本规范化 - 停用词移除 | 移除常见但意义不大的词语 (如“的”, “是”, “在”) | 减少噪声,聚焦重要词汇 (对LLM可能非必需或需谨慎) | NLTK (stopwords), spaCy (is_stop) | 可能移除对LLM理解上下文重要的词语 |
文本规范化 - 词形还原 (Lemmatization) | 将词语还原为其字典中的基本形式 (lemma) | 统一词形,保留词义,优于词干提取 | NLTK (WordNetLemmatizer), spaCy (token.lemma_) | 计算成本略高于词干提取 |
过滤低质量/不相关内容 | 移除格式错误、无意义、与任务无关的文本 | 提高数据集信噪比,确保模型学习有效信息 | 启发式规则 (长度、重复率、特殊字符比例), 基于模型的分类器 (如fastText进行语言识别或质量评分) | 过滤标准过于严格可能丢失有用数据,过于宽松则引入噪声 |
HTML/XML标签移除 | 清除网页抓取数据中的HTML或XML标签 | 提取纯文本内容,避免模型学习无关的标记语言 | BeautifulSoup, lxml, 正则表达式 | 可能错误移除标签内的有用文本或破坏原始结构 |
Unicode规范化 | 将文本转换为统一的Unicode表示 (如NFC, NFD) | 确保字符表示一致性,避免因编码问题导致的错误 | Python unicodedata.normalize() | 选择错误的规范化形式可能导致问题 |
处理缺失文本数据 | 针对文本字段本身为空或元数据缺失的情况 | 确保数据集完整性,避免训练错误 | Pandas (df.dropna(subset=['text_column'])), 过滤空字符串 | 删除过多数据可能导致样本不足或偏倚 |
错误修正 (拼写、语法) | 纠正文本中的拼写或基本语法错误 | 提高文本质量,帮助模型学习正确的语言模式 (对LLM可能非首要,因其对噪声有一定鲁棒性) | pyspellchecker, language_tool_python (需谨慎使用,可能改变原意) | 自动修正可能引入新错误或改变原始语义 |
内容过滤 (有害、偏见) | 识别并移除或标记仇恨言论、歧视性语言等不良内容 | 确保数据集的伦理合规性,防止模型学习和放大有害偏见 | 基于关键词/规则的过滤器, HAP评分器, 训练专门的分类器进行检测 | 难以完美覆盖所有有害内容,可能存在误判,文化背景差异导致判断标准不一 |
数据格式化
大型语言模型(LLM)需要特定结构格式的数据才能有效地理解任务并进行学习。整个数据集中格式的一致性至关重要。下面是两种常见的格式
Alpaca
-
指令监督微调数据集
[ { "instruction":"人类指令(必填)", "input":"人类输入(选填)", "output":"模型回答(必填)", "system":"系统提示词(选填)", "history":[ ["第一轮指令(选填)","第一轮回答(选填)"], ["第二轮指令(选填)","第二轮回答(选填)"]] } ]
-
预训练数据集
[ {"text": "document"}, {"text": "document"} ]
-
偏好数据集
[ { "instruction": "人类指令(必填)", "input": "人类输入(选填)", "chosen": "优质回答(必填)", "rejected": "劣质回答(必填)" } ]
-
多模态数据集
[ { "instruction": "人类指令(必填)", "input": "人类输入(选填)", "output": "模型回答(必填)", "images": [ "图像路径(必填)" ] } ]
ShareGPT
-
指令监督微调数据集
[ { "conversations": [ { "from": "human", "value": "人类指令" }, { "from": "function_call", "value": "工具参数" }, { "from": "observation", "value": "工具结果" }, { "from": "gpt", "value": "模型回答" } ], "system": "系统提示词(选填)", "tools": "工具描述(选填)" } ]
-
偏好数据集
[ { "conversations": [ { "from": "human", "value": "人类指令" }, { "from": "gpt", "value": "模型回答" }, { "from": "human", "value": "人类指令" } ], "chosen": { "from": "gpt", "value": "优质回答" }, "rejected": { "from": "gpt", "value": "劣质回答" } } ]
数据增强(高级)
微调数据集,特别是针对专业化任务的数据集,其规模往往有限。数据增强技术通过扩展数据集的规模和多样性,有助于提升模型的泛化能力、减少过拟合,并增强模型对输入变化的鲁棒性。
技术 | 描述 | 优点 | 缺点 | 典型用例/有效性 | 资源强度 |
---|---|---|---|---|---|
同义词替换 | 将词语替换为其同义词 | 简单易实现,增加词汇多样性 | 可能改变原句语义,需要高质量的同义词库 | 文本分类,情感分析;对简单任务有效 | 低 |
随机插入/删除/交换 | 随机在文本中插入、删除或交换词语/字符 | 简单快速,引入噪声以增强鲁棒性 | 容易破坏语义完整性,可能产生无意义文本 | 提高模型对噪声的鲁棒性;需谨慎使用 | 低 |
回译 (Back-Translation) | 将文本翻译到另一种语言再翻译回原文 | 生成语义相似但表达多样的句子,保持较高流畅度 | 依赖翻译质量,可能引入翻译错误或风格变化 | 文本生成,释义;对多种任务有效 | 中 |
释义 (LLM-based Paraphrasing) | 使用LLM生成现有文本的不同表达方式 | 生成高质量、语义一致的释义,多样性好 | 计算成本较高 (若使用大型LLM API),可能继承LLM偏见 | 问答,摘要,文本生成;效果通常较好 | 高 |
上下文增强 (Contextual Augmentation) | 基于上下文替换词语,如使用BERT建议 | 生成的替换更符合上下文语义 | 实现相对复杂,依赖预训练模型的质量 | 文本分类,自然语言理解任务 | 中 |
噪声注入 (Noise Injection) | 向数据中添加少量随机变化 | 提高模型鲁棒性,使其能处理不完美输入 | 可能降低数据质量,噪声水平难以控制 | 适用于需要处理嘈杂输入的场景 | 低 |
基于提示的LLM生成 (Prompt-based) | 使用精心设计的提示引导LLM生成新样本、指令或变体 | 灵活性高,可生成高度定制化的数据,适用于多种任务 | 提示工程复杂,生成质量依赖提示和LLM能力,可能产生幻觉或偏见 | 指令微调,对话生成,特定领域数据生成;潜力巨大 | 高 |
教师-学生模型合成数据 (Teacher-Student) | 使用大型LLM (教师) 生成数据,用于微调小型LLM (学生) | 可为资源受限场景生成大量高质量数据,实现知识蒸馏 | 教师模型的偏见可能传递给学生模型,生成成本(API或计算)可能较高 | 资源受限的微调,特定任务的数据生成 | 高 |
主动学习 (Active Learning) | 模型选择最不确定的样本进行标注或增强 | 提高标注效率,用更少的数据达到更好效果 | 实现复杂,依赖模型不确定性度量的准确性 | 数据标注成本高昂的场景,迭代式数据收集 | 中 |
数据评估
在进行微调之前评估数据集质量至关重要,这有助于防止计算资源的浪费,及早诊断潜在问题,并对模型性能设定切合实际的期望。一个高质量的数据集应具备清洁、代表性、平衡和准确标注等特性。下面介绍一些数据评估的关键指标与方法。
质量维度 | 评估方法/指标 | 描述 | 重要性 |
---|---|---|---|
标签准确性 | 人工审核 (专家审查、多标注员交叉验证), LLM即法官 (与参考答案或标准比较), 一致性评分 (如黄金标准集对比) | 验证标注是否正确反映了真实情况或符合标注指南。 | 错误的标签会导致模型学习错误的模式,严重影响模型性能和可靠性。 |
数据一致性 | 标注员间一致性 (IAA) 指标 (Cohen's Kappa, Fleiss' Kappa), 数据集内部格式和标签使用的一致性检查 | 衡量不同标注员对相同数据标注的一致程度,以及数据内部是否存在矛盾或不规范之处。 | 高一致性表明标注指南清晰、标注员理解到位,数据质量较高;低一致性则反之。 |
任务相关性 | 领域专家人工审核, 关键词/主题分析, 与任务描述的语义相似度评估 | 确保数据集中的每个样本都与预定义的微调任务和目标领域直接相关。 | 不相关的数据会引入噪声,分散模型的学习重点,降低其在目标任务上的表现 |
数据多样性 | 分布分析 (类别、长度、风格等), 覆盖边缘案例分析, 语言变体检查, 视角多样性评估 | 数据集应包含广泛的输入类型、语言风格、潜在场景和用户群体,以增强模型的泛化能力。 | 缺乏多样性会导致模型在未见过的、但属于任务范畴的输入上表现不佳,容易过拟合到训练数据中的特定模式。 |
内容覆盖度 | 主题模型分析 (如LDA), 关键词覆盖率统计, 与领域知识图谱对比, 缺失场景识别 | 评估数据集是否充分覆盖了任务所需知识范围、关键概念和重要子主题。 | 覆盖度不足会导致模型在某些方面知识欠缺,可能产生幻觉或无法处理特定类型的查询/输入。 |
语言质量 | 清晰度、连贯性、流畅性、模糊性评估 (人工或LLM辅助), 困惑度 (Perplexity) | 评估文本数据本身的语言学质量,确保文本易于理解且无歧义,尤其对生成任务重要。 | 低语言质量的输入数据可能误导模型,影响其学习正确的语言模式和生成高质量的输出。 |
数据平衡性 | 类别分布统计 (对分类任务), 少数群体代表性分析 | 检查数据集中不同类别或群体的样本数量是否均衡,避免模型偏向多数类或忽略少数群体。 | 不平衡的数据会导致模型在少数类上性能不佳,产生偏见。 |
数据划分合理性 | 验证集/测试集与训练集的分布一致性检查 (如使用分层抽样), 确保无数据泄露 | 评估数据划分是否能真实反映模型在未见数据上的表现,验证集和测试集是否具有代表性且与训练集独立。 | 不合理的划分会导致对模型性能的评估产生偏差,可能高估或低估模型的真实泛化能力。 |
常用工具介绍
MinerU
https://github.com/opendatalab/MinerU是一款将PDF转化为机器可读格式的工具(如markdown、json),可以很方便地抽取为任意格式。 MinerU诞生于书生-浦语的预训练过程中。
- 删除页眉、页脚、脚注、页码等元素,确保语义连贯
- 输出符合人类阅读顺序的文本,适用于单栏、多栏及复杂排版
- 保留原文档的结构,包括标题、段落、列表等
- 提取图像、图片描述、表格、表格标题及脚注
- 自动识别并转换文档中的公式为LaTeX格式
- 自动识别并转换文档中的表格为HTML格式
- 支持多种输出格式,如多模态与NLP的Markdown、按阅读顺序排序的JSON、含有丰富信息的中间格式等
easy-dataset
https://github.com/ConardLi/easy-dataset 是一个专为创建大型语言模型(LLM)微调数据集而设计的应用程序。它提供了直观的界面,用于上传特定领域的文件,智能分割内容,生成问题,并为模型微调生成高质量的训练数据。
- 创建项目
- 配置模型,支持Ollama,OpenAI等多种模型提供商(我自己在VLLM上有一个Qwen3 32B,这里我直接修改OpenAI配置)
- 上传文档,等待自动分割
- 查看切分后的文本块(如果有问题,可以自行修改),并生成问题
- 查看问题,验证问题使用的文本块是否正确,如果不对,请手动修改。也可以手动添加问题,及其关联的文本块。
- 批量构造数据集
- 查看每一条数据集,观察问题和回答是否正确,并确认
- 选择文件格式JSONL,数据集风格Alpace,导出数据集
至此我们的数据集构建完成。
构建高质量的LLM微调数据集是一个复杂但至关重要的过程。微调数据集的构建涉及人类专业知识与AI辅助之间更深层次的共生关系。LLM不仅将消费数据,还将积极参与数据的策划、清洗、增强和质量评估,并在人类的监督下完成这些工作。人类的监督对于定义目标、处理模糊性、确保伦理对齐以及验证AI生成的数据/评估结果仍然至关重要。数据集构建是人机协作的成果,利用AI的可扩展性和人类的细致判断力,以更高效的方式创建更高质量的数据集。(据说DeepSeek找北大,OpenAI找博士做数据)
LLaMA Factory微调Qwen3 8B
配置数据集
使用上面导出的数据集,命名为CCER.json。
-
将CCER.json数据集添加到LLaMA Factory的data目录
-
修改
dataset_info.json
注册数据集将我们的ccer数据集添加进去,可以看到LLaMA Factory自带了很多数据集
{ ... "ccer": { "file_name":"CCER.json" }, ... }
配置微调参数
- 选择模型、模型路径
- 选择微调方法,有lora,full,freeze三种,选择lora
- 选择训练数据集,在下拉框中,可以看到我们上一步注册
ccer
数据集
通用训练参数
- 学习率
- 描述:控制模型参数更新的步长。
- 建议:
- 常见范围是 1×10−4 到 5×10−4 (例如,
1e-4
,3e-4
)。 - 具体最佳值取决于模型、数据集和批次大小,需要实验调整。
- 可以配合学习率调节器 (learning rate scheduler) 使用,如
cosine
或linear
衰减。
- 常见范围是 1×10−4 到 5×10−4 (例如,
- 训练轮数
- 描述:整个训练数据集被模型学习的次数。
- 建议:
- 通常 1 到 5 个 epochs 可能就足够了,具体取决于数据集大小和任务复杂度。
- 密切监控验证集上的性能,以避免过拟合,并根据需要进行早停。
- 批处理大小
- 描述:每次参数更新所用的样本数量。
- 建议:
- 在显存允许的范围内,较大的批次大小通常能提供更稳定的梯度。
- 常见的批次大小有 4, 8, 16, 32 等。
LoRA参数
- LoRA秩(r)
- 描述:LoRA 适配器中低秩分解矩阵的秩。它直接决定了添加到模型中的可训练参数数量。
r
越大,可训练参数越多,理论上模型能学习到更复杂的模式,但也可能增加过拟合的风险和计算成本。 - 建议:
- 通常从较小的值开始尝试,如 4, 8, 16, 或 32,如果任务非常复杂或数据集非常大,可以尝试更大的
r
值,如 64 甚至 128。 - 权衡性能提升和增加的参数量/训练时间。较小的
r
值可以实现更快的训练和更小的模型文件。
- 通常从较小的值开始尝试,如 4, 8, 16, 或 32,如果任务非常复杂或数据集非常大,可以尝试更大的
- 描述:LoRA 适配器中低秩分解矩阵的秩。它直接决定了添加到模型中的可训练参数数量。
- LoRA缩放系数
- 描述:用于调整 LoRA 适配器输出的权重。通常,它被设置为与
r
相同的值或r
的两倍。这个参数可以看作是对 LoRA 适配器激活的“强度”进行调整。 - 建议:
- 一个常见的做法是将
lora_alpha
设置为r
的两倍。例如,如果r=8
,则lora_alpha=16
。 - 需要实验确定
- 一个常见的做法是将
- 描述:用于调整 LoRA 适配器输出的权重。通常,它被设置为与
- LoRA随即丢弃
- 描述:在 LoRA 层的 A 矩阵之后应用 dropout,以防止过拟合。
- 建议:
- 如果担心过拟合,可以设置一个较小的值,如 0.05 或 0.1。某些数据集或任务,不需要 dropout (可以设置为 0)。
- 如果训练数据较少,或者模型表现出过拟合的迹象,可以尝试增加 dropout 值。
- LoRA+ 学习率比例(λ)
- 描述:LoRA+ 是一种对标准 LoRA微调方法的改进。对于嵌入维度较大的模型,这种做法可能略优于LoRA微调。
- 建议:
- λ 应该大于等于 1。
- 标准的 LoRA 微调效果未达到预期,或者希望在相似的计算成本下获得更好的性能和更快的收敛速度,可以尝试 LoRA+。
- rslora
- 描述:rsLoRA 旨在解决标准 LoRA 在使用较高秩 (r) 时可能出现的训练不稳定和性能下降问题。
- 建议:
- 如果在使用标准 LoRA 并尝试增加秩时观察到训练困难、收敛缓慢或性能反而下降的情况,此时可以尝试 rsLoRA。
- LoRA 在高秩下表现不佳或训练不稳定,那么 rsLoRA 是一个很好的选择。
- DoRA
- 描述:DoRA 的目标是进一步缩小 LoRA 与全参数微调之间的性能差距,逼近全参数微调。
- 建议:
- 对微调后的模型性能有非常高的要求,如果发现标准 LoRA 的效果与全参数微调仍有一定差距,DoRA 提供了一个有潜力缩小这一差距的选项。
- PiSSA
- 描述:PiSSA 的核心思想是改进 LoRA 中低秩适配器矩阵 A 和 B 的初始化方式以及优化目标,逼近全参数微调。
- 建议:
- 期望更快收敛和更好性能时。
- 需要对模型量化时,可以尝试**,**减少量化误差(与 QLoRA 结合时)。
开始微调
方便的查看进度以及loss趋势
模型导出与测试
LLaMA Factory可以方便的导出模型到指定目录。
可以明显看出微调前后,对同一问题,微调后模型回答正确。
至此,大模型微调完成。整个过程看似比较简单,但在实际工作中,需要不停的实验,尝试不同的数据集,参数组合,才能真正提升性能。
💡 优秀的模型,需要的数据质量 远大于 数量。