大模型理论基础初步学习笔记——第七章 大模型之Adaptation

大模型理论基础初步学习笔记——第七章 大模型之Adaptation

  • 第7章 大模型之Adaptation
    • 7.1 引言
      • 7.1.1 为什么需要Adaptation?
      • 7.1.2 通用的adaptation配置
        • 交叉熵损失:
    • 7.2 当前主流的几种Adaptation方法
      • 7.2.1 Probing
        • 7.2.1.0 探针概念
        • 7.2.1.1 Probing方法的引入
        • 7.2.1.2 Probing的适用性和适配
        • 7.2.1.3 固定长度表示的策略
        • 7.2.1.4 总结
      • 7.2.2 Fine-tuning
        • 7.2.2.0 微调概念
        • 7.2.2.1 Fine-tuning对于zero-shot能力
        • 7.2.2.2 用于人类对齐语言模型的Fine-tuning
        • 7.2.2.3 微调的过程和影响
        • 7.2.2.4 总结
      • 7.2.3 Lightweight Fine-tuning
        • 7.2.3.0 轻量级微调概念
        • 7.2.3.1 轻量级微调的变体
        • 7.2.3.2 Prompt Tuning
        • 7.2.3.3 Prefix Tuning
        • 7.2.3.3 Adapter Tuning
        • 7.2.3.4 Lightweight Fine-tuning的其他性质
        • 7.2.3.5 总结
    • 7.3 总体总结
    • 参考:

第7章 大模型之Adaptation

本文GitHub地址https://github.com/panda-like-bamboo/Study-CS324

7.1 引言

7.1.1 为什么需要Adaptation?

  1. 语言模型的训练方式

    • 语言模型,如GPT-3,通常是 “任务不可知” 的,也就是说,它们在训练时没有特定的下游任务目标。相反,它们被设计为能够在多个不同任务上运行,捕捉语言的通用特性和结构。
    • 这种"任务不可知"的方法带来了灵活性和广泛适用性的优点,因为同一个模型可以用于多种应用。
  2. 挑战与优势

    • 优势:模型的广泛适用性使其可以应用于各种任务,而不需要针对每个任务进行特定调整或训练。
    • 挑战:不同下游任务与语言模型的预训练方式可能差异巨大,导致性能下降。通用模型在某些特定任务上可能不如专门为该任务训练的模型表现出色。
  3. 例子分析

  • Premise: I have never seen an apple that is not red.
  • Hypothesis: I have never seen an apple.
  • Correct output: Not entailment (the reverse direction would be entailment)

这个例子是一个自然语言推理(NLI)任务的样本,其中包括前提(Premise)和假设(Hypothesis)。在这个任务中,模型的目标是判断给定的前提和假设之间是否存在蕴涵(entailment)关系。

  • 前提(Premise):我从未见过非红色的苹果。
  • 假设(Hypothesis):我从未见过苹果。
  • 正确输出:不是蕴涵(Not entailment)

分析:

  • 3.1. 前提中的信息:前提表达了一个条件,即作者从未见过非红色的苹果。这暗示了作者已经见过红色的苹果。
  • 3.2. 假设中的信息:假设是作者从未见过苹果,但由于前提提到已经见过红色的苹果,所以假设与前提存在矛盾。
  • 3.3. 正确输出解释:由于前提和假设之间存在矛盾,因此正确的输出是不是蕴涵(Not entailment)。即,从前提无法得出假设的真实性。

总体而言,这个例子强调了在自然语言推理任务中,模型需要理解前提和假设之间的逻辑关系,以正确判断它们之间是否存在蕴涵关系。

  • 模型在训练时可能没有接触到这种特定的格式,因此这样的任务可能远离其训练范围。
  • 例子强调了在一些下游任务上,模型可能面临性能挑战,因为它们的数据格式和任务要求可能与模型的训练方式不太匹配。
  1. 引出问题
    即如何将"任务不可知"的模型适应于特定任务的需求,以实现最佳性能。这涉及到如何调整模型引入额外的训练,以使其适应不同的应用场景。

7.1.2 通用的adaptation配置

下面提供使用预训练语言模型(LM)的参数来适配(adapt)下游任务的一般设置。下面我将这个过程分为相关且逐渐递进的各个部分:

  1. 预训练语言模型(Pre-trained LM):
    在适配阶段的开始,我们已经有了一个预训练的语言模型,用参数 θ L M θLM θLM表示。这个模型被训练来理解和生成语言,但不是特别针对任何特定任务。

  2. 下游任务数据集(Downstream Task Dataset):
    我们获得了一组来自下游任务分布 P t a s k P_{task} Ptask的样本数据。这些数据可以是文本分类、情感分析等任务的特定实例,每个样本由输入x和目标输出y组成,如: ( x ( 1 ) , y ( 1 ) ) , … , ( x ( n ) , y ( n ) ) \left(x^{(1)}, y^{(1)}\right), \ldots,\left(x^{(n)}, y^{(n)}\right) (x(1),y(1)),,(x(n),y(n))

  3. 适配参数(Adaptation Parameters):
    为了使预训练的LM适合特定的下游任务,我们需要找到一组参数 γ \gamma γ,这组参数可以来自现有参数的子集或引入的新的参数, Γ \Gamma Γ。这些参数将用于调整模型,以便它在特定任务上的表现更好。

  4. 任务损失函数(Task Loss Function):
    我们需要定义一个损失函数 ℓ task  \ell_{\text {task }} task 来衡量模型在下游任务上的表现。例如,交叉熵损失是一种常见的选择,用于衡量模型预测的概率分布与真实分布之间的差异。

  5. 优化问题(Optimization Problem):
    我们的目标是找到一组适配参数 γ adapt  \gamma_{\text {adapt }} γadapt ,使得任务损失在整个下游数据集上最小化。数学上,这可以通过以下优化问题表示:
    γ adapt  = argmin ⁡ γ ∈ Γ 1 n ∑ i = 1 n ℓ task  ( γ , θ L M , x i , y i ) . \gamma_{\text {adapt }}=\operatorname{argmin}_{\gamma \in \Gamma} \frac{1}{n} \sum_{i=1}^n \ell_{\text {task }}\left(\gamma, \theta_{\mathrm{LM}}, x_i, y_i\right) . γadapt =argminγΓn1i=1ntask (γ,θLM,xi,yi).

公式注释:

  • 目标:找到一组适配参数 γ(gamma),使得在整个下游数据集上执行某个任务的平均损失最小化。

  • 符号说明:

    • γ:适配参数的集合。
    • Γ:所有可能的适配参数的集合。
    • ℓ_task(γ, θ_LM, x_i, y_i):表示在任务上的损失函数,它取决于适配参数 γ、语言模型参数 θ_LM、输入数据 x_i 和相应的标签 y_i。
    • i:数据集中的索引,表示第i个样本。
    • n:数据集中样本的数量。
    • Σ:表示求和。
    • argmin:表示使得后面的表达式最小化的参数。
  • 公式表示:

    • ( \gamma_{\text{adapt}} = \arg\min_{\gamma \in \Gamma} \frac{1}{n} \sum_{i=1}^n \ell_{\text{task}}(\gamma, \theta_{\mathrm{LM}}, x_i, y_i) )。
    • 其中,( \gamma_{\text{adapt}} ) 是最小化平均损失的适配参数,( \arg\min ) 表示对适配参数进行优化,γ ∈ Γ 表示适配参数取自所有可能的适配参数的集合。
    • ( \frac{1}{n} \sum_{i=1}^n ) 表示对整个下游数据集上的每个样本损失进行求平均,( \ell_{\text{task}}(\gamma, \theta_{\mathrm{LM}}, x_i, y_i) ) 表示每个样本在任务上的损失。

这个公式的目标是找到适配参数的最优组合,以最小化整个下游数据集上任务的平均损失。

通过这个过程,我们可以取得一组适配参数 γ adapt  \gamma_{\text {adapt }} γadapt ,用于参数化适配后的模型 p a d a p t p_{adapt} padapt。这样,我们就可以将通用的、任务无关的预训练语言模型适配到特定的下游任务上,以实现更好的性能。这种适配方法将模型的通用性与特定任务的效能结合在一起,既保留了模型的灵活性,又确保了在特定任务上的高效表现。

交叉熵损失:

交叉熵损失(Cross-Entropy Loss)通常用于衡量两个概率分布之间的差异性,常用于分类问题中的损失函数。在深度学习中,交叉熵损失经常用于衡量模型输出的概率分布与真实标签之间的差异。

假设有一个分类问题,每个样本有多个类别,交叉熵损失的一般形式可以表示为:

[
\ell_{\text{CE}}(p,q) = -\sum_{i} p_i \log(q_i)
]

其中:

  • (p) 是真实的概率分布,通常表示为一个one-hot编码的向量,其中真实类别对应的元素为1,其他元素为0。
  • (q) 是模型的预测概率分布,通常表示为一个softmax函数的输出,表示每个类别的概率。
  • (p_i) 和 (q_i) 分别表示真实标签和模型预测值中第 (i) 个类别的概率。

在实际应用中,交叉熵损失可用于训练分类模型,通过最小化损失来调整模型参数,使得模型的输出更接近真实标签的分布。

7.2 当前主流的几种Adaptation方法

7.2.1 Probing

Probing(探针)策略是一种在大规模预训练阶段广泛使用的微调策略。以下是Probing方法的引入及其应用,以及固定长度表示的策略的讨论。

7.2.1.0 探针概念

在自然语言处理(NLP)领域,探针通常指的是一种用于检查和理解预训练语言模型内部知识表示的技术。预训练语言模型,如BERT(Bidirectional Encoder Representations from Transformers)或GPT(Generative Pre-trained Transformer),在大规模语料库上进行预训练,学到了丰富的语言知识。为了深入了解这些模型学到的内容,研究人员使用探针任务,这些任务通常是简单的监督学习任务,通过模型内部表示来解决。

下面是探针在NLP中的一般过程:

  1. 选择探针任务: 为了了解模型在特定语言方面的知识,研究人员选择一个特定的任务,例如语法分析、情感分析、语义角色标注等。这个任务通常是监督学习任务,有已标注的数据集可用。

  2. 冻结预训练模型: 预训练的语言模型被冻结,不再更新。这样,模型在探针任务上的学习主要通过微调来实现。

  3. 微调探针任务: 使用探针任务的标注数据,对冻结的预训练模型进行微调。微调过程中,模型学习适应特定任务的特征,但并不改变其在大规模预训练语料上学到的通用知识。

  4. 分析结果: 完成微调后,研究人员分析模型在探针任务上的性能。通过观察模型在这个任务上的表现,研究人员可以推断出模型对于特定语言特性的理解程度,以及模型在学习过程中保留了哪些知识。

通过使用探针技术,研究人员能够更详细地了解预训练语言模型的内部表示,揭示模型在处理语言任务时的认知能力和语言知识。这有助于我们理解模型的强弱之处,进一步优化模型或提出改进的训练方法。

7.2.1.1 Probing方法的引入

Probing是一种用于分析和理解模型内部表示的技术,通过引入一个新的参数集 Γ \Gamma Γ,定义了线性或浅前馈网络的Probing。例如,通过预测词性标注(POS)来检查表示是否包含POS信息。

7.2.1.2 Probing的适用性和适配

Probing适用于仅编码器模型,例如BERT,但也可用于解码器模型。对于Adaptation,可以从语言模型(LM)的最后一层表示中训练一个Probing到输出.

7.2.1.3 固定长度表示的策略

Probing方法通过线性或浅前馈网络学习预训练模型的输出,分析和理解模型表示。固定长度表示的策略包括CLS token策略和平均化token策略,为适应任务提供了有效的解决方案。

7.2.1.4 总结

Probing作为分析工具,通过冻结语言模型表示编码器和优化特定任务的探针来工作。固定长度表示的策略进一步促进了这一目的,提供了灵活而有效的解决方案。

7.2.2 Fine-tuning

Fine-tuning使用语言模型参数 θ L M θLM θLM作为初始化,并在微调过程中更新语言模型参数和任务特定的预测头参数。下面是微调对于zero-shot能力、人类对齐语言模型以及零样本性能的影响进行了讨论。

7.2.2.0 微调概念

“Fine-tuning”(微调)是指在一个已经经过预训练的模型基础上,通过在特定任务上进行进一步的训练,使其适应特定任务或领域的过程。微调的目的是将预训练模型的泛化能力应用于具体任务,从而提高模型在任务上的性能。

以下是微调的一般步骤:

  1. 预训练模型: 通常,微调开始于一个在大规模语料库上进行了预训练的模型。这个预训练可以是在自然语言处理(NLP)任务中,如语言建模、文本生成、或其他相关任务中进行的。

  2. 选择任务: 确定要在预训练模型上执行微调的具体任务。这可以是分类、命名实体识别、情感分析等各种自然语言处理任务。

  3. 准备数据: 收集并准备用于微调的标注数据。这些数据包含了模型在任务上需要学习的样本。对于监督学习任务,数据通常包括输入和相应的标签。

  4. 调整模型结构: 在某些情况下,可能需要微调模型的结构,以适应特定任务的要求。这可能包括添加、修改或删除某些层次或组件。

  5. 微调过程: 使用任务相关的标注数据,对预训练模型进行进一步的训练。在这个微调阶段,模型的权重将根据任务特定的数据进行调整,以使其更好地适应目标任务。

  6. 评估性能: 完成微调后,通过使用验证集或其他评估数据集来评估模型在目标任务上的性能。这有助于确定微调是否成功,并且模型是否达到了预期的性能水平。

微调的优势在于能够在相对较小的标注数据集上获得良好的性能,因为模型已经在大规模的通用数据上学到了许多有用的特征。微调是迁移学习的一种形式,通过利用预训练模型的知识,可以在特定任务上实现更好的泛化性能。

7.2.2.1 Fine-tuning对于zero-shot能力

ero-shot learning(零样本学习)是一种机器学习范式,在训练阶段没有见过的任务或类别上进行泛化的能力。它允许模型在没有任何具体示例的情况下解释和处理全新的信息。这个能力对于许多实际应用至关重要,特别是当新任务或类别的样本难以获得时。

零样本学习的能力使得模型具有更高的灵活性和泛化能力,能够在未见过的任务上迅速适应。这在现实世界中极为重要,因为我们常常会遇到一些新的、未在训练数据中出现过的任务或情境。零样本学习模型可以迅速解决这些问题,而无需每次都进行繁琐的重新训练。

7.2.2.2 用于人类对齐语言模型的Fine-tuning

微调在人类对齐语言模型中发挥关键作用,通过收集人类示例和使用强化学习目标微调,可以使模型更好地理解和满足人类需求。

7.2.2.3 微调的过程和影响

微调的过程包括收集人类书写的示范行为基于指令的采样与人类偏好以及使用强化学习目标微调。微调可以显著提高模型在特定任务和场景下的性能,但需要关注偏见和虚构信息等问题。

7.2.2.4 总结

微调是强大的工具,可以使预训练的语言模型更好地符合人类期望和需求。虽然存在挑战和限制,如偏见和虚构信息的产生,但微调仍然是现代机器学习中的重要工具。

7.2.3 Lightweight Fine-tuning

轻量级微调(Lightweight Fine-Tuning)是一种特殊的微调技术,旨在结合全面微调的表现力和更节省资源的优点。轻量级微调试图在不需要为每个任务存储完整语言模型的同时,保持与全面微调相同的表现力。换句话说,它希望在减小模型存储需求和计算负担的同时,仍然实现出色的性能。

7.2.3.0 轻量级微调概念

轻量级微调是微调(Fine-tuning)的一种变体,它注重在具有较小标注数据集的情况下对预训练模型进行调整。在轻量级微调中,主要考虑到数据稀缺或有限的情况,通常涉及一些策略以防止模型在小规模数据上过拟合。以下是轻量级微调的一些关键特点和步骤:

  1. 小规模数据集: 轻量级微调通常应用于只有少量标注数据的情况,这可能是因为特定任务的数据成本较高,或者是由于某些领域的特殊性导致标注数据的有限性。

  2. 特征提取: 轻量级微调可能会侧重于仅微调模型的顶层或几个顶层,而不是对整个模型进行全面的微调。这个过程有时被称为特征提取,因为底层的预训练特征在大多数情况下是通用的,而任务特定的信息主要集中在模型的上层。

  3. 冻结底层: 在轻量级微调中,可以选择冻结底层的模型参数,使其在微调过程中不再更新。这有助于保留预训练模型在通用任务上学到的知识,减少在小规模数据集上的过拟合风险。

  4. 使用预训练模型的学习率: 为了避免在微调过程中引入大量噪声,可以选择使用相对较小的学习率。这意味着对于底层的预训练模型,保留其在大规模数据上学到的权重,而对上层使用较小的学习率以更好地适应任务特定的信息。

  5. 数据增强: 数据增强是一种常见的策略,特别在数据有限的情况下。通过对训练数据进行轻微的变换,例如旋转、翻转或缩放,可以生成更多的训练样本,有助于提高模型的泛化性能。

  6. 早停策略: 为了防止在小规模数据上过拟合,可以使用早停(early stopping)策略。这意味着在验证性能不再提高时停止微调,以避免在训练集上的过度拟合。

轻量级微调是在资源有限或标注数据受限的情况下,有效利用预训练模型的一种策略。通过这种方式,可以在小规模数据上实现相对较好的性能,同时最大限度地减少对大量标注数据的需求。

让我们更加具体地讨论轻量级微调,并使用一个自然语言处理(NLP)的示例来说明。

场景: 假设我们有一个预训练的语言模型(例如,BERT或GPT),我们想要将其应用于一个特定的任务,如情感分析,但是我们只有很小规模的情感标注数据。

具体步骤:

  1. 选择任务和数据: 我们选择情感分析作为我们的任务,并且只有一个包含有限标注数据的小型数据集,其中包含一些句子和对应的情感标签(例如,正面或负面)。

  2. 加载预训练模型: 我们加载预训练的语言模型,例如BERT。这个模型在大规模语料库上进行了预训练,已经学到了语言的一般特征。

  3. 冻结底层: 我们选择冻结预训练模型的底层(例如,冻结BERT的前几个层),以防止在微调过程中过度调整通用特征。这有助于防止在小规模数据上出现过拟合。

  4. 定义顶层任务: 我们添加一个新的顶层(输出层)来适应我们的情感分析任务。这一层将根据我们的情感标签进行训练,连接到预训练模型的输出。

  5. 微调顶层: 我们只微调我们新添加的顶层,而不对整个模型进行全面的微调。通过使用较小的学习率,我们保留底层模型在大规模数据上学到的通用知识。

  6. 数据增强: 由于我们的标注数据很有限,我们可以应用数据增强技术,如对句子进行轻微的扰动、替换或翻转,以生成更多的训练样本。

  7. 早停策略: 我们使用早停策略来监控验证集上的性能。如果性能不再提高,我们停止微调,以防止在小规模数据上过拟合。

示例代码(使用Python和PyTorch):

# 加载预训练模型
pretrained_model = BertModel.from_pretrained('bert-base-uncased')

# 冻结底层
for param in pretrained_model.parameters():
    param.requires_grad = False

# 添加新的情感分析顶层
num_labels = 2  # 正面和负面
emotion_classifier = nn.Sequential(
    nn.Linear(pretrained_model.config.hidden_size, 512),
    nn.ReLU(),
    nn.Dropout(0.2),
    nn.Linear(512, num_labels)
)

# 定义模型
model = nn.Sequential(pretrained_model, emotion_classifier)

# 定义优化器和损失函数
optimizer = optim.Adam(emotion_classifier.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

# 进行微调
for epoch in range(num_epochs):
    for inputs, labels in dataloader:
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

    # 在验证集上评估性能,使用早停策略

    # 如果性能不再提高,停止微调
    if performance_not_improving():
        break

这个示例演示了轻量级微调的基本步骤,其中重点是冻结底层、添加任务特定顶层、微调顶层、使用数据增强和早停策略。这样的策略可以帮助在小规模数据上有效地使用预训练模型,并取得良好的性能。

7.2.3.1 轻量级微调的变体

轻量级微调有许多变体,其中一些主要的方法包括:

  1. 提示调整(Prompt Tuning):通过微调模型的输入prompt提示来优化模型的表现。提示调整可以被视为一种更灵活的微调方法,允许用户通过调整输入提示来导向模型的输出,而不是直接修改模型参数。
  2. 前缀调整(Prefix Tuning):与提示调整类似,前缀调整也集中在输入部分。它通过添加特定前缀来调整模型的行为,从而对特定任务进行定制。
  3. 适配器调整(Adapter Tuning):适配器调整是通过在模型的隐藏层之间插入可训练的“适配器”模块来微调模型的一种方法。这些适配器模块允许模型在不改变原始预训练参数的情况下进行微调,从而降低了存储和计算的需求。
7.2.3.2 Prompt Tuning

提示调整,主要应用于文本分类任务。与传统微调方法不同,Prompt Tuning侧重于优化输入提示而不是改变模型的内部参数。以下是主要观点的总结:

  1. Prompt Tuning的核心思想: Prompt Tuning通过在输入前添加可学习的、连续的标记嵌入,这些嵌入定义为 Γ,来进行工作。这些额外的标记嵌入通过在带标签的任务数据上进行训练来学习,从而优化输入提示。

  2. 输入长度的改变: 添加了k个标记嵌入后,新的输入长度为 L’ = L + k,其中L是原始输入的长度。这些额外的标记嵌入的学习是在带标签的任务数据上进行的。

  3. 冻结预训练语言模型: 整个预训练的语言模型在Prompt Tuning过程中被冻结,使模型的主体部分不会在微调中发生改变。这突显了通过调整输入提示而不改变预训练参数,可以获得竞争性能。

  4. 性能与冻结规模的关系: 随着冻结语言模型规模的增加,Prompt Tuning的性能越来越有竞争力,可以与全面微调(模型调整)相媲美。这表明即使在不改变预训练参数的情况下,通过调整输入提示可以实现出色的性能。

  5. 初始化策略: 提示调整涉及不同的初始化策略,包括随机词汇词嵌入、类标签词嵌入以及随机初始化。提示调整的第二个版本(Prompt tuning v2)是全层版本,对文本分类和生成任务都有助益。

  6. 轻量级微调的创新方法: 总体而言,Prompt Tuning是一种创新的轻量级微调方法,通过在输入上添加可学习的嵌入而不是改变整个模型的结构来实现任务特定的优化。这不仅减少了计算和存储需求,还允许使用较大的冻结模型来实现与全面微调相当的性能。在文本分类等任务中,Prompt Tuning提供了一种灵活和高效的解决方案。

7.2.3.3 Prefix Tuning

以下是对文中7.2.3.3节关于"Prefix Tuning"(前缀调整)的详细解释:

1. Prefix Tuning简介:

  • 适用任务: Prefix Tuning是一种专为语言生成任务设计的微调方法,已经在BART和GPT-2等模型上进行了开发。
  • 目标: Prefix Tuning的目标是通过在输入的起始位置添加k个位置,并在每个注意力层连接额外的可学习权重,实现对模型进行微调。这些额外的权重作为键(keys)和值(values)在微调过程中允许模型学习特定任务的上下文和结构。

2. 区别于Prompt Tuning的关键特征:

  • 输入修改方式: 与Prompt Tuning不同,Prefix Tuning不仅仅添加可学习的输入,还在每个注意力层中添加可学习的权重。这些额外的权重有助于更好地捕获任务特定的依赖关系和上下文信息。

3. 注意力操作的定义:

  • 广义注意力操作: Prefix Tuning使用了一个广义的注意力操作,接收三个参数:键( K K K)、值( V V V)和查询( Q Q Q)。
  • 维度定义: 这三个参数分别具有维度 R d × L ′ ℝ^{d×L^′} Rd×L R d × L ′ ℝ^{d×L^′} Rd×L R d × L ℝ^{d×L} Rd×L
  • 定义公式: 注意力操作定义为 Attn-op ( Q , K , V ) = V softmax ( K T Q d ) \text{Attn-op}(Q,K,V) = V \text{softmax}\left(\frac{K^TQ}{\sqrt{d}}\right) Attn-op(Q,K,V)=Vsoftmax(d KTQ)

4. 对自注意力头的定义:

  • 初始化参数: 对于自注意力,设置 L ′ L^{'} L = L L L,并定义 K K K = W key x 1 : L W_{\text{key}}x_{1:L} Wkeyx1:L V V V = W value x 1 : L W_{\text{value}}x_{1:L} Wvaluex1:L Q Q Q = W query x 1 : L W_{\text{query}}x_{1:L} Wqueryx1:L,其中 W key W_{\text{key}} Wkey, W value W_{\text{value}} Wvalue, W query W_{\text{query}} Wquery是学习到的权重矩阵。
  • 头部计算: 对于注意力头 i i i,通过将可学习的权重 P ( i ) key P(i)_{\text{key}} P(i)key, P ( i ) value ∈ R d × k P(i)_{\text{value}} \in \mathbb{R}^{d \times k} P(i)valueRd×k与键和值连接,计算具有较大的 L ′ = L + k L' = L + k L=L+k的注意力。计算公式为 K prefix = [ P ( i ) key , K ] K_{\text{prefix}} = [P(i)_{\text{key}}, K] Kprefix=[P(i)key,K] V prefix = [ P ( i ) value , V ] V_{\text{prefix}} = [P(i)_{\text{value}}, V] Vprefix=[P(i)value,V]

5. 参数学习与模型性能:

  • 参数增强模型性能: 所有层级的可训练参数可以增强模型的性能,允许模型在更细粒度上进行优化。

6. 总结:

  • 微调手段: Prefix Tuning通过在注意力机制的键和值部分添加可学习的权重为模型提供了一种强大的微调手段。
  • 特定任务优化: 这种方法允许模型更好地捕捉任务特定的模式,并与Prompt Tuning等其他技术相辅相成,提供了一种灵活和强大的任务特定优化手段。
7.2.3.3 Adapter Tuning

1. Adapter Tuning简介:

  • 微调技术: Adapter Tuning是一种微调技术,其主要思想是在每个(冻结的)Transformer层之间添加新的学习“bottleneck”层,这个新层称为适配器(Adapter)。

2. 适配器的计算方式:

  • 残差网络结构: 适配器通常是操作于序列中每个元素 x ∈ R d x \in \mathbb{R}^d xRd的2层残差网络。
  • 计算公式: 适配器的计算定义为 Adapter ( x ) = x + W up σ ( W down x ) \text{Adapter}(x) = x + W_{\text{up}}\sigma(W_{\text{down}}x) Adapter(x)=x+Wupσ(Wdownx)
  • 投影操作: W down ∈ R r × d W_{\text{down}} \in \mathbb{R}^{r \times d} WdownRr×d W up ∈ R d × r W_{\text{up}} \in \mathbb{R}^{d \times r} WupRd×r是学习到的权重,它们分别将 x x x投影到一个瓶颈维度 r r r,然后再投影回维度 d d d
  • 激活函数: σ \sigma σ表示一个非线性激活函数。

更详细地解释一下适配器的计算方法:

适配器的计算过程由以下公式定义:
$ \text{Adapter}(x) = x + W_{\text{up}}\sigma(W_{\text{down}}x) $

其中, x x x 是输入向量, W down W_{\text{down}} Wdown W up W_{\text{up}} Wup 是学习到的权重矩阵, σ \sigma σ 是非线性激活函数。这个公式可以分为几个步骤:

  1. 投影到瓶颈维度:

    • 通过矩阵 W down W_{\text{down}} Wdown,将输入向量 x x x 投影到一个瓶颈维度 r r r。这是一个线性投影操作,表达式为 W down x W_{\text{down}}x Wdownx
  2. 非线性激活:

    • 对投影结果应用非线性激活函数 σ \sigma σ。这通常是一个常见的激活函数,如sigmoid或ReLU。
  3. 再投影回原维度:

    • 将激活后的结果通过矩阵 W up W_{\text{up}} Wup 再投影回原始维度 d d d。这同样是一个线性投影操作,表达式为 W up σ ( W down x ) W_{\text{up}}\sigma(W_{\text{down}}x) Wupσ(Wdownx)
  4. 与原始输入相加:

    • 将上述结果与原始输入向量 x x x 相加,得到最终的适配器输出 Adapter ( x ) \text{Adapter}(x) Adapter(x)。这是一个元素级别的相加操作。

总的来说,适配器通过引入可学习的权重矩阵,在每个输入向量上执行两次线性投影,并使用非线性激活函数进行非线性变换,最终得到一个适应性更强的输出。这允许模型在每个 Transformer 层之间引入微小的调整,以适应特定任务的需求,而不必对整个模型进行大规模的调整。

3. 整体效果和灵活性:

  • 效果描述: 适配器调整的结果 Adapter ( x ) \text{Adapter}(x) Adapter(x)是一个在 R d \mathbb{R}^d Rd中与 x x x具有相同维度的向量。
  • 模型调整: 这种方法允许在不改变原始Transformer层的情况下,通过引入新的可学习层来调整模型。
  • 与其他技术结合使用: 这种方法可以与提示调整和前缀调整等技术结合使用,提供了一种高效、可扩展的解决方案。

4. 适配器设计的优势:

  • 不改变整体结构: 适配器的设计使其可以在不牺牲整体模型结构的情况下,增强特定任务的性能。
  • 任务特定优化: 通过在每个层之间添加适配器,可以实现对特定任务的微调和优化。

5. 在自然语言处理中的应用:

  • 任务解决方案: 适配器调整与其他技术相结合,为自然语言处理任务提供了一种高效、可扩展的解决方案。

总的来说,Adapter Tuning是一种强大的微调方法,通过在Transformer层之间引入适配器层,为模型提供了灵活性,使其能够在不改变整体结构的情况下进行任务特定的优化。

7.2.3.4 Lightweight Fine-tuning的其他性质

1. 表达能力的复杂性:

  • Lightweight Fine-tuning的表达能力相当复杂,因为它与特定的预训练语言模型(LM)密切相关。如果预训练LM的权重为0,那么Prompt/Prefix Tuning将不会产生作用。这表明Fine-tuning的有效性与底层预训练模型的参数密切相关。

2. 个性化模型的实现方法:

  • 通过Prompt/Prefix/Adapter Tuning等方法,可以实现个性化模型的部署。例如,对于N个用户,可以使用Prefix Tuning存储N个前缀,每个用户一个。然后,在一个小批量内,通过在每个输入之前附加相应的用户特定前缀,可以并行运行每个用户的个性化模型。这种方法实现了用户特定的调整,同时有效地利用了并行处理的能力。

3. 方法的鲁棒性提升:

  • Lightweight Fine-tuning方法的鲁棒性得到了提升,它们倾向于在与全面微调相比,改善分布外(out-of-distribution,OOD)的性能。例如,Prompt Tuning方法在OOD情况下的性能提高了,特别是在不同主题或领域的文本上的任务中表现更好。这说明这些轻量级微调方法在处理未见过的数据时更为鲁棒。

4. Prefix Tuning提高领域外准确性:

  • Prefix Tuning在领域外(OOD)的任务中有助于提高模型的准确性。例如,在XSUM摘要任务中,通过在新闻文章上进行微调,并在体育或在{世界,英国,商业}文章上进行训练,然后在{健康,科技}文章上进行测试,可以提高模型在领域外数据上的性能。评估指标为ROUGE-L,用于衡量生成的摘要与参考摘要的匹配程度。
7.2.3.5 总结
  • 冻结(灰色):整个/大部分语言模型
  • 优化(蓝色,根据任务变化):少量额外参数(参数的<1%)
  • 方法:提示调整、前缀调整、适配器调整,以及其他方法(LoRA,BitFit等)

7.3 总体总结

我们需要将大型语言模型适配到各种不同的下游任务中,这些任务可能与语言建模有很大不同。

  1. 探测法(Probing):探测法在冻结的语言模型之上训练一个特定任务的预测头,将语言模型视为良好的表示提取器。冻结语言模型倾向于限制该方法的表现能力。
  2. 微调(Fine-tuning):微调将大型语言模型参数视为下游任务的进一步训练的初始化,这比探测更具表现力,但也更昂贵,因为我们必须为每个下游任务保存整个模型。
  3. 轻量级微调(Lightweight fine-tuning):轻量级微调在微调和探测之间取得了平衡,只优化少量参数(模型的<1%),但它优化了模型的高杠杆部分,因此仍然非常具有表现力。
    通过上述方法,可以更灵活地应对各种不同的下游任务,既实现了对特定任务的精确适配,又在一定程度上控制了计算和存储的成本,从而在实际应用中取得更好的性能和效率。

参考:

[1]datawhale讲义: https://github.com/datawhalechina/so-large-lm
[2]CS324: https://stanford-cs324.github.io/winter2022/lectures/
[3]Designing and Interpreting Probes with Control Tasks
[4]Prompt Tuning
[5]Prompt tuning v2
[6]Prefix Tuning
[7]Adapter Tuning
[8]Prompt Tuning方法提高了OOD的准确性
[9]LoRA
[10]BitFit

你可能感兴趣的:(学习,笔记,自然语言处理,语言模型,人工智能)