使用PEFT适配器训练
Sentence Transformers 已与 PEFT(Parameter-Efficient Fine-Tuning,参数高效微调)集成,允许您在不微调所有模型参数的情况下微调嵌入模型。相反,使用 PEFT 方法,您只需微调一小部分(额外的)模型参数,与完整模型微调相比,性能损失很小。
PEFT 适配器模型可以像任何其他模型一样加载,例如 tomaarsen/bert-base-uncased-gooaq-peft,它不包含 model.safetensors 而只包含一个微小的 adapter_model.safetensors
from sentence_transformers import SentenceTransformer
# Download from the 🤗 Hub
model = SentenceTransformer("tomaarsen/bert-base-uncased-gooaq-peft")
# Run inference
sentences = [
"is toprol xl the same as metoprolol?",
"Metoprolol succinate is also known by the brand name Toprol XL. It is the extended-release form of metoprolol. Metoprolol succinate is approved to treat high blood pressure, chronic chest pain, and congestive heart failure.",
"Metoprolol starts to work after about 2 hours, but it can take up to 1 week to fully take effect. You may not feel any different when you take metoprolol, but this doesn't mean it's not working. It's important to keep taking your medicine"
]
embeddings = model.encode(sentences)
print(embeddings.shape)
# [3, 768]
# Get the similarity scores for the embeddings
similarities = model.similarity(embeddings[0], embeddings[1:])
print(similarities)
# tensor([[0.7913, 0.4976]])
兼容性方法
SentenceTransformer 支持 7 种与 PEFT 适配器交互的方法
add_adapter(): 为当前模型添加一个新的适配器进行训练。
load_adapter(): 从文件或 Hugging Face Hub 仓库加载适配器权重。
active_adapters(): 获取当前活动的适配器。
set_adapter(): 告诉您的模型使用特定的适配器并禁用所有其他适配器。
enable_adapters(): 启用所有适配器。
disable_adapters(): 禁用所有适配器。
get_adapter_state_dict(): 获取包含权重的适配器状态字典。
delete_adapter(): 从模型中删除适配器。
添加新适配器
向模型添加新适配器就像在初始化好的 Sentence Transformer 模型上调用 add_adapter() 并传入一个(PeftConfig 的子类)一样简单。在以下示例中,我们使用一个 LoraConfig 实例。
from sentence_transformers import SentenceTransformer
# 1. Load a model to finetune with 2. (Optional) model card data
model = SentenceTransformer(
"all-MiniLM-L6-v2",
model_card_data=SentenceTransformerModelCardData(
language="en",
license="apache-2.0",
model_name="all-MiniLM-L6-v2 adapter finetuned on GooAQ pairs",
),
)
# 3. Create a LoRA adapter for the model & add it
peft_config = LoraConfig(
task_type=TaskType.FEATURE_EXTRACTION,
inference_mode=False,
r=64,
lora_alpha=128,
lora_dropout=0.1,
)
model.add_adapter(peft_config)
# Proceed as usual... See https://sbert.net.cn/docs/sentence_transformer/training_overview.html
加载预训练适配器
我们基于 bert-base-uncased 基础模型创建了一个名为 tomaarsen/bert-base-uncased-gooaq-peft 的小型适配器模型。
这个 adapter_model.safetensors 只有 9.44MB,仅占基础模型 model.safetensors 大小的 2.14%。要加载这样的适配器模型,您可以直接加载此适配器
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("tomaarsen/bert-base-uncased-gooaq-peft")
embeddings = model.encode(["This is an example sentence", "Each sentence is converted"])
print(embeddings.shape)
# (2, 768)
或者您可以加载基础模型,然后将适配器加载到其中
from sentence_transformers import SentenceTransformer
model = SentenceTransformer("bert-base-uncased")
model.load_adapter("tomaarsen/bert-base-uncased-gooaq-peft")
embeddings = model.encode(["This is an example sentence", "Each sentence is converted"])
print(embeddings.shape)
# (2, 768)
在大多数情况下,前者更简单,因为它无论模型是否是适配器模型都能工作。
训练脚本
请参阅以下示例文件,了解 PEFT 如何与 Sentence Transformers 一起使用的完整示例
training_gooaq_lora.py: 这是一个简单的食谱,用于使用出色的 MultipleNegativesRankingLoss 在 GooAQ 问答数据集上微调 bert-base-uncased,但它已改编为使用 PEFT 中的 LoRA 适配器。
该脚本用于训练 tomaarsen/bert-base-uncased-gooaq-peft,在 NanoBEIR 基准测试中达到了 0.4705 NDCG@10;仅略低于 tomaarsen/bert-base-uncased-gooaq,后者通过使用完整模型微调的修改脚本获得了 0.4728 NDCG@10。