参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2

2024-05-29 09:12

本文主要是介绍参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2

参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning

  • 今天,我们继续了解下来自清华大学发布的两种参数高效微调方法P-Tuning和P-Tuning v2。
  • 可以简单的将P-Tuning是认为针对Prompt Tuning的改进,P-Tuning v2认为是针对Prefix Tuning的改进。
  • 不过,P-Tuning是21年3月份发布的,而Prompt Tuning是21年4月发布的。

1 P-Tuning

1.1 P-Tuning概述

  • 论文链接:GPT Understands, Too (202103)

  • Prompt Tuning原理如下图所示:冻结主模型全部参数,在训练数据前加入一小段Prompt,只训练Prompt的表示层,即一个Embedding模块。论文实验表明,只要模型规模够大,简单加入 Prompt tokens 进行微调,就能取得很好的效果。

在这里插入图片描述

  • P Tuning原理如下图所示:在Prompt-Tuning的基础上,对Prompt部分进行进一步的编码计算,加速收敛。具体来说,PEFT中支持两种编码方式,一种是LSTM,一种是MLP。与Prompt-Tuning不同的是,Prompt的形式只有Soft Prompt。

在这里插入图片描述

  • P Tuning将Prompt转换为可以学习的Embedding层,并用MLP+LSTM的方式来对Prompt Embedding进行一层处理

    • 相比Prefix Tuning,P Tuning仅限于输入层,没有在每一层都加virtual token
    • 经过预训练的LM的词嵌入已经变得高度离散,如果随机初始化virtual token,容易优化到局部最优值,而这些virtual token理论是应该有相关关联的。因此,作者通过实验发现用一个prompt encoder来编码会收敛更快,效果更好。即用一个LSTM+MLP去编码这些virtual token以后,再输入到模型
    • 作者在实验中发现,相同参数规模,如果进行全参数微调,Bert的在NLU(自然语言理解)任务上的效果,超过GPT很多;但是在P-Tuning下,GPT可以取得超越Bert的效果。

    在这里插入图片描述

1.2 P-Tuning轻量微调bloom模型

1.2.1 peft中的P-Tuning

我们来看下peft\tuners\p_tuning.py中的内容:

  • 可以看到,peft支持两种编码方式,即MLP和LSTM。
# peft\tuners\p_tuning.py
class PromptEncoderReparameterizationType(str, enum.Enum):MLP = "MLP"LSTM = "LSTM"
  • P-Tuning在peft中默认的编码方式为MLP。
# peft\tuners\p_tuning.py
@dataclass
class PromptEncoderConfig(PromptLearningConfig):encoder_reparameterization_type: Union[str, PromptEncoderReparameterizationType] = field(default=PromptEncoderReparameterizationType.MLP,metadata={"help": "How to reparameterize the prompt encoder"},)encoder_hidden_size: int = field(default=None,metadata={"help": "The hidden size of the prompt encoder"},)encoder_num_layers: int = field(default=2,metadata={"help": "The number of layers of the prompt encoder"},)encoder_dropout: float = field(default=0.0,metadata={"help": "The dropout of the prompt encoder"},)def __post_init__(self):self.peft_type = PeftType.P_TUNING
  • 如下代码所示,经过LSTM或MLP去编码virtual token以后,再输入到模型。
class PromptEncoder(torch.nn.Module):"""Input shape: (`batch_size`, `total_virtual_tokens`)Output shape: (`batch_size`, `total_virtual_tokens`, `token_dim`)"""def __init__(self, config):super().__init__()self.token_dim = config.token_dimself.input_size = self.token_dimself.output_size = self.token_dimself.hidden_size = config.encoder_hidden_sizeself.total_virtual_tokens = config.num_virtual_tokens * config.num_transformer_submodulesself.encoder_type = config.encoder_reparameterization_type# embeddingself.embedding = torch.nn.Embedding(self.total_virtual_tokens, self.token_dim)if not config.inference_mode:if self.encoder_type == PromptEncoderReparameterizationType.LSTM:lstm_dropout = config.encoder_dropoutnum_layers = config.encoder_num_layers# LSTMself.lstm_head = torch.nn.LSTM(input_size=self.input_size,hidden_size=self.hidden_size,num_layers=num_layers,   # 深层LSTMdropout=lstm_dropout,   bidirectional=True,      # 双向batch_first=True,        # batch_size在第一维)self.mlp_head = torch.nn.Sequential(torch.nn.Linear(self.hidden_size * 2, self.hidden_size * 2),torch.nn.ReLU(),torch.nn.Linear(self.hidden_size * 2, self.output_size),)elif self.encoder_type == PromptEncoderReparameterizationType.MLP:encoder_num_layers_default = PromptEncoderConfig.encoder_num_layerslayers = [torch.nn.Linear(self.input_size, self.hidden_size),torch.nn.ReLU(),torch.nn.Linear(self.hidden_size, self.hidden_size),torch.nn.ReLU(),torch.nn.Linear(self.hidden_size, self.output_size),]self.mlp_head = torch.nn.Sequential(*layers)else:raise ValueError("Prompt encoder type not recognized. Please use one of MLP (recommended) or LSTM.")def forward(self, indices):# 1、先进行embeddinginput_embeds = self.embedding(indices)# 2、embedding后,再进行编码if self.encoder_type == PromptEncoderReparameterizationType.LSTM:output_embeds = self.mlp_head(self.lstm_head(input_embeds)[0])elif self.encoder_type == PromptEncoderReparameterizationType.MLP:output_embeds = self.mlp_head(input_embeds)else:raise ValueError("Prompt encoder type not recognized. Please use one of MLP (recommended) or LSTM.")return output_embeds
  • peft\peft_model.py中PeftModelForCausalLM代码如下,通过配置文件的类型来判断PEFT方法到底是PrefixTuning/PTuningV2,还是PromptTuning/PTuningV1。
    • 如果是Prompt Tuning/P-TuningV1,则将虚拟token的embedding直接concat到原始输入序列的前面,送入base model模型进行推理。
    • 如果是Prefix Tuning/P-TuningV2,需要给每一个transformer block的key和value添加虚拟token的embedding。
        # peft\peft_model.pyif peft_config.peft_type == PeftType.PREFIX_TUNING:#  如果为PREFIX_TUNING,需要给每一个transformer block的key和value添加虚拟token的embedding......else:# PromptTuning/PTuningV1 分支if inputs_embeds is None:# 计算prompt以外输入内容的embeddinginputs_embeds = self.word_embeddings(input_ids)# concat prompt labelsif labels is not None:prefix_labels = torch.full((batch_size, peft_config.num_virtual_tokens), -100).to(labels.device)kwargs["labels"] = torch.cat((prefix_labels, labels), dim=1)# prompt内容的embedding    prompts = self.get_prompt(batch_size=batch_size)prompts = prompts.to(inputs_embeds.dtype)# 将prompt embedding 和原始的embedding 一起送到base model进行推理计算inputs_embeds = torch.cat((prompts, inputs_embeds), dim=1)return self.base_model(inputs_embeds=inputs_embeds, **kwargs)

1.2.2 轻量微调bloom模型

我们只需要在加载原模型后、配置训练器前加peft的代码即可。

from peft import PromptEncoderConfig, TaskType, get_peft_model, PromptEncoderReparameterizationTypeconfig = PromptEncoderConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=10,encoder_reparameterization_type=PromptEncoderReparameterizationType.MLP,encoder_dropout=0.1, encoder_num_layers=5, encoder_hidden_size=1024)model = get_peft_model(model, config)# 打印可训练参数信息
model.print_trainable_parameters()trainable params: 3,159,040 || all params: 348,928,000 || trainable%: 0.9053558327219369
  • 配置训练器、模型训练及推理和参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning中2.1一样。
  • 显存消耗情况:
(base) root@autodl-container-adbc11ae52-f2ebff02:~# nvidia-smi 
Tue May 28 15:15:53 2024       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 525.89.02    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:B1:00.0 Off |                  N/A |
| 33%   59C    P2   168W / 250W |   2870MiB / 11264MiB |     45%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------++-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

2 P-Tuning V2

Prompt Tuning和P-Tuning等方法存在两个主要的问题:

  • 第一,缺乏模型参数规模和任务通用性。

    • 缺乏规模通用性:Prompt Tuning论文中表明当模型规模超过100亿个参数时,提示优化可以与全量微调相媲美。但是对于那些较小的模型(从100M到1B),提示优化和全量微调的表现有很大差异,这大大限制了提示优化的适用性。
    • 缺乏任务普遍性:尽管Prompt Tuning和P-tuning在一些 NLU 基准测试中表现出优势,但对硬序列标记任务(即序列标注)的有效性尚未得到验证。
  • 第二,缺少深度提示优化。我们知道在Prompt Tuning和P-tuning中,只被插入transformer第一层的输入embedding序列中,在接下来的transformer层中,插入Prompt的位置的embedding是由之前的transformer层计算出来的。

    • 由于序列长度的限制,可调参数的数量是有限的。
    • 输入embedding对模型预测只有相对间接的影响。

考虑到这些问题,作者提出了P-Tuning v2。

2.1 P-Tuning V2概述

  • 论文地址:P-Tuning v2: Prompt Tuning Can Be Comparable to Fine-tuning Universally Across Scales and Tasks(2110)
  • Prefix Tuning原理如下图所示:相较于Prompt-Tuning和P-tuning,Prefix-Tuning不再将Prompt加在输入的Embedding层,而是将其作为可学习的前缀,放置在Transformer模型中的每一层中,具体表现形式为past_key_values。

在这里插入图片描述

  • P-Tuning V2和Prefix Tuning的区别主要在于:移除重参数化的编码器,即没有MLP。我们之前分析Prefix Tuning源码时,也看到了在peft库中将P-Tuning V2和Prefix Tuning进行了集成:
# peft/tuners/prefix_tuning.py# Based on https://github.com/THUDM/P-tuning-v2/blob/main/model/prefix_encoder.py
# with some refactor
class PrefixEncoder(torch.nn.Module):def __init__(self, config):super().__init__()self.prefix_projection = config.prefix_projectiontoken_dim = config.token_dimnum_layers = config.num_layersencoder_hidden_size = config.encoder_hidden_sizenum_virtual_tokens = config.num_virtual_tokensif self.prefix_projection and not config.inference_mode:# Use a two-layer MLP to encode the prefix# Prefix Tuning 进行重新参数化编码(通过MLP)self.embedding = torch.nn.Embedding(num_virtual_tokens, token_dim)self.transform = torch.nn.Sequential(torch.nn.Linear(token_dim, encoder_hidden_size),torch.nn.Tanh(),torch.nn.Linear(encoder_hidden_size, num_layers * 2 * token_dim),)else:# P-Tuning v2 self.embedding = torch.nn.Embedding(num_virtual_tokens, num_layers * 2 * token_dim)def forward(self, prefix: torch.Tensor):if self.prefix_projection:# Prefix Tuning# 先进行Embedding 此时shape为:(batch_size, num_virtual_tokens)# 再进行重新参数化编码,此时shape为:(batch_size, num_virtual_tokens, 2*layers*hidden)prefix_tokens = self.embedding(prefix)past_key_values = self.transform(prefix_tokens)else:# P-Tuning v2, 没有进行重参数化编码past_key_values = self.embedding(prefix)return past_key_values

P-Tuning V2具体做法基本同Prefix Tuning,可以看作是将文本生成的Prefix Tuning技术适配到NLU任务中,然后做了一些改进:

  • 1、移除重参数化的编码器。以前的方法利用重参数化功能来提高训练速度和鲁棒性(如:Prefix Tuning中的MLP、P-Tuning中的LSTM)。在作者发现重参数化的改进很小,尤其是对于较小的模型,同时还会影响模型的表现。
  • 2、针对不同任务采用不同的提示长度
    • 提示长度在提示优化方法的超参数搜索中起着核心作用。在实验中,作者发现不同的理解任务通常用不同的提示长度来实现其最佳性能。
    • 从图3中,可以观察到,针对简单任务:较短的Prompt(20)即可取得不错的效果。针对复杂任务:如阅读理解,需要更长的Prompt(100)。
    • 重参数化与最佳提示长度有密切关联。例如,在RTE、CoNLL04和BoolQ中,MLP重参数化比嵌入更早达到最佳结果。

在这里插入图片描述

  • 3、引入多任务学习(MPT-2)。先在多任务的Prompt上进行预训练,然后再适配下游任务。

2.2 论文部分实验

  • 对于简单的NLU任务,如SST-2(单句分类),Prompt Tuning和P-Tuning在较小的规模下没有显示出明显的劣势。但是当涉及到复杂的挑战时,如:自然语言推理(RTE)和多选题回答(BoolQ),它们的性能会非常差。
  • 相反,P-Tuning v2在较小规模的所有任务中都与微调的性能相匹配。并且,P-tuning v2在RTE中的表现明显优于微调,特别是在BERT中。

在这里插入图片描述

  • P-Tuning v2在一些困难的NLU任务中,作者选择了三个典型的序列标注任务(名称实体识别(NER)、抽取式问答(QA)和语义角色标签(SRL)),共八个数据集。作者发现P-Tuning v2在所有任务上都能与全量微调相媲美,下图只展示了NER任务的实验结果。

在这里插入图片描述

  • P-Tuning v2是一种在不同规模和任务中都可与微调相媲美的提示方法。P-Tuning v2对从330M到10B的模型显示出一致的改进,并在序列标注等困难的序列任务上以很大的幅度超过了Prompt Tuning和P-Tuning。

2.3 轻量微调bloom模型

我们只需要在加载原模型后、配置训练器前加peft的代码即可。

from peft import PrefixTuningConfig, get_peft_model, TaskType# 和Prefix Tuning不同的是设置prefix_projection=False
config = PrefixTuningConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=10, prefix_projection=False)model = get_peft_model(model, config)# 打印可训练参数信息
model.print_trainable_parameters()trainable params: 491,520 || all params: 346,260,480 || trainable%: 0.1419509382069822
  • 配置训练器、模型训练及推理和参数高效微调PEFT(一)快速入门BitFit、Prompt Tuning、Prefix Tuning中2.1一样。
  • 显存消耗情况:
(base) root@autodl-container-adbc11ae52-f2ebff02:~# nvidia-smi 
Tue May 28 15:18:39 2024       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 525.89.02    Driver Version: 525.89.02    CUDA Version: 12.0     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA GeForce ...  On   | 00000000:B1:00.0 Off |                  N/A |
| 33%   56C    P2   189W / 250W |   2826MiB / 11264MiB |     45%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------++-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
+-----------------------------------------------------------------------------+

这篇关于参数高效微调PEFT(二)快速入门P-Tuning、P-Tuning V2的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1013245

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

高效录音转文字:2024年四大工具精选!

在快节奏的工作生活中,能够快速将录音转换成文字是一项非常实用的能力。特别是在需要记录会议纪要、讲座内容或者是采访素材的时候,一款优秀的在线录音转文字工具能派上大用场。以下推荐几个好用的录音转文字工具! 365在线转文字 直达链接:https://www.pdf365.cn/ 365在线转文字是一款提供在线录音转文字服务的工具,它以其高效、便捷的特点受到用户的青睐。用户无需下载安装任何软件,只

4B参数秒杀GPT-3.5:MiniCPM 3.0惊艳登场!

​ 面壁智能 在 AI 的世界里,总有那么几个时刻让人惊叹不已。面壁智能推出的 MiniCPM 3.0,这个仅有4B参数的"小钢炮",正在以惊人的实力挑战着 GPT-3.5 这个曾经的AI巨人。 MiniCPM 3.0 MiniCPM 3.0 MiniCPM 3.0 目前的主要功能有: 长上下文功能:原生支持 32k 上下文长度,性能完美。我们引入了

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题: