PEFT简介及微调大模型DeepSeek-R1-Distill-Qwen-1.5B

🤗 PEFT(参数高效微调)是由Huggingface团队开发的开源框架,专为大型预训练模型(如GPT、LLaMA、T5等)设计,用于高效地将大型预训练模型适配到各种下游应用,而无需对模型的所有参数进行微调,因为微调成本过高。PEFT 方法仅微调少量(额外的)模型参数,从而显著降低计算和存储成本,同时获得与完全微调模型相当的性能。这使得在消费级硬件上训练和存储大型语言模型 (LLMs) 变得更加容易。


一、介绍与安装

1、作用

  • 降低计算与存储成本
    PEFT通过冻结大部分预训练参数,仅调整少量新增或特定层参数(如低秩矩阵、适配器模块),可将训练参数量缩减至原模型的0.1%-1%。例如,微调12B参数的模型时,显存需求从80GB降至18GB,模型保存文件仅需几MB。

  • 缓解灾难性遗忘
    传统全参数微调可能覆盖预训练阶段学到的通用知识,而PEFT通过保留主体参数,使模型在适应新任务时仍保持原有能力。

  • 支持多任务适配
    PEFT允许在同一模型中集成多种任务的适配器(Adapter),例如LoRA或Prefix Tuning,实现灵活的多任务学习。

2、支持的高效微调方法
  • LoRA(低秩适应):通过向权重矩阵添加低秩分解的增量矩阵(如秩r=8)进行微调,适用于文本生成、分类等任务。

  • Prefix Tuning/Prompt Tuning:在输入层添加可学习的连续提示(Prompt),引导模型输出,适合少样本学习。

  • AdaLoRA:动态调整低秩矩阵的秩,增强复杂任务(如多领域适应)的灵活性。

  • IA3:通过向量缩放激活层参数,在少样本场景下性能超越全参数微调。

3、技术优势
  • 生态友好
    无缝对接Transformers、Accelerate等库,支持分布式训练与混合精度计算,简化部署流程。
  • 性能无损
    实验表明,PEFT微调后的模型性能与全参数微调相当,甚至在某些少样本任务中表现更优。
  • 存储高效
    适配器文件体积小(如LoRA的adapter_model.bin仅几MB),便于共享与版本管理。
4、安装
  • 方式一:从 PyPI 安装🤗PEFT
pip install peft
  • 方式二:Source
pip install git+https://github.com/huggingface/peft

二、微调大模型DeepSeek-R1-Distill-Qwen-1.5B

1、使用modelscope 下载数据集和模型
  • 下载数据集
#数据集下载
!modelscope download --dataset himzhzx/muice-dataset-train.catgirl --local_dir ./data
  • 下载模型
#模型下载
from modelscope import snapshot_download
model_dir = snapshot_download("deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B",cache_dir='./models')
2、改造数据集

由于 transformers 的 Trainer 训练器默认 接收的的数据集格式化为 :

{
	'input_ids':'xxx',
	'attention_mask':'xxx',
	'labels':'xxx',
}

需要对上述下载的数据集进行改造,改造代码如下:

#数据集处理
class Mydata(Dataset):
  def __init__(self, tokenizer, max_len = 255):
    with open("./data/muice-dataset-train.catgirl.json", 'r', encoding='utf-8') as f:
      self.json_data = json.load(f)
    self.tokenizer = tokenizer
    self.max_len = max_len

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

  def __getitem__(self, index):
    data = self.json_data[index]
    question = data['instruction']
    answener = data['output']
    q = self.tokenizer.apply_chat_template(
        [{'role':'user','content':question}],
        tokenize = False,
        add_generation_prompt = True
    )
    q_input_ids = self.tokenizer.encode(q)
    a_input_ids = self.tokenizer.encode(answener)
    input_ids = q_input_ids + a_input_ids
    attention_mask = [1]*len(input_ids)
    labels = [-100]*len(q_input_ids) + a_input_ids

    if len(input_ids) > self.max_len:
      input_ids = input_ids[:self.max_len]
      attention_mask = attention_mask[:self.max_len]
      labels = labels[:self.max_len]
    else:
      padding_len = self.max_len - len(input_ids)
      input_ids = input_ids + [self.tokenizer.pad_token_id] * padding_len
      attention_mask = attention_mask + [0]*padding_len
      labels = labels + [-100]*padding_len

    return {
        'input_ids':torch.tensor(input_ids, dtype=torch.long),
        'attention_mask':torch.tensor(attention_mask, dtype=torch.long),
        'labels':torch.tensor(labels, dtype=torch.long)
    }


dataset = Mydata(tokenizer)

# dataset[0]

train_data = DataLoader(dataset, batch_size=32, shuffle=True)

for i in train_data:
  print(i)
  break
3、配置 Lora 参数
#配置 lora 参数
lora_config = LoraConfig(
    r=16,
    lora_alpha=32,
    lora_dropout=0.05,
    task_type=TaskType.CAUSAL_LM,
    target_modules=['q_proj','v_proj','k_proj', 'o_proj']
)
#将 lora 与原始模型 合并在一起
lora_model = get_peft_model(model, lora_config)

#打印模型总参数,以及可训练参数和占比
lora_model.print_trainable_parameters()
4、开始训练
#配置训练参数

output_dir = './lora/train'

train_arg = TrainingArguments(
    output_dir=output_dir,
    per_device_train_batch_size=4,
    gradient_accumulation_steps=8,
    num_train_epochs=3,
    logging_steps=10,
    save_steps=500,
    learning_rate=2e-5,
    save_total_limit=2,
    fp16=False,
    report_to="none"
)

#创建Trainer
trainer = Trainer(
    model=lora_model,
    args=train_arg,
    train_dataset=dataset,
    processing_class=tokenizer
)

#开始训练
trainer.train()

训练过程:
在这里插入图片描述

5、模型保存
#将 lora 权重合并到 基础模型上
merge_model = lora_model.merge_and_unload() #合并
merge_model.save_pretrained("./merge_model")  #保存
tokenizer.save_pretrained("./merge_model")  #保存

在这里插入图片描述

完整代码下载:git源码

### 准备环境 为了在本地环境中对 `deepseek-r1:1.5b` 进行微调,需安装必要的库和工具。主要依赖项包括 PyTorch 和 Hugging Face Transformers 库。 ```bash pip install torch transformers trl datasets accelerate bitsandbytes ``` 这些包提供了加载预训练模型、处理数据集以及执行高效训练所需的功能[^2]。 ### 加载模型与分词器 首先定义如何加载目标模型及其对应的分词器: ```python from transformers import AutoModelForCausalLM, AutoTokenizer model_name = "DeepSeek-R1/deepseek-r1-1_5b" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForCausalLM.from_pretrained( model_name, load_in_8bit=True, # 使用 int8 推理优化内存占用 device_map="auto" # 自动分配到可用设备上运行 ) ``` 这段代码片段展示了如何利用 HuggingFace 提供的 API 来获取指定版本的大规模语言模型实例,并配置为适合本地资源条件下的最优性能设置。 ### 数据准备 对于特定任务的数据集整理至关重要。这里假设有一个 CSV 文件形式的任务专属语料库可供使用。可以借助 Pandas 或者直接通过 Huggingface Datasets 工具来读取并转换成适用于后续训练流程的形式。 ```python import pandas as pd from datasets import Dataset df = pd.read_csv('path/to/your/dataset.csv') dataset = Dataset.from_pandas(df) def preprocess_function(examples): return tokenizer(examples['text'], truncation=True, padding='max_length') tokenized_datasets = dataset.map(preprocess_function, batched=True) ``` 此部分操作确保了原始文本能够被正确编码成为 token ID 列表,同时保持长度一致以便批量处理效率最大化。 ### 训练过程 采用 SFTTrainer 类来进行监督微调(Supervised Fine-Tuning),这是针对对话类应用较为推荐的方式之一。另外还可以考虑引入 LoRA (Low Rank Adaptation) 技术以减少参数更新量级带来的额外开销。 ```python from peft import LoraConfig, get_peft_model from trl import SFTTrainer peft_config = LoraConfig(target_modules=["query_key_value"], r=8, lora_alpha=32, bias="none") trainer = SFTTrainer( model=model, train_dataset=tokenized_datasets["train"], eval_dataset=tokenized_datasets["test"], peft_config=peft_config, max_seq_length=512, tokenizer=tokenizer, args=TrainingArguments(output_dir="./results", num_train_epochs=3), ) trainer.train() ``` 上述脚本实现了基于给定数据集上的迭代优化循环,期间会不断调整权重直至收敛或达到预定轮次结束。值得注意的是,实际部署前还需经过充分测试验证最终效果是否满足预期标准。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

为啥全要学

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

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

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

打赏作者

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

抵扣说明:

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

余额充值