大模型全量微调与部分参数微调技术概述

本文探讨了大模型微调的两种策略:全量微调和部分参数微调。在部分参数微调中,介绍了Adaper-Tuning、LORA和Prefix-Tuning方法。Adater-Tuning通过降维降低成本和过拟合风险;LORA利用低秩矩阵适应任务需求;Prefix-Tuning则通过附加训练 Embedding 层实现自动化提示词工程。并提到了微调实战案例,如使用LORA微调ChatGLM3-6B。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 全量微调

1.1 全量微调的主要步骤

  1. 选择预训练模型:根据任务需求选择合适的基础模型(如BERT、GPT等)
  2. 准备任务特定数据:收集并处理针对特定任务的标注数据集
  3. 设置微调参数:选择合适的学习率、批次大小和训练周期
  4. 更新所有权重:使用梯度下降等优化算法调整模型的全部参数
  5. 验证与测试:在验证集和测试集上评估模型性能

1.2 全量微调的缺点

  • 需要大量计算资源
  • 训练时间长
  • 易导致过拟合
  • 不适合快速部署多任务

1.3 全量微调实战

使用 Hugging Face 的 transformers 库来微调一个BERT模型,用于一个简单的情感分析任务(二分类问题)。

import torch
from torch.utils.data import DataLoader, RandomSampler, SequentialSampler
from transformers import BertTokenizer, BertForSequenceClassification, AdamW
from transformers import get_linear_schedule_with_warmup
from sklearn.model_selection import train_test_split
import pandas as pd
from tqdm import tqdm

# 例子中的数据
data = {
    'text': ["I love this product", "This is the worst thing I've ever bought"],
    'label': [1, 0]
}
df = pd.DataFrame(data)

# 划分训练集和测试集
train_texts, val_texts, train_labels, val_labels = train_test_split(df['text'], df['label'], test_size=0.2, random_state=2020)

# 载入预训练的BERT模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased')

# 编码文本
train_encodings = tokenizer(train_texts.to_list(), truncation=True, padding=True, max_length=64)
val_encodings = tokenizer(val_texts.to_list(), truncation=True, padding=True, max_length=64)

# 转换为torch dataset
class SentimentDataset(torch.utils.data.Dataset):
    def __init__(self, encodings, labels):
        self.encodings = encodings
        self.labels = labels

    def __getitem__(self, idx):
        item = {key: torch.tensor(val[idx]) for key, val in self.encodings.items()}
        item['labels'] = torch.tensor(self.labels[idx])
        return item

    def __len__(self):
        return len(self.labels)

train_dataset = SentimentDataset(train_encodings, train_labels.to_list())
val_dataset = SentimentDataset(val_encodings, val_labels.to_list())

# 数据加载器
train_loader = DataLoader(train_dataset, batch_size=16, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=16, shuffle=False)

# 优化器和学习率调度器
optimizer = AdamW(model.parameters(), lr=5e-5)
num_training_steps = len(train_loader) * 3 # 总训练步数
scheduler = get_linear_schedule_with_warmup(optimizer, num_warmup_steps=0, num_training_steps=num_training_steps)

# 微调模型
device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
model.to(device)
model.train()

for epoch in range(3):  # 迭代3个epoch
    for batch in tqdm(train_loader):
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        loss = outputs.loss
        loss.backward()
        optimizer.step()
        scheduler.step()
        optimizer.zero_grad()

# 评估模型
model.eval()
total = correct = 0
with torch.no_grad():
    for batch in val_loader:
        batch = {k: v.to(device) for k, v in batch.items()}
        outputs = model(**batch)
        predictions = outputs.logits.argmax(dim=1)
        correct += (predictions == batch['labels']).sum().item()
        total += batch['labels'].size(0)

print(f"Accuracy: {correct / total:.2f}")

2. 部分参数微调

2.1 Adaper-Tuning

  • 结构:Adapter-Tuning 方法在 Transformer 的每个层之间插入了一个 Adapter 层。每个 Adapter 层通常包含两个小的前馈网络(Feed-Forward Networks,FFNs),这两个网络分别称为“下投影”(down-project)和“上投影”(up-project),之间插入一个非线性激活函数。
  • 功能:Adapter 层的目的是将输入维度降低到一个较低的维度(通过下投影),然后再升回原始维度(通过上投影)。这样做可以在不显著增加参数数量的情况下引入模型的可训练性,从而让模型能够适应新任务。
  • 优点:Adapter 只需训练少量参数,保持了模型的其他部分不变,从而减少了训练成本和风险。

过拟合

  • 是指模型在训练数据上表现得很好,但在新的未见过的数据上表现较差的现象
  • 模型过于复杂,训练数据量不足等因素引起的 

2.2 LORA 

2.2.1 概念介绍

LoRA 通过将大的权重矩阵分解为两个较小的矩阵,实际上降低了在微调过程中需要优化的参数数量。这种方法显著减少了存储和计算的需求。例如,假设原始权重矩阵 W 是 m×n维,通过LoRA分解为两个 m×r  和r×n维的矩阵(其中 r 是低秩,远小于 d),需要调整的参数数量从 mn 减少到 mr+rn。这在参数数量上通常会有显著的降低,尤其是当 r 相对于 ddd 很小的时候。

2.2.2 LORA微调示例

from peft import LoraConfig, get_peft_model

# 配置LoRA
lora_config = LoraConfig(
    r=8,               # 低秩矩阵的秩
    lora_alpha=16,     # 缩放因子
    target_modules=["q_proj", "k_proj", "v_proj", "o_proj"],  # 应用LoRA的层
    lora_dropout=0.1,  # Dropout率
    bias="none",       # 是否包含偏置项
    task_type="CAUSAL_LM"  # 任务类型
)

# 应用LoRA配置
model = get_peft_model(model, lora_config)

Adapter 是通过添加额外的层来实现参数的引入,而 LoRA 是在现有层的权重矩阵中引入修改。

2.2.3 参考资源

2.3 Prefix-Tuning

基本原理如下:

  1. 虚拟 Token 引入

    • 在 Prefix-Tuning 中,会引入一组可学习的虚拟 Token,这些 Token 不来自实际输入数据,而是作为模型训练过程中可调整的参数存在。这些虚拟 Token 被称为“Prefix”(前缀),它们在模型处理任何实际输入之前被添加到输入序列中。
  2. 前缀的嵌入表示

    • 这些前缀 Token 有自己的嵌入表示,这些表示在训练过程中是可学习的。通过训练,这些嵌入能够捕捉到特定于任务的信息,从而指导模型更好地理解和生成与任务相关的输出。
  3. 微调与任务适应

    • 在微调过程中,只有前缀的嵌入表示是可训练的,而预训练模型的其他权重保持固定不变。这样做的好处是显著减少了需要训练的参数数量,同时允许模型快速适应新任务。
  4. 任务特定的调整

    • 由于前缀在不同任务中可以有不同的表示,这使得同一个预训练模型可以通过加载不同的前缀来适应多种不同的下游任务,例如翻译、摘要或者表格到文本生成等。

2.4 部分微调实战 

低配置部署 ChatGLM3-6B | 智谱 × 魔搭社区(LORA)

使用P-Tuning微调Chatglm2-6B,喂饭级教程_哔哩哔哩_bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据与算法架构提升之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值