1. 使用Hugging Face PEFT库对进行LoRA微调
任务目标
本案例将加载预训练的 模型,使用 Hugging Face PEFT 库为其注入 LoRA 适配器,在一个小型文本数据集上完成微调,并通过困惑度(Perplexity)指标验证微调前后模型性能的变化。
环境依赖
需要安装以下 Python 包:
pip install transformers datasets peft accelerate torch
完整实现代码
import math
import torch
from datasets import load_dataset
from transformers import AutoTokenizer, AutoModelForCausalLM, DataCollatorForLanguageModeling, Trainer, TrainingArguments
from peft import LoraConfig, get_peft_model, TaskType
# 1. 加载模型与分词器
model_name = ""
tokenizer = AutoTokenizer.from_pretrained(model_name)
tokenizer.pad_ = tokenizer.eos_
model = AutoModelForCausalLM.from_pretrained(model_name)
# 2. 配置 LoRA
lora_config = LoraConfig(
task_type=TaskType.CAUSAL_LM,
r=8,
lora_alpha=32,
lora_dropout=0.1,
target_modules=["c_attn"], # 的注意力层模块
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters() # 应显示仅约 0.1% 参数可训练
# 3. 加载小型数据集(使用 WikiText-2 的 1% 子集)
dataset = load_dataset("wikitext", "wikitext-2-raw-v1", split="train[:1%]")
dataset = dataset.filter(lambda x: len(x["text"]) > 50) # 过滤过短样本
# 4. 数据预处理
def tokenize_function(examples):
return tokenizer(examples["text"], truncation=True, max_length=128)
tokenized_dataset = dataset.map(tokenize_function, batched=True, remove_columns=["text"])
data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)
# 5. 微调前评估(困惑度)
def compute_perplexity(model, dataset):
model.eval()
total_loss = 0.0
count = 0
with torch.no_grad():
for batch in torch.utils.data.DataLoader(dataset.select(range(50)), batch_size=4, collate_fn=data_collator):
input_ids = batch["input_ids"].to(model.device)
attention_mask = batch["attention_mask"].to(model.device)
labels = batch["labels"].to(model.device)
outputs = model(input_ids=input_ids, attention_mask=attention_mask, labels=labels)
total_loss += outputs.loss.item() * input_ids.size(0)
count += input_ids.size(0)
avg_loss = total_loss / count
return math.exp(avg_loss)
# 将模型移至 GPU(如可用)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
# 微调前困惑度
ppl_before = compute_perplexity(model, tokenized_dataset)
print(f"微调前困惑度: {ppl_before:.2f}")
# 6. 配置训练参数并微调
training_args = TrainingArguments(
output_dir="./-lora-finetuned",
per_device_train_batch_size=4,
num_train_epochs=3,
logging_steps=50,
save_strategy="no",
report_to=[],
disable_tqdm=False,
)
trainer = Trainer(
model=model,
args=training_args,
train_dataset=tokenized_dataset,
data_collator=data_collator,
)
trainer.train()
# 7. 微调后评估
ppl_after = compute_perplexity(model, tokenized_dataset)
print(f"微调后困惑度: {ppl_after:.2f}")
print(f"困惑度下降幅度: {ppl_before - ppl_after:.2f}")
# 8. 保存 LoRA 适配器
model.save_pretrained("./-lora-adapter")
运行方式
将上述代码保存为 finetune__lora.py,在终端执行:
python finetune__lora.py
验证方法与判定标准
- 参数效率验证:运行代码时,
model.print_trainable_parameters()应输出可训练参数占比约为 0.1%(约 0.3M 参数),证明 LoRA 仅微调少量参数。 - 训练收敛验证:训练日志中的 loss 应随步数增加呈下降趋势。
- 效果验证:程序最终打印的微调后困惑度应明显低于微调前困惑度(例如从约 30 降至 20 以下),且困惑度下降幅度为正值,即证明 LoRA 微调有效提升了模型对训练数据分布的拟合能力。
预期输出示例
trainable params: 294,912 || all params: 125,619,456 || trainable%: 0.2347
微调前困惑度: 32.45
...
微调后困惑度: 18.72
困惑度下降幅度: 13.73
以上数值仅为基于代码逻辑的示例,实际结果会因随机种子和数据集采样而略有不同。