2025年4月17日 星期四 乙巳(蛇)年 正月十八 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > 人工智能

用Python微调DeepSeek R1

时间:03-27来源:作者:点击数:11

微调前的准备工作

在正式开始微调大语言模型之前,我们先来了解一下技术前提条件和设置要求。

Python库和框架

微调大语言模型需要用到以下Python库和框架:

  • unsloth:这个库可太厉害了,它能让像Llama - 3、Mistral、Phi - 4和Gemma 2这些大语言模型的微调速度提高2倍,内存使用减少70%,而且不会降低模型的准确性!
  • torch:它是基于PyTorch进行深度学习的基础构建模块。提供了强大的张量库,和NumPy有些类似,但它有个巨大的优势,就是支持GPU加速,这在处理大语言模型时至关重要。
  • transformers:这是一个功能强大且广受欢迎的自然语言处理(NLP)开源库。它提供了易于使用的接口,让我们可以轻松访问各种最先进的预训练模型。毕竟,预训练模型是任何微调任务的基础,这个库可帮了大忙。
  • trl:Python中的trl包是一个专门用于基于Transformer模型进行强化学习(RL)的库。它建立在Hugging Face transformers库之上,充分利用其优势,让基于Transformer的强化学习变得更易上手、更高效。
计算要求

微调模型是一种让大语言模型的回答更结构化、更具领域针对性的技术,而且不需要对所有参数进行全面训练。不过,对于大多数普通计算机硬件来说,微调大型大语言模型仍然不太现实。因为所有可训练参数以及实际的大语言模型都要存储在GPU的虚拟随机存取存储器(vRAM)中,而大语言模型庞大的规模成了实现这一目标的主要障碍。

所以,在本文中,我们将微调一个相对较小的大语言模型——DeepSeek - R1 - Distill,它有47.4亿个参数。这个模型至少需要8 - 12GB的vRAM

数据准备策略

微调大语言模型需要结构化且特定任务的数据。数据准备策略有很多,比如从社交媒体平台、网站、书籍或研究论文中收集数据。在本文中,我们会使用datasets库来加载Hugging Face Hub上的数据。具体来说,我们会使用Hugging Face上的yahma/alpaca - cleaned数据集

Python实现步骤

安装所需包

使用谷歌Colab进行微调任务有个很大的好处,就是大多数包已经预装好了。我们只需要安装一个包,那就是unsloth。安装包的代码如下:

  • !pip install unsloth
初始化模型和分词器

我们将使用unsloth包来加载预训练模型,因为它提供了许多有用的技术,能帮助我们更快地下载和微调大语言模型。加载模型和分词器的代码如下:

  • from unsloth import FastLanguageModel
  • model, tokenizer = FastLanguageModel.from_pretrained(
  • model_name = "unsloth/DeepSeek-R1-Distill-Llama-8B-unsloth-bnb-4bit",
  • max_seq_length = 2048,
  • dtype = None,
  • load_in_4bit = True
  • )

这里解释一下代码:

  • 我们指定了model_nameunsloth/DeepSeek - R1 - Distill - Llama - 8B - unsloth - bnb - 4bit,这是为了访问预训练的DeepSeek - R1 - Distill模型。
  • max_seq_length定义为2048,这设置了模型可以处理的输入序列的最大长度。合理设置这个值,有助于优化内存使用和处理速度。
  • dtype设置为None,这样能让模型根据可用硬件自动适配数据类型,我们就不用手动去检查和指定数据类型啦,unsloth会帮我们处理好一切。
  • load_in_4bit这个参数可以增强推理能力并减少内存使用,简单来说,就是将模型量化为4位精度。
添加LoRA适配器

我们要给预训练的大语言模型添加LoRA矩阵,这有助于微调模型的回答。使用unsloth,整个过程非常简单,只需要几行代码。具体实现如下:

  • model = FastLanguageModel.get_peft_model(
  • model,
  • r = 64,
  • target_modules = ["q_proj", "k_proj", "v_proj", "o_proj",
  • "gate_proj", "up_proj", "down_proj",],
  • lora_alpha = 32,
  • lora_dropout = 0.05, # Can be set to any, but = 0 is optimized
  • bias = "none", # Can be set to any, but = "none" is optimized
  • use_gradient_checkpointing = "unsloth", # True or "unsloth" for very long context
  • random_state = 3977,
  • use_rslora = False, # unsloth also supports rank stabilized LoRA
  • loftq_config = None # And LoftQ
  • )

代码解释:

  • 我们使用FastLanguageModelget_peft_model方法重新初始化了模型,以便使用PEFT技术。
  • 这里需要传入之前获取的预训练模型。
  • r = 64这个参数定义了LoRA自适应中低秩矩阵的秩。通常这个秩在8 - 128范围内时能得到较好的效果。
  • lora_dropout = 0.05这个参数在训练LoRA适配器模型时,给低秩矩阵引入了随机失活(dropout)。它可以防止模型过拟合。
  • target_modules指定了我们想要应用LoRA自适应的模型中特定类或模块的名称列表。
数据准备

现在,我们已经在预训练的大语言模型上设置好了LoRA适配器,接下来就可以着手构建用于训练模型的数据了。为了构建数据,我们需要以特定的方式指定提示(prompt),使其包含输入、指令和响应。

  • 指令(Instructions):表示向大语言模型提出的主要问题。
  • 输入(Input):意味着除了指令或问题外,我们还传递了一些数据让模型进行分析。
  • 响应(Response):表示大语言模型的输出。它用于说明大语言模型的响应应该如何根据特定指令(问题)进行调整,无论是否传递了输入(数据)。

提示的结构如下:

  • alpaca_prompt = """Below is an instruction that describes a task, paired with an input that provides further context. Write a response that appropriately completes the request.
  • ### Instruction:
  • {}
  • ### Input:
  • {}
  • ### Response:
  • {}"""

我们创建了一个函数,用于将所有数据按照alpaca_prompt的格式进行正确构建,代码如下:

  • EOS_TOKEN = tokenizer.eos_token
  • def formatting_prompts_func(examples):
  • instructions = examples["instruction"]
  • inputs = examples["input"]
  • outputs = examples["output"]
  • texts = []
  • for instruction, input, output in zip(instructions, inputs, outputs):
  • text = alpaca_prompt.format(instruction, input, output) + EOS_TOKEN
  • texts.append(text)
  • return { "text" : texts, }

现在,我们要加载用于微调模型的数据集,在我们的例子中是yahma/alpaca - cleaned。代码如下:

  • from datasets import load_dataset
  • dataset = load_dataset("yahma/alpaca-cleaned", split = "train")
  • dataset = dataset.map(formatting_prompts_func, batched = True,)
训练模型

现在我们既有了结构化的数据,又有了带有LoRA适配器或矩阵的模型,接下来就可以开始训练模型啦。为了训练模型,我们需要初始化一些超参数,这些超参数不仅有助于训练过程,还会在一定程度上影响模型的准确性。

我们将使用SFTTrainer和超参数来初始化一个训练器,代码如下:

  • from trl import SFTTrainer
  • from transformers import TrainingArguments
  • from unsloth import is_bfloat16_supported
  • trainer = SFTTrainer(
  • model = model,
  • tokenizer = tokenizer,
  • train_dataset = dataset,
  • dataset_text_field = "text",
  • max_seq_length = max_seq_length,
  • dataset_num_proc = 2,
  • packing = False,
  • args = TrainingArguments(
  • per_device_train_batch_size = 2,
  • gradient_accumulation_steps = 4,
  • warmup_steps = 5,
  • max_steps = 120,
  • learning_rate = 2e-4,
  • fp16 = not is_bfloat16_supported(),
  • bf16 = is_bfloat16_supported(),
  • logging_steps = 1,
  • optim = "adamw_8bit",
  • weight_decay = 0.01,
  • lr_scheduler_type = "linear",
  • seed = 3407,
  • output_dir = "outputs",
  • report_to = "none",
  • )
  • )

现在,使用这个训练器来启动模型的训练,代码如下:

  • trainer_stats = trainer.train()

运行这段代码后,模型就会开始训练,并在控制台记录所有步骤以及相应的训练损失。

对微调后的模型进行推理

模型训练完成后,接下来要做的就是对微调后的模型进行推理,评估它的回答。进行推理的代码如下:

  • FastLanguageModel.for_inference(model)
  • inputs = tokenizer(
  • alpaca_prompt.format(
  • "Continue the fibonnaci sequence.",
  • "1, 1, 2, 3, 5, 8",
  • ""
  • ), return_tensors = "pt").to("cuda")
  • outputs = model.generate(**inputs, max_new_tokens = 64, use_cache = True)
  • tokenizer.batch_decode(outputs)

代码解释:

  • 我们使用unsloth包中的FastLanguageModel来加载微调后的模型进行推理,这种方法能得到更快的结果。
  • 为了对模型进行推理,我们首先要将查询转换为结构化的提示,然后对提示进行分词。
  • 设置return_tensors = "pt"是为了让分词器返回一个PyTorch张量,然后使用.to("cuda")将这个张量加载到GPU上,以提高处理速度。
  • 接着调用model.generate()来生成查询的响应。
  • 在生成响应时,我们设置max_new_tokens = 64,这指定了模型应该生成的最大新令牌数。
  • use_cache = True也能加快生成速度,特别是对于较长的序列。
  • 最后,我们将微调后模型输出的张量解码为文本。
保存微调后的模型

这一步完成了模型微调的整个过程,现在我们可以保存微调后的模型,以便将来进行推理或使用。我们还需要将分词器和模型一起保存。下面是将微调后的模型保存到Hugging Face Hub的方法:

  • model.push_to_hub_merged("<YOUR_HF_ID>/<MODEL_NAME>", tokenizer, save_method = "merged_4bit", token = "<YOUR_HF_TOKEN>")
  • model.push_to_hub_merged("<YOUR_HF_ID>/<MODEL_NAME>", tokenizer, save_method = "merged_16bit", token = "<YOUR_HF_TOKEN>")

这里需要注意:

  • 你需要设置模型的名称,这个名称将用于在Hugging Face Hub上设置模型的ID。
  • 可以选择上传4位精度或16位精度的完整合并模型。合并模型意味着将预训练模型和LoRA矩阵一起上传到Hugging Face Hub,当然也有其他选项,比如只上传LoRA矩阵而不上传模型。

总结

本文主要讨论了以下几个要点:

  • 大语言模型从最通俗的角度来说,就是深度学习架构(如Transformer)的精妙应用,通过大量的语言文本数据进行训练。
  • DeepSeek - R1 - Zero模型通过大规模强化学习(RL)训练,且没有经过监督微调(SFT)作为初步步骤,在推理方面表现出色。
  • 微调大语言模型就是为模型提供特定任务的数据,使其回答更符合特定用途,从而提高准确性,让回答更具针对性和领域专业性。
  • 我们使用的主要Python库和框架有unslothtorchtransformerstrl。此外,还讨论了微调大语言模型的计算要求。
  • 我们构建了用于有效微调模型的数据集,然后使用SFTTrainer对模型进行训练。

DeepSeek无疑是2025开年AI圈的一匹黑马,在一众AI大模型中,DeepSeek以低价高性能的优势脱颖而出。DeepSeek的上线实现了AI界的又一大突破,各大科技巨头都火速出手,争先抢占DeepSeek大模型的流量风口。

DeepSeek的爆火,远不止于此。它是一场属于每个人的科技革命,一次打破界限的机会,一次让普通人也能逆袭契机。

DeepSeek的优点

read-normal-img

掌握DeepSeek对于转行大模型领域的人来说是一个很大的优势,目前懂得大模型技术方面的人才很稀缺,而DeepSeek就是一个突破口。现在越来越多的人才都想往大模型方向转行,对于想要转行创业,提升自我的人来说是一个不可多得的机会。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐