3.4 Prefix-Tuning 原理与实战

目录

1 P-Tuning回顾:

2 Prefix-Tuning原理:

2.1 区别:

2.2 机制:

2.3 计算方式:

3 环境配置:

4 代码实战演练(基于Bloom模型):

4.1 导包

4.2 加载数据集

4.3 数据集处理

4.4 创建模型

4.4.1 配置文件

4.4.2 构建模型

4.5 配置训练参数

4.6 创建训练器

4.7 模型训练

4.8 模型推理


1 P-Tuning回顾:

2 Prefix-Tuning原理:

2.1 区别

  1. Prefix-Tuning的核心想法是向每个Transformer块添加可训练的张量,而不是像在P-Tuning中那样仅向输入嵌入层添加张量;
  2. Prompt-tuning微调的是加入的prompt_encoder模块中embedding的那部分参数;而Prefix tuning将prefix参数(可训练的张量)添加到所有的transformer层。

2.2 机制

将多个prompt vectors 放在每个multi-head attention的key矩阵和value矩阵之前

2.3 计算方式:

相当于微调后会训出一个固定的前缀向量。推理的时候输入的token向量化后会和这个前缀向量拼起来,再进行后面的qkv操作,模型的结构和参数都没有变,只是输入变了;注意只是将prompt vectors加在K、V上,Q、K、V的维度是一样的,但是seq_len不一定要一样。

3 环境配置:

4 代码实战演练(基于Bloom模型):

4.1 导包

from datasets import Dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForSeq2Seq, TrainingArguments, Trainer

4.2 加载数据集

ds = Dataset.load_from_disk("../data/alpaca_data_zh/")
ds

4.3 数据集处理

tokenizer = AutoTokenizer.from_pretrained("Langboat/bloom-1b4-zh")
tokenizer

def process_func(example):
    MAX_LENGTH = 256
    input_ids, attention_mask, labels = [], [], []
    instruction = tokenizer("\n".join(["Human: " + example["instruction"], example["input"]]).strip() + "\n\nAssistant: ")
    response = tokenizer(example["output"] + tokenizer.eos_token)
    input_ids = instruction["input_ids"] + response["input_ids"]
    attention_mask = instruction["attention_mask"] + response["attention_mask"]
    labels = [-100] * len(instruction["input_ids"]) + response["input_ids"]
    if len(input_ids) > MAX_LENGTH:
        input_ids = input_ids[:MAX_LENGTH]
        attention_mask = attention_mask[:MAX_LENGTH]
        labels = labels[:MAX_LENGTH]
    return {
        "input_ids": input_ids,
        "attention_mask": attention_mask,
        "labels": labels
    }

tokenized_ds = ds.map(process_func, remove_columns=ds.column_names)
tokenized_ds

4.4 创建模型

model = AutoModelForCausalLM.from_pretrained("Langboat/bloom-1b4-zh", low_cpu_mem_usage=True)

4.4.1 配置文件

from peft import PrefixTuningConfig, get_peft_model, TaskType

config = PrefixTuningConfig(task_type=TaskType.CAUSAL_LM, num_virtual_tokens=10, prefix_projection=True)
config

prefix_projection=True 时,模型将会在输入的前缀嵌入上应用一个线性变换(通常是一个全连接层),使得前缀向量可以映射到与主模型输入相同的特征空间中。

一般来讲,Prefix-Tuning包含这个,P-Tuning不包含这个。 

4.4.2 构建模型

model = get_peft_model(model, config)
model.prompt_encoder

 ModuleDict(
  (default): PrefixEncoder(
    (embedding): Embedding(10, 2048)
    (transform): Sequential(
      (0): Linear(in_features=2048, out_features=2048, bias=True)
      (1): Tanh()
      (2): Linear(in_features=2048, out_features=98304, bias=True)
    )
  )
)

model.print_trainable_parameters()

 trainable params: 205,641,728 || all params: 1,508,753,408 || trainable%: 13.629909759249406

4.5 配置训练参数

args = TrainingArguments(
    output_dir="./chatbot",
    per_device_train_batch_size=1,
    gradient_accumulation_steps=8,
    logging_steps=10,
    num_train_epochs=1
)

4.6 创建训练器

trainer = Trainer(
    model=model,
    args=args,
    train_dataset=tokenized_ds,
    data_collator=DataCollatorForSeq2Seq(tokenizer=tokenizer, padding=True),
)

4.7 模型训练

trainer.train()

4.8 模型推理

model = model.cuda()
ipt = tokenizer("Human: {}\n{}".format("数学考试有哪些技巧?", "").strip() + "\n\nAssistant: ", return_tensors="pt").to(model.device)
print(tokenizer.decode(model.generate(**ipt, max_length=256, do_sample=True)[0], skip_special_tokens=True))
### P-tuning v2 的微调原理详解 P-tuning v2 是一种针对预训练语言模型的提示微调方法,由清华大学的研究团队提出。该方法的核心目标是通过设计特定的连续型提示(continuous prompt),使模型能够更好地适应各种自然语言处理任务,尤其是对于较小规模的语言模型[^1]。 #### 提示学习的基础概念 传统的迁移学习通常依赖于全量参数微调(fine-tuning),即调整整个模型的所有权重来适配下游任务。然而,这种方法存在两个主要问题:一是计算成本高,二是容易过拟合到小型数据集上。相比之下,提示学习(prompt learning)仅优化少量可学习参数,从而显著降低资源消耗并提高泛化能力。P-tuning v2 就是在这一背景下提出的改进版本[^3]。 #### 连续型提示的设计 在 P-tuning v2 中,引入了一组虚拟标记(virtual tokens),这些标记被嵌入到输入序列中作为额外的信息源。具体来说,假设原始输入为 \(X\),则新的输入形式可以表示为 \([P, X]\),其中 \(P\) 表示一组长度固定的连续型提示向量。这些提示向量会被初始化并通过梯度下降算法进行更新,以便最大化目标任务上的表现。 以下是实现过程中的几个关键技术点: 1. **提示初始化策略** - 初始阶段,提示向量可以通过随机方式或者基于某些启发式规则设定其值域范围。 - 实验表明,采用正态分布采样的初始值往往能带来更稳定的学习曲线。 2. **联合优化机制** - 不同于早期版本只关注提示本身的质量提升,P-tuning v2 同时考虑到了如何让基础模型更好地响应所给定的提示信号。 - 此外还探索了多种损失函数组合方案以进一步增强整体框架的有效性[^2]。 3. **跨模态扩展潜力** - 鉴于当前多模态应用日益增多的趋势,研究者也尝试验证此技术能否顺利迁移到图像-文本等领域内的复杂场景之中去。 ```python import torch from transformers import BertTokenizer, BertForMaskedLM tokenizer = BertTokenizer.from_pretrained('bert-base-uncased') model = BertForMaskedLM.from_pretrained('bert-base-uncased') def create_continuous_prompt(prompt_length=10): """创建一个指定长度的连续型提示""" return torch.randn((1, prompt_length, model.config.hidden_size)) # 假设我们有一个大小为10的连续型提示 continuous_prompt = create_continuous_prompt() input_ids = tokenizer("This is a test sentence.", return_tensors="pt")["input_ids"] inputs_embeds = model.bert.embeddings(input_ids) # 将连续型提示拼接到实际输入之前 full_inputs_embeds = torch.cat([continuous_prompt, inputs_embeds], dim=1) attention_mask = torch.ones(full_inputs_embeds.shape[:2]) outputs = model(inputs_embeds=full_inputs_embeds, attention_mask=attention_mask) logits = outputs.logits ``` 上述代码片段展示了如何构建并利用连续型提示完成一次前向传播操作。值得注意的是,在真实应用场景下还需要定义合适的反向传播路径以及相应的超参调节流程等细节部分。 --- #### 性能比较分析 通过对多个基准测试集合上的实验结果对比发现,当应用于中小规模预训练模型时,P-tuning v2 显著优于其他几种主流的方法论,包括但不限于标准 Fine-Tuning 和初代 Prompt Tuning 技术。特别是在 SuperGLUE 数据集中,它能够在低于十亿参数级别的条件下达到甚至超越完全微调所带来的收益水平。 综上所述,凭借创新性的架构设计思路及其卓越的实际运用成效,使得 P-tuning v2 成为了当下极具竞争力的一项研究成果之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值