1. 论文介绍
1.1 之前的方法存在的局限性
- 缺乏跨尺度的普遍性。
模型参数较少时,远不如微调
- 任务间缺乏通用性。
有效性可能只能局限在一些特定的任务中
1.2 当前方法的改进
如上图所示,不同层中的promote被添加为前缀令牌
1.3 优化与实现
- embedding VS MLP重参数化
作者的观点是:它的有用性取决于任务和数据集。(如上图
- Prompt 长度
一般来说,简单的分类任务喜欢较短的提示(少于20个);硬序列标记任务倾向于较长的序列(大约100个)。
- 多任务学习
对于P-Tuning v2来说,多任务是可选的,但可以通过提供更好的初始化来进一步提高性能
- 分类头
使用语言建模头来预测语言表达器可以实现快速调整模型,但我们发现在全数据设置中没有必要,并且与序列标记不兼容。
2. 代码
以执行的SequenceClassification的Roberta的模型为例,即
2.1调用
P-Tuning v2在forward函数中:通过调用get_prompt获得的embedding传入到RobertaModel类的参数
2.1.1 get_prompt
get_prompt使用PrefixEncoder类生成embedding
def get_prompt(self, batch_size):
prefix_tokens = self.prefix_tokens.unsqueeze(0).expand(batch_size, -1).to(self.roberta.device)
past_key_values = self.prefix_encoder(prefix_tokens)
past_key_values = past_key_values.view(
batch_size,
self.pre_seq_len,
self.n_layer * 2,
self.n_head,
self.n_embd
)
past_key_values = self.dropout(past_key_values)
past_key_values = past_key_values.permute([2, 0, 3, 1, 4]).split(2)
return past_key_values
prefix_encoder 用的只是最简单的embedding
2.1.2RobertaModel类
get_prompt得到的embedding传入了RobertaModel类的past_key_values参数
主要关注该类中的传入参数:past_key_values,在该类中的embeddings,encoder,输出都使用了
2.1.2.1 RobertaEmbeddings
embeddings即实例化之后的RobertaEmbeddings,在当前这个例子中,由于有传入position_ids所以其实embedding并不受到P-Tuning v2作用
2.1.2.2 RobertaEncoder
encoder,即RobertaEncoder实例化,其中的forward函数中会遍历RobertaEncoder所有的层结构并将P-Tuning v2生成的embedding,这也是主要的影响因素
最终作用在自注意力机制RobertaSelfAttention中
2.1.2.3 BaseModelOutputWithPoolingAndCrossAttentions
在BaseModelOutputWithPoolingAndCrossAttentions实际上输出的是RobertaEncoder输出的最后一层作为past_key_values
2.1.3 和 P-Tuning v1进行对比
在P-Tuning v1传入的是inputs_embeds,只会作用一次