参考链接:https://blog.csdn.net/qq_56591814/article/details/131293940、https://www.bilibili.com/video/BV1WkbzeUEVD/?spm_id_from=333.880.my_history.page.click&vd_source=e01172ea292c1c605b346101d7006c61
# 一、为什么要对大模型进行微调
通常,要对大模型进行微调,有以下一些原因:
-
第一个原因是,因为大模型的参数量非常大,训练成本非常高,每家公司都去从头训练一个自己的大模型,这个事情的性价比非常低;
-
第二个原因是,
Prompt Engineering
的方式是一种相对来说容易上手的使用大模型的方式,但是它的缺点也非常明显。因为通常大模型的实现原理,都会对输入序列的长度有限制,Prompt Engineering
的方式会把Prompt
搞得很长。越长的Prompt
,大模型的推理成本越高,因为推理成本是跟Prompt
长度的平方正向相关的。另外,Prompt
太长会因超过限制而被截断,进而导致大模型的输出质量打折口,这也是一个非常严重的问题。对于个人使用者而言,如果是解决自己日常生活、工作中的一些问题,直接用Prompt Engineering
的方式,通常问题不大。但对于对外提供服务的企业来说,要想在自己的服务中接入大模型的能力,推理成本是不得不要考虑的一个因素,微调相对来说就是一个更优的方案。 -
第三个原因是,
Prompt Engineering
的效果达不到要求,企业又有比较好的自有数据,能够通过自有数据,更好的提升大模型在特定领域的能力。这时候微调就非常适用。 -
第四个原因是,要在个性化的服务中使用大模型的能力,这时候针对每个用户的数据,训练一个轻量级的微调模型,就是一个不错的方案。
-
第五个原因是,数据安全的问题。如果数据是不能传递给第三方大模型服务的,那么搭建自己的大模型就非常必要。通常这些开源的大模型都是需要用自有数据进行微调,才能够满足业务的需求,这时候也需要对大模型进行微调。
# 二、大模型微调的技术手段
根据微调对整个预训练模型的调整程度,微调可以分为全微调和部分微调两个方法:
-
全微调(
Full Fine-tuning, FFT
):FFT
是指对整个预训练模型进行微调,包括所有的模型参数。在这种方法中,预训练模型的所有层和参数都会被更新和优化,以适应目标任务的需求。这种微调方法通常适用于任务和预训练模型之间存在较大差异的情况,或者任务需要模型具有高度灵活性和自适应能力的情况。FFT
需要较大的计算资源和时间,但可以获得更好的性能。 -
参数高效微调(
Parameter-Efficient Fine-Tuning, PEFT
):PEFT
旨在通过最小化微调参数数量和计算复杂度,提升预训练模型在新任务上的表现,从而减轻大型预训练模型的训练负担。PEFT
方法可以通过多种方式进行分类,比如根据其基本方法或结构进行区分 —— 是否向模型引入新的参数,还是仅微调不分现有的参数;根据微调目的进行分类 —— 是否旨在最小化内存占用或仅追求存储效率。我们首先基于基本方法 & 结构进行分类,下图展示了这个分类体系的30
种PEFT
方法。接下来对PEFT
的分类进行详细介绍。
# 2.1 Additive methods
主要思想是通过添加额外的参数或层来扩充现有的预训练模型,并仅训练新添加的参数。到目前为止,这是参数高效微调方法中最大且广泛探索的类别。这种方法又分为:
Adapters
:即在Transformer
子层后引入小型全连接网络,这种方法被广泛采用。Adapters
有多种变体,例如修改适配器的位置、剪枝以及使用重参数化来减少可训练参数的数量。Soft Prompts
:GPT-2
旨在通过修改输入文本来控制语言模型的行为。然而,这些方法很难进行优化,且存在模型输入长度、训练示例的数量等限制,由此引入了soft
概念。Soft Prompts
将模型的一部分输入嵌入通过梯度下降进行微调,将在离散空间中寻找提示的问题转化为连续优化问题。Soft Prompts
可以仅对输入层进行训练(《GPT Understands, Too》、Prompt Tuning),也可以对所有层进行训练(Prefix-Tuning)。others
:例如LeTS
,LST
和(IA)^3
尽管这些方法引入了额外的参数到网络中,但它们通过减少梯度和优化器状态的大小,减少了训练时间,提升了内存效率。此外可以对冻结的模型参数进行量化(参考论文), additive PEFT
方法能够微调更大的网络或使用更大的批次大小,这提高了在 GPU
上的训练吞吐量。此外,在分布式设置中优化较少的参数大大减少了通信量。
# 2.2 Selective methods
最早的 selective PEFT
方法是仅微调网络的几个顶层(冻结前层),现代方法通常基于层的类型(Cross-Attention is All You Need)或内部结构,例如仅微调模型的偏置(BitFit)或仅特定的行(Efficient Fine-Tuning of BERT Models on the Edge)。
# 2.3 Reparametrization-based PEFT(重参数化)
利用低秩表示来最小化可训练参数的数量。Aghajanyan 等人(2020)证明了在低秩子空间中可以有效地进行微调,对于更大的模型或经过更长时间预训练的模型,需要进行调整的子空间更小。最知名的基于重参数化的方法 LoRa
,它将参数矩阵进行简单的低秩分解来更新权重。最近的研究(Karimi Mahabadi 等,2021;Edalati 等,2022)还探索了 Kronecker product reparametrization
的使用,它在秩和参数数量之间取得了更有利的权衡。
LoRA
背后有一个假设:我们现在看到的这些大语言模型,它们都是被过度参数化的。而过度参数化的大模型背后,都有一个低维的本质模型。
大白话说:大模型参数很多,但并不是所有的参数都是发挥同样作用的;大模型中有其中一部分参数,是非常重要的,是影响大模型生成结果的关键参数,这部分关键参数就是上面提到的低维的本质模型。
LoRA
的基本思路,包括以下几步:
-
首先,要适配特定的下游任务,要训练一个特定的模型,将
Y=WX
变成Y=(W+∆W)X
,这里面∆W
主是我们要微调得到的结果; -
其次,将
∆W
进行低维分解∆W=AB
(∆W
为m*n
维,A
为m*r
维,B
为r*n
维,r
就是上述假设中的低维); -
接下来,用特定的训练数据,训练出
A
和B
即可得到∆W
,在推理的过程中直接将∆W
加到W
上去,再没有额外的成本。 -
另外,如果要用
LoRA
适配不同的场景,切换也非常方便,做简单的矩阵加法即可:(W+∆W)-∆W+∆W'
。
该方法认为模型权重矩阵在特定微调后具有较低的本征秩,故基于秩分解的概念,将预训练模型的现有权重矩阵分成两个较小的矩阵。
# 2.4 Hybrid methods
混合多种 PEFT
方法,例如, MAM Adapter
结合了 Adapters
和 Prompt tuning
; UniPELT
加入了 LoRa
, Compacter
和 KronAB
对适配器进行了重参数化以减少其参数数量;最后, S4
是一个自动化算法搜索的结果,它结合了所有的 PEFT
类别,额外参数数量增加 0.5% 的情况下最大化准确性。
# 三、使用 LLaMA-Factory 微调 Qwen2 模型
# 3.1 运行 Qwen2 模型
首先进入下载 Qwen2 的 github 网页的运行文件。运行 Qwen2/examples/demo/web_demo.py
即可在网页端运行 Qwen2
模型。
若本地没有大模型参数文件,则会下载 hugging face
中的参数文件。但是 hugging face
由于网络原因会导致模型下载失败。因此选择国内的 ModelScope 网站下载所需要的 Qwen2
大模型参数文件。找到对应的模型参数文件,依次点击模型文件 - 下载模型 - SDK 下载,即可获得模型参数文件的下载方式,一个示例下载的 python
程序如下所示:
#模型下载 | |
from modelscope import snapshot_download | |
model_dir = snapshot_download('qwen/Qwen2-1.5B-Instruct') |
待下载完成模型文件后,更改 web_demo.py
文件的 DEFAULT_CKPT_PATH
参数为所下载模型参数文件的路径,一个示例的路径为: DEFAULT_CKPT_PATH = 'E:/python/9_LLM/2_FineTuning/4_Qwen/qwen/Qwen2-1___5B-Instruct'
之后即可成功运行 web_demo.py
,并与所下载的大模型参数文件对应的大模型进行对话。
# 3.2 下载并运行 LLaMA-Factory
首先进入 github
的 LLaMA-Factory 网页,下载 LLaMA-Factory
工具箱。运行 LLaMA-Factory-main/src/webui.py
即可运行 LLaMA-Factory
的网页可视化界面。可视化界面如下所示:
# 3.3 准备数据集
在 LLaMA-Factory-main/data
文件夹下保存了几组示例数据集的 json
文件。其中 dataset_info.json
包含了所有可用的数据集。参考 LLaMA-Factory 的说明文件,如果希望使用自定义数据集,需要在 dataset_info.json
文件中添加数据集描述,目前 LLaMA-Factory
仅支持 alpaca
格式和 sharegpt
格式的数据集。完整的数据集描述如下,具体的示例可以参考初始 dataset_info.json
文件:
"数据集名称": { | |
"hf_hub_url": "Hugging Face 的数据集仓库地址(若指定,则忽略 script_url 和 file_name)", | |
"ms_hub_url": "ModelScope 的数据集仓库地址(若指定,则忽略 script_url 和 file_name)", | |
"script_url": "包含数据加载脚本的本地文件夹名称(若指定,则忽略 file_name)", | |
"file_name": "该目录下数据集文件夹或文件的名称(若上述参数未指定,则此项必需)", | |
"formatting": "数据集格式(可选,默认:alpaca,可以为 alpaca 或 sharegpt)", | |
"ranking": "是否为偏好数据集(可选,默认:False)", | |
"subset": "数据集子集的名称(可选,默认:None)", | |
"split": "所使用的数据集切分(可选,默认:train)", | |
"folder": "Hugging Face 仓库的文件夹名称(可选,默认:None)", | |
"num_samples": "该数据集所使用的样本数量。(可选,默认:None)", | |
"columns(可选)": { | |
"prompt": "数据集代表提示词的表头名称(默认:instruction)", | |
"query": "数据集代表请求的表头名称(默认:input)", | |
"response": "数据集代表回答的表头名称(默认:output)", | |
"history": "数据集代表历史对话的表头名称(默认:None)", | |
"messages": "数据集代表消息列表的表头名称(默认:conversations)", | |
"system": "数据集代表系统提示的表头名称(默认:None)", | |
"tools": "数据集代表工具描述的表头名称(默认:None)", | |
"images": "数据集代表图像输入的表头名称(默认:None)", | |
"chosen": "数据集代表更优回答的表头名称(默认:None)", | |
"rejected": "数据集代表更差回答的表头名称(默认:None)", | |
"kto_tag": "数据集代表 KTO 标签的表头名称(默认:None)" | |
}, | |
"tags(可选,用于 sharegpt 格式)": { | |
"role_tag": "消息中代表发送者身份的键名(默认:from)", | |
"content_tag": "消息中代表文本内容的键名(默认:value)", | |
"user_tag": "消息中代表用户的 role_tag(默认:human)", | |
"assistant_tag": "消息中代表助手的 role_tag(默认:gpt)", | |
"observation_tag": "消息中代表工具返回结果的 role_tag(默认:observation)", | |
"function_tag": "消息中代表工具调用的 role_tag(默认:function_call)", | |
"system_tag": "消息中代表系统提示的 role_tag(默认:system,会覆盖 system column)" | |
} | |
} |
添加完成数据集描述后,即可在在 LLaMA-Factory-main/data
文件夹内创建对应数据集名称的 json
文件,即可完成自定义数据集的添加。数据集的格式需要和数据集描述一致,详细的示例可以参考初始在 LLaMA-Factory-main/data
文件夹下的其他 json
数据集文件。
# 3.4 使用 LLaMA-Factory 进行大模型微调
在准备好微调的数据集之后,即可再次运行 LLaMA-Factory-main/src/webui.py
,启动 LLaMA-Factory 的可视化界面,其中的部分参数定义如下,需要注意的是数据路径应该指定为本地计算机 LLaMA-Factory-main/data
文件夹的绝对路径:
定义完成训练参数后即可点击 “开始” 按钮,开始模型的微调训练。模型训练完毕后,点击 Chat
选项卡,检查点路径选择训练好的大模型,即可开始与微调完成的大模型进行在线对话。点击 Export
选项卡,指定导出目录以及其他设置,点击 “开始导出”,即可导出训练完毕的大模型。至此,已经完成使用 LLaMA-Factory
进行大模型微调的全部过程。