传统 embedding vs. P-Tuning 里的 embedding
1. 传统 Prompt 是“死的”
在普通的 Prompt Learning(提示学习) 里,我们会给大模型一个固定的文本提示(Prompt),让它更容易理解任务,比如:
📌 例子 1:情感分析任务
-
普通输入:
这个电影真好看!
-
如果模型没学过情感分析,它可能不会判断“好看”是积极情绪。
-
用 Prompt 让它更容易理解:
这个电影真好看![情感分析] => 它的情感是:
-
这样,模型更可能回答 “积极”。
这里的 “[情感分析] => 它的情感是:” 就是一个 Prompt,但这个 Prompt 是 固定的,不能自动优化。
2. P-Tuning:让 Prompt 变成“活的”
P-Tuning 不直接使用文本 Prompt,而是让模型学出一组“最优的提示”。
👉 这个最优提示不是文本,而是一组可训练的 embedding(向量)。
📌 例子 2:P-Tuning 版本
假设我们仍然做情感分析,但不直接给 "情感分析"
这个文本,而是让模型自己学习一个最合适的提示:
[𝑣1, 𝑣2, 𝑣3, 𝑣4, 𝑣5] + "这个电影真好看!"
其中 [𝑣1, 𝑣2, 𝑣3, 𝑣4, 𝑣5]
不是普通的词,而是可训练的 embedding(一串向量)。
这意味着:
- 这 5 个 embedding 可能对应着一些类似 “情感判断”、“评分”、“积极/消极” 之类的信息,但它们不是具体的汉字,而是神经网络里的一组数值(向量)。
- 训练时,这些 embedding 会调整,找到最适合这个任务的“提示”方式。
3. 传统 embedding vs. P-Tuning 里的 embedding
你可能会问:
“embedding 不是文本转向量的东西吗?怎么会和 Prompt 关联?”
这里有两个不同的 embedding 概念:
-
普通 embedding(词向量)
- 比如
"电影"
这个词,在 Word2Vec 里有个向量[0.2, 0.5, -0.3, ...]
。 - 这是 对输入文本本身做 embedding,让计算机理解文本。
- 比如
-
P-Tuning 里的可训练 embedding
- 不是从文本转出来的,而是 单独创建一组向量,作为 Prompt 的一部分。
- 它的作用是 让模型更容易适应任务,就像让模型自己“想办法找到最优的提示”。
📌 类比
- 传统 embedding:像是字典,每个单词都有固定的定义。
- P-Tuning embedding:像是 AI 自己创造的“专属记号”,它发现“如果给自己一个特定的记号(embedding),就能更好地回答问题”。
4. 真实应用场景
🚀 假设你在训练一个 LLaMA 模型,让它做新闻分类:
- 传统方式:你可能会写
"这是一篇 [财经] 新闻,内容如下:..."
,让它学财经分类。 - P-Tuning 方式:你不给
"财经"
这个词,而是让它学到 “一个特殊的 embedding 组合”,这组 embedding 可能等效于 “财经” 这个提示,但它不是具体的汉字,而是数值向量。
最终:
- 模型学到的 embedding 就相当于最适合这个任务的 Prompt。
- 但这个 Prompt 不是固定文本,而是可以优化的向量,在训练过程中不断调整。
5. 总结
✔ Prompt 只是“提示”,但 P-Tuning 让提示变成了“可训练的 embedding”
✔ 传统 Prompt 是死的,P-Tuning 让 Prompt 变活了(可学习)
✔ P-Tuning 本质上是“让模型自动找到最适合的 Prompt 方式”
✔ 它的 Prompt 不是文本,而是一组 embedding 向量,这些向量会在训练时不断优化
📌 换句话说:
P-Tuning = 不让人手写 Prompt,而是让 AI 自己找到最优的提示方式(embedding) 🎯
下面使用 P-Tuning 进行文本分类的代码示例,我们使用 Hugging Face 的 transformers 库和 OpenPrompt 框架来实现。
下面是一个使用 P-Tuning 进行文本分类的代码示例,我们使用 Hugging Face 的 transformers 库和 OpenPrompt 框架来实现。
📌 任务:情感分析
我们用一个预训练的 GPT 模型,并使用 P-Tuning 来让它更好地识别文本的情感(积极 / 消极)。
1️⃣ 安装依赖
先安装 openprompt
和 transformers
:
pip install openprompt transformers
2️⃣ 加载 GPT 预训练模型
from transformers import AutoModelForCausalLM, AutoTokenizer
# 加载 GPT-2 预训练模型
model_name = "gpt2"
model = AutoModelForCausalLM.from_pretrained(model_name)
tokenizer = AutoTokenizer.from_pretrained(model_name)
我们选择 GPT-2 作为基础模型,但你也可以用其他支持 P-Tuning 的模型,如 gpt2-medium
或 LLaMA
。
3️⃣ 定义 P-Tuning 任务
使用 openprompt
设定 P-Tuning 任务:
from openprompt.data_utils import InputExample
from openprompt.plms import load_plm
from openprompt.prompts import SoftTemplate
from openprompt import PromptForClassification
# 定义数据
data = [
InputExample(text_a="这部电影真的太棒了!", label=1),
InputExample(text_a="太无聊了,看得我想睡觉", label=0)
]
# 载入预训练语言模型 (PLM)
plm, tokenizer, model_config = load_plm("gpt2", "gpt2")
# 使用 Soft Prompt (P-Tuning 的核心部分)
template = SoftTemplate(
model=plm,
text='{"placeholder":"text_a"} 它的情感是 {"mask"}',
tokenizer=tokenizer
)
# 设定分类任务
model = PromptForClassification(
plm=plm,
template=template,
freeze_plm=True, # 关键点:不调整 GPT-2 的参数,只训练 Prompt
label_words={"0": "消极", "1": "积极"}
)
🔍 代码解析
-
SoftTemplate
{"placeholder":"text_a"}
:表示输入的文本它的情感是 {"mask"}
:这里的{"mask"}
位置是 GPT 需要预测的部分- P-Tuning 的核心 就是让
{"mask"}
前的内容变成可训练 embedding,而不是固定文本。
-
freeze_plm=True
- 这行代码确保 GPT-2 本身的参数不会改变,我们只优化 Prompt 的 embedding。
-
label_words
- 让 GPT 学会预测
"消极"
或"积极"
作为分类标签。
- 让 GPT 学会预测
4️⃣ 训练 P-Tuning
from openprompt import PromptDataLoader
from transformers import AdamW
# 定义 DataLoader
train_dataloader = PromptDataLoader(
dataset=data,
tokenizer=tokenizer,
template=template,
tokenizer_wrapper_class=plm.wrapper_class,
batch_size=2
)
# 训练 P-Tuning Prompt(只优化 Prompt 的 embedding)
optimizer = AdamW(model.template.parameters(), lr=1e-3)
for epoch in range(5):
for batch in train_dataloader:
loss = model(batch)
loss.backward()
optimizer.step()
optimizer.zero_grad()
print(f"Epoch {epoch + 1}: Loss = {loss.item():.4f}")
🔍 代码解析
PromptDataLoader
用于处理数据,使其符合 P-Tuning 格式。- 只优化 Prompt embedding(
model.template.parameters()
)。 loss.backward()
+optimizer.step()
进行反向传播优化。
5️⃣ 测试 P-Tuning 效果
def predict(text):
example = InputExample(text_a=text)
batch = template.wrap_one_example(example)
batch = tokenizer(batch, return_tensors="pt")
with torch.no_grad():
output = model(batch)
label = output.argmax(dim=-1).item()
return "积极" if label == 1 else "消极"
print(predict("这部电影真的很好看!")) # 应该输出:积极
print(predict("太差了,我再也不会看了!")) # 应该输出:消极
📌 总结
- P-Tuning 的核心 是:用可训练的 embedding 代替固定的文本 Prompt,让模型自己学习最优的提示方式。
- 不修改模型参数,只是优化 Prompt embedding,训练更高效。
- 适用于分类、情感分析、问答等 NLP 任务,相比普通 Prompt,效果更好。
💡 你可以试试改成自己的数据集,比如电商评论分类、电影评分预测等! 🚀