当前位置: 首页 > article >正文

大模型(LLMs)微调篇

大模型(LLMs)微调篇

一、如果想要在某个模型基础上做全参数微调,究竟需要多少显存?

一般 n B的模型,最低需要 16-20 n G的显存。(cpu offload基本不开的情况下)

二、为什么SFT之后感觉LLM傻了?

SFT的重点在于激发大模型的能力,如果抱着灌注领域知识而不是激发能力的想法,去做SFT的话,可能确实容易把LLM弄傻。

三、SFT 指令微调数据 如何构建?

  1. 选择多个有代表性的任务;
  2. 每个任务实例数量不应太多,防止过拟合;
  3. 平衡不同任务的比例,防止较大的数据集压倒整个分布。

四、领域模型Continue PreTrain 数据选取?

技术标准文档或领域相关数据是领域模型Continue PreTrain的关键。

五、领域数据训练后,通用能力往往会有所下降,如何缓解模型遗忘通用能力?

在领域训练的过程中加入通用数据集,领域数据与通用数据的比例在1:5到1:10之间是比较合适的。

六、领域模型Continue PreTrain ,如何 让模型在预训练过程中就学习到更多的知识?

领域模型Continue PreTrain时可以同步加入SFT数据,即MIP,Multi-Task Instruction PreTraining。

七、进行SFT操作的时候,基座模型选用Chat还是Base?

资源有限就用在Chat模型基础上训练,资源充足就在Base模型上训练。

八、领域模型微调 指令&数据输入格式 要求?

在Chat模型上进行SFT时,请一定遵循Chat模型原有的系统指令&数据输入格式。

九、领域模型微调 领域评测集 构建?

领域评测集时必要内容,建议有两份,一份选择题形式自动评测、一份开放形式人工评测。

十、领域模型词表扩增是不是有必要的?

领域词表扩增真实解决的问题是解码效率的问题,给模型效果带来的提升可能不会有很大。

十一、如何训练自己的大模型?

一般分为两个阶段训练:

  1. 扩充领域词表,在海量领域文档数据上二次预训练LLaMA模型;
  2. 构造指令微调数据集,在第一阶段的预训练模型基础上做指令精调。

十二、训练中文大模型有啥经验?

链家技术报告《Towards Better Instruction Following Language Models for Chinese: Investigating the Impact of Training Data and Evaluation》中,介绍了开源模型的训练和评估方法:
在这里插入图片描述
还对比了各因素的消融实验:
在这里插入图片描述
消融实验结论:
•扩充中文词表后,可以增量模型对中文的理解能力,效果更好
•数据质量越高越好,而且数据集质量提升可以改善模型效果
•数据语言分布,加了中文的效果比不加的好
•数据规模越大且质量越高,效果越好,大量高质量的微调数据集对模型效果提升最明显。解释 下:数据量在训练数据量方面,数据量的增加已被证明可以显著提高性能。值得注意的是,如

此巨大的改进可能部分来自belle-3.5和我们的评估数据之间的相似分布。评估数据的类别、主 题和复杂性将对评估结果产生很大影响
•扩充词表后的LLaMA-7B-EXT的评估表现达到了0.762/0.824=92%的水平
他们的技术报告证明中文大模型的训练是可行的,虽然与ChatGPT还有差距。这里需要指出后续
RLHF也很重要,我罗列在这里,抛砖引玉。
扩充中文词表后,可以增量模型对中文的理解能力,效果更好。数据质量越高越好,而且数据集质量提升可以改善模型效果。

十三、指令微调的好处?

有以下好处:
1.对齐人类意图,能够理解自然语言对话(更有人情味)
2.经过微调(fine-tuned),定制版的GPT-3在不同应用中的提升非常明显。OpenAI表示,它可 以让不同应用的准确度能直接从83%提升到95%、错误率可降低50%。解小学数学题目的正确 率也能提高2-4倍。(更准)
踩在巨人的肩膀上、直接在1750亿参数的大模型上微调,不少研发人员都可以不用再重头训练自 己的AI模型了。(更高效)

十四、预训练和微调哪个阶段注入知识的?

预训练阶段注入知识的,微调是在特定任务训练,以使预训练模型的通用知识跟特定任务的要求结合,使模型在特定任务上表现更好。

十五、想让模型学习某个领域或行业的知识,是应该预训练还是应该微调?

可以使用预训练和微调相结合的方式,先用篇章数据进行预训练以获取广泛的知识,再用问答对数据进行微调,使模型更好的学习到特定领域的知识。
当然,GPT大模型的预训练和微调,从实现方式来讲是没有什么差别的,都是decoder only的语言模型训练并更新参数,如果样本集小,没有大量的篇章文档数据,我认为只进行微调也能注入知识 的,不必太纠结预训练。而且特定领域跟预训练模型的分布差别不大,也不用二次预训练。

十六、多轮对话任务如何微调模型?

这里列举了 ChatGLM-6B 的生成对话的例子

    >>> from transformers import AutoTokenizer, AutoModel
    >>> tokenizer = AutoTokenizer.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True)
    >>> model = AutoModel.from_pretrained("THUDM/chatglm-6b", trust_remote_code=True).half().cuda()
    >>> model = model.eval()
    >>> response, history = model.chat(tokenizer, "你好", history=[])
    >>> print(f"response:{response}")
    >>> print(f"history:{history}")
    response:你好👋!我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。
    history:["你好", "你好👋!我是人工智能助手 ChatGLM-6B,很高兴见到你,欢迎问我任何问题。"]

•response 为 ChatGLM-6B 模型的 当前反馈

•history 为 ChatGLM-6B 模型的 历史记录的保存
说白了,就是 ChatGLM-6B 模型简单的把上一轮对话扔进下一轮的input里,这种方法好处是简单,缺点是随着轮数的增加,history 存储的 对话会越来越多,导致 max_length 增加,从而 出现爆显问题。
•解决方法:
•对 历史对话 做一层文本摘要,取其精华去其糟粕
•将 历史对话 做成一个 embedding
•如果是 任务型对话,可以将 用户意图 和 槽位 作为 上一轮信息 传递给 下一轮

十七、微调后的模型出现能力劣化,灾难性遗忘是怎么回事?

所谓的灾难性遗忘:即学习了新的知识之后,几乎彻底遗忘掉之前习得的内容。这在微调ChatGLM-6B模型时,有同学提出来的问题,表现为原始ChatGLM-6B模型在知识问答如“失眠怎么 办”的回答上是正确的,但引入特定任务(如拼写纠错CSC)数据集微调后,再让模型预测“失眠怎 么办”的结果就答非所问了。
我理解ChatGLM-6B模型是走完 “预训练-SFT-RLHF” 过程训练后的模型,其SFT阶段已经有上千指令微调任务训练过,现在我们只是新增了一类指令数据,相对大模型而已,微调数据量少和微调任 务类型单一,不会对其原有的能力造成大的影响,所以我认为是不会导致灾难性遗忘问题,我自己 微调模型也没出现此问题。
应该是微调训练参数调整导致的,微调初始学习率不要设置太高,lr=2e-5或者更小,可以避免此 问题,不要大于预训练时的学习率。

十八、微调模型需要多大显存?

在这里插入图片描述

十九、大模型LLM进行SFT操作的时候在学习什么?

(1)预训练->在大量无监督数据上进行预训练,得到基础模型->将预训练模型作为SFT和RLHF的起点。
(2) SFT->在有监督的数据集上进行SFT训练,利用上下文信息等监督信号进一步优化模型->将SFT训练后的模型作为RLHF的起点。
(3) RLHF->利用人类反馈进行强化学习,优化模型以更好地适应人类意图和偏好->将RLHF训练后的模型进行评估和验证,并进行必要的调整。

二十、预训练和SFT操作有什么不同

下面使用一个具体的例子进行说明。

问题:描述计算机主板的功能
回答:计算机主板是计算机中的主要电路板。它是系统的支撑。

进行预训练的时候,会把这句话连接起来,用前面的词来预测后面出现的词。在计算损失的时候,问句中的损失也会被计算进去。

进行SFT操作则会构建下面这样一条训练语料。

输入:描述计算机主板的功能[BOS]计算机主板是计算机中的主要电路板。它是系统的支撑。[EOS]
标签:[.	][BOS]计算机主板是计算机中的主要电路板。它是系统的支撑。[EOS]

其中BOS和EOS是一些特殊字符,在计算损失时,只计算答句的损失。在多轮对话中,也是一样的,所有的问句损失都会被忽略,而只计算答句的损失。

因此SFT的逻辑和原来的预训练过程是一致的,但是通过构造一些人工的高质量问答语料,可以高效地教会大模型问答的技巧。

二十一、样本量规模增大,训练出现OOM错

•问题描述:模型训练的样本数量从10万,增大300万,训练任务直接报OOM了。
•解决方案,对数据并行处理,具体实现参考海量数据高效训练,核心思想自定义数据集本次的 主要目标是使向量化耗时随着处理进程的增加线性下降,训练时数据的内存占用只和数据分段 大小有关,可以根据数据特点,灵活配置化。核心功能分为以下几点:
•均分完整数据集到所有进程(总的GPU卡数)
•每个epoch训练时整体数据分片shuffle一次,在每个进程同一时间只加载单个分段大小 数据集
•重新训练时可以直接加载向量化后的数据。

二十二、大模型LLM进行SFT 如何对样本进行优化?

对于输入历史对话数据进行左截断,保留最新的对话记录。去掉样本中明显的语气词,如嗯嗯,啊啊之类的。去掉样本中不合适的内容,如AI直卖,就不应出现转人工的对话内容。样本中扩充用户特征标签,如年龄,性别,地域,人群等。

二十三、模型参数迭代实验

验证历史对话轮次是否越长越好,通过训练两个模型,控制变量max_source_length| max_target_length,对训练好之后的模型从Loss、Bleu指标、离线人工评估等角度进行对比分析。

二十四、微调大模型的一些建议

模型结构:

  • 模型结构 + 训练目标: 使用 Causal Decoder + LM。这种结构有很好的 zero-shot 和 few-shot 能力,能够产生涌现效应。
  • Layer Normalization: 使用 Pre RMS Norm,而不是传统的 Post Layer Norm,以提高模型的稳定性和性能。
  • 激活函数: 使用 GeGLU 或 SwiGLU,这些激活函数在处理大规模数据时表现更好。
  • Embedding层后不添加Layer Normalization: 在 embedding 层后不添加 layer normalization,否则会影响 LLM 的性能。
  • 位置编码: 使用 ROPE 或 ALiBi。ROPE 应用更广泛,因为它在处理长序列时表现更好。
  • 去除偏置项: 去除 dense 层和 layer norm 的偏置项,有助于提升模型的稳定性和训练效率。

训练配置:

  • Batch Size: 选用很大的 batch size,动态地增加 batch size 的策略,GPT3 逐渐从 32K 增加到 3.2M tokens。
  • 学习率调度: 先 warmup 再衰减。学习率先线性增长,再余弦衰减到最大值的 10%。最大值一般在 5e-5 到 1e-4 之间。
  • 梯度裁剪: 通常将梯度裁剪为 1.0,以防止梯度爆炸。
  • 权重衰减: 采用 AdamW 优化器,权重衰减系数设置为 0.1。AdamW 相当于 Adam 加了一个 L2 正则项,有助于防止过拟合。
  • 混合精度训练: 采用 bfloat16,而不是 float16 来训练。bfloat16 在处理大规模数据时更稳定。

训练崩溃挽救:

  • 选择一个好的断点: 跳过训练崩溃的数据段,进行断点重训。选择一个好的断点的标准是:损失标度 lossscale > 0;梯度的 L2 范数 < 一定值 && 波动小。

通过这些建议,可以有效地提升大模型微调的效率和性能,同时减少训练过程中的不稳定性和崩溃风险。

二十五、微调大模型时,如果 batch size 设置太小 会出现什么问题?

当 batch size 较小时,更新方向(即对真实梯度的近似)会具有很高的方差,导致的梯度更新主要是噪声。经过一些更新后,方差会相互抵消,总体上推动模型朝着正确的方向前进,但个别更新可能不太有用,可以一次性应用(使用更大 batch size 进行更新)。

二十六、微调大模型时,如果 batch size 设置太大 会出现什么问题?

当 batch size 非常大时,我们从训练数据中抽样的任何两组数据都会非常相似(因为它们几乎完全匹配真实梯度)。因此,在这种情况下,增加 batch size 几乎不会改善性能,因为你无法改进真实的梯度预测。换句话说,你需要在每一步中处理更多的数据,但并不能减少整个训练过程中的步数,这表明总体训练时间几乎没有改善。但是更糟糕的是你增加了总体的 FLOPS。
在这里插入图片描述通过观察这些线性图,我们可以发现使用更大的 batch size 通常需要较少的训练 step。然而,这将相应地增加需要处理的数据。当 batch size 从 2048 翻倍时,达到同样性能所需要的 step 几乎没有任何改善,但你需要花费两倍的计算资源。Google 的经验研究也有类似的观察,即在在固定的 epoch budget 下,当 batch size 达到临界值时,模型的性能会 batch size 的增加而降低。可以如下说明:
在这里插入图片描述

二十七、微调大模型时, batch size 如何设置问题?

各种结果表明似乎存在着一个关于数据并行程度的临界点,通过找到这个临界点,我们可以有效的平衡训练的效率和模型的最终效果。

OpenAI 发现最优步长:

在采用最优 step size 时,从含有噪声的梯度中获得的损失的最优改进现在变为:
在这里插入图片描述
从这些公式中我们可以得出两个结论:

  1. 无论我们如何准确地估计真实梯度,总存在一个最大步长
  2. 批处理大小越大,我们优化模型的步长就越大(有一个上限)

左侧的图表说明了为什么使用更大的批次模型可以取得更多提升。但是当 batch size 太大时,我们会遇到收益递减的问题(因为分母中的 1 开始占主导地位)。但是需要注意的事,这仅在学习率调整良好的情况下有效。因此,OpenAI 建议将学习率调整到一个相对接近最优值的数值是理论能有效的前提。
在这里插入图片描述

在进行一些其他数学计算后,OpenAI 发现噪声尺度可以通过以下方式估计:

噪声尺度 = 梯度方差 梯度范数 \text{噪声尺度} = \frac{\text{梯度方差}}{\text{梯度范数}} 噪声尺度=梯度范数梯度方差
在这里插入图片描述
其中,H 是参数的真实 Hessian 矩阵,C 是相对于梯度的每个示例的协方差矩阵,g 是真实梯度。为了进一步简化这个方程,OpenAI作出了一个(不切实际的)假设,即优化是完全 well- conditioned 的。在这种情况下,Hessian 矩阵只是单位矩阵的倍数,噪声尺度简化就可以简化为以下形式:
在这里插入图片描述
他们经验上发现结果相当接近。该方程表明噪声尺度等于个别梯度分量的方差之和,除以梯度的 norm。OpenAI 使用以上结论在后续的 scaling law 工作中预测了模型的最优 batch size 大小。
在这里插入图片描述
•Learning rate as temperature
前面的结论有提到一个前提,就是模型的 LR 是调的比较好的。这是因为 OpenAI 发现噪声尺度基本符合以下规律
在这里插入图片描述

在使用 SGD 和小 batch 进行更新时,可以大概近似为
在这里插入图片描述
这表明
在这里插入图片描述在这里插入图片描述
从以上内容,我们可以得知:
1.高温度导致较小的噪声尺度。其中的直觉是在高温度下,相对于方差,梯度幅度较大。
2.当学习率以一个常数因子衰减时,噪声尺度大致以相同的因子增长。因此,如果学习率太小, 噪声尺度将被放大。

二十八、微调大模型时, 优化器如何?

除了Adam和AdamW,其他优化器如Sophia也值得研究,它使用梯度曲率而非方差进行归一化,可能提高训练效率和模型性能。

二十九、哪些因素会影响内存使用?

内存使用受到模型大小、批量大小、LoRA参数数量以及数据集特性的影响。例如,使用较短的训练序列可以节省内存。

三十、进行领域大模型预训练应用哪些数据集比较好?

通过分析发现现有的开源大模型进行预训练的过程中会加入书籍、论文等数据。主要是因为这些数据的数据质量较高,领域相关性比较强,知识覆盖率(密度)较大,可以让模型更适应考试。给我们自己进行大模型预训练的时候提供了一个参考。同时领域相关的网站内容、新闻内容也是比较重要的数据。

三十一、用于大模型微调的数据集如何构建?

进行大模型微调时,数据是比较重要的,数据的高度决定模型效果的高度,因此数据的质量重要性大于数据的数量的重要性,因此对于构建微调数据时的几点建议如下所示:

  1. 选取的训练数据要干净、并具有代表性。
  2. 构建的prompt尽量多样化,提高模型的鲁棒性。
  3. 进行多任务同时进行训练的时候,要尽量使各个任务的数据量平衡。

三十二、大模型训练loss突刺原因和解决办法

参考:A Theory on Adam Instability in Large-Scale Machine Learning

32.1 大模型训练loss突刺是什么?

loss spike指的是预训练过程中,尤其容易在大模型(100B以上)预训练过程中出现的loss突然暴涨的情况。
在这里插入图片描述

32.2 为什么大模型训练会出现loss突刺?

大模型训练使用的Adam优化器会导致 loss突刺。首先回顾一下Adam优化器的结构(这里介绍的是较为传统的Adam优化器,现在nlp任务更偏向于使用带有正则化项的Adamw变体):

Adam优化器 = 梯度 梯度平方和 \text{Adam优化器} = \frac{\text{梯度}}{\sqrt{\text{梯度平方和}}} Adam优化器=梯度平方和 梯度
在这里插入图片描述
在这里插入图片描述
Adam算法是牛顿下降法的一个迭代逼近。
在这里插入图片描述
一切显得十分完美,但是理想很丰满,现实很骨感,收敛过程并不是一帆风顺的。首先我们想象一下 ut 这个更新参数 的变化趋势。
在这里插入图片描述
在这里插入图片描述

进入正态分布的稳态之后,理想的更新参数变化趋势应该是方差越来越小,所有更新参数逐渐向0靠近。这应该是一个单向的过程,即稳定的单峰状态(unimodal)不会再次进入非稳定的双峰状态(bimodal),但事实并非如此,更新参数会再次进入非稳定的双峰状态。

本文在理论层面做了研究和解释,从中心极限定理(可以结合道尔顿板实验理解)出发,认为随机事件的叠加进入单峰的正态分布的必要条件之一是各个随机事件事件之间应该是相互独立的,但是梯度变化以及更新参数的变化并不能特别好的满足独立性这一条件,而这一点恰恰是导致更新参数振荡,loss spike出现以及loss 不收敛的重要原因之一。
在这里插入图片描述

造成梯度变化不独立的原因(1、浅层参数长时间不更新2、batch太大,后期梯度更新趋于平稳)。上述的理论有些晦涩,本文作者可能也了解这一点,之后开始直接点题,结合实验观察抛出了重要现象和结论。即训练过程中loss spike的出现与:梯度更新幅度,e 大小,batch大小这三个条件密切相关。
在这里插入图片描述
在这里插入图片描述
5.这个阶段模型处于非稳态,梯度变化幅度较大,每一次的梯度变化和更新参数变化事件之间又出 现了一定的独立性,因此经过一定的时间之后模型有可能再次进入稳态,loss再次drop back down
(注意,本文着重提了这个再次drop back down并不是一定出现的,也很有可能loss长期处于flat
状态,再也无法收敛)
因此我们得出一些结论,loss spike的出现和浅层的梯度更新幅度,e 大小密切相关(batch大小带来的相关性问题倒是显得没那么大说服力),实际上就是浅层网络参数突然进入到了之前长时间不 在的状态与模型深层参数当前的状态形成了连锁反应造成了模型进入非稳态。同时一般情况即使出 现loss spike也会自动回复到正常状态,但也有可能再也不会

32.3 大模型训练loss突刺 如何解决?

本文最后提到了防止loss spike出现的一些方法:

  1. 如之前提到的PaLM和GLM130B提到的出现loss spike后更换batch样本的方法(常规方法,但是成本比较高)
  2. 减小learning rate,这是个治标不治本的办法,对更新参数的非稳态没有做改进
  3. 减小 e 大小。或者直接把 e 设为0,重新定义在 vt 等于 0 时候的值(这应该是个值得尝试的办法)
    在这里插入图片描述

值得一提的是智谱华章在本文发表之前,在去年的GLM130B训练时似乎也观察到了浅层梯度变化和loss spike相关这一现象(GLM-130B: An Open Bilingual Pre-trained Model),他采取的是把浅层梯度直接乘以缩放系数 a 来减小浅层梯度更新值。
在这里插入图片描述

其实这块我有个自己的想法,e 和 a 是否也可以做衰减,随着训练过程逐渐减小,来避免loss spike的现象。另外假设我们能一次性加载所有样本进行训练(实际上不可能做到),是否还会出现loss spike的现象。最后目前流行的fp8,fp16混合训练,如果upscale设置的过小,导致梯度在进入优化器之前就下溢,是不是会增加浅层梯度长时间不更新的可能性,进而增加loss spike的出现的频率。(这么看来似乎提升upscale大小以及优化 e 大小是进一步提升模型效果的一个思路)

总结

大模型(LLMs)微调面涵盖了从显存需求到优化器选择等多个方面。全参数微调需16-20倍模型大小的显存。SFT后模型“变傻”因数据量少和领域知识灌注不当。指令微调数据应具代表性、适量且平衡。领域模型Continue PreTrain需高质量数据,如技术标准文档。通用能力下降可通过混合通用数据缓解。MIP(Multi-Task Instruction PreTraining)可提升预训练知识量。SFT基座模型选择取决于资源。领域评测集需选择题和开放题结合。词表扩增主要提升解码效率。训练自定义大模型分两阶段:领域预训练和指令精调。优化器建议包括AdamW和Sophia。loss突刺由Adam优化器引起,可通过调整学习率和e大小缓解。


http://www.kler.cn/a/396978.html

相关文章:

  • 【大数据学习 | HBASE高级】hbase-phoenix 与二次索引应用
  • python面向对象基础入门
  • Spring Boot框架:电商系统的技术革新
  • 基本数据类型和包装类型的区别、缓存池、自动拆箱装箱(面试题)
  • 【CICD】CICD 持续集成与持续交付在测试中的应用
  • Python期末复习 | 列表、元组、字典、集合与字符串 | 代码演示
  • Linux 用户账户信息配置文件详解
  • 快速认识和上手Protobuf
  • 无插件H5播放器EasyPlayer.js网页web无插件播放器选择全屏时,视频区域并没有全屏问题的解决方案
  • 如何使用 XML Schema
  • 从0安装mysql server
  • flask+vue使用jwt验证
  • 躺平成长-人工智能进行编程-(12)
  • notepad++下载安装教程
  • SpringBoot项目实现登录——集成JWT令牌和验证码的登录业务
  • 网络安全审计
  • 什么是SSL VPN?其中的协议结构是怎样的?
  • 自动化测试工具Ranorex Studio(三十四)-自定义报告模板
  • 基于微信小程序的公务员考试学习平台的设计与实现,LW+源码+讲解
  • 解答疑问,为什么在本地明明拉取了镜像,但是k8s-pod依旧ImagePullBackOff
  • STM32 ADC --- 任意单通道采样
  • 社交媒体的隐私新标准:Facebook的数据保护策略
  • NDNF-RNASeq
  • Prometheus 和 Grafana 以进行服务器监控
  • 【微软报告:多模态基础模型】(1)从专家到通用助手
  • 【论文复现】智慧医疗:纹理特征VS卷积特征