大语言模型Fine-tuning踩坑经验之谈


©作者 | FelixCoder



前言


由于 ChatGPT 和 GPT4 兴起,如何让人人都用上这种大模型,是目前 AI 领域最活跃的事情。当下开源的  LLM(Large language model)非常多,可谓是百模大战。面对诸多开源本地模型,根据自己的需求,选择适合自己的基座模型和参数量很重要。选择完后需要对训练数据进行预处理,往往这一步就难住很多同学,无从下手,更别说 training。


然后再对模型进行 finetuning 来更好满足自己的下游任务。那么对于如果要训练一个专家模型。预训练也是必不可缺的工作。不管是预训练还是  finetuning(微调),无论选用何种方案,都避免不了训练中产生的灾难性遗忘问题,那么怎么减少和避免这种情况的发生,也是本文想讲的一个重点。对于推理,在 GPU 资源不富裕的情况,如何最小化的利用内存,提升推理效率,也是可以讨论的内容。




模型选择


先看一下最好的模型有哪些,以下数据是最新 LLM 排行,来自 UC 伯克利 [1]

▲ FireShot Capture 015 - Chatbot Arena Leaderboard Week 8_ Introducing MT-Bench and Vicuna-33B_ - lmsys.org.png


当然这里前 3 名都闭源模型,后面开源模型,大多数也都是英文的模型。如果 GPU 资源充足(至少 A100*8),这里也可以基于开源模型做中文的预训练,最后再 finetuning 。但我们没有 GPU 资源, 我们可以选择开源的中文模型直接做微调。 


具体有哪些中文模型可以选择,可以参考这两个地址 中文语言理解测评基准(CLUE[2] 和 SuperCLUE 琅琊榜 [3]。开源领域 ChatGLM,LLAMA,RWKV 主要就是这 3 种模型, 中文好一点就是 ChatGLM,潜力最好的就是 LLAMA,RNN 架构决定 RWKV 有很好的推理效率(随输入长度内存占比线性自增,而 LLAMA 则是指数增加) 和  Length Extrapolation (关于长度外推性,可以参考苏神的文章 [4])。


当然 MPT-7B-StoryWriter-65k+ [5] 模型也有较长的外推能力,主要在于,注意力这块使用了 ALIBI [6]。要拥有什么样的长度,取决你的需求。对于对话模型,往往不需要那么长的外推能力。但对于想做知识库领域相关的应用, 需要模型能够看更多的内容,是有这个需求的。


这里不做推荐,一切来自你的具体需求和 GPU 资源,不知道怎么样选择,可以将您的需求和资源情况留言,我给你做一个选择。




模型大小选择


当然对于模型参数的选择,往往是参数越大效果越好。如果资源充足,当然是推荐 30B 以上的模型。不管是 6B, 7B 和 13B 同样的训练数据,同样训练参数,模型参数量大效果则优于低参数的模型。那么根据模型参数,如何预估我们的训练所需的内存开销,这里有一个简单的方法 比如 6B 模型,60 亿规模参数,根据以下公式计算: 


模型参数 + 梯度参数 + 优化器参数 = 6B * 1bytes + 6GB + 2*6GB = 24GB 


以上是全量预训练,当然如果采用 lora 这种方法,则会有更低内存占用。当然我们还可以对模型进行量化,来提高内存效率。 


注意:参数多量化低的模型要优于参数低量化高的模型,举例 :33B-fb4 模型要优于 13b-fb16 模型.




数据处理


对于 LLM 训练,数据质量很重要。预训练时,我们可以将数据先进行预处理,比如对数据进行一定规则的筛选,数据去重,去除一些低质量的数据。同时,我们可能面临各种类型的数据,PDF,Word,HTML,代码文件等等,对于这种不同类型的数据我们需要都处理成文本,同时还过滤掉一些干扰项或乱码的数据。


当然,我们也可以利用一些工具去处理,比如 justext [7]trafilatura [8],来提取文档主要内容,减少数据的噪音。对于空的文档或文档长度低于 100 进行过滤,进一步减少噪音。


对于一些机器生成的文本或 OCR 识别错误的文本,质量不高,由没有什么逻辑性,虽然比较难以检测,但是还是会有一些工具能做这样的事情,比如 ctrl-detector [9]。当然对于一些有毒的或带有偏见的数据,可以采用 PerspectiveAPI [10] 或垃圾邮件检测的办法来过滤。


我们还不得不考虑数据的一些隐私风险,也需要考虑,比如身份证号,银行卡等信息,比如 presidio 和 pii-codex 等工具提供了检测、分析和处理文本数据中的个人身份信息的能力。


指令微调数据,我们可以使用 PromptSource [11] 来创建微调数据。当然我们还可以让 GPT4 给我们标注一些数据,这样蒸馏知识,可以让数据质量进一步提升。这里我分享一个我使用的 Prompt 工程:


first_prompt = """
作为一位专业的xxxx,您的任务是从给定的上下文回答问题。
给定的上下文:
"""

last_prompt = """
请综合上述信息,你给出的回复需要包含以下三个字段:
1.questions: 基于上下文内容,提出与这个内容相关的问题,至少两个以上。
2.answers: 然后根据问题,分别给出每个问题的答案,请用 markdown 格式。
3.instruction: 给出上下文内容的总结,尽量精简,用 markdown 格式。
请按照以下JSON格式来回答:
前括号
      "questions": [
          "<内容相关问题1>",
          "<内容相关问题2>"
      ],
      "answers": [
           "<内容相关问题1的答案>",
           "<内容相关问题2的答案>"
      ],
      instruction: "<总结性的内容>"
后括号
注意:如果碰到上下文内容信息不够,无法回答问题的情况,answers和questions可以返回空。
最后强调一下:你的回复将直接用于javascript的JSON.parse解析,所以注意一定要以标准的JSON格式做回答,不要包含任何其他非JSON内容,否则你将被扣分!!!
"""



微调方案


目前对于 LLM 微调方案有很多,我将常用的一些方案和相关资料做一个列举。 
  • Prefix-Tuning(P-Tuning v2)[12]
  • Prompt Tuning [13]
  • Lora / QLora [14]


根据实际经验,这里推荐采用 Lora 或 QLora。简单介绍一下 QLoRA,重点改进是将模型采用 4bit 量化后加载,训练时把数值反量化到 bf16 后进行训练,利用 LoRA 可以锁定原模型参数不参与训练,只训练少量 LoRA 参数的特性使得训练所需的显存大大减少。例如 33B 的 LLaMA 模型经过这种方式可以在 24GB 的显卡上训练,也就是说消费级单卡都可以实现,大大降低了微调的门槛。


英文模型需要做词表扩充吗?


对于像 LLaMA 模型的词表大小是 32K,其主要针对英语进行训练(具体详见 LLaMA 论文 [15]),对多语种支持不是特别理想(可以对比一下多语言经典模型 XLM-R 的词表大小为 250K)。


通过初步统计发现,LLaMA 词表中仅包含很少的中文字符,所以在切词时会把中文切地更碎,需要多个 byte token 才能拼成一个完整的汉字,进而导致信息密度降低。比如,在扩展词表后的模型中,单个汉字倾向于被切成 1 个 token,而在 LLaMA 中可能就需要 2-3 个才能组合成一个汉字,显著降低模型的推理效率。


如何避免灾难遗忘


通常我们有以下方式,可以减少或避免灾难性遗忘问题

 

  • 将重要的权重冻结 - 像 Lora 就是采用的这种方案,只学习部分网络权重。但这里 Lora 的配置其实是要注意一下,如果你是用 Lora 做预训练,lora 训练模块可以配上 q_proj,v_proj,k_proj,o_proj  如果是微调则只需要训练  q_proj,v_proj  lora_rank 的设置也有讲究,初始设 lora_ran 为 8,训练存在遗忘时,可以将 lora_rank 改为 64(原因是与原模型数据领域相差较大的话,需要更大的秩,原论文有说明)。

  • 复习 - 跟人一样,在预训练或微调时,回看之前训练的数据。还可以专门把特征图存起来,量化以后放在一个类似于记忆库的地方,之后在新任务上训练的时候从这个记忆库里重构出记忆和新数据一起训练。感兴趣可以看这篇论文 [16]。 
  • MoE - 稀疏门控制的专家混合层,最近爆出 GPT4 是由 8 个 220B 的模型组合。关于 Moe 相关资料 [17] 大家自行了解。 




推理加速


对于推理,一般我们采用量化方案,这里有两个办法。第一个则是采用 ggml 工具,比如 llama.cpp [18] 针对 llama 模型,将模型量化运行在 cpu 或 gpu 上,也可以 cpu 和 gpu 一起跑,内存则大大减少,推理速度有极大的提高。 

▲ image.png


这里如果将 llama.cpp 运行在 gpu 上, 编译时一定要加 LLAMA_CUBLAS=1,同时推理的时候,指定  --gpu-layers|-ngl  来分配运行在 gpu 上的层数,当然越大,占用 gpu 的内存会越多。


如果是 RWKV 模型,则考虑采用 rwkv.cpp [19],此方法与 llama.cpp 类似,使用方式也是类似的。


还有 Llama 模型还可以考虑使用 exllama [20] 纯 GPU 的加速,虽然还不够完善,但也可以值得一试。


另一个,采用 LLM Accelerator [21],LLM 存在大量的相似性推理,基于此,可以做一些优化加速推理,具体请看论文。最后采用架构上的调整,faster transformer [22] 要优于传统的 transformer 架构。




总结


最后总结几条原则: 
  • 参数多量化低的模型要优于参数低量化高的模型 
  • 模型质量与训练数据质量是存在相关性的 
  • 扩充中文词表有助于提高推理效率 
  • 微调推荐采用 Lora QLora 方案 
  • 模型加速必然需要对模型进行量化


参考文献

[1] https://lmsys.org/blog/2023-06-22-leaderboard/[2] https://www.cluebenchmarks.com/index.html[3] https://www.superclueai.com/[4] https://kexue.fm/archives/9431[5] https://huggingface.co/mosaicml/mpt-7b-storywriter[6] https://arxiv.org/abs/2108.12409[7] https://github.com/miso-belica/jusText[8] https://github.com/adbar/trafilatura[9] https://github.com/salesforce/ctrl-detector[10] https://perspectiveapi.com/[11] https://github.com/bigscience-workshop/promptsource[12] https://github.com/THUDM/P-tuning-v2[13] https://zhuanlan.zhihu.com/p/415168620[14] https://github.com/artidoro/qlora[15] https://arxiv.org/abs/2302.13971v1[16] https://arxiv.org/abs/1910.02509[17] https://zhuanlan.zhihu.com/p/542465517[18] https://github.com/ggerganov/llama.cpp[19] https://github.com/saharNooby/rwkv.cpp[20] https://github.com/turboderp/exllama[21] https://arxiv.org/pdf/2304.04487.pdf[22] https://github.com/NVIDIA/FasterTransformer

更多阅读



#投 稿 通 道#

 让你的文字被更多人看到 



如何才能让更多的优质内容以更短路径到达读者群体,缩短读者寻找优质内容的成本呢?答案就是:你不认识的人。


总有一些你不认识的人,知道你想知道的东西。PaperWeekly 或许可以成为一座桥梁,促使不同背景、不同方向的学者和学术灵感相互碰撞,迸发出更多的可能性。 


PaperWeekly 鼓励高校实验室或个人,在我们的平台上分享各类优质内容,可以是最新论文解读,也可以是学术热点剖析科研心得竞赛经验讲解等。我们的目的只有一个,让知识真正流动起来。


📝 稿件基本要求:

• 文章确系个人原创作品,未曾在公开渠道发表,如为其他平台已发表或待发表的文章,请明确标注 

• 稿件建议以 markdown 格式撰写,文中配图以附件形式发送,要求图片清晰,无版权问题

• PaperWeekly 尊重原作者署名权,并将为每篇被采纳的原创首发稿件,提供业内具有竞争力稿酬,具体依据文章阅读量和文章质量阶梯制结算


📬 投稿通道:

• 投稿邮箱:hr@paperweekly.site 

• 来稿请备注即时联系方式(微信),以便我们在稿件选用的第一时间联系作者

• 您也可以直接添加小编微信(pwbot02)快速投稿,备注:姓名-投稿


△长按添加PaperWeekly小编



🔍


现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧


··

相关推荐

  • OceanGPT:面向海洋科学的大型语言模型初探
  • 年终盘点!2023年顶会论文合集(含CVPR、ECCV、NIPS、AAAI、ACL、KDD、ICML等)
  • SFT微调的数据组合及训练策略如何影响大模型性能:4个经典问题及实验结论分享
  • 24 个常见的 Docker 疑难杂症处理技巧
  • 我准备组队学习了
  • Java21 分代 ZGC 和虚拟线程上手体验
  • 算法的末日来了!阿里裁掉大量算法,数量远超其他岗位,因为算法拿着高薪,就知道调参发论文!
  • [211渣硕] 腾讯/阿里/携程 详细NLP算法实习 面经
  • Tree of Thoughts(ToT):让大模型能动地解决问题
  • 终于发表了第一篇 CCF A 类顶会!
  • 实现订单 30 分钟未支付则自动取消,我有五种方案!
  • Object o = new Object() 占用多少字节?
  • 美团一面:为什么 MySQL 不建议使用 NULL 作为列默认值?5 分钟彻底搞懂!
  • 语雀停服八小时,P0级事故!故障原因和补偿来了!!
  • 协同发展,生态聚合丨1024程序员节暨「源聚一堂」开源技术沙龙(北京站)成功举办
  • 周鸿祎称程序员节是唯一不能放假的节日;苹果官宣十月 Mac 发布会:来势凶猛;Firefox 119 发布|极客头条
  • 用了这些IDEA插件以后,我写代码快了10倍!
  • 浅谈多人游戏原理和简单实现
  • 【深度学习】激光雷达分割与测距SOTA算法!已开源!
  • 【深度学习】NIPS 2022 表格数据还需要深度学习吗?