您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
业务架构设计
4月18-19日 在线直播
基于UML和EA进行系统分析设计
4月25-26日 北京+在线
AI 智能化软件测试方法与实践
5月23-24日 上海+在线
     
   
 
 订阅
大模型核心技术综述:微调、推理与优化指南
 
作者:柏企
  164  次浏览      28 次
 2025-4-7
 
编辑推荐:
本文探索了检索增强生成(RAG)应用中的文本生成部分,重点介绍了大语言模型(LLM)的使用。希望对你的学习有帮助。
本文来自于微信公众号柏企阅文 ,由火龙果软件Linda编辑,推荐。

1. 什么是大语言模型?

大语言模型(LLM)是非常庞大的深度学习模型,它们在大量数据上进行预训练。其底层的Transformer是一组神经网络,由具有自注意力能力的编码器和解码器组成。编码器和解码器从文本序列中提取含义,并理解其中单词和短语之间的关系。

Transformer神经网络架构允许使用非常大的模型,这些模型通常包含数千亿个参数。如此大规模的模型可以摄取大量数据,这些数据通常来自互联网,也可以来自如包含超过500亿个网页的Common Crawl,以及约有5700万页面的维基百科等来源。

2. 语言建模(LM)

语言和交流的过程可以简化为计算吗?

语言模型通过从一个或多个文本语料库中学习来生成概率。文本语料库是一种语言资源,由一种或多种语言的大量结构化文本组成。文本语料库可以包含一种或多种语言的文本,并且通常带有注释。

语言模型可以根据其在训练过程中学习到的统计模式,预测最可能跟随某个短语的单词(或多个单词)。在图中,语言模型可能会估计“天空的颜色是”这个短语后面跟着“蓝色”一词的概率为91%。

构建语言模型的最早方法之一是基于n - gram。n - gram是从给定文本样本中连续的n个项目组成的序列。在这里,模型假设序列中下一个单词的概率仅取决于前面固定数量的单词:

其中, wi表示单词, k是窗口大小。

然而,n - gram语言模型在很大程度上已被神经语言模型所取代。神经语言模型基于神经网络,这是一种受生物神经网络启发的计算系统。这些模型利用单词的连续表示或嵌入来进行预测:

神经网络将单词表示为权重的非线性组合。因此,它可以避免语言建模中的维度灾难问题。已经有几种神经网络架构被提出用于语言建模。

3. 基础模型和大语言模型

这与自然语言处理(NLP)应用程序早期的方法有很大不同,早期是训练专门的语言模型来执行特定任务。相反,研究人员在大语言模型中观察到了许多涌现能力,这些能力是模型从未接受过训练的。

例如,大语言模型已被证明能够执行多步算术运算、解乱序单词的字母,以及识别口语中的冒犯性内容。最近,基于OpenAPI的GPT系列大语言模型构建的流行聊天机器人ChatGPT,通过了美国医学执照考试等专业考试。

基础模型通常是指在广泛数据上进行训练的任何模型,它可以适应各种下游任务。这些模型通常使用深度神经网络创建,并使用自监督学习在大量未标记数据上进行训练。

在训练过程中,从语料库中提取文本序列并进行截断。语言模型计算缺失单词的概率,然后通过基于梯度下降的优化机制对这些概率进行微调,并反馈给模型以匹配真实情况。这个过程在整个文本语料库上重复进行。

尽管如此,大语言模型通常在与语言相关的数据(如文本)上进行训练。而基础模型通常在多模态数据(文本、图像、音频等的混合)上进行训练。更重要的是,基础模型旨在作为更特定任务的基础或基石:

基础模型通常通过进一步训练进行微调,以完成各种下游认知任务。微调是指采用预训练的语言模型,并使用特定数据针对不同但相关的任务进行训练的过程。这个过程也被称为迁移学习。

4. 大语言模型的架构

早期的大语言模型大多是使用带有长短期记忆网络(LSTM)和门控循环单元(GRU)的循环神经网络(RNN)模型创建的。然而,它们面临挑战,主要是在大规模执行NLP任务方面。但这正是大语言模型预期要发挥作用的领域。这就促使了Transformer的诞生!

一开始,大语言模型主要是使用自监督学习算法创建的。自监督学习是指处理未标记数据以获得有用的表示,这些表示可以帮助下游的学习任务。

通常,自监督学习算法使用基于人工神经网络(ANN)的模型。我们可以使用几种架构来创建人工神经网络,但大语言模型中使用最广泛的架构是循环神经网络(RNN)。

RNN可以利用其内部状态来处理可变长度的输入序列。RNN具有长期记忆和短期记忆。RNN有一些变体,如长短期记忆网络(LSTM)和门控循环单元(GRU)。

使用LSTM单元的RNN训练速度非常慢。此外,对于这样的架构,我们需要按顺序或串行地输入数据。这就无法进行并行化处理,也无法利用可用的处理器核心。

或者,使用GRU的RNN模型训练速度更快,但在更大的数据集上表现较差。尽管如此,在很长一段时间里,LSTM和GRU仍然是构建复杂NLP系统的首选。然而,这样的模型也存在梯度消失问题:

当反向传播多层时,梯度可能会变得非常小,导致训练困难。

RNN的一些问题通过在其架构中添加注意力机制得到了部分解决。在像LSTM这样的循环架构中,可以传播的信息量是有限的,并且保留信息的窗口较短。

然而,有了注意力机制,这个信息窗口可以显著增加。注意力是一种增强输入数据某些部分,同时削弱其他部分的技术。其背后的动机是网络应该更多地关注数据的重要部分:

其中, &i是注意力权重,表示对每个输入部分的关注程度。

注意力和自注意力之间有一个微妙的区别,但它们的动机是相同的。注意力机制是指关注另一个序列不同部分的能力,而自注意力是指关注当前序列不同部分的能力。

自注意力允许模型访问来自任何输入序列元素的信息。在NLP应用中,这提供了关于远距离标记的相关信息。因此,模型可以捕获整个序列中的依赖关系,而无需固定或滑动窗口。

带有注意力机制的RNN模型在性能上有了显著提升。然而,循环模型本质上很难扩展。但是,自注意力机制很快被证明非常强大,以至于它甚至不需要循环顺序处理。

2017年,谷歌大脑团队推出的Transformer[2]可能是大语言模型历史上最重要的转折点之一。Transformer是一种深度学习模型,它采用自注意力机制,并一次性处理整个输入:

与早期基于RNN的模型相比,Transformer有一个重大变化,即它没有循环结构。在有足够训练数据的情况下,Transformer架构中的注意力机制本身就可以与带有注意力机制的RNN模型相媲美。

使用Transformer模型的另一个显著优势是它们具有更高的并行化程度,并且需要的训练时间大大减少。这正是我们利用可用资源在大量基于文本的数据上构建大语言模型所需要的优势。

许多基于人工神经网络的自然语言处理模型都是使用编码器 - 解码器架构构建的。例如,seq2seq是谷歌最初开发的一系列算法。它通过使用带有LSTM或GRU的RNN将一个序列转换为另一个序列。

最初的Transformer模型也使用了编码器 - 解码器架构。编码器由编码层组成,这些层逐层迭代处理输入。解码器由解码层组成,对编码器的输出进行同样的处理:

每个编码器层的功能是生成编码,其中包含关于输入中哪些部分相互相关的信息。输出编码随后作为输入传递给下一个编码器。每个编码器由一个自注意力机制和一个前馈神经网络组成。

此外,每个解码器层获取所有编码,并利用其中包含的上下文信息生成输出序列。与编码器一样,每个解码器由一个自注意力机制、一个对编码的注意力机制和一个前馈神经网络组成。

5. 预训练

在这个阶段,模型以自监督的方式在大量非结构化文本数据集上进行预训练。预训练的主要挑战是计算成本。

存储10亿参数模型所需的GPU内存:

1个参数 -> 4字节(32位浮点数)

10亿参数 -> 4× 字节 = 4GB

存储10亿参数模型所需的GPU内存 = 4GB(32位全精度)

让我们计算训练10亿参数模型所需的内存:

模型参数

梯度

ADAM优化器(2个状态)

激活值和临时内存(大小可变)

-> 4字节参数 + 每个参数额外20字节

所以,训练所需的内存大约是存储模型所需内存的20倍。

存储10亿参数模型所需内存 = 4GB(32位全精度)

训练10亿参数模型所需内存 = 80GB(32位全精度)

6. 数据并行训练技术

6.1 分布式数据并行(DDP)

分布式数据并行(DDP)要求模型权重以及训练所需的所有其他额外参数、梯度和优化器状态都能在单个GPU中容纳。如果模型太大,则应使用模型分片。

6.2 全分片数据并行(FSDP)

全分片数据并行(FSDP)通过在多个GPU之间分布(分片)模型参数、梯度和优化器状态来减少内存使用。

7. 微调

微调有助于我们通过调整预训练的大语言模型(LLM)的权重,使其更好地适应特定任务或领域,从而充分发挥这些模型的潜力。这意味着与单纯的提示工程相比,你可以用更低的成本和延迟获得更高质量的结果。

与提示相比,微调通常在引导大语言模型的行为方面要有效得多。通过在一组示例上训练模型,你可以缩短精心设计的提示,节省宝贵的输入令牌,同时不牺牲质量。你通常还可以使用小得多的模型,这反过来又可以减少延迟和推理成本。

例如,经过微调的Llama 7B模型在每个令牌的基础上,成本效益比现成的模型(如GPT-3.5)高得多(大约50倍),且性能相当。

如前所述,微调是针对其他任务对已经训练好的模型进行调整。其工作方式是获取原始模型的权重,并对其进行调整以适应新任务。

模型在训练时会学习完成特定任务,例如,GPT-3在大量数据集上进行了训练,因此它学会了生成故事、诗歌、歌曲、信件等。人们可以利用GPT-3的这种能力,并针对特定任务(如以特定方式生成客户查询的答案)对其进行微调。

有多种方法和技术可以对模型进行微调,其中最流行的是迁移学习。迁移学习源自计算机视觉领域,它是指冻结网络初始层的权重,只更新后面层的权重的过程。这是因为较底层(更接近输入的层)负责学习训练数据集的通用特征,而较上层(更接近输出的层)学习更具体的信息,这些信息直接与生成正确的输出相关。

7.1 PEFT

PEFT,即参数高效微调(Parameter Efficient Fine-Tuning),是一组以最节省计算资源和时间的方式微调大型模型的技术或方法,同时不会出现我们可能在全量微调中看到的性能损失。之所以采用这些技术,是因为随着模型越来越大,例如拥有1760亿参数的BLOOM[3]模型,在不花费数万美元的情况下对其进行微调几乎是不可能的。但有时为了获得更好的性能,使用这样的大型模型又几乎是必要的。这就是PEFT发挥作用的地方,它可以帮助解决在处理这类大型模型时遇到的问题。

以下是一些PEFT技术:

7.2 迁移学习

迁移学习是指我们获取模型的一些已学习参数,并将其用于其他任务。这听起来与微调相似,但实际上有所不同。在微调中,我们重新调整模型的所有参数,或者冻结一些权重并调整其余参数。但在迁移学习中,我们从一个模型中获取一些已学习参数,并将其用于其他网络。这在我们的操作上给予了更大的灵活性。例如,在微调时我们无法改变模型的架构,这在很多方面限制了我们。但在使用迁移学习时,我们只使用训练好的模型的一部分,然后可以将其附加到任何具有不同架构的其他模型上。

迁移学习在使用大语言模型的NLP任务中经常出现,人们会使用像T5这样的预训练模型中Transformer网络的编码器部分,并训练后面的层。

7.3 Adapters 适配器

适配器是最早发布的参数高效微调技术之一。相关论文Parameter-Efficient Transfer Learning for NLP[4]表明,我们可以在现有的Transformer架构上添加更多层,并且只对这些层进行微调,而不是对整个模型进行微调。他们发现,与完全微调相比,这种技术可以产生相似的性能。

在左边,是添加了适配器层的修改后的Transformer架构。我们可以看到适配器层添加在注意力堆栈和前馈堆栈之后。在右边,是适配器层本身的架构。适配器层采用瓶颈架构,它将输入缩小到较小维度的表示,然后通过非线性激活函数,再将其放大到输入的维度。这确保了Transformer堆栈中的下一层能够接收适配器层生成的输出。

论文作者表明,这种微调方法在消耗更少计算资源和训练时间的同时,性能可与完全微调相媲美。他们在GLUE基准测试中,仅增加3.6%的参数,就能达到全量微调0.4%的效果。

7.4 LoRA——低秩自适应

LoRA是一种与适配器层类似的策略,但它旨在进一步减少可训练参数的数量。它采用了更严谨的数学方法。LoRA通过修改神经网络中可更新参数的训练和更新方式来工作。

从数学角度解释,我们知道预训练神经网络的权重矩阵是满秩的,这意味着每个权重都是唯一的,不能通过组合其他权重得到。但在这篇论文Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning[5]中,作者表明,当预训练语言模型针对新任务进行调整时,权重具有较低的“内在维度”。这意味着权重可以用更小的矩阵表示,即它具有较低的秩。反过来,这意味着在反向传播过程中,权重更新矩阵的秩较低,因为大部分必要信息已经在预训练过程中被捕获,在微调过程中只进行特定任务的调整。

更简单的解释是,在微调过程中,只有极少数权重会有较大的更新,因为神经网络的大部分学习是在预训练阶段完成的。LoRA利用这一信息来减少可训练参数的数量。

以GPT-3 175B为例,LoRA研究团队证明,即使全秩(即d)高达12288,非常低的秩(即图1中的r可以是1或2)也足够了,这使得LoRA在存储和计算上都非常高效。

图2展示了矩阵A{d*r}和B[r*k]的维度为[d*k],而我们可以改变r的值。r值越小,需要调整的参数就越少。虽然这会缩短训练时间,但r值过小时也可能导致信息丢失并降低模型性能。然而,使用LoRA时,即使秩较低,性能也能与完全训练的模型相当甚至更好。

用HuggingFace实现LoRA微调

要使用HuggingFace实现LoRA微调,你需要使用PEFT库将LoRA适配器注入模型,并将它们用作更新矩阵。

from transformers import AutoModelForCausalLM
from peft import get_peft_config, get_peft_model, LoraConfig, TaskType
model = AutoModelForCausalLM.from_pretrained(model_name_or_path, device_map="auto", trust_remote_code=True)
peft_config = LoraConfig(
    task_type=TaskType.CAUSAL_LM, inference_mode=False, r=32, lora_alpha=16, lora_dropout=0.1,
    target_modules=['query_key_value']
)
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()

完成这些后,你就可以像平常一样训练模型了。但这一次,它将比平常花费更少的时间和计算资源。

LoRA的效率

论文的作者表明,LoRA仅用总可训练参数的2%就能超越全量微调的效果。

至于它训练的参数数量,我们可以通过秩r参数在很大程度上进行控制。例如,假设权重更新矩阵有100,000个参数,A为200,B为500。权重更新矩阵可以分解为较低维度的较小矩阵,A为200×3,B为3×500。这样我们就只有200×3 + 3×500 = 2100个可训练参数,仅占总参数数量的2.1%。如果我们决定只将LoRA应用于特定层,这个数量还可以进一步减少。

由于训练和应用的参数数量比实际模型少得多,文件大小可以小至8MB。这使得加载、应用和传输学习到的模型变得更加容易和快速。

7.5 QLoRA

QLoRA如何与LoRA不同?它是一种4位Transformer。

QLoRA是一种微调技术,它将高精度计算技术与低精度存储方法相结合。这有助于在保持模型高性能和准确性的同时,使模型大小保持较小。

QLoRA使用LoRA作为辅助手段来修复量化过程中引入的误差。

QLoRA的工作原理

QLoRA通过引入3个新概念来帮助减少内存使用,同时保持相同的性能质量。它们是4位Normal Float、双重量化和分页优化器。

4位Normal Float(NF4)

4位NormalFloat是一种新的数据类型,是保持16位性能水平的关键因素。它的主要特性是:数据类型中的任何位组合,例如0011或0101,都会从输入张量中分配到数量相等的元素。

QLoRA对权重进行4位量化,并以32位精度训练注入的适配器权重(LORA)。

QLoRA有一种存储数据类型(NF4)和一种计算数据类型(16位BrainFloat)。

我们将存储数据类型反量化为计算数据类型以进行前向和反向传递,但我们只对使用16位BrainFloat的LORA参数计算权重梯度。

归一化:首先对模型的权重进行归一化,使其具有零均值和单位方差。这确保了权重分布在零附近,并落在一定范围内。

量化:然后将归一化后的权重量化为4位。这涉及将原始的高精度权重映射到一组较小的低精度值。对于NF4,量化级别被选择为在归一化权重的范围内均匀分布。

反量化:在前向传递和反向传播过程中,量化后的权重被反量化回全精度。这是通过将4位量化值映射回其原始范围来完成的。反量化后的权重用于计算,但它们以4位量化形式存储在内存中。

数据会被量化到“桶”或“箱”中。数字2和3都落入相同的量化区间2。这种量化过程通过“四舍五入”到最接近的量化区间,让你可以使用更少的数字。

双重量化

双重量化是指对4位NF量化过程中使用的量化常数进行量化的独特做法。虽然这看起来不太起眼,但相关研究论文指出,这种方法有可能平均每个参数节省0.5位。这种优化在采用块wise k位量化的QLoRA中特别有用。与对所有权重一起进行量化不同,这种方法将权重分成不同的块或片段,分别进行量化。

块wise量化方法会生成多个量化常数。有趣的是,这些常数可以进行第二轮量化,从而提供了额外的节省空间的机会。由于量化常数的数量有限,这种策略仍然有效,减轻了与该过程相关的计算和存储需求。

分页优化器

如前所述,分位数量化涉及创建桶或箱来涵盖广泛的数值范围。这个过程会导致多个不同的数字被映射到同一个桶中,例如在量化过程中,2和3都被转换为值3。因此,权重的反量化会引入1的误差。

在神经网络中更广泛的权重分布上可视化这些误差,就可以看出分位数量化的固有挑战。这种差异凸显了为什么QLoRA更像是一种微调机制,而不是一种独立的量化策略,尽管它适用于4位推理。在使用QLoRA进行微调时,LoRA调整机制就会发挥作用,包括创建两个较小的权重更新矩阵。这些矩阵以更高精度的格式(如脑浮点16或浮点16)维护,然后用于更新神经网络的权重。

值得注意的是,在反向传播和前向传递过程中,网络的权重会进行反量化,以确保实际训练是以更高精度格式进行的。虽然存储仍然采用较低精度,但这种有意的选择会引入量化误差。然而,模型训练过程本身具有适应和减轻量化过程中这些低效性的能力。从本质上讲,采用更高精度的LoRA训练方法有助于模型学习并积极减少量化误差。

用HuggingFace进行QLoRA微调

要使用HuggingFace进行QLoRA微调,你需要同时安装BitsandBytes库和PEFT库。BitsandBytes库负责4位量化以及整个低精度存储和高精度计算部分。PEFT库将用于LoRA微调部分。

import torch
from peft import prepare_model_for_kbit_training, LoraConfig, get_peft_model
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
model_id = "EleutherAI/gpt-neox-20b"
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)
model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=bnb_config, device_map={"":0})
model.gradient_checkpointing_enable()
model = prepare_model_for_kbit_training(model)
config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["query_key_value"],
    lora_dropout=0.05,
    bias="none",
    task_type="CAUSAL_LM"
)
model = get_peft_model(model, config)

7.6IA3

IA3(通过抑制和放大内部激活注入适配器,Infused Adapter by Inhibiting and Amplifying Inner Activations[6])是一种基于适配器的技术,与LoRA有些相似。作者的目标是在避免上下文学习(ICL,in context learning或Few-Shot prompting)相关问题的同时,复制其优势。ICL在成本和推理方面可能会变得复杂,因为它需要用示例来提示模型。更长的提示需要更多的时间和计算资源来处理。但ICL可能是开始使用模型的最简单方法。

IA3通过引入针对模型激活的缩放向量来工作。总共引入了3个向量,lv、ik和lff。这些向量分别针对注意力层中的值、键以及密集层中的非线性层。这些向量与模型中的默认值进行逐元素相乘。一旦注入,这些参数在训练过程中就会被学习,而模型的其余部分保持冻结。这些学习到的向量本质上是针对手头的任务对预训练模型的权重进行缩放或优化。

到目前为止,这似乎是一种基本的基于适配器的参数高效微调(PEFT)方法。但不止如此。作者还使用了3个损失项来增强学习过程。这3个损失项是LLM、LUL和LLN。LLM是标准的交叉熵损失,它增加了生成正确响应的可能性。然后是LUL,即非似然损失(Unlikelihood Loss)。这个损失项通过等级分类(Rank Classification)来降低错误输出的概率。最后是LLN,它是一种长度归一化损失,对所有输出选择的长度归一化对数概率应用软max交叉熵损失。这里使用多个损失项是为了确保模型更快、更好地学习。因为我们试图通过少样本示例进行学习,这些损失是必要的。

现在让我们谈谈IA3中的两个非常重要的概念:等级分类和长度归一化。

在等级分类中,模型被要求根据正确性对一组响应进行排序。这是通过计算潜在响应的概率得分来完成的。然后使用LUL来降低错误响应的概率,从而增加正确响应的概率。但是在等级分类中,我们面临一个关键问题,即由于概率的计算方式,令牌较少的响应会排名更高。生成的令牌数量越少,概率就越高,因为每个生成令牌的概率都小于1。为了解决这个问题,作者提出将响应的得分除以响应中的令牌数量。这样做将对得分进行归一化。这里需要非常注意的一点是,归一化是在对数概率上进行的,而不是原始概率。对数概率是负数,且在0到1之间。

示例用法

对于序列分类任务,可以按如下方式为Llama模型初始化IA3配置:

peft_config = IA3Config(
    task_type=TaskType.SEQ_CLS, target_modules=["k_proj""v_proj""down_proj"], feedforward_modules=["down_proj"]
)

7.7 P-Tuning

P-Tuning方法旨在优化传递给模型的提示的表示。在P-Tuning论文[7]中,作者强调了提示工程在使用大语言模型时是一种非常强大的技术。P-Tuning方法建立在提示工程的基础上,并试图进一步提高优质提示的有效性。

P-Tuning通过为你的提示创建一个小型编码器网络来工作,该网络为传入的提示创建一个软提示。要使用P-Tuning调整你的大语言模型,你应该创建一个表示你的提示的提示模板。还有一个上下文x,用于模板中以获得标签y。这是论文中提到的方法。提示模板中使用的令牌是可训练和可学习的参数,这些被称为伪令牌。我们还添加了一个提示编码器,它帮助我们针对手头的特定任务更新伪令牌。提示编码器通常是一个双向LSTM网络,它为模型学习提示的最佳表示,然后将该表示传递给模型。LSTM网络连接到原始模型。这里只有编码器网络和伪令牌被训练,原始网络的权重不受影响。训练完成后,LSTM头部被丢弃,因为我们有可以直接使用的hi。

简而言之,提示编码器只改变传入提示的嵌入,以更好地表示任务,其他一切都保持不变。

7.8 Prefix Tuning

Prefix Tuning可以被视为P-Tuning的下一个版本。P-Tuning的作者发表了一篇关于P-Tuning V-2[8]的论文,解决了P-Tuning的问题。在这篇论文中,他们实现了本文中介绍的Prefix Tuning。Prefix Tuning和P-Tuning没有太大区别,但仍然可能导致不同的结果。让我们深入解释一下。

在P-Tuning中,我们只在输入嵌入中添加可学习参数,而在Prefix Tuning中,我们在网络的所有层中添加这些参数。这确保了模型本身更多地了解它正在被微调的任务。我们在提示以及Transformer层的每一层激活中附加可学习参数。与P-Tuning的不同之处在于,我们不是完全修改提示嵌入,而是只在每一层提示的开头添加很少的可学习参数。

在Transformer的每一层,我们将一个带有可学习参数的软提示与输入连接起来。这些可学习参数通过一个非常小的MLP(只有2个全连接层)进行调整。这样做是因为论文的作者指出,直接更新这些提示令牌对学习率和初始化非常敏感。软提示增加了可训练参数的数量,但也大大提高了模型的学习能力。MLP或全连接层稍后可以去掉,因为我们只关心软提示,在推理时,软提示将被附加到输入序列中,引导模型。

7.9 Prompt Tuning(并非提示工程)

Prompt Tuning是最早基于仅使用软提示进行微调这一想法的论文之一。Prompt Tuning是一个非常简单且易于实现的想法。它包括在输入前添加一个特定的提示,并为该特定提示使用虚拟令牌或新的可训练令牌。在这个过程中,可以对这些新的虚拟令牌进行微调,以更好地表示提示。这意味着模型被调整为更好地理解提示。以下是论文中Prompt Tuning与全量微调的比较:

从图中可以看到,如果我们想将模型用于多个任务,全模型微调需要存在多个模型副本。但使用Prompt Tuning,你只需要存储学习到的提示令牌的虚拟令牌。例如,如果你使用“对这条推文进行分类:{tweet}”这样的提示,目标将是为该提示学习新的更好的嵌入。在推理时,只有这些新的嵌入将用于生成输出。这使得模型能够调整提示,以帮助自己在推理时生成更好的输出。

Prompt Tuning的效率

使用Prompt Tuning的最大优点是学习到的参数规模很小。文件大小可能只有KB级别。由于我们可以确定新令牌的维度大小和使用的参数数量,因此可以极大地控制要学习的参数数量。论文作者展示了,即使可训练令牌的数量非常少,该方法的表现也相当出色。并且随着使用更大的模型,性能只会进一步提升。

另一个很大的优点是,我们可以在不做任何修改的情况下,将同一个模型用于多个任务,因为唯一被更新的只是提示令牌的嵌入。这意味着,只要模型足够大且足够复杂,能够执行这些任务,你就可以将同一个模型用于推文分类任务和语言生成任务,而无需对模型本身进行任何修改。但一个很大的限制是,模型本身不会学到任何新东西。这纯粹是一个提示优化任务。这意味着,如果模型从未在情感分类数据集上进行过训练,Prompt Tuning可能不会有任何帮助。需要特别注意的是,这种方法优化的是提示,而不是模型。所以,如果你无法手工制作一个能较好完成任务的硬提示,那么尝试使用提示优化技术来优化软提示就没有任何意义。

硬提示与软提示

硬提示可以被看作是一个定义明确的提示,它是静态的,或者充其量是一个模板。一个生成式人工智能应用程序也可以使用多个提示模板。

提示模板允许提示被存储、重复使用、共享和编程。生成式提示可以被整合到程序中,用于编程、存储和重复使用。

软提示是在Prompt Tuning过程中创建的。

与硬提示不同,软提示无法在文本中查看和编辑。提示由嵌入(一串数字)组成,它从更大的模型中获取知识。

可以肯定的是,软提示的一个缺点是缺乏可解释性。人工智能发现了与特定任务相关的提示,但无法解释为什么选择这些嵌入。就像深度学习模型本身一样,软提示是不透明的。

软提示可作为额外训练数据的替代品。

7.10 LoRA与Prompt Tuning对比

现在我们已经探索了各种参数高效微调(PEFT)技术。那么问题来了,是使用像适配器(Adapter )和LoRA这样的添加式技术,还是使用像P-Tuning和Prefix Tuning这样基于提示的技术呢?

在比较LoRA与P-Tuning和Prefix Tuning时,可以肯定地说,就充分发挥模型性能而言,LoRA是最佳策略。但根据你的需求,它可能不是最有效的。如果你想在与模型预训练任务差异很大的任务上训练模型,毫无疑问,LoRA是有效调整模型的最佳策略。但如果你的任务或多或少是模型已经理解的,只是挑战在于如何正确地向模型提供提示,那么你应该使用Prompt Tuning技术。Prompt Tuning不会修改模型中的许多参数,主要侧重于传入的提示。

需要注意的一个重要点是,LoRA将权重更新矩阵分解为较小的低秩矩阵,并使用它们来更新模型的权重。即使可训练参数较少,LoRA也会更新神经网络目标部分中的所有参数。而在Prompt Tuning技术中,只是向模型添加了一些可训练参数,这通常有助于模型更好地适应和理解任务,但并不能帮助模型很好地学习新特性。

7.11 LoRA和PEFT与全量微调对比

参数高效微调(PEFT)是作为全量微调的替代方案被提出的。在大多数任务中,已有论文表明,像LoRA这样的PEFT技术即使不比全量微调更好,也与之相当。但是,如果你希望模型适应的新任务与模型预训练的任务完全不同,PEFT可能并不够。在这种情况下,有限数量的可训练参数可能会导致严重问题。

如果我们试图使用像LLaMA或Alpaca这样基于文本的模型构建一个代码生成模型,我们可能应该考虑对整个模型进行微调,而不是使用LoRA来调整模型。这是因为这个任务与模型已知和预训练的内容差异太大。另一个典型的例子是训练一个只懂英语的模型来生成尼泊尔语的文本。

8. 大语言模型推理

在使用大语言模型(LLM)进行推理时,我们通常可以配置各种参数来微调其输出和性能。以下是一些关键参数的详细介绍:

Top-k采样:在每一步只对可能性最高的k个词元进行采样,这样可以增加多样性并避免重复。k值越高,输出的多样性越强,但可能连贯性会变差。

温度参数:影响下一个可能词元的概率分布,用于控制随机性和 “创造性”。较低的温度会生成更可能出现但可能重复的文本,而较高的温度则会鼓励多样性,产生更不可预测的输出。

Top-P(核)采样:Top-P或核采样将词元的选择限制在累计概率达到某个阈值的词汇子集内,有助于控制生成输出的多样性。

最大长度:设置大语言模型生成的最大词元数,防止输出过长。

上下文提示:通过提供特定的上下文提示或输入,可以引导模型生成与该上下文一致的文本,确保生成的输出在给定的上下文中相关且连贯。

重复惩罚:对出现重复n - gram的序列进行惩罚,鼓励多样性和新颖性。

采样方式:在确定性(贪心)和基于随机采样的生成方式中选择。贪心模式在每一步选择最可能的词元,而随机采样则引入随机性。贪心模式优先考虑准确性,而随机采样鼓励多样性和创造性。

束搜索:保留多个潜在序列,在每一步扩展最有希望的序列,与Top-k采样相比,旨在生成更连贯、更准确的输出。

9. 提示工程

提示工程,也称为上下文提示,是指在不更新模型权重的情况下,与大语言模型进行沟通,引导其行为以获得期望结果的方法。这是一门实证科学,提示工程方法的效果在不同模型之间可能差异很大,因此需要大量的实验和探索。

什么是提示?

我们与大语言模型交互时使用的自然语言指令被称为提示。构建提示的过程称为提示工程。

提示的作用

大语言模型根据提示中的指令进行推理并完成任务的过程被称为上下文学习。

少样本提示

大语言模型在没有任何示例的情况下响应提示指令的能力称为零样本学习。

当提供单个示例时,称为单样本学习。

如果提供多个示例,则称为少样本学习。

上下文窗口,即大语言模型可以提供和推理的最大词元数,在零样本/单样本/少样本学习中至关重要。

9.1 思维链(CoT)提示

思维链(CoT)提示[9](Wei等人,2022)会生成一系列短句子,逐步描述推理逻辑,即推理链或推理依据,最终得出答案。在使用大型模型(例如参数超过500亿的模型)处理复杂推理任务时,CoT的优势更为明显。而简单任务使用CoT提示的受益则相对较小。

9.2 PAL(程序辅助语言模型)

Gao等人(2022)PAL: Program-aided Language Models[10]提出了一种方法,使用大语言模型读取自然语言问题,并生成程序作为中间推理步骤。这种方法被称为程序辅助语言模型(PAL),它与思维链提示的不同之处在于,它不是使用自由形式的文本获取解决方案,而是将解决方案步骤交给诸如Python解释器这样的程序运行时处理。

9.3 ReAct提示

ReAct的灵感来自于 “行动” 和 “推理” 之间的协同作用,这种协同作用使人类能够学习新任务并做出决策或进行推理。

CoT由于无法访问外部世界或更新自身知识,可能会导致事实幻觉和错误传播等问题。

ReAct是一种将推理和行动与大语言模型相结合的通用范式。ReAct促使大语言模型为任务生成语言推理轨迹和行动。这使系统能够进行动态推理,创建、维护和调整行动方案,同时还能与外部环境(例如维基百科)进行交互,将更多信息纳入推理过程。下图展示了ReAct的一个示例以及执行问答任务所涉及的不同步骤。

10. 模型优化技术

模型压缩方法包括:(a)剪枝、(b)量化和(c)知识蒸馏。

10.1 量化

模型量化是一种用于减小大型神经网络(包括大语言模型LLM)大小的技术,通过修改其权重的精度来实现。大语言模型的量化之所以可行,是因为实证结果表明,虽然神经网络训练和推理的某些操作必须使用高精度,但在某些情况下,可以使用低得多的精度(例如float16),这可以减小模型的整体大小,使其能够在性能和准确性可接受的情况下,在性能较弱的硬件上运行。

模型大小的趋势

一般来说,在神经网络中使用高精度与更高的准确性和更稳定的训练相关。使用高精度在计算上也更为昂贵,因为它需要更多且更昂贵的硬件。谷歌和英伟达的相关研究表明,神经网络的某些训练和推理操作可以使用较低的精度。

除了研究之外,这两家公司还开发了支持低精度操作的硬件和框架。例如,英伟达的T4加速器是低精度GPU,其张量核心技术比K80的效率要高得多。谷歌的TPU引入了bfloat16的概念,这是一种为神经网络优化的特殊基本数据类型。低精度的基本思想是,神经网络并不总是需要使用64位浮点数的全部范围才能表现良好。

bfloat16数值格式

bfloat16数值格式

随着神经网络越来越大,利用低精度的重要性对使用它们的能力产生了重大影响。对于大语言模型来说,这一点更为关键。

英伟达的A100 GPU最先进的版本有80GB内存。在下面的表格中可以看到,LLama2 - 70B模型大约需要138GB内存,这意味着要部署它,我们需要多个A100 GPU。在多个GPU上分布模型不仅意味着要购买更多的GPU,还需要额外的基础设施开销。另一方面,量化版本大约需要40GB内存,因此可以轻松地在一个A100上运行,显著降低了推理成本。这个例子甚至还没有提到在单个A100中,使用量化模型会使大多数单个计算操作执行得更快。

使用llama.cpp进行4位量化的示例,大小可能会因方法略有不同

量化如何缩小模型?:量化通过减少每个模型权重所需的比特数来显著减小模型的大小。一个典型的场景是将权重从FP16(16位浮点数)减少到INT4(4位整数)。这使得模型可以在更便宜的硬件上运行,并且 / 或者运行速度更快。然而,降低权重的精度也会对大语言模型的整体质量产生一定影响。研究表明,这种影响因使用的技术而异,并且较大的模型对精度变化的影响较小。较大的模型(超过约700亿参数)即使转换为4位,也能保持其性能,像NF4这样的一些技术表明对其性能没有影响。因此,对于这些较大的模型,4位似乎是在性能与大小 / 速度之间的最佳折衷,而6位或8位可能更适合较小的模型。

大语言模型量化的类型:获得量化模型的技术可以分为两类。

训练后量化(PTQ):将已经训练好的模型的权重转换为较低精度,而无需任何重新训练。虽然这种方法简单直接且易于实现,但由于权重值精度的损失,可能会使模型性能略有下降。

量化感知训练(QAT):与PTQ不同,QAT在训练阶段就整合了权重转换过程。这通常会带来更好的模型性能,但计算要求更高。一种常用的QAT技术是QLoRA。

本文将只关注PTQ策略及其关键区别。 3. 更大的量化模型与更小的未量化模型:我们知道降低精度会降低模型的准确性,那么你会选择较小的全精度模型,还是选择推理成本相当的更大的量化模型呢?尽管理想的选择可能因多种因素而异,但Meta的最新研究提供了一些有见地的指导。虽然我们预期降低精度会导致准确性下降,但Meta的研究人员已经证明,在某些情况下,量化模型不仅表现更优,而且还能减少延迟并提高吞吐量。在比较8位的130亿参数模型和16位的70亿参数模型时,也可以观察到相同的趋势。本质上,在比较推理成本相似的模型时,更大的量化模型可以超越更小的未量化模型。随着网络规模的增大,这种优势更加明显,因为大型网络在量化时质量损失较小。 4. 在哪里可以找到已经量化的模型?:幸运的是,在Hugging Face Hub上可以找到许多已经使用GPTQ(有些与ExLLama兼容)、NF4或GGML进行量化的模型版本。快速浏览一下就会发现,这些模型中有很大一部分是由大语言模型社区中一位有影响力且备受尊敬的人物TheBloke量化的。该用户发布了多个使用不同量化方法的模型,因此人们可以根据具体的用例选择最合适的模型。要轻松试用这些模型,可以打开一个Google Colab,并确保将运行时更改为GPU(有免费的GPU可供使用)。首先安装Hugging Face维护的transformers库以及所有必要的库。由于我们将使用由Auto - GPTQ量化的模型,因此还需要安装相应的库:

!pip install transformers
!pip install accelerate
!pip install optimum
!pip install auto - gptq

你可能需要重新启动运行时,以便安装的库可用。然后,只需加载已经量化的模型,这里我们加载一个之前使用Auto - GPTQ量化的Llama - 2 - 7B - Chat模型,如下所示:

from transformers import AutoModelForCausalLM, AutoTokenizer
import torch

model_id = "TheBloke/Llama-2-7b-Chat-GPTQ"
tokenizer = AutoTokenizer.from_pretrained(model_id, torch_dtype=torch.float16, device_map="auto")
model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.float16, device_map="auto")

量化大语言模型:如前所述,Hugging Face Hub上已经有大量量化模型,在许多情况下,无需自己压缩模型。然而,在某些情况下,你可能希望使用尚未量化的模型,或者你可能希望自己压缩模型。这可以通过使用适合你特定领域的数据集来实现。为了演示如何使用AutoGPTQ和Transformers库轻松量化模型,我们采用了Optimum(Hugging Face用于优化训练和推理的解决方案)中简化版的AutoGPTQ接口:

from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig

model_id = "facebook/opt-125m"
tokenizer = AutoTokenizer.from_pretrained(model_id)
quantization_config = GPTQConfig(bits=4, dataset = "c4", tokenizer=tokenizer)
model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto", quantization_config=quantization_config)

 

模型压缩可能很耗时。例如,一个1750亿参数的模型至少需要4个GPU小时,尤其是使用像 “c4” 这样的大型数据集时。值得注意的是,量化过程中的比特数或数据集可以通过GPTQConfig的参数轻松修改。更改数据集会影响量化的方式,因此,如果可能的话,使用与推理时看到的数据相似的数据集,以最大化性能。 6. 量化技术:在模型量化领域已经出现了几种最先进的方法。让我们深入了解一些突出的方法:

- GPTQ:有一些实现选项,如AutoGPTQ、ExLlama和GPTQ - for - LLaMa,这种方法主要侧重于GPU执行。 - NF4:在bitsandbytes库中实现,它与Hugging Face的transformers库紧密合作。它主要被QLoRA方法使用,以4位精度加载模型进行微调。 - GGML:这个C库与llama.cpp库紧密合作。它为大语言模型提供了一种独特的二进制格式,允许快速加载和易于读取。值得注意的是,它最近转换为GGUF格式,以确保未来的可扩展性和兼容性。

许多量化库支持多种不同的量化策略(例如4位、5位和8位量化),每种策略在效率和性能之间都提供了不同的权衡。

10.2 蒸馏

知识蒸馏(KD; Hinton等人,2015年;Gou等人,2020年)Distilling the Knowledge in a Neural Network[11]是一种构建更小、成本更低模型(“学生模型”)的直接方法,通过将预训练的高成本模型(“教师模型”)的能力转移到学生模型中,来加快推理速度。除了要求学生模型的输出空间与教师模型匹配,以便构建合适的学习目标之外,对学生模型的架构构建方式并没有太多限制。

教师模型已经在训练数据上进行了微调,因此,其概率分布可能与真实数据非常接近,并且在生成的token上不会有太多变化。

当温度>1时,概率分布会变得更宽泛。

T > 1时 => 教师模型的输出 -> 软标签 学生模型的输出 -> 软预测

T = 1时 => 教师模型的输出 -> 硬标签 学生模型的输出 -> 硬预测

蒸馏对于生成式解码器模型的效果并不显著,它对仅编码器模型(如BERT)更为有效,因为这类模型存在大量的表示冗余。

10.3 剪枝

网络剪枝是指在保持模型能力的同时,通过修剪不重要的模型权重或连接来减小模型大小。这一过程可能需要也可能不需要重新训练。剪枝可分为非结构化剪枝和结构化剪枝。

非结构化剪枝允许删除任何权重或连接,因此不会保留原始网络架构。非结构化剪枝通常与现代硬件的适配性不佳,并且无法真正加快推理速度。

结构化剪枝旨在保持矩阵乘法中部分元素为零的密集形式。为了适配硬件内核的支持,它们可能需要遵循特定的模式限制。这里我们主要关注结构化剪枝,以在Transformer模型中实现高稀疏性。

构建剪枝网络的常规工作流程包含三个步骤:

训练一个密集网络直至收敛;

对网络进行剪枝,去除不需要的结构;

可选步骤,重新训练网络,通过新的权重恢复模型性能 。

通过网络剪枝在密集模型中发现稀疏结构,同时使稀疏网络仍能保持相似性能,这一想法的灵感来源于彩票假设(LTH):一个随机初始化的、密集的前馈网络包含多个子网络,其中只有一部分(稀疏网络)是 “中奖彩票”,当单独训练时,这些子网络能够达到最佳性能。

结论

在本篇文章中,我们探索了检索增强生成(RAG)应用中的文本生成部分,重点介绍了大语言模型(LLM)的使用。内容涵盖了语言建模、预训练面临的挑战、量化技术、分布式训练方法,以及大语言模型的微调。此外,还讨论了参数高效微调(PEFT)技术,包括适配器、LoRA和QLoRA;介绍了提示策略、模型压缩方法(如剪枝和量化),以及各种量化技术(GPTQ、NF4、GGML)。最后,对用于减小模型大小的蒸馏和剪枝技术进行了讲解。

 
   
164 次浏览       28
相关文章

基于图卷积网络的图深度学习
自动驾驶中的3D目标检测
工业机器人控制系统架构介绍
项目实战:如何构建知识图谱
 
相关文档

5G人工智能物联网的典型应用
深度学习在自动驾驶中的应用
图神经网络在交叉学科领域的应用研究
无人机系统原理
相关课程

人工智能、机器学习&TensorFlow
机器人软件开发技术
人工智能,机器学习和深度学习
图像处理算法方法与实践

最新活动计划
DeepSeek软件测试应用实践 4-12[在线]
DeepSeek大模型开发实践 4-19[在线]
UAF架构体系与实践 4-11[北京]
AI智能化软件测试方法与实践 5-23[上海]
基于 UML 和EA进行分析设计 4-26[北京]
业务架构设计与建模 4-18[北京]
 
 
最新文章
AIGC技术与应用全解析
详解知识图谱的构建全流程
大模型升级与设计之道
自动驾驶和辅助驾驶系统
ROS机器人操作系统底层原理
最新课程
人工智能,机器学习和深度学习
人工智能与机器学习应用实战
人工智能-图像处理和识别
人工智能、机器学习& TensorFlow+Keras框架实践
人工智能+Python+大数据
成功案例
某综合性科研机构 人工智能与机器学习
某银行 人工智能+Python+大数据
北京 人工智能、机器学习& TensorFlow
某领先数字地图提供商 Python数据分析
中国移动 人工智能、机器学习和深度学习