AI大模型微调教程3

部署运行你感兴趣的模型镜像

https://www.bilibili.com/video/BV1r9ieYhEuZ?spm_id_from=333.788.videopod.episodes&vd_source=3969f30b089463e19db0cc5e8fe4583a&p=10

1、目录

2、大模型概览

few-shot中放10个例子, 变成finetune的data中放1000个例子,把这些知识存到模型中。

多任务可以提高模型的泛化能力。

3、PEFT(Parameter Efficient Fine-Tuning)

4、微调

几种微调方法:

Full Finetune时占用的资源大小:

改造的方法:继承原先的类,修改部分方法。

改动最核心的单元:那就是线性转化,即矩阵乘积的部分。

核心思想:把所有的线性转化遍历一遍,然后判断下该转换是否需要替换。

5、基于peft微调实例

(1)训练代码

from transformers import AutoTokenizer, AutoModelForSequenceClassification, TrainingArguments, Trainer, DataCollatorWithPadding
from peft import get_peft_model, LoraConfig, TaskType
from datasets import load_dataset, Dataset, DatasetDict
import torch
import pandas as pd
import os

# 1. 加载预训练模型和分词器
model_name = "/data/xiehao/workspace/models/bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

# 2. 配置LORA
peft_config = LoraConfig(
    task_type=TaskType.SEQ_CLS,       # 序列分类任务
    r=8,                              # 低秩矩阵的秩
    lora_alpha=32,                    # 缩放因子
    lora_dropout=0.1,                 # dropout
    target_modules=["query", "value"] # 对哪些模块引用Lora(这里是注意力中的query和value层)
)

# 将模型转为 PEFT模型(Lora)
model = get_peft_model(model, peft_config)
model.print_trainable_parameters()  # 查看可训练参数量

# 3. 加载数据集(以情感分析为例)
data_dir = "/data/xiehao/workspace/datas/sst2/data"

# 获取文件路径(使用通配匹配)
files = os.listdir(data_dir)
train_file = [f for f in files if f.startswith("train")][0]
val_file   = [f for f in files if f.startswith("dev")][0]   # dev 对应 validation
test_file  = [f for f in files if f.startswith("test")][0]

# 完整路径
train_path = os.path.join(data_dir, train_file)
val_path   = os.path.join(data_dir, val_file)
test_path  = os.path.join(data_dir, test_file)

# 用 pandas 读取 Parquet
train_df = pd.read_parquet(train_path)
val_df   = pd.read_parquet(val_path)
test_df  = pd.read_parquet(test_path)

# 转为 Hugging Face Dataset
train_dataset = Dataset.from_pandas(train_df)
val_dataset   = Dataset.from_pandas(val_df)
test_dataset  = Dataset.from_pandas(test_df)

# 构建成 DatasetDict
dataset = DatasetDict({
    "train": train_dataset,    # 只对训练集采样 1000 条用于快速训练
    "validation": val_dataset,
    "test": test_dataset
})

# 分词函数
def tokenize_function(examples):
    return tokenizer(examples["sentence"], truncation=True, max_length=512)

# 对数据集进行分词
tokenized_datasets = dataset.map(tokenize_function, batched=True)

# 4. 设置训练参数
data_collator = DataCollatorWithPadding(tokenizer)

training_args = TrainingArguments(
    output_dir="./lora-sst2",
    learning_rate=2e-4,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,      # 推荐设置
    num_train_epochs=3,
    weight_decay=0.01,
    logging_dir="./logs",
    logging_steps=10,
    save_strategy="epoch",
    eval_strategy="epoch",              # 老版本用 eval_strategy
    report_to="none"
)

# 5. 创建 Trainer
trainer = Trainer(
    model=model,
    args=training_args,                 # ✅ 引用正确的变量名
    train_dataset=tokenized_datasets["train"],
    eval_dataset=tokenized_datasets["validation"],  # 推荐加入验证集
    data_collator=data_collator,
    tokenizer=tokenizer,
)

# 6. 开始训练
trainer.train()

# 7. 保存 LoRA 适配器
model.save_pretrained("/data/xiehao/workspace/models/lora-sst2-adapter")

训练日志:

数据集:https://www.modelscope.cn/datasets/jxm/sst2/dataPeview

(2)推理的代码

from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
from peft import PeftModel, PeftConfig

# 1. 指定路径
base_model_name = "/data/xiehao/workspace/models/bert-base-uncased"          # 原始 BERT 模型
lora_adapter_path = "/data/xiehao/workspace/models/lora-sst2-adapter"        # 你保存的 LoRA 权重

# 2. 加载分词器
tokenizer = AutoTokenizer.from_pretrained(base_model_name)

# 3. 加载基础模型(不带分类头)
model = AutoModelForSequenceClassification.from_pretrained(
    base_model_name,
    num_labels=2  # 必须和训练时一致
)

# 4. 使用 PEFT 加载 LoRA 适配器
model = PeftModel.from_pretrained(model, lora_adapter_path)

# 5. 设置为评估模式(关闭 dropout 等)
model.eval()

# 6. 创建推理 pipeline(推荐方式,最简单)
classifier = pipeline(
    "text-classification",
    model=model,
    tokenizer=tokenizer,
    device=0 if torch.cuda.is_available() else -1  # 使用 GPU (0) 或 CPU (-1)
)

# 7. 测试一些句子
sentences = [
    "This movie is amazing! I loved every minute of it.",
    "It was boring and poorly acted.",
    "A fantastic film with great direction."
]

results = classifier(sentences)

# 8. 打印结果
for sentence, result in zip(sentences, results):
    label = "正面 (Positive)" if result["label"] == "LABEL_1" else "负面 (Negative)"
    score = result["score"]
    print(f"句子: {sentence}")
    print(f"预测: {label}, 置信度: {score:.4f}\n")

运行结果:

(3)代码解读

1)transformers:是Hugging Face的Transformers库

AutoTokenizer:匹配模型的分词器

AutoModelForSequenceClassification:分类任务的预训练模型

TrainingArguments:训练的超参

Trainer:训练接口

DataCollatorWithPadding:动态填充batch中的样本到相同长度

【DataCollatorWithPadding说明】

为什么要填充到相同长度?

因为GPU和深度学习框架(比如PyTorch)要求一个batch的输入必须是”规则的张量“(即形状统一),才能进行高效的并行计算。

为什么要动态?

节省空间,每一批相同即可。

工作流程?

  • 通过DataLoader拿到一个batch的原始样本(未对齐长度)
  • 找出这个batch中最长的序列
  • 把所有其他样本用[PAD]填充到相同长度
  • 返回input_ids, attention_mask, token_type_ids等张量
  • 模型通过attention_mask忽略padding位置

2)peft:Parameter-Efficient Fine-Tuning库,用于轻量微调

LoraConfig:LoRA的配置类,定义低秩适配参数

get_peft_model:将原始模型包装为支持LoRA的模型

TaskType.SEQ_CLS:指定任务类型为“序列分类”

3)tokenizer = AutoTokenizer.from_pretrained(model_name)

加载模型对应的分词器。

它会自动识别这是BERT分词器,并加载其词汇表

4)model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2)

加载预训练的Bert模型,并在顶部添加一个分类头(classifier head),输出2个类别。

此时的整个模型是“全参数可训练”的。

5)创建 LoRA 配置对象

peft_config = LoraConfig(
    task_type=TaskType.SEQ_CLS,       # 序列分类任务
    r=8,                              # 低秩矩阵的秩(rank),越小越轻量
    lora_alpha=32,                    # 缩放因子,影响 LoRA 权重对原权重的影响程度
    lora_dropout=0.1,                 # 在 LoRA 层中加入 dropout,防止过拟合
    target_modules=["query", "value"] # 对哪些模块应用 LoRA(通常是注意力机制中的 Q 和 V)
)

r=8: 表示新增的小矩阵维度是 d × 8 和 8 × d,大幅减少参数量。

lora_alpha=32: 控制 LoRA 更新的强度,通常设置为 2×r 或更大。

output = (W + (1/α) * B @ A)

target_modules=["query", "value"]: 只在 self-attention 的 query 和 value 投影层上加 LoRA,这是常见做法,节省计算资源。

6)model = get_peft_model(model, peft_config)

将原始 BERT 模型转换为 PEFT 模型(即带 LoRA 适配器的模型)。

此时,原始 BERT 参数被冻结(不可训练),只有 LoRA 新增的小矩阵是可训练的。

7)model.print_trainable_parameters()

打印当前模型中可训练参数的数量和总参数比例。比如上例中是0.27%。

8)data_collator = DataCollatorWithPadding(tokenizer)

创建一个“数据整理器”,在每个 batch 中将不同长度的序列动态填充到该 batch 内的最大长度,提高效率。

9)配置训练超参

training_args = TrainingArguments(
    output_dir="./lora-sst2",
    learning_rate=2e-4,
    per_device_train_batch_size=16,
    per_device_eval_batch_size=16,
    num_train_epochs=3,
    weight_decay=0.01,
    logging_dir="./logs",
    logging_steps=10,
    save_strategy="epoch",
    eval_strategy="epoch",
    report_to="none"
)
参数含义
output_dir保存模型检查点的目录
learning_rate=2e-4LoRA 推荐学习率(比全参数微调高)
per_device_*_batch_size每张 GPU 的 batch 大小
num_train_epochs=3训练 3 轮
weight_decay=0.01L2 正则化,防过拟合
logging_steps=10每 10 步记录一次 loss
save_strategy="epoch"每个 epoch 保存一次 checkpoint
eval_strategy="epoch"每个 epoch 在验证集上评估一次
report_to="none"不连接 wandb/tensorboard

L1/L2正则化的区别:

正则化核心操作效果
L1惩罚权重的绝对值之和让部分权重变为 0 → 实现特征选择模型压缩
L2惩罚权重的平方和让所有权重变小、更分散 → 提升泛化能力,防止过拟合

L1让模型依赖某几个重要的特征,L2让模型不要依赖某几个重要的特征。

10)创建推理pipeline

classifier = pipeline(
    "text-classification",
    model=model,
    tokenizer=tokenizer,
    device=0 if torch.cuda.is_available() else -1  # 使用 GPU (0) 或 CPU (-1)
)

pipeline是Hugging Face Transformers库提供的一个接口,它的特点是:

自动化:自动处理分词、张量转换、模型前向传播、输出解码等步骤

简单易用:一行代码就能构建一个完整的NLP应用

Hugging Face中预定义的任务:

任务字符串用途
"text-classification"情感分析、垃圾邮件检测等
"token-classification"命名实体识别(NER)、词性标注
"question-answering"阅读理解(给一段文本和问题,返回答案)
"summarization"文本摘要
"translation"机器翻译
"text-generation"生成文本(如 GPT)

当调用classifier(text)时,pipeline的内部过程:

  1. 分词(Tokenization)
    inputs = tokenizer(text, return_tensors="pt")
  2. 移动到 GPU(如果指定)
    inputs = {k: v.to(model.device) for k, v in inputs.items()}
  3. 前向传播(Forward Pass)
    with torch.no_grad():
        outputs = model(**inputs)
  4. 解码输出(Decode logits)
    probs = torch.softmax(outputs.logits, dim=-1)
    pred_class = probs.argmax().item()
    confidence = probs.max().item()
  5. 返回人类可读结果
    return [{"label": "POSITIVE", "score": 0.9987}]

您可能感兴趣的与本文相关的镜像

Llama Factory

Llama Factory

模型微调
LLama-Factory

LLaMA Factory 是一个简单易用且高效的大型语言模型(Large Language Model)训练与微调平台。通过 LLaMA Factory,可以在无需编写任何代码的前提下,在本地完成上百种预训练模型的微调

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值