浅谈大模型 SFT 的实践落地:10 问 10 答

来源|知乎—周星星

地址|https://zhuanlan.zhihu.com/p/685582706

前言

SFT 是 “低端” 的工作,但它与业务紧密相连。相较于难以实施且多数公司没资源训练的预训练,以及调试难度高的强化学习,SFT 可谓效果立竿见影,SFT 在实际应用中更易显现成效。

本文关注如何通过 SFT 逼近大模型的表现,既确保效果又兼顾模型的泛化能力,从而满足业务需求,实现大模型的有效落地。接下来,我将采用 10 问 10 答的分享分享一些经验,这些经验源自实际业务中的实践、社区的交流和 阅读过的 Paper 中,不断总结出来的个人心得,这些经验也会随时间不断更新。期待与大家的交流探讨。

Q1: 常见 SFT 的开发流程是如何的?

第一步,根据业务场景调整提示词(prompt):业务团队会提供具体场景,或者给出他们编写的 prompt,也可能只提供场景和数据,需要算法工程师自行编写。编写优秀的 prompt 对发挥模型的最大性能至关重要,一个出色的 prompt 可能将性能提升至 80 分以上直接得到业务要求,而一个普通的 prompt 可能只能得到 50 分。这里可以参考 OpenAI 和 文心一言 的相关教程。这里也介绍一些个人的经验:

越详细越好,给到的定义越细越好:例如多标签分类分类,不同的标签起码要有 1-2 句标签定义,你会发现大 size 的模型是十分遵循你的标签定义的,写得越详细越贴近业务,效果越好。

不要让模型理解任何歧义,如现在你输入是好几篇微博,你应该输入 “微博 1:{微博 1 的内容}\n 微博 2:{微博 2 的内容}… 微博 n:{微博 n 的内容}”,通过一个明确的前缀让模型知道输入的是不同的微博,而不只是简单用换行符把不同的微博内容进行拼接。

遵循 System message,Input,Instruction 三段式:这样输出的结果格式和效果会较为稳定。

通过模型输出的解析调整 prompt:现在的模型除了输出答案,还会输出解析理由,通过浏览模型判断错误的例子模型是怎么解释的,从而反馈到调整 prompt,看看是不是 prompt 里的定义没说清楚。

第二步,尝试闭源和开源,并进行对比:Prompt 调整至差不多了,可以尝试使用不同的开源模型,如 Llama2 、 Qwen 、 Baichuan 等。实测下来,确实不同的开源模型擅长点不一样。如果开源模型效果不佳。这时考虑闭源模型,如 Chatgpt4、 Kimi 、 Qwen-max… ,以评估这闭源领先的 LLM 是否能解决这类场景问题,这一步工程师也要积累经验,对闭源和开源的效果差距要熟悉。若业务接受闭源模型的效果和成本,则直接调 API 就好。若不接受,则需转向微调闭源模型。

第三步,认真准备数据集:选定最佳闭源模型后,精选数据集,通常每个子任务的数据量不应超过 1K 条,数据集必须包含任务的边界样本和困难样本,并确保数据的多样性和标签的平衡。

第四步,上线迭代:最后,进行训练、上线和持续的迭代优化,以确保模型性能不断提升并满足业务需求。

这里推荐 OpenAI 在 2023 年 11 月 6 日 Dev Day 上的一个分会场的分享,会场的主题是如何使 LLM 的效果最大化。

Q2: 训练数据要注重什么?

确保回答格式和风格的统一,如大家看 gpt4 的回答风格就是先复述理解问题,再回答,再总结,这就是一个格式的统一。经验是,训练数据的格式和风格越统一,越能最大限度地发挥模型在具体任务的效果上限。这在 LIMA、YI、 Reformatted Alignment 的论文中都有提到。

数据集既要包含难也要包含易:数据集应同时包含容易错的 “Boundary use cases” 边界数据,但也要包含常规的 “Easy” 数据,以确保模型能够处理各种难度级别的样本。

注意任务的多样性和标签的平衡。例如,若两个任务难度相当,但任务 1 的数据占比远大于任务 2,那么微调后的模型在处理任务 2 时可能表现不佳。

避免引入模型在预训练阶段未接触过的知识:以减少模型产生幻觉的风险。

这里可以吸收下 Llama2、Yi、Qwen、Deepseek 和 Tigerbot 等报告的 SFT 数据篇中的宝贵经验。

Q3: 大 size 和小 size 模型的选择?

在效率和资源都达标和到位的情况上,优先用大 size 的模型进行实验和微调,因为大 size 的模型在容错性上比小 size 的好太多。尽管大尺寸模型也可能存在多任务不稳定、标签不平衡等问题,但其表现通常会比小尺寸模型更为稳定。因此,选用大尺寸模型其实是节省了人力成本,避免了很多之后可能会遇到的各种坑。

Q4: 多任务训练时怎么确保每个任务都优秀?

阿里巴巴的 一篇研究 深入探讨了这一现象。

很尴尬的是,目前实践下来,任务的相互影响是一个普遍现象,例如

训练集中包含四个任务,现在针对任务 1 补充了大量 bad cases 后重新训练,这种调整很可能会对其他任务产生或正或负的影响。

训练集本身存在的任务数据不平衡也是一个不可忽视的问题,某个任务占比大,那其它占比小的任务大概率效果也是不稳定的。

有两种方法应对这种挑战:

不同任务独立训练模型:针对每个任务单独训练一个模型。当某个任务至关重要,且要求性能指标高度稳定时,这是不得不采用的方法。

任务取舍与额外训练:例如,在四个任务中,若其中两个任务尤为重要,可以在全部任务训练完毕后,对这两个关键任务额外训练多一个 epoch。这种做法能最大程度地确保重要任务的效果。

Q5: SFT 真的不能学到知识?

很遗憾的说,经过一年的实践和普遍的认知。常识和世界知识难以通过 SFT 灌输给模型。

SFT 更应该关注激发模型在预训练中已学到的知识、让模型学习业务所需要的特定规则、以及输出格式稳定。

那么,何为常识和世界知识?例如,“2023 年 NBA 总冠军是掘金” 便属于世界知识。如果 LLM 的训练数据仅更新至 2022 年,那么它自然无法得知这一信息。

即便你的 SFT 数据中包含 “谁是 2023 年 NBA 总冠军?答案是掘金” 这样的问答对,训练后的模型可能只能回答这个语序的问题,而无法举一反三。比如,当你问 “掘金在哪一年获得了 NBA 总冠军?” 时,它无法回答“2023 年”。

这种举一反三的能力需要模型在预训练阶段就接触过 “2023 年 NBA 总冠军是掘金” 这类知识的多种不同文本表达,如这条知识在预训练文本中出现在不同的表述中(主动句、被动句、出现在新闻语料、出现在聊天对话语料等等等等)。因此,从这个角度看,SFT 并不能学得常识、世界知识。

类似的研究可以看看这几篇论文 https://arxiv.org/abs/2309.14316 、http://arxiv.org/abs/2309.14402

但这并不意味着我们应该放弃 SFT。相反,我们应当关注 SFT 在以下方面:

激发预训练知识:虽然 SFT 不能直接学的新知识,但需要靠它激发模型在预训练中已学到的知识。

稳定格式输出:通过 SFT,我们可以训练模型以稳定的格式输出结果,便于线上的稳定。

更遵循具体任务:如多标签多分类时,模型老输出一些不在标签体系的任务。

学习业务逻辑:SFT 能够教导模型特定的业务规则,如让他习得 “买了 20 万以上的车算有钱人”。

Q6: 怎么科学挑选数据集?

众多论文如 LIMA、LLaMa2 和 Yi 等均印证了 ”Quality is all you need“ 的观点。对于大部分业务场景,50 条~几百条数据足矣,本人倾向于让工程师与业务团队共同审核每条数据,并确保数据的多样性。数据挑选涉及几个场景:

场景 1 精简业务数据:随着业务的发展,各种任务数据会不断累积。当某个子任务的数据过于庞大时,可能会影响其他任务的泛化能力。因此,当数据量超过一定阈值时,我们需要剔除 “冗余” 数据。

场景 2 筛选开源数据:当面临新的业务场景却缺乏专用 SFT 训练数据时,我们需要从海量的开源数据中精准 “筛选” 出对该场景有益的数据作为训练集。

场景 3 诡探数据秘密:探索我们的训练集中哪些数据对具体的业务场景带来增益最大。

这些场景都引出了一个核心问题:“如何科学地筛选数据集?” 关于这个问题,我在另一篇博文中进行了探讨。

Q7: 怎么解决幻觉问题

幻觉问题是影响业务精准度的一个重要因素,它常导致召回率尚可,精确率却偏低。

实际体验下来,不论开源还是闭源模型,都容易 “过度联想”,从而在某些业务场景下无法使用。

一个例子:

某个任务是 “根据网民的发帖记录判断该网民是否有孩子”,若网民帖子中仅提及 “喜欢回家吃饭”,LLM 模型却可能过度解读,推断出“此人有孩子,因为爱回家吃饭表明其顾家,很可能有家庭和孩子”。这种过度联想问题,通过修改提示语(如添加“请你做出判断时不要过度臆想” 等限制)无法完全解决,它依然会影响的精确率,导致某些业务无法使用。

目前,尚缺乏完美的解决方案,但可以考虑通过 SFT 或当积累更多相关场景数据后尝试运用强化学习方法来改善。关于幻觉问题的更多探讨,可以参考以下的综述。

https://dl.acm.org/doi/abs/10.1145/3571730

https://arxiv.org/abs/2311.05232

不过,从另一个角度看,个人觉得” 喜欢联想 “(或者说喜欢 YY)不是大模型的缺点。毕竟,联想是人类创新、发掘新思路的源泉之一。

Q8: BERT 开发与 LLM 开发有什么不同之处?

相同点:

BERT 模型所面临的问题,LLM 同样可能会遭遇。例如:

标签不平衡问题:在进行分类任务时,如果正反标签比例为 8:2,无论是 BERT 还是 LLM,模型都可能出现偏差。

多任务平衡:在进行多任务学习时,任务之间的平衡同样重要,Q4 对这一问题进行了讨论。

不同点:

开发体验差异:当 BERT 遇到难以处理的情况时,可能需要标注 50 甚至上百条类似数据才能解决问题。而 LLM 则更为高效,往往仅需标注 2~4 条数据即可解决这一场景的 bad cases。在数据集需求上,BERT 可能需要近万条数据才能达到理想效果,而 LLM 可能仅需不到 1K 的数据就能实现相似的效果。这使得 LLM 在迭代速度和效率上更具优势。

模型规模调整策略不同:当 BERT 的效果不佳时,我们可能会尝试增加模型规模。然而,对于 LLM 来说,当效果达到预期时,我们反而会考虑减小模型规模,这主要是因为 LLM 的参数量通常非常庞大,越大的效率会越慢。

Q9: 该选什么微调方法, Full tuning\P-tuning\Lora?

经过实际测试,发现在某些特定场景下,全量调优(full tuning)确实表现更佳,但优势并不明显。在数据量有限且应用场景不多的情况下,为了保持模型的泛化能力,Lora 方法表现得最为稳定。考虑到泛化性,Lora 已经足够应对大多数需求。

此外,DeepMind 的一篇研究 SFT Scaling law 的论文中探讨了不同数据量下不同训练方式的效果及其对泛化性的影响。该研究指出,当数据量仅在几千条时,P-tuning 是最佳选择;数据量在几千至万条之间时,Lora 更为适合;而当数据量达到百万级别时,Full-tunning 效果最佳。此外,使用 Full-tunning 会导致训练后的模型泛化性不如 Lora。当然,论文的实验任务是一个多语种的翻译任务,其它任务可能会不一样,但大概的趋势是这样。

因此在大多数场景下,我仍推荐使用 Lora,因为稳定,效果不差,能尽可能保留模型原来的泛化性。

Q10: SFT 还有什么方面值得研究?

现在开源的 SFT 越来越完备了,SFT 需要做的东西越来越少,多做实验,快速迭代才是王道

消除幻觉:对于依赖高精准率的应用来说,这是一个重要的解决方向。

精选数据集和任务配比:现在更多是实验工程,期待有如 Less 等扎实的工作不断涌现。

设置科学设计问答格式和 Data format:这是为了激发模型的最大潜能,这个可能要 model by model。

探寻更高效的微调技巧:Lora 表现出色且稳定,但仍在探索其他方法。Lora 虽好,但仍有提升空间。目前已有一些如 Lora+、PLora、PiSSA 等工作的出现。

END