📖阅读时长:20分钟

🕙发布时间:2025-02-02

近日热文:全网最全的神经网络数学原理(代码和公式)直观解释
欢迎关注知乎和公众号的专栏内容
LLM架构专栏
知乎LLM专栏
知乎【柏企
公众号【柏企科技说】【柏企阅文】# 微调DeepSeek LLM:使用监督微调(SFT)与Hugging Face数据集的详细指南

介绍

DeepSeek LLM是一个强大的开源语言模型,但为了在特定应用中充分发挥其潜力,微调至关重要。在本指南中,我们将逐步介绍如何使用监督微调(SFT)和Hugging Face数据集对DeepSeek LLM进行微调,并提供在特定领域数据集上进行训练的代码详细讲解。我们还将讨论所使用的损失函数、为何使用数据子集,以及低秩适应(LoRA)技术如何实现高效内存的微调。
来源:DeepSeek AI

监督微调(SFT)概述

监督微调(SFT)是在有标签的数据集上对预训练模型进行进一步训练的过程,目的是让模型在特定任务中更专业,比如客户支持、医疗问答或电商推荐等任务。

微调的工作原理

微调需要在特定任务的有标签数据上训练模型,其中:

  • 输入(X):提供给模型的文本数据。
  • 目标(Y):基于有标签数据的预期输出(例如,情感标签、聊天机器人回复或摘要文本)。
  • 损失函数:用于衡量模型的预测与预期输出的匹配程度。在文本生成中,最常用的损失函数是交叉熵损失。

例如,在IMDB情感数据集上进行微调时:

  • 输入(X):像 “这部电影视觉效果很棒,但情节很薄弱。” 这样的电影评论。
  • 目标(Y):正确的标签,例如 “正面” 或 “负面” 情感。

对于文本生成任务,输入可以是一个问题,而目标则是模型生成的正确回复。
使用的损失函数:交叉熵损失

对于语言模型,我们使用交叉熵损失,它用于计算预测的词元分布与实际目标分布之间的差异,

目标是在训练过程中最小化这个损失,以便模型学习生成更准确的文本输出。

为何使用数据子集?

在资源有限的硬件上对像DeepSeek LLM这样的大型语言模型进行微调时,使用完整数据集(例如包含25,000个样本的IMDB数据集)进行训练可能会导致训练时间过长和GPU内存问题。为了缓解这些问题,我们采取了以下措施:

  • 选择子集:选取500个样本用于训练,100个样本用于评估。
  • 保持代表性:这个子集保留了足够的多样性,以实现合理的性能。

使用较小的数据集可以加快实验速度,同时有效地展示微调概念。对于生产级别的微调,应该在更强大的基础设施上使用更大的数据集。

加载DeepSeek LLM

在微调之前,我们需要加载DeepSeek LLM并为训练做好准备。
安装所需库
首先,安装必要的依赖项:

pip install -U torch transformers datasets accelerate peft bitsandbytes

使用4位量化加载模型
我们使用4位量化,使大型模型能够在有限的GPU内存下运行:

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
from peft import LoraConfig, get_peft_model
model_name = "deepseek-ai/deepseek-llm-7b-base"
bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_compute_dtype=torch.float16
)
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
    model_name,
    quantization_config=bnb_config,
    device_map="auto"
)
lora_config = LoraConfig(
    r=8,
    lora_alpha=32,
    target_modules=["q_proj", "v_proj"],
    lora_dropout=0.05,
    bias="none"
)
model = get_peft_model(model, lora_config)
model.print_trainable_parameters()
print("✅ DeepSeek LLM Loaded with LoRA and 4-bit Precision!")

使用Hugging Face数据集进行训练

为了进行微调,我们需要一个高质量的数据集。Hugging Face提供了各种数据集的访问途径。
选择数据集
在这个示例中,我们使用IMDB数据集对DeepSeek LLM进行情感分类的微调:

from datasets import load_dataset
dataset = load_dataset("imdb")

预处理数据集
将文本转换为模型可接受的分词输入:

def tokenize_function(examples):
    inputs = tokenizer(
        examples["text"],
        truncation=True,
        padding="max_length",
        max_length=512
    )
    inputs["labels"] = inputs["input_ids"].copy()
    return inputs
tokenized_datasets = dataset.map(tokenize_function, batched=True)
small_train_dataset = tokenized_datasets["train"].shuffle(seed=42).select(range(500))
small_test_dataset = tokenized_datasets["test"].shuffle(seed=42).select(range(100))
print("Tokenized Sample:")
print(small_train_dataset[0])

什么是LoRA(低秩适应)?

LoRA(低秩适应)是一种旨在使像DeepSeek LLM这样的大型模型的微调在内存使用上更高效的技术,它通过以下方式实现:

  • 冻结模型的大部分权重
  • 在关键层(例如注意力层)引入低秩可训练矩阵

这大大减少了可训练参数的数量,同时保留了模型的性能。LoRA使得在资源受限的硬件(例如Colab GPU)上对大型语言模型进行微调成为可能。
LoRA的工作原理

  • 将参数更新分解为低秩矩阵:(这里需要使用公式编辑工具插入低秩矩阵分解公式,若无法直接插入公式,可使用文字描述:假设原始参数为W,LoRA将其更新分解为W' = W + BA,其中B和A是低秩矩阵)。
  • 仅对分解后的矩阵(例如注意力投影)应用更新
  • 与全量微调相比,减少了内存和计算成本

代码详解:微调DeepSeek LLM

设置训练参数

from transformers import TrainingArguments, Trainer
training_args = TrainingArguments(
    output_dir="./results",
    evaluation_strategy="epoch",
    learning_rate=3e-4,
    per_device_train_batch_size=1,
    gradient_accumulation_steps=8,
    num_train_epochs=0.5,
    weight_decay=0.01,
    save_strategy="epoch",
    logging_dir="./logs",
    logging_steps=50,
    fp16=True,
)

初始化训练器

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=small_train_dataset,
    eval_dataset=small_test_dataset,
)
print("🚀 Trainer Initialized!")

开始微调

print("🚀 Starting Fine-Tuning...")
trainer.train()

保存微调后的模型

trainer.save_model("./fine_tuned_deepseek")
tokenizer.save_pretrained("./fine_tuned_deepseek")
print("✅ Fine-Tuned Model Saved Successfully!")

文章参考资料

本文由mdnice多平台发布


柏企科技圈
15 声望4 粉丝