大模型微调

月伴飞鱼 2025-04-07 11:55:24
AI相关 > AI实践
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!

为什么需要微调?

我们平常接触到的大模型如 GPT、DeepSeek 等都是基于海量的通用数据训练而成的。

它们具备非常强大的语言理解和生成能力,能够处理多种自然语言任务。

但是,这些模型在某些特定领域或任务上的表现可能并不理想,或者说还能够做到表现的更好。

微调基本流程

以下是一个常见的模型微调的过程:

选定一款用于微调的预训练模型,并加载。

准备好用于模型微调的数据集,并加载。

准备一些问题,对微调前的模型进行测试(用于后续对比)。

设定模型微调需要的超参数。

执行模型微调训练。

还使用上面的问题,对微调后的模型进行测试,并对比效果。

如果效果不满意,继续调整前面的数据集以及各种超参数,直到达到满意效果。

得到微调好的模型。

预训练模型

预训练模型就是我们选择用来微调的基础模型,就像是一个已经受过基础教育的学生,具备了基本的阅读、写作和理解能力。

这些模型(如 GPT、DeepSeek 等)已经在大量的通用数据上进行了训练,能够处理多种语言任务。

  • 选择一个合适的预训练模型是微调的第一步。

一般来说,为了成本和运行效率考虑,都会选择一些开源的小参数模型来进行微调。

比如 Matellama、阿里的 qwen,以及最近爆火的 DeepSeek(蒸馏版)。

数据集

数据集就是我们用于模型微调的数据,它包含了特定领域的知识和任务要求。

这些数据需要经过标注和整理,以便模型能够学习到特定领域的模式和规律。

比如,如果我们想让模型学会算命,就需要准备一些标注好的命理学知识作为数据集。

一般情况下,用于模型训练的数据集是没有对格式强要求的。

  • 比如常见的结构化数据格式:JSON、CSV、XML 都是支持的。

可以获取公开数据集的网站:

  • Hugging Face:是 AI 模型和数据共享的中心。

  • 也可以选择国内的一些类似社区,比如 GitCode 的 AI 社区。

通过平台微调大模型

目前市面上很多 AI 相关平台都提供了在线微调模型的能力。

比如以最近比较火的硅基流动为例:https://cloud.siliconflow.cn/

进入硅基流动后台的第二项功能就是模型微调。

选择预训练模型:

尝试新建一个微调任务,选择 Qwen2.5-7B

准备数据集。

验证数据集:

数据集上传完成后,下一步就是输入一个微调后模型的名字,以及设置验证数据集。

验证数据集就是从我们的整体数据中划分出来的一部分数据。

  • 它通常占总数据的一小部分(比如 10%~20%)。

这部分数据在训练过程中不会被用来直接训练模型,而是用来评估模型在未见过的数据上的表现。

简单来说,验证数据集就像是一个模拟考试,用来检查模型是否真正学会了知识,而不是只是背诵了训练数据。

超参数设置:

训练轮数(Number of Epochs)

Epoch 是机器学习中用于描述模型训练过程的一个术语,指的是模型完整地遍历一次整个训练数据集的次数。

换句话说,一个 Epoch 表示模型已经看到了所有训练样本一次。

学习率(Learning Rate)

决定了模型在每次更新时参数调整的幅度,通常在 (0, 1) 之间。

  • 也就是告诉模型在训练过程中学习的速度有多快。

学习率越大,模型每次调整的幅度就越大,学习率越小,调整的幅度就越小。

批量大小(Batch Size)

是指在模型训练过程中,每次更新模型参数时所使用的样本数量。

它是训练数据被分割成的小块,模型每次处理一个小块的数据来更新参数。

预训练

从零开始训练一个模型,一般这个流程叫做预训练。

这个过程的目的就是让模型掌握语言的通用规律,以及基本的语言理解能力。

目前我们市面上主流的大模型,比如 ChatGPT、DeepDeek 等等,都属于 自回归模型。

  • 而 自回归模型 的本质就是:用过去的自己来预测未来的自己

我们都知道,大模型输出文本的时候是按照 Token 来输出的。

Token 简单理解就是把句子拆成最小语义单元(如中文拆字 / 词,英文拆词或子词)。

当你给定模型一个问题时,模型先会预测出第一个 Token,然后根据问题和第一个 Token 再去预测第二个 Token。

直到整句话输出完成,比如下面的例子。

a26de0e993c1dfce1f975f6baa838335.jpeg

回答被拆分出了 4 个 Token,每个 Token 都是根据前面的问题 + 已经输出的 Token 预测出来的。

那怎么能让模型把后面输出的每个 Token 预测的更准确呢?

这就要靠我们的预训练数据集了,在预训练的数据集中,这些关键字出现在一起的次数越多,那模型输出的概率越大。

  • 所以我们的数据集越丰富,模型预测 Token 输出的准确率就越高,最终的输出效果也就更好。

所以在预训练的过程中,我们一般用海量非结构化文本(比如书籍、网页、对话)。

通过「预测下一个词」来训练模型,这也就意味着预训练的数据集格式是没有明确要求的。

但是在特定领域的微调上,就不能用非结构化文本了,我们可以这样理解:

预训练阶段:就像婴儿学说话,听到的是各种声音(非结构化),不管是什么,直接让他多听,慢慢多就能学会语言规律。

指令微调阶段

就像教小孩做事「听到问题要回答」,需要明确告诉他这是什么问题,正确答案是什么。

如果继续用没规律(非结构化)对话,他对你要让他学的事情就不会印象太深刻。

而预训练的过程,我们可以理解成一个无需人工监督,自己学习和锻炼能力的过程。

对应的,想要让模型具备特定的能力,就要用到监督微调了。

微调分类

监督微调

监督微调(Supervised Fine-Tuning,SFT),顾名思义就是需要人去监督微调的过程。

怎么 监督 呢?

就是通过标注过的数据直接教模型做事,适合有明确目标的任务。

最简单的,我们直接告诉模型输入对应的输出是什么就可以了。

比如:我们想训练一个中英翻译模型,把英文翻译为中文就是一个非常明确的需求场景。

所以在数据集里只需要有输入、输出就可以了。

{"input": "Hello", "output": "你好"}

指令微调

那假如我们想让模型具备多种语言理解的能力呢,这时候只靠两个字段就不够了。

因为在 Input 是同样一个词语的时候,根据我们想让模型完成的不同任务,output 可能是不一样的。

这时候我们就要多引入一个指令的概念,比如这个数据集。

[
  {
    "instruction": "将这句英文翻译成法语",
    "input": "Hello, how are you?",
    "output": "Bonjour, comment ça va ?"
  },
  ...
]

我们告诉模型明确的指令:

将英文翻译为法语,再将 Input(英文)、Output(法语)告诉模型, 模型就能准确理解要做什么了,这就是指令微调。

指令微调的数据集制作相对还是比较简单的,因为我们要执行的任务一般很明确,往往也有比较明确的答案了。

  • 比如想要微调模型在翻译方面的能力,那就用现成的翻译 API 来构造数据集。

想要微调模型在数学解题方面的能力,其实也有现成的题目 + 答案可以用来构造。

所以指令微调场景的数据集一般不太难做,主要进行一些格式转换的工作即可。

对话微调

对话微调(Dialogue Tuning) 是通过多轮对话数据训练模型生成连贯、符合语境的回复。

  • 强调对话历史的上下文理解和回复的自然流畅性。

其核心在于教会模型处理对话中的逻辑关系、情感表达和角色身份。

  • 对话微调的数据集通常包含对话的上下文以及对应的回复。
[
  {
    "dialogue": [
      {"role": "user", "content": "今天天气怎么样?"},
      {"role": "assistant", "content": "北京今日多云转晴,气温22℃,适合户外活动。"},
      {"role": "user", "content": "那适合去长城吗?"},
      {"role": "assistant", "content": "长城景区海拔较高,建议携带外套,注意防晒。"}
    ]
  },
  ...
]

对话微调数据集的核心特点:

  • 包含多轮对话上下文、标注角色身份,注重回复连贯性与逻辑性。

通过这样的数据,模型可以学习到在不同对话场景下如何生成合适的回复,从而提高对话的连贯性和相关性。

对话微调的数据集制作也不困难,一般可从在线聊天平台、客服对话记录、或者一些公开的访谈记录来获取数据。

也能通过众包方式让标注人员模拟对话生成,只需整理为特定格式,如标注对话角色、意图等。

领域适配

基于微调让模型对特定领域进行适配。

预训练的模型虽然基于海量数据具备了通用的文字理解和生成能力。

但是由于预训练的数据集在特定领域可能并不会覆盖的那么全面。

  • 这些模型在某些特定领域或任务上的表现可能并不理想,这时候就需要进行领域适配微调。

领域适配(Domain Adaptation)是指将模型在特定领域的数据上进行微调,使其更好地适应特定领域的任务和需求。

怎么进行领域适配呢?

我们需要在特定领域的数据集上对模型进行训练。

这些数据集通常包含该领域的专业术语、特定格式和相关任务的标注。

例如,在医疗领域,数据集可能包含病历文本、医学术语以及对应的诊断结果等信息。

[
  {
    "instruction": "分析患者的症状描述",
    "input": "55岁男性,持续性胸骨后疼痛3小时,含服硝酸甘油无效",
    "output": "可能诊断:急性心肌梗死(STEMI),建议立即行心电图检查及心肌酶谱检测",
    "domain": "医疗"
  },
  {
    "instruction": "解释法律条款",
    "input": "《民法典》第1032条",
    "output": "该条款规定自然人享有隐私权,任何组织或个人不得以刺探、侵扰、泄露、公开等方式侵害他人隐私权",
    "domain": "法律"
  },
  ...
]

在领域适配的任务上,数据集的准备相对就困难一点了。

首先我们可以尝试去一些开源数据集平台(如 HuggingFace) 上检索是否有复合我们需求的数据集。

如果没有找到合适的,或者开源数据集无法完全满足我们的需求的时候,可能就得靠我们自己的一些领域文献来构造数据集。

将领域文献构造成数据集,一般就两个途径:

第一个就是靠纯人工整理,或者与领域专家合作标注数据(可以借助一些三方的标注平台)

将数据处理为模型可接受的格式,可能涉及术语标准化等工作。

第二个就是借助 AI 辅助生成

注意这里 AI 起到的作用只是辅助和提效,并不能完全自动化,就算大家真的能够借助某些工具全自动将领域文献转化成数据集。

不建议大家直接用,在不经过人工二次确认的情况下,质量肯定难以保障,最终模型微调的效果也不会很好。

文本分类

它是自然语言处理中的一个经典任务,目的就是通过标注数据训练模型对文本进行类别预测或标签分配。

这类任务需要模型理解文本语义与类别特征的关系,适用于需要结构化输出的场景。

怎么进行文本分类呢?

我们需要使用标注了类别的文本数据集对模型进行训练,让模型学习文本特征与类别的映射关系。

  • 文本分类数据集的关键在于构建符合业务需求的分类标签。

例如从评论中区分出好评和差评,从新闻中区分出客集新闻和金融新闻。

[
  {"text": "这款手机续航长达48小时,拍照效果惊艳", "label": "positive"},
  {"text": "系统频繁卡顿,客服响应速度慢", "label": "negative"},
  {"text": "量子计算机突破新型纠错码技术", "label": "science_news"},
  {"text": "央行宣布下调存款准备金率0.5个百分点", "label": "finance_news"}
]

文本分类任务的数据集,一般可以借助一些专业的第三方标注平台来做:

  • 这类平台往往配备了丰富的标注工具,能满足不同文本分类需求。

例如在新闻文本分类中,标注员可利用平台的快速标注功能,将新闻精准划分为政治、经济、娱乐等类别。

模型推理微调

对于推理模型的微调其实是监督微调的一种特殊形式,通过在数据集中显式标注思维链(Chain of Thought, COT)。

  • 训练模型不仅给出最终答案,还能生成逻辑推导过程。

其核心在于让模型学会「分步思考」,适用于需要复杂逻辑推理的场景(如数学证明、代码调试)。

在推理模型(比如 DeepSeek-R1)的回答中,<think></think> 中包含的这部分其实就是模型的推理过程。

它其实是根后面的答案一起作为一个回答输出的,只不过在大部分的 C 端应用中对这部分提取出来做了特殊展示。

随着最近推理模型 DeepSeek-R1 的爆火,开始让推理模型走进大众的视野。

大家在选择模型进行微调时,也会去选择具备推理能力的模型,如 DeepSeek-R1 的蒸馏版本。

[
  {
    "instruction": "解决数学应用题",
    "input": "小明买了3支铅笔,每支2元;又买了5本笔记本,每本比铅笔贵4元。总花费多少?",
    "chain_of_thought": [
      "铅笔单价:2元/支 → 3支总价:3×2=6元",
      "笔记本单价:2+4=6元/本 → 5本总价:5×6=30元",
      "合计花费:6+30=36元"
    ],
    "output": "总花费为36元"
  },
  ...
]

其实并不是所有任务都适合用推理模型,因为推理模型的幻觉比较大,有些情况选择推理模型反而会起到相反的效果。

在处理简单明确的任务时,推理模型可能会把问题复杂化,导致思考过度、响应较慢,甚至增加幻觉的风险。

比如如果你让推理模型去完成检索、解释类的任务时。

  • 当它找不到可以参考的信息就会按照自己的思考过程进行输出,结果并不一定准确。

数据集中的思维链,在某些特定场景下可能比较容易获取。

  • 比如在数学推理任务的微调上,一般数据集本身带的解题过程就可以作为思维链。

还有就是靠带推理能力的大模型蒸馏获取,像 OPEN AI 的 O1、O3 这种模型。

为了避免大家窃取思考过程,思维链都是直接隐藏掉的,但是我们的国货之光 DeepDeek 是完全开源且开放思考过程的。

目前很多带思维链的开源数据集都是从 DeepSeek-R1 蒸馏而来。

  • 或者我们也可以引导不具备推理能力的模型来产出思考过程。

知识蒸馏

蒸馏技术并不属于微调的范畴,但是我们实际上是可以通过微调来达到蒸馏的效果。

  • 所以这里我把它当作是一种特殊的微调(并不严谨)。

知识蒸馏(Knowledge Distillation)是将复杂模型(教师模型)的知识迁移到轻量级模型(学生模型)的技术。

  • 通过优化学生模型使其输出接近教师模型的软标签,从而在保持性能的同时降低推理成本。

简单来说,如果大模型已经完全可以满足你在特定任务上的诉求,但是部署成本又太高了。

你完全可以选择一个小模型,然后从大模型里把你任务里需要用到的领域知识提取出来,构造成数据集,再去微调小模型。

  • 从而让这个小模型也能在你的特定领域完成任务,这就可以理解为一个模型蒸馏的过程。

模型蒸馏的数据集构造应该是最简单的,在你完全信任大模型输出的条件下,你可以直接将大模型产出的问答对作为数据集。

最后在进行人工的质量评估和验证即可。

强化学习微调

强化学习微调(Reinforcement Learning from Human Feedback,RLHF)是在监督微调的基础上。

  • 通过人类来主动反馈优化模型生成质量的方法。

其核心在于引入奖励模型(Reward Model)评估生成结果的合理性,并通过强化学习策略(如 PPO 算法)调整模型参数。

  • 使生成内容更符合人类偏好。
[
  {
    "input": "请推荐一部科幻电影",
    "output": "《星际穿越》是一部经典科幻片,探讨了时间与亲情。",
    "reward_score": 4.5  // 人类标注的质量评分(0-5分)
  },
  {
    "input": "解释黑洞理论",
    "output": "黑洞是由暗物质构成的神秘天体,会吞噬一切物质。",
    "reward_score": 2.0  // 包含错误信息,得分低
  }
]

多模态微调

多模态微调(Multimodal Fine-Tuning)指通过文本、图像、语音等多模态数据训练模型。

  • 使其具备跨模态理解与生成能力。

它和文本类模型的微调可以说是并列的两个范畴,其中也包括监督/非监督微调、强化学习微调等范畴。

需要注意的是,想要做一个多模态的微调任务,前提是选择的预训练模型一定也要具备基础的多模态理解能力

多模态微调任务涉及多种模态的数据(如文本、图像、音频等)。

  • 模型需要能够理解和处理这些不同模态的信息,并有效地进行融合和交互。

如果预训练模型本身不具备多模态能力,那么在微调阶段将面临很大的挑战,难度不亚于从零训练一个多模态模型。

  • 所以你想用多模态数据集去微调 DeepSeek 就先别考虑了。
[
  {
    "text": "一只猫在追蝴蝶",
    "image_url": "https://example.com/cat.jpg",
    "caption": "一只橘色的猫正在追逐花园里的白色蝴蝶"
  },
  {
    "audio": "audio.wav",
    "text": "会议录音转写:今天的议题是...",
    "summary": "会议讨论了Q3销售目标与市场策略"
  }
]

注意这里的图片、视频、音频等多模态数据可以是 CND 地址、base64 编码,或者直接放在 HuggingFace 上。

常用格式

对于模型微调的数据集,是没有明确的格式要求的,我们一般在代码中抹除各种微调数据集格式的差异。

目前广泛被大家使用的有两种数据集格式,AlpacaShareGPT

Alpaca

Alpaca 的 JSON 结构逐渐被抽象为一种 通用数据格式,并且扩展了一些字段如 system(系统提示)和 history(历史对话)。

  • 支持多轮交互任务。

适用于多种微调场景,很多主流框架(如 LLaMA-Factory、DeepSpeed)都可以直接加载 Alpaca 格式的数据集。

这里参考 LLaMA-Factory 给出的几种在不同微调场景中 Alpaca 格式的数据案例。

Alpaca格式的指令微调数据集

6dc11ba45752455a894dc2602bd714ea.jpeg

Alpaca格式的领域适配微调数据集

528eef4875f3e2ba06c2e40c28de949a.jpeg

Alpaca格式的偏好数据集

5242be271b339df5b819d2d56e9de3eb.jpeg

ShareGPT

ShareGPT 最早是一种数据格式标准,由社区设计用于规范多轮对话和工具调用场景的模型训练数据存储方式。

其核心目标是通过结构化字段(如 conversations 列表、tools 工具描述)。

  • 支持复杂交互(如用户提问 → 工具调用 → 结果整合)。

随着格式的普及,社区基于 ShareGPT 格式构建了多个具体的数据集,这类数据集被称为 ShareGPT 格式数据集。

ShareGPT 格式的核心特征如下:

角色标签包括:

human(用户)、gpt(模型)、function_call(工具调用指令)。

observation(工具返回结果)等,覆盖完整工具调用流程。

消息顺序规则:

humanobservation 必须出现在奇数位置,gptfunction_call 在偶数位置,确保逻辑连贯性。

通过 tools 字段定义外部工具(如天气查询 API、计算函数),使模型能动态调用外部资源生成响应。

通过 conversations 列表完整记录对话历史,适用于需上下文理解的场景(如医疗问诊中的连续追问)。

ShareGPT格式的指令微调数据集

6417e9a2c545b4af795bebe5ca75c6b1.jpeg

这里的 Function Call 就像是模型使用的工具指令。

比如你想知道今天的天气,模型就会调用一个天气查询工具,输入地点和日期,工具返回结果后,模型再告诉你答案。

这个过程让模型能借助外部工具完成复杂任务:

  • 比如查询实时数据或进行计算,从而变得更强大、更实用,也更像人类解决问题的方式。

ShareGPT格式的偏好数据集

69231aa790fb827ad35c445f52248bab.jpeg

ShareGPT格式的多模态数据集

44896388ae7031d0b8eb579673a92072.jpeg

特殊的 ShareGPT 格式数据集:OpenAI 格式

5ae3d9637f7e59f3d9a8c4fbbb4e5151.jpeg

OpenAI 格式可以视为 ShareGPT 格式的一种特殊情况,主要关注用户、助手和系统之间的简单对话。

  • 其特点是使用 messages 列表来组织对话,每条消息包含 role(角色)和 content(内容)字段。

角色可以是system(系统)、user(用户)或assistant(助手),分别表示系统提示、用户输入和模型回答。

在实际应用中,OpenAI 格式的数据集可以兼容支持 ShareGPT 格式的系统。

  • 但 ShareGPT 格式提供了更丰富的对话结构和功能支持。

格式对比

下面是两种数据集格式的详细对比,大家可以根据自己的实际需求场景选择合适的格式。

对比维度 Alpaca 格式 ShareGPT 格式
核心设计目标 单轮指令驱动任务(如问答、翻译、摘要) 多轮对话与工具调用(如聊天机器人、API 交互)
数据结构 以 instruction、input、output 为主体的 JSON 对象 以 conversations 列表为核心的多角色对话链(human/gpt/function_call/observation)
对话历史处理 通过 history 字段记录历史对话(格式:[[“指令”, “回答”], …]) 通过 conversations 列表顺序自然体现多轮对话(角色交替出现)
角色与交互逻辑 仅区分用户指令和模型输出,无显式角色标签 支持多种角色标签(如 human、gpt、function_call),强制奇偶位置规则
工具调用支持 不原生支持工具调用,需通过 input 或指令隐式描述 通过 function_call 和 observation 显式实现工具调用,支持外部 API 集成
典型应用场景 - 指令响应(如 Alpaca-7B) - 领域知识问答 - 文本结构化生成 - 多轮对话(如 Vicuna) - 客服系统 - 需实时数据查询的交互(如天气、计算)
优势 - 结构简洁,任务导向清晰 - 适合快速构建单轮任务数据集 - 支持复杂对话流与外部工具扩展 - 更贴近真实人机交互场景
局限 - 多轮对话需手动拼接 history - 缺乏动态工具交互能力 - 数据格式更复杂 - 需严格遵循角色位置规则
支付宝打赏 微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者!