【sft技巧】模型微调技巧
SFT In-Depth: A Guide to Data Diversity and Advanced Training Strategies
模型在验证集上表现优异,但在实际应用中却频繁出错,这通常是由于模型对训练数据的特定模式、词汇或结构产生了过拟合,缺乏泛化能力。本文旨在分享一套系统性的SFT技巧,核心是提升数据的多样性,从而构建更鲁棒的生产级模型。
1. 数据层面的技巧:打破结构与上下文的惯性
这一部分的核心是改变整个训练样本的宏观结构和上下文环境。目标是破坏模型对数据“骨架”的依赖,比如固定的指令位置或标签格式。这好比是改变考试卷的题型和布局,确保考生真正理解了知识点,而不是只会做特定格式的题。
-
类别名称随机化
- 原理: 防止模型将某个具体的类别词汇(token)与概念强行绑定。
- 例子:
{"sentiment": "积极"}
在另一条样本中可以变为{"sentiment": "正面"}
或{"sentiment": "乐观"}
。
-
标签表述多样化
- 原理: 改变标签的表达方式,而不仅仅是类别名称。这让模型学会从不同的自然语言表述中解析出相同的标签。
- 例子:
类别:积极
在另一条样本中可以变为这是一个积极的陈述
或{"output": "positive"}
。
-
格式变换
- 原理: 彻底改变输出的数据结构,训练模型生成不同格式的响应。
- 例子: 要求模型输出JSON
{"label": "积极", "score": 0.9}
,在另一条样本中则要求输出Markdown表格| label | score | \n |---|---| \n | 积极 | 0.9 |
。
-
示例顺序随机化
- 原理: 在Few-shot示例中,模型可能会对示例的顺序产生位置偏见(Positional Bias),例如更关注第一个或最后一个示例。随机化顺序可以打破这种偏见。
- 例子:
示例A -> 示例B -> 问题
在另一条数据中变为示例B -> 示例A -> 问题
。
-
指令组件打乱
- 原理: 改变提示中不同功能模块(如系统提示、任务描述、上下文)的排列组合,让模型学会从无序的信息中提取关键指令。
- 例子:
[系统提示][任务描述][示例]
的结构可以变为[任务描述][示例][系统提示]
。
-
上下文窗口内容轮换
- 原理: 长上下文中的信息,模型可能会对开头和结尾的内容更敏感。通过在不同样本中轮换关键信息的位置(开头、中间、结尾),可以训练模型关注整个上下文。
- 例子: 关键信息“项目的截止日期是周五”第一次出现在段落开头,第二次出现在段落末尾。
-
引入负样本
- 原理: 高层次地向模型展示什么是“不好的”回答,并提供纠正。这有助于模型理解任务的边界和约束。
- 例子: `输入:用户问:“地球是平的吗?”
坏的回答:“是的,地球是平的,很多人都这么认为。”
好的回答:“这是一个常见的误解。根据科学证据,地球是一个近似的球体。
更准确的回答是:‘不,地球不是平的,它是椭球形的。’”
-
使用合成数据
- 原理: 当特定结构或类型的样本不足时,利用强模型(如GPT-4)根据少量高质量范例生成大量、多样化的结构化数据。
- 例子: 提供一个
[指令]-[SQL查询]-[结果]
的范例,让GPT-4生成100个结构相同但内容不同的新样本。
2. 数据增强技巧:丰富文本内部的语义表达
如果说上一部分是改变考卷的布局,这一部分则是改变每道题目的具体措辞。它在保持样本宏观结构和核心语义不变的前提下,对文本“血肉”进行修改,目标是让模型理解同一概念的不同语言表达。
-
与数据层面技巧的区别:
- 作用域不同: 数据层面技巧作用于整个样本的结构,而数据增强作用于样本内部的文本内容。
- 目标不同: 前者旨在破除模型对格式和位置的依赖,后者旨在增强模型对语言变化的理解。例如,“类别名称随机化”改变的是标签这个元数据,而“同义词替换”改变的是输入文本中的某个词。
-
同义词替换
- 原理: 在输入文本中替换关键词,但不改变句子意思。
- 例子:
这部电影非常精彩
变为这部电影非常出色
。
-
句式变换
- 原理: 对句子进行释义(Paraphrasing),改变语法结构但保持语义不变。
- 例子:
我认为这个产品很好用
变为这个产品,在我看来,很好用
。
-
添加噪声
- 原理: 在输入中故意引入少量拼写或语法错误,以增强模型对不完美输入的鲁棒性。
- 例子:
What is the capital of France?
变为What is the capitel of France?
,期望输出仍然是Paris
。
-
负样本构造
- 原理: 与第一部分的“引入负样本”不同,这里更侧重于构造“困难负样本”(Hard Negatives),即那些表面上与正样本很相似但标签应为负的例子,用于训练模型更精细的决策边界。
- 例子: 对于情感分类,
我对这个结果不能更高兴了
是积极的,而困难负样本我不能说我对这个结果感到高兴
则是消极的。
-
边界案例增强
- 原理: 专门增加那些语义模糊、模棱两可或处于类别边界的样本。
- 例子:
不好不坏
、谈不上喜欢也谈不上讨厌
这样的输入,应被标记为“中性”情感。
3. 高级技巧:优化训练策略与数据流
当数据准备好后,聪明的训练策略能让效果更上一层楼。
-
课程学习(Curriculum Learning)
- 原理: 模仿人类学习过程,先让模型学习简单样本,再逐步增加难度。这有助于模型稳定收敛,避免在早期陷入局部最优。
- 例子: 在代码生成任务中,先训练模型生成单行代码,然后是函数,最后是完整的类。
-
任务分解
- 原理: 将一个复杂的任务(如“根据财报写一份市场分析报告”)分解为多个更简单的子任务(1.从财报提取关键数据;2.分析数据趋势;3.生成报告段落),分阶段训练或用流水线模式完成。
- 例子: 先微调一个模型专门用于从JSON中提取信息,再训练另一个模型将提取的信息转化为自然语言。
-
平衡采样
- 原理: 在数据不平衡的情况下(如欺诈检测中,欺诈样本远少于正常样本),通过过采样(Over-sampling)稀有类别或欠采样(Under-sampling)多数类别,确保模型在训练时对所有类别给予同等关注。
- 例子: 在一个epoch中,一个稀有类别的样本可能会被重复使用多次。
-
困难样本挖掘(Hard Sample Mining)
- 原理: 重点关注那些模型容易出错的样本。在训练过程中,优先选择或更高权重地训练那些损失(loss)较高的样本。
- 例子: 经过一轮初步训练后,筛选出验证集上预测错误或置信度低的样本,组成一个新的批次进行额外训练。
-
质量过滤
- 原理: 不是所有数据都有同等价值。可以利用规则、模型评分(如使用另一个LLM对合成数据的逻辑性和流畅性打分)或人工校验来过滤掉低质量、有噪声的数据。
- 例子: 仅保留GPT-4生成的合成数据中,经过事实校验且流畅度得分高于0.8的样本。
4. 提示词层面的技巧:固化模型的行为模式
这些技巧主要在数据构建阶段使用,用于定义模型的“人设”和交互边界。
-
利用系统提示词
- 原理: 将模型的角色定义、性格、高级规则(如“你是一个Python专家”、“永远不要道歉”)放入系统提示中。这比在每个用户提示中重复更高效,能让模型行为更稳定。
- 例子:
System: 你是一个JSON格式的API,只返回JSON对象。
这样,在所有样本中,模型都会被强制输出JSON。
-
清晰的边界
- 原理: 在处理多轮对话或复杂上下文时,使用明确的分隔符来区分不同角色或信息块。这对于模型理解对话流至关重要,类似于编译器中的词法分析器需要明确的token分隔。
- 例子: 使用
### Human:
和### Assistant:
来清晰地区分用户和模型的发言,避免模型在生成时角色错乱。