随着大语言模型(Large Language Models, LLMs)的快速发展,如何高效地对其进行任务适配已成为自然语言处理领域的关键课题。其中,大语言模型微调成为目前备受关注的一个方法,微调的核心原因是赋予大模型更加定制化的功能。微调的目的是将通用模型转变为专用模型,弥合通用预训练模型与特定应用需求之间的差距,确保语言模型更贴近人类的期望。
通过微调,可以使模型更好地适应特定领域的需求和特征。通过引入特定领域的数据集进行微调,大模型可以学习该领域的知识和语言模式,这有助于模型在特定任务上取得更好的性能。继上一篇文章(工具推荐|研究了DeepSeek在内的几十种模型微调方法后,强烈推荐这几种模型微调工具.....),我们将继续深入探讨现代语言模型微调的技术体系。本文涵盖数据集构建策略、参数优化方法以及算力资源评估三个核心维度,旨在为研究者和从业者提供技术参考。
常见的数据集构造
第一种策略,统一处理单轮对话与多轮对话的数据,通过conversations进行组织,训练时每一个样本如下
{
"conversation_id":44,
"category":"Brainstorming",
"conversation":[
{
"human":"怎么能够有效地提升个人能力?",
"assistant":"提升个人能力可以通过以下几个方面实现:nn1. 学习新知识和技能:阅读相关书籍、参加课程和工作坊、观看教育视频等学习方式,可以帮助你掌握新的知识和技能,从而提升个人能力。nn2. 持续练习和实践:不断地练习和实践所学的知识和技能,可以帮助你更好地掌握和应用这些技能,提高你的表现和效率。nn3. 寻求反馈和改进:寻求他人的反馈和建议可以帮助你发现自己的不足之处,进一步完善和改进自己的能力。nn4. 建立良好的工作和生活习惯:建立良好的工作和生活习惯,如合理安排时间、注意健康、保持积极态度等,可以提高你的工作效率和生活品质,从而提升个人能力。nn5. 社交和交流:与他人交流和合作,可以帮助你更好地了解他人的观点和经验,从而提升自己的能力和见识。"
},
{
"human":"对于初学者来说,如何快速掌握编程技能?",
"assistant":"以下是几个建议,可以帮助初学者快速掌握编程技能:nn1. 学习基础知识:建议先学习编程语言的基础知识和语法,例如变量、数据类型、控制结构、函数等。可以通过在线课程、编程书籍、视频教程等方式学习。nn2. 实践编程:进行实际的编程练习是非常重要的,可以通过参加编程挑战、编写小项目等方式来进行实践。nn3. 寻求反馈:可以寻求他人的反馈和建议,例如在线编程社区、编程导师等,他们可以帮助你发现问题并及时纠正。nn4. 阅读优秀代码:阅读和分析优秀的代码可以帮助你学习其他程序员的编程思路和技巧,从而提高自己的编程能力。nn5. 不断学习和更新:编程技术和工具在不断更新和发展,因此需要不断学习新的知识和技能,例如学习新的编程语言、框架、工具等,以跟上技术的发展和变化。nn总之,学习编程需要耐心和坚持,并且需要不断地实践和学习。通过以上建议,可以帮助初学者快速掌握编程技能。"
},
{
"human":"除了参加编程挑战和阅读代码,还有哪些方式可以提升自己的编程能力呢?",
"assistant":"除了参加编程挑战和阅读代码,还有以下几种方式可以提升自己的编程能力:nn1. 参与开源项目:加入一个开源项目,可以让你了解到实际的软件开发流程和团队合作方式,并且可以与其他开发人员合作,学习和分享编程技巧和经验。nn2. 进行代码重构:对已经编写的代码进行重构,可以帮助你了解更好的编程实践和设计模式,从而提高代码的可读性和可维护性。nn3. 练习算法和数据结构:算法和数据结构是编程中的重要基础,练习算法和数据结构可以帮助你了解不同的数据结构和算法,从而更好地解决实际问题。nn4. 学习软件工程和架构:学习软件工程和架构的知识,可以帮助你了解如何设计和构建可靠、可扩展和可维护的软件系统。nn5. 参加编程社区和论坛:参加编程社区和论坛可以让你与其他开发人员分享和讨论编程经验和技巧,了解最新的技术趋势和解决方案。nn总之,提升编程能力需要不断地学习和实践,并与其他开发人员和编程专家进行交流和合作,以获取更多的经验和知识。"
},
{
"human":"你有没有推荐的编程挑战网站?",
"assistant":"当然,以下是一些值得推荐的编程挑战网站:nn1. HackerRank:HackerRank 是一个全球领先的技术招聘平台,提供数百种编程挑战和比赛,包括算法、数据结构、数学、SQL、AI 等多个技术领域。nn2. LeetCode:LeetCode 是一个在线编程学习和实践平台,提供数千道编程题目,主要涵盖算法和数据结构。nn3. Codeforces:Codeforces 是一个全球知名的编程竞赛网站,提供数百个比赛和练习题目,主要涵盖算法和数据结构。nn4. Codewars:Codewars 是一个在线编程学习和实践平台,提供数千道编程题目,主要涵盖算法、数据结构、面向对象编程等多个技术领域。nn5. Project Euler:Project Euler 是一个非营利性的在线编程挑战平台,提供一系列数学和计算机科学问题,需要用编程语言进行解答。nn以上这些编程挑战网站可以帮助你提高编程能力,并且可以与其他编程爱好者进行交流和竞争。"
},
{
"human":"在学习编程的过程中,如何避免陷入困境和放弃呢?",
"assistant":"学习编程是一个需要长期坚持和不断学习的过程,以下是一些避免陷入困境和放弃的方法:nn1. 制定合理的学习计划:制定合理的学习计划,包括学习时间、学习内容、目标等,可以帮助你更好地管理时间和精力,避免学习过程中的松懈和分心。nn2. 寻找合适的学习资源:选择适合自己的学习资源,例如在线课程、编程书籍、视频教程等,可以让你更好地了解和掌握编程知识和技能。nn3. 寻求帮助和支持:在学习过程中,遇到问题和困难是很正常的,可以寻求他人的帮助和支持,例如参加编程社区、找到编程导师等。nn4. 进行实践和项目:实践和项目是学习编程的重要组成部分,可以帮助你更好地了解和掌握编程技能,同时也可以提高学习的兴趣和动力。nn5. 坚持并保持兴趣:坚持学习和保持兴趣是学习编程的关键。可以通过参加编程社区、参加编程竞赛、与其他编程爱好者交流等方式来保持兴趣和动力。nn总之,学习编程需要耐心和坚持,并需要不断学习和实践。通过以上方法可以帮助你避免陷入困境和放弃。"
}
],
}
第二种策略,将历史对话数据与当前轮的对话数据进行分离,遵循alpaca数据集的数据构造策略,训练时每一个样本如下
{
"instruction": "谢谢",
"input": "",
"output": "不用谢! 很高兴我提供的信息能够帮助到你! 如果还有什么其他问题也可以向我提问。",
"history": [
[
"请你给我写一个面试准备计划,我想要去面试微软的程序员岗位",
"首先,你可以去微软官网寻找招聘信息并申请面试。n其次,您可以在社交媒体平台寻找微软公司对程序员的面试问题,并做好准备。n最后,您可以自己对面试过程进行模拟,熟悉话题并减少紧张感。n我希望你能面试成功。"
]
]
}
指令微调数据集
数据集名称 | 任务 | 公开时间 | 样本数 |
---|---|---|---|
GLUE | NLP | 2018 | 1,485,043 |
SuperGLUE | NLP | 2019 | 196,309 |
E2E NLG Challenge | NLP | 2020 | 50K |
WikiSQL | NLP | 2017 | 80,645 |
WebNLG | NLP | 2017 | 27,731 |
SAMSum | Daily Chat | 2019 | 16,369 |
OASST1 | Daily Chat | 2023 | 161,443 |
WMT | Others | 2019 | 124,448,248 |
XSUM | Others | 2018 | 200,000 |
DART | Others | 2021 | 82,000 |
-
moss-003-sft-data:由复旦大学MOSS团队开源的中英文多轮对话数据,包含100万+数据
-
Stanford Alpaca (en):由斯坦福大学发布的英文指令微调数据集,基于Self-Instruct方法生成。
-
Stanford Alpaca (zh):Stanford Alpaca的中文版本,适用于中文指令微调任务。
-
Alpaca GPT4 (en&zh):基于GPT-4生成的指令数据集,支持中英文。
-
Glaive Function Calling V2 (en&zh):专注于函数调用任务的指令数据集,支持中英文。
-
LIMA (en):高质量英文指令数据集,强调简洁和清晰的指令。
-
Guanaco Dataset (multilingual):多语言指令数据集,支持多种语言。
-
BELLE 2M (zh):BELLE项目开源的中文指令数据集,包含200万条数据。
-
BELLE 1M (zh):BELLE项目的中文指令数据集,包含100万条数据。
-
BELLE 0.5M (zh):BELLE项目的中文指令数据集,包含50万条数据。
-
BELLE Dialogue 0.4M (zh):BELLE项目的中文对话数据集,包含40万条数据。
-
BELLE School Math 0.25M (zh):BELLE项目的中文数学题数据集,包含25万条数据。
-
BELLE Multiturn Chat 0.8M (zh):BELLE项目的中文多轮对话数据集,包含80万条数据。
-
UltraChat (en):高质量的英文对话数据集,包含多轮对话数据。
-
OpenPlatypus (en):专注于问答和知识推理的英文数据集。
-
CodeAlpaca 20k (en):专注于代码生成的指令数据集,包含2万条数据。
-
Alpaca CoT (multilingual):支持思维链(Chain-of-Thought)的多语言指令数据集。
-
OpenOrca (en):高质量的英文指令数据集,基于OpenAI的GPT-4生成。
-
SlimOrca (en):OpenOrca的精简版本,数据量较小但质量高。
-
MathInstruct (en):专注于数学推理的英文指令数据集。
-
Firefly 1.1M (zh):中文指令数据集,包含110万条数据。
-
Wiki QA (en):基于维基百科的英文问答数据集。
-
Web QA (zh):基于中文网页的问答数据集。
-
WebNovel (zh):中文网络小说数据集,适用于文本生成任务。
-
Nectar (en):高质量的英文指令数据集,基于GPT-4生成。
-
deepctrl (en&zh):支持中英文的指令数据集,适用于控制任务。
-
Advertise Generating (zh):中文广告生成数据集。适用于广告文案生成任务。
-
ShareGPT Hyperfiltered (en):高质量的英文对话数据集,经过严格过滤。
-
ShareGPT4 (en&zh):基于GPT-4生成的对话数据集,支持中英文。
-
UltraChat 200k (en):UltraChat的精简版本,包含20万条数据。
-
AgentInstruct (en):专注于智能体任务的指令数据集。
-
LMSYS Chat 1M (en):大规模的英文对话数据集,包含100万条数据。
-
Evol Instruct V2 (en):基于进化算法的指令数据集,支持复杂任务。
-
Cosmopedia (en):高质量的英文指令数据集,涵盖广泛的主题。
-
STEM (zh):中文科学、技术、工程和数学(STEM)数据集。
-
Ruozhiba (zh):中文对话数据集,适用于多轮对话任务。
-
Neo-sft (zh):中文指令数据集,适用于轻量级微调。
-
Magpie-Pro-300K-Filtered (en):高质量的英文指令数据集,包含30万条数据。
-
Magpie-ultra-v0.1 (en):Magpie的精简版本,数据量较小但质量高。
-
WebInstructSub (en):基于网页数据的英文指令数据集。
-
OpenO1-SFT (en&zh):支持中英文的指令数据集,适用于多任务微调。
-
LLaVA mixed (en&zh):结合视觉和语言的多模态指令数据集,支持中英文。
-
Pokemon-gpt4o-captions (en&zh):基于Pokemon主题的图文数据集,支持中英文。
-
Open Assistant (de):德文指令数据集,适用于德语任务微调。
-
Dolly 15k (de):德文指令数据集,包含1.5万条数据。
-
Alpaca GPT4 (de):基于GPT-4生成的德文指令数据集。
-
OpenSchnabeltier (de):德文指令数据集,适用于多任务微调。
-
Evol Instruct (de):基于进化算法的德文指令数据集。
-
Dolphin (de):高质量的德文指令数据集。
-
Booksum (de):德文书籍摘要数据集。
-
Airoboros (de):德文指令数据集,适用于多任务微调。
-
Ultrachat (de):德文对话数据集,适用于多轮对话任务。
全参微调(FFT)
全参微调是指在微调过程中,更新预训练模型的所有参数,而不仅仅是部分参数。这种方法通常用于任务数据与预训练数据差异较大的场景,或者需要模型在特定任务上达到最佳性能的情况。
全参微调的优点:
-
性能优越:由于更新了所有参数,模型可以更好地适应目标任务,通常在性能上优于部分微调方法(如LoRA、P-Tuning等)。
-
灵活性高:适用于各种任务类型(如分类、生成、翻译等)。
-
无需额外设计:不需要像LoRA或Adapter等方法那样引入额外的模块或参数。
全参微调的缺点:
-
计算资源需求高:需要加载和更新整个模型的参数,显存和计算资源需求较高。
-
过拟合风险:如果任务数据量较小,模型容易过拟合。
-
训练时间长:由于需要更新所有参数,训练时间通常较长。
特性 | 全参微调(FFT) | 参数高效微调(如LoRA、Adapter) |
---|---|---|
参数更新范围 | 更新所有参数 | 仅更新部分参数或引入少量额外参数 |
计算资源需求 | 高(需要高端GPU,如A100) | 低(可在消费级GPU上运行) |
训练时间 | 较长 | 较短 |
性能 | 通常更优 | 可能略低 |
过拟合风险 | 较高(数据量小时) | 较低 |
适用场景 | 数据量大、任务复杂、资源充足 | 数据量小、资源有限 |
参数高效微调(PEFT)
将预训练语言模型(LM)应用于下游任务并进行微调,已成为处理 NLP 任务的标准方法。与直接使用开箱即用的预训练 LLM(例如零样本推理)相比,在下游数据集上微调这些预训练模型能够显著提升性能。
然而,随着模型规模的不断增大,在消费级硬件上对其进行全面参数微调(full fine-tuning)变得愈加不可行。
此外,针对每个下游任务独立存储和部署微调模型也变得非常昂贵,因为微调后的模型(无论是调整模型的所有参数还是部分参数)与原始预训练模型的规模相当。
因此,近年来研究者们提出了多种参数高效迁移学习方法(Parameter-efficient Transfer Learning),即固定大部分预训练语言模型(PLM)参数,仅调整模型的一小部分参数,从而在不进行全面微调的情况下,仍能达到与全参数微调相近的性能。这些调整的参数可以是模型自身的,也可以是额外添加的参数。
学术表达:Parameter Efficient Fine-Tuning (参数高效微调),调整预训练大型模型的参数,使其适应特定任务或领域,同时尽量减少引入的额外参数数量或所需的计算资源。
高效微调技术可以粗略分为以下三大类:选取一部分参数更新(S)、增加额外参数(A)、引入重参数化(R)。而在增加额外参数这类方法中,又主要分为类适配器(Adapter-like)方法和软提示(Soft prompts)两个小类。还有一类方法综合了不同参数高效微调方法的设计空间称为混合微调方法。
选择性微调
不需要额外的参数,从骨干模型中选择一小部分参数,并使它们可调,而在下游任务的微调过程中保持大多数参数不变。根据所选的参数分组可以分为结构化掩码和非结构化掩码。
选择性微调-BitFit:BitFit(论文:BitFit: Simple Parameter-efficient Fine-tuning or Transformer-based Masked Language-models)是一种稀疏的微调方法,它训练时只更新bias的参数或者部分bias参数。对于Transformer模型而言,冻结大部分 transformer-encoder 参数,只更新bias参数跟特定任务的分类层参数。涉及到的bias参数有attention模块中计算query,key,value跟合并多个attention结果时涉及到的bias,MLP层中的bias,Layernormalization层的bias参数。
加法微调
根据在额外的可微调模块或参数方面上的不同可分为基于Adapter(适配器),soft prompt(软提示),其他。
基于适配器-Adapter Tuning
Adapter Tuning(论文:Parameter-Efficient Transfer Learning for NLP),该方法设计了Adapter结构,并将其嵌入Transformer的结构里面,针对每一个Transformer层,增加了两个Adapter结构(分别是多头注意力的投影之后和第二个feed-forward层之后),在训练时,固定住原来预训练模型的参数不变,只对新增的 Adapter 结构和 Layer Norm 层进行微调,从而保证了训练的高效性。每当出现新的下游任务,通过添加Adapter模块来产生一个易于扩展的下游模型,从而避免全量微调与灾难性遗忘的问题。
基于提示-Prefix Tuning
在Prefix Tuning之前的工作主要是人工设计离散的模版或者自动化搜索离散的模版。对于人工设计的模版,模版的变化对模型最终的性能特别敏感,加一个词、少一个词或者变动位置都会造成比较大的变化。而对于自动化搜索模版,成本也比较高;同时,以前这种离散化的token搜索出来的结果可能并不是最优的。
除此之外,传统的微调范式利用预训练模型去对不同的下游任务进行微调,对每个任务都要保存一份微调后的模型权重,一方面微调整个模型耗时长;另一方面也会占很多存储空间。
基于上述两点,Prefix Tuning提出固定预训练LM,为LM添加可训练,任务特定的前缀,这样就可以为不同任务保存不同的前缀,微调成本也小;同时,这种Prefix实际就是连续可微的Virtual Token(Soft Prompt/Continuous Prompt),相比离散的Token,更好优化,效果更好。
重参数化微调
表示在两种等价形式之间转换模型参数。具体而言,重参数化微调在训练期间引入额外的低秩可训练参数,然后将这些参数与原始模型集成以进行推理。这种方法分为两种主要策略:低秩分解 和 LoRA 衍生方法。
Lora
神经网络包含很多全连接层,其借助于矩阵乘法得以实现,然而,很多全连接层的权重矩阵都是满秩的。当针对特定任务进行微调后,模型中权重矩阵其实具有很低的本征秩(intrinsic rank),因此,论文的作者认为权重更新的那部分参数矩阵尽管随机投影到较小的子空间,仍然可以有效的学习,可以理解为针对特定的下游任务这些权重矩阵就不要求满秩。
LoRA(论文:LoRA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS),该方法的核心思想就是通过低秩分解来模拟参数的改变量,从而以极小的参数量来实现大模型的间接训练。
在涉及到矩阵相乘的模块,在原始的PLM旁边增加一个新的通路,通过前后两个矩阵A,B相乘,第一个矩阵A负责降维,第二个矩阵B负责升维,中间层维度为r,从而来模拟所谓的本征秩(intrinsic rank)。
可训练层维度和预训练模型层维度一致为d,先将维度d通过全连接层降维至r,再从r通过全连接层映射回d维度,其中,r<<d,r是矩阵的秩,这样矩阵计算就从d x d变为d x r + r x d,参数量减少很多。
QLora
QLoRA(论文:QLORA: Efficient Finetuning of Quantized LLMs),使用一种新颖的高精度技术将预训练模型量化为 4 bit,然后添加一小组可学习的低秩适配器权重,这些权重通过量化权重的反向传播梯度进行微调。QLORA 有一种低精度存储数据类型(4 bit),还有一种计算数据类型(BFloat16)。实际上,这意味着无论何时使用 QLoRA 权重张量,我们都会将张量反量化为 BFloat16,然后执行 16 位矩阵乘法。QLoRA提出了两种技术实现高保真 4 bit微调——4 bit NormalFloat(NF4) 量化和双量化。此外,还引入了分页优化器,以防止梯度检查点期间的内存峰值,从而导致内存不足的错误,这些错误在过去使得大型模型难以在单台机器上进行微调。具体说明如下:
-
4bit NormalFloat(NF4):对于正态分布权重而言,一种信息理论上最优的新数据类型,该数据类型对正态分布数据产生比 4 bit整数和 4bit 浮点数更好的实证结果。
-
双量化:对第一次量化后的那些常量再进行一次量化,减少存储空间。
-
分页优化器:使用NVIDIA统一内存特性,该特性可以在在GPU偶尔OOM的情况下,进行CPU和GPU之间自动分页到分页的传输,以实现无错误的 GPU 处理。该功能的工作方式类似于 CPU 内存和磁盘之间的常规内存分页。使用此功能为优化器状态(Optimizer)分配分页内存,然后在 GPU 内存不足时将其自动卸载到 CPU 内存,并在优化器更新步骤需要时将其加载回 GPU 内存。
混合微调
探索了不同参数高效微调方法的设计空间,并结合了它们的优势。近年来,涌现出了许多针对语言模型的参数高效微调(PELT)方法,在模型训练参数极大的减少的情况下,模型效果与全量微调相当。但是不同的PELT方法在同一个任务上表现差异可能都非常大,这让针对特定任务选择合适的方法非常繁琐。
基于此,作者提出了UniPELT方法,将不同的PELT方法作为子模块,并通过门控机制学习激活最适合当前数据或任务的方法。UniPELT(论文:UNIPELT: A Unified Framework for Parameter-Efficient Language Model Tuning)是 LoRA、Prefix Tuning和Adapter的门控组合。
更具体地说,LoRA 重新参数化用于 WQ 和 WV 注意力矩阵,Prefix Tuning应用于每一Transformer层的key和value,并在Transformer块的feed-forward子层之后添加Adapter。对于每个模块,门控被实现为线性层,通过GP参数控制Prefix-tuning方法的开关,GL控制LoRA方法的开关,GA控制Adapter方法的开关。可训练参数包括 LoRA 矩阵 WA(Down)和WB(Up),提示调优参数Pk和Pv、Adapter参数和门函数权重。即图中蓝颜色的参数为可学习的参数。
总的来说,PEFT总览如下所示:
微调涉及不同的数据集大小,最大迭代轮次,微调方法,GPU实际算力配置和现实世界中各种情况,目前学术界和工业界均没有一个准确且客观的估算体系。因此我们假定了一些条件来说明部分比较流行的微调方法所需的算力和时间初步预估。
例如:A100 80 GB上Llama 2模型的最大可能PEFT(参数高效微调)配置
例如:在A100 80 GB显卡上进行Llama2 Chat模型的完整微调配置
使用不同的微调方法在不同大小的模型上采用不同精度进行微调时的显存开销估计
原文始发于微信公众号(安全极客):技术研究|深度探讨大语言模型微调技术
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论