临沂企业建站系统模板,毕设给学校做网站,桂林网站建设服务,网站备案通过简介
Prefix Tuning是2021.01提出来的#xff0c;在它之前#xff0c;我们使用prompt主要是人工设计模板或者自动化搜索模板#xff0c;也就是prompt范式的第一阶段#xff0c;就是在输入上加上prompt文本#xff0c;再对输出进行映射。这种离散模板对模型的鲁棒性很差。…简介
Prefix Tuning是2021.01提出来的在它之前我们使用prompt主要是人工设计模板或者自动化搜索模板也就是prompt范式的第一阶段就是在输入上加上prompt文本再对输出进行映射。这种离散模板对模型的鲁棒性很差。所以后续的研究都将离散生成prompt方式转成连续的方式。
Prefix Tuning是在模型输入前添加一个连续的且是任务特定的向量序列该序列称之为prefix然后在训练的时候固定PLM的所有参数只更新优化特定任务的prefix。
实现思路
1、与Full Fine Tuning对比
从下图上看对于FFT,我们在微调的时候需要更新所有的PLM的参数训练时需要大量的数据而且耗费的资源和时间比较多。
Prefix Tuning针对特定的任务只更新前缀那部分的参数训练时只需要很少的数据训练速度也非常快。 2、自回归模型与Encoder-Decoder模型的实现区别
对于类似于GPT-2的自回归模型最终的结果 z [PREFIX; x; y]参考下图的上半部分
对于类似于BART的Encoder-Decoder模型最终的结果z [PREFIX; x; PREFIX0 ; y]参考下图的下半部分 实验效果 从实验的效果看还是非常不错的 在HF的PEFT中的实现
1、下面是代码实现
2、我们需要关注的仅仅是PrefixTuningConfig类的num_virtual_tokens
from peft import PromptTuningConfig, PromptTuningInit, get_peft_model
from transformers import get_linear_schedule_with_warmup
from tqdm import tqdmpeft_config PrefixTuningConfig(task_typeCAUSAL_LM, num_virtual_tokens20)
model get_peft_model(model, peft_config)
model.print_trainable_parameters()
#trainable params: 983,040 || all params: 560,197,632 || trainable%: 0.1754809274167014lr 3e-2
num_epochs 50optimizer torch.optim.AdamW(model.parameters(), lrlr)
lr_scheduler get_linear_schedule_with_warmup(optimizeroptimizer,num_warmup_steps0,num_training_steps(len(train_dataloader) * num_epochs),
)device cuda
model model.to(device)for epoch in range(num_epochs):model.train()total_loss 0for step, batch in enumerate(tqdm(train_dataloader)):batch {k: v.to(device) for k, v in batch.items()}outputs model(**batch)loss outputs.losstotal_loss loss.detach().float()loss.backward()optimizer.step()lr_scheduler.step()optimizer.zero_grad()model.eval()eval_loss 0eval_preds []for step, batch in enumerate(tqdm(eval_dataloader)):batch {k: v.to(device) for k, v in batch.items()}with torch.no_grad():outputs model(**batch)loss outputs.losseval_loss loss.detach().float()eval_preds.extend(tokenizer.batch_decode(torch.argmax(outputs.logits, -1).detach().cpu().numpy(), skip_special_tokensTrue))eval_epoch_loss eval_loss / len(eval_dataloader)eval_ppl torch.exp(eval_epoch_loss)train_epoch_loss total_loss / len(train_dataloader)train_ppl torch.exp(train_epoch_loss)print(f{epoch}: {train_ppl} {train_epoch_loss} {eval_ppl} {eval_epoch_loss})
结论
1、prefix部分到底使用多少个虚拟token直接影响模型微调的参数量级以及处理长文本的能力。默认的prefix长度为10
2、不同的前缀长度有不一样的性能表现在一定程度上长度越长prefix的效果越明显但也可能出现降低的问题。
3、实验表明prefix长度对推理速度影响不大因为prefix上的attention计算是并行的。
4、前缀调整通过向输入序列插入特定于任务的前缀来修改模型的更多层因此需要对更多参数进行微调
5、与Fine-tuning对比Fine-tuning需要根据不同的任务训练所有的参数所以所有的任务都需要copy一份model但是prefix-tuning只需要优化prefix所以只需要存储一个大的Transformer和一个学习得来的特定任务的prefix。
6、此外prefix-tuning是模块化的训练一个上游LM引导下游的LM而下游的LM保持不变。因此一个单一的LM可以一次性支持多个任务。所以基于prefix的体系结构可以使我们能再单个batch中处理多个用户的任务。