掘金 人工智能 15小时前
LLM参数有效性学习综述
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文深入探讨了大模型微调的多种技术,包括全参数微调的显存占用分析,以及Prefix-tuning-V2和LoRA等高效微调方法。Prefix-tuning-V2通过在Transformer各层前插入可训练的虚拟Token Embedding来优化模型,而LoRA则通过低秩分解矩阵在不改变原始模型结构的情况下实现参数高效微调,显著降低了显存和存储成本。此外,文章还介绍了DyLoRA、AdapterFusion和AdapterDrop等进阶技术,它们在动态调整秩、融合多任务知识和优化推理效率方面进行了创新。最后,QLoRA结合了LoRA和量化技术,进一步提升了微调效率。

💰 **全参数微调显存分析与优化**:全参数微调(Full Fine-tuning)需要大量显存,主要消耗在模型参数、梯度、优化器状态和中间激活值上。例如,一个3B参数的模型,在FP16精度下,模型参数占用6GB,梯度占用6GB,AdamW优化器状态占用36GB。通过使用低精度优化器(如8bit Adam)、梯度检查点、ZeRO优化和混合精度训练等手段,可以有效降低显存占用。

🧩 **Prefix-tuning-V2 (PT-V2) 的Soft-Prompt机制**:PT-V2是一种Soft-Prompt方法,通过在Transformer的每一层前插入可训练的虚拟Token Embedding来引导模型行为。与P-Tuning仅修改Embedding层不同,PT-V2在所有层都加入参数,将连续前缀添加到句子表征中,在Attention模块的Key和Value向量上实现,从而在不改变模型参数量的前提下提升特定任务的性能。

🚀 **LoRA:低秩适配器实现高效微调**:LoRA(Low-Rank Adaptation)在大模型Transformer的特定层(如Attention模块的Query、Key、Value权重)旁插入低秩矩阵(A和B),仅训练这些低秩矩阵,冻结原模型参数。其核心思想是W + △W = W + BA,其中B和A的秩r远小于原始维度。LoRA能极大减少训练参数量(如3MB),不引入推理延迟,且对模型输入序列长度无限制。

💡 **LoRA超参与进阶优化**:LoRA的秩(r)决定了参数量和表达能力,通常选择4或5。`lora_alpha`作为缩放因子,影响模型对任务的适应速度,过大可能导致过拟合。DyLoRA通过动态调整秩来优化性能。AdapterFusion结合多任务学习和Adapter,通过Attention机制融合不同任务的Adapter知识。AdapterDrop则通过在训练和推理时移除部分Adapter层来降低计算开销和提高推理速度,尤其在多任务场景下效果显著。

📊 **QLoRA:LoRA与量化的结合**:QLoRA进一步提升了微调效率,它将LoRA技术与模型量化相结合。通过在微调过程中对模型参数进行量化,显著减少了显存占用,使得在消费级显卡上也能进行大规模模型的微调。这为在资源受限的环境下进行大模型微调提供了更优的解决方案。

全参数微调

1.显存占用分析:

如果微调一个3B的模型:

前向计算激活值显存占用计算公式:

激活占用显存(全部重计算的激活内存) = 模型层数 * batch_size * seq_len * hidden_size *单参数字节数

比如,24层、batch_size=8、seq_len=1024、hidden_dim=2048:

24 * 8 * 1024 * 2048 * 2(FP16) = 16GB

优化手段:

Prefix-tuning-V2

PT方法是一种针对大模型的soft-prompt方法。是受到语言模型 In-context Learning 的启发:即只要有合适的上下文就可以很好的解决自然语言问题。但是对于特定的任务找到离token需要花费很长时间,PT提出使用连续的 virtual token embedding 来替换离散token。

在训练的时候只更新Predix部分的参数,而 LLM 中其他部分参数固定。

P-Tuning:仅仅对大模型的embedding加入新的参数。

P-Tuning-V2:将大模型的embedding层和每一层都加上新的参数。

具体来说,PT-V2就是对于transformers的每一层,都在句子表征前面插入可训练的 virtual token embedding 。 对于自回归模型(GPT系列),在句子前添加连续前缀,即

。对于Encoder-Decoder模型(T5),则在Ecoder和Decoder前都添加连续前缀,即

添加前缀的过程如上图所示

具体实现:token插入在 attention 模块的Key、Value向量上面。代码层面:

if kv_cache is not None:    cache_k, cache_v = kv_cache    key_layer = torch.cat((cache_k, key_layer), dim=0)    value_layer = torch.cat((cache_v, value_layer), dim=0)if use_cache:    kv_cache = (key_layer, value_layer)else:    kv_cache = None

Self-Attention的公式是:softmax(QKTdk)Vsoftmax(\frac{Q·K^T}{\sqrt{d^k}})·V,将token向量加入到K和V中shape是不变的:

原来的:Q=[m,n],K=[m,n],V=[m,n],计算之后:[m,n]

P-tuning-V2: Q=[m,n], k=[m+k,n], V=[m+k,n],计算之后:[m,n]

LoRA

1.技术原理

在大模型上,对每个Transformer块中插入额外的可训练低秩矩阵,并且可以只对指定层(权重矩阵),比如只对query_key_value权重矩阵。并在训练过程中,冻结预训练模型的权重,仅仅需要训练更新低秩矩阵的参数。当“秩值”远小于原始参数维度时,新增的低秩矩阵参数量也就很小。

训练完成后,我们仅仅会得到一个约3MB大小的权重文件,实现用非常低的成本来微调大模型。

详细一点讲:

LoRA的思想也很简单,再原始Pretrained Weights旁边增加一个旁路,做一个降纬再升纬的操作。训练是固定Pretrained Weights,只训练降纬矩阵A和升纬矩阵B。初始化时,用随机高斯分布初始化A,用0矩阵初始化B。前向计算时,模型的每一层输入和输出纬度保持不变,输出是将Pretrained Weights的输出和BA的输出叠加(相加)

具体的,假设Pretrained Weights的权重矩阵为:W0RdkW_0 \in{\mathbb{R} ^{d * k}},

它的更新过程为:W0+W=W0+BA,BRdr,ARrkW_0 + \bigtriangleup{W} = W_0 + BA, B \in{\mathbb{R} ^{d * r}}, A \in{\mathbb{R} ^{r * k}}, 其中秩 r << min(d,k)。

每一层的输出:h=W0xh = W_0x

它的前向计算为:h=W0x+Wx=W0X+BAx=(W0+BA)xh = W_0 x + \bigtriangleup{W}x = W_0X + BA x = (W_0 + BA) x

也就是可以把左右两部分的参数先相加再去乘以x

这种思想有点类似于残差连接,同时使用这个旁路的更新来模拟full finetuning的过程。

在生产部署时,LoRA可以不引入推理延迟,只需要将Pretrained Weight参数和LoRA参数BA进行合并即可得到微调后的模型参数,即合并后的模型参数为:W=W0+BAW = W_0 + BA,在推理时,微调前是计算:h=W0xh=W_0x,现在是计算h=Wxh=Wx,参数纬度没有改变,因此没有任何额外延迟。同时,不向通过Prefix-tuning微调后的模型,需要固定输入的序列长度,通过LoRA没有这个限制。

2.超参:

  作用:秩决定了LoRA的参数的数量和表达能力。

  选择策略:并不是越大越好,通常4、5即可。

  公式:W0+W=W0+loraalpharBAW_0 + \bigtriangleup{W} = W_0 + \frac{lora_alpha}{r}BA

    作用:用于控制LoRA模块输出的缩放因子。过大的alpha会使LoRA更新幅度更大,意味着模型会更快的适应特定任务,但是可能导致过拟合。过小的alpha会使更新更温和,有助于模型的稳定性和泛化能力,但是需要更多训练步骤。

    选择策略:先选择与r相同的,再看情况调整。

3.执行细节

config = LoraConfig(    task_type=TaskType.CAUSAL_LM,    # 需要训练的模型层的名字,主要就是 attention部分的层    target_modules=["q_proj", "k_proj", "v_proj", "o_proj", "gate_proj", "up_proj", "down_proj"],    inference_mode=False, # 训练模式    r=8, # Lora 秩,就是经过降纬矩阵之后的维度    lora_alpha=32, # Lora alaph,归一化系数    lora_dropout=0.1# Dropout 比例)

FP16+LoRA:显存大概16GB,单卡A100足够。

4.代码实现:

 # Dense result, 原始权重的结果,图1蓝色dense_result = self.matmul(input_tensor, weight)if self.has_bias:    bias = self.cast(self.bias, self.dtype)    dense_result = self.bias_add(dense_result, bias)# LoRA result, LoRA权重的结果,图1橘色input_tensor = self.lora_dropout(input_tensor)input_tensor = self.lora_a_matmul(input_tensor, lora_a)input_tensor = self.lora_b_matmul(input_tensor, lora_b)input_tensor = self.mul(input_tensor, scaling)# 将两部分叠加dense_result = self.add(dense_result, input_tensor)

参考:

    zhuanlan.zhihu.com大模型LoRA微调:寻找合适的lora_rank、lora_alpha

LoRA优化-DyLoRA

DyLoRA通过动态调整低秩适配器的秩,解决了传统LoRA在秩选择和动态调整方面的局限性。

AdapterFusion

此方法是多任务的思路引入到Adapter学习中。为了整合来自多个任务的知识,通常有两种方法,一个是按一定顺序微调,这个问题是需要先验来确定顺序,且模型容易出现“灾难遗忘”现象。二是采用多任务学习(Multi-task learning),但这种方法的问题是不同的任务会相互影响,也难以平衡数据集大小差距很大的任务。

而之前的工作,Adapter Tuning的一个优势就是不用更新预训练模型的参数,而是插入比较少的新的参数就可以很好地学会一个任务。此时,Adapter 的参数某种程度上就表达了解决这个任务需要的知识。

因此,AdapterFusion是想把多任务和Adapter-Tuning结合起来,可以利用多个任务来做大模型的微调。具体的,AdapterFusion分为两个阶段:

在不同任务下引入各自的Adapter模块,用于学习特定任务的信息。在这一阶段有两种训练方式:

    Single-Task Adapters(ST-A):对于N个任务,模型都分别独立进行优化,各个任务之间互不干扰,互不影响。Multi-Task Adapters(MT-A):N个任务通过多任务学习的方式,进行联合优化。

将预训练模型参数与特定任务的Adapter参数固定,引入新的模型参数AdapterFusion来学习组合多个Adapter中的知识。具体实现如下:

AdapterFusion的结构就是一个attention,他的参数包括query,key和value矩阵参数。在transformer的每一层都存在。他的query就是transformer每一层的输出结果key和value是N的任务Adapter的输出。通过AdapterFusion层,模型可以为不同任务对应的Adapter分配不同的权重,聚合N个任务的信息

AdapterDrop

大量预训练的 Transformer 模型的微调计算成本高,推理速度慢,并且具有大量存储要求。最近的方法通过训练较小的模型、动态减小模型大小以及训练轻量级适配器来解决这些缺点。在本文中,我们提出了 AdapterDrop,在训练和推理期间从较低的转换器层中移除适配器,它结合了所有三个方向的概念。论文中表明,当同时对多个任务执行推理时,AdapterDrop 可以动态减少计算开销,而任务性能的降低最小。AdapterDrop进一步修剪来自 AdapterFusion 的适配器,这提高了推理效率,同时完全保持了任务性能。

对Adapter Tuning的改造

下图是比较标准的Adapter和Adapter-Drop的微调过程,左边每一层都包含Adapter模块,右边在第一层drop掉了Adapter(红色方块)。箭头表示模型训练时计算前传和梯度Backward的流转方向:

上面实验表明,从较低的 Transformer 层中删除Adapter可以显著提高多任务设置中的推理速度。 例如,将前五个Transformer层中的Adapter丢弃,在对 8 个任务进行推理时,速度提高了 39%。并且即使有多个丢弃层,AdapterDrop 也能保持良好的结果。

对AdapterFusion的改造

下图是标准的AdapterFusion和采用AdapterFusion-Drop的微调过程,AdapterFusion是与多任务的思路结合起来,每个任务采用一个Adapter。图中左边图是标准的AdapterFusion,采用三个adapter(红色、蓝色、黄色格子),右边是AdapterFusion-Drop,在每一层中随机的drop一些adapter。

上面实验表明,可以移除 AdapterFusion 中的大多数Adapter而不影响任务性能。使用剩余的两个Adapter,实现了与具有八个Adapter的完整 AdapterFusion 模型相当的结果,并将推理速度提高了 68%。


因此,作者建议在实际部署这些模型之前执行 AdaperFusion-Drop。 这是一种简单而有效的技术,即使在完全保持性能的情况下也能实现效率提升。总之,AdapterDrop 通过从较低的 Transformer 层删除可变数量的Adaper来提升推理速度。 当对多个任务执行推理时,动态地减少了运行时的计算开销,并在很大程度上保持了任务性能。

QLoRA

LoRA+量化

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

大模型微调 LoRA Prefix-tuning Adapter QLoRA
相关文章