📖阅读时长: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!")
文章参考资料
- DeepSeek LLM:GitHub仓库
- IMDB数据集:Hugging Face数据集
- BitsAndBytes(量化):官方仓库
本文由mdnice多平台发布
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。