大数跨境
0
0

DeepSeek-R1模型架构深度解读(八)微调DeepSeek-R1

DeepSeek-R1模型架构深度解读(八)微调DeepSeek-R1 AI算法之道
2025-02-16
0
导读:DeepSeek-R1 模型微调
点击蓝字
 
关注我们










01


引言



DeepSeek R1 引入了一种全新的 LLM 训练方式,使这些模型在思考和执行一系列推理后做出反应的方式发生了令人印象深刻的变化。

在响应前进行思考和推理的这一微小变化,在大多数指标上都取得了非常显著的效果。这就是为什么 DeepSeek R1 成为几乎所有大模型开发人员的首选。

在本文中,我们将对 DeepSeek-R1 模型的蒸馏版本进行微调,特别是对生成的响应进行定制,使其与我们人类一样富有情感和吸引力!

闲话少说,我们直接开始吧!







02


准备工作

在对 LLM 进行实际微调之前,我们先简要介绍一下相关准备工作。

  • Python 库和框架
    • unsloth,这个软件包使 Llama-3、Mistral、Phi-4 和 Gemma 等大型语言模型的微调速度提高了 2 倍,内存使用量减少了 70%,而且准确性没有降低!更多信息,请参考官网,https://docs.unsloth.ai/。

    • torch,这个软件包是使用 PyTorch 进行深度学习的基本构件。它提供了一个功能强大的张量库,与 NumPy 类似,但具有 GPU 加速的额外优势,这在使用 LLM 时至关重要。

    • transformers 是一个强大而流行的自然语言处理(NLP)开源库。它为各种最先进的预训练模型提供了易于使用的接口。由于预训练模型是任何微调任务的基础,该软件包有助于轻松访问训练好的模型。

    • trl 软件包是一个专门用于使用Transformer模型进行强化学习(RL)的库。它建立在 Hugging Face 的Transformer库之上,利用其优势使使用Transformer的强化学习变得更易用、更高效。

  • 算力要求

    对模型进行微调是一种使 LLM 的响应更有条理和针对特定领域的技术。微调模型的技术有很多,其中有些技术无需进行完整的参数训练就能完成微调过程。

    然而,由于所有可训练参数和实际 LLM 都存储在 GPU 的 vRAM中,因此对于大多数普通计算机硬件来说,微调更大 LLM 的过程仍然不可行,而 LLM 的巨大体积则是实现微调的主要障碍。

    因此,在本文中,我们将微调 DeepSeek-R1 LLM 的蒸馏版本,即 DeepSeek-R1-Distill,其中包含 47.4 亿个参数。这个 LLM 至少需要 8-12 GB 的 vRAM,为了让所有人都能使用,我们将使用谷歌 Colab 的免费 T4 GPU,它有 16 GB 的 vRAM。






    03


    数据准备策略

    要对 LLM 进行微调,我们需要结构化的特定任务的数据。数据准备策略有很多种,包括从社交媒体平台、网站、书籍或研究论文中获取数据。
    在本文中,我们将使dataset库加载 Hugging Face Hub 中的数据。我们将使用来自 Hugging Face 的 HumanLLMs/Human-Like-DPO-Dataset 数据集,该数据集的下载地址如下:



    DPO数据集:


    https://huggingface.co/datasets/HumanLLMs/Human-Like-DPO-Dataset









    04


    环境准备

    使用 Google Colab 进行微调的一大好处是,大部分软件包都已安装。我们只需安装一个软件包,即 unsloth。
    安装软件包的过程如下:
    pip install unsloth
    接着,我们将使用 unsloth 软件包加载预训练模型,因为它提供了许多有用的技术,可以帮助我们更快地下载和微调 LLM。
    from unsloth import FastLanguageModelmodel, 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,    # token = "hf_...", # use one if using gated models like meta-llama/Llama-2-7b-hf)
    在上述代码中:
    • 我们指定了model_name为 "unsloth/DeepSeek-R1-Distill-Llama-8B-unsloth-bnb-4bit",用于访问预先训练好的 DeepSeek-R1-Distill 模型。
    • 我们将 max_seq_length 定义为 2048,它设定了模型可以处理的输入序列的最大长度。通过合理设置,我们可以优化内存使用和处理速度。
    • dtype 设置为 None,这有助于映射获取模型的数据类型,使其与现有硬件兼容。有了它,我们就不必明确检查和提及数据类型,unsloth 会处理好一切。
    • load_in_4bit 可以增强推理能力,减少内存使用量。基本上,我们将模型量化为 4 比特精度。



    05
    添加LoRA Adapters
    我们将在预训练的 LLM 中添加 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 = 16,    lora_dropout = 0, # 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 = 3927,    use_rslora = False,  # unsloth also supports rank stabilized LoRA    loftq_config = None, # And LoftQ)
    在上述代码中:
    • 我们使用 FastLanguageModel 中的 get_peft_model 函数重新初始化了模型,以便使用 PEFT 技术。
    • 我们还需要传递上一步中获取的预训练模型 model。
    • 在这里,r=64 参数定义了 LoRA 自适应中低秩矩阵的秩。一般来说,秩在 8-128 之间时效果最好。
    • lora_dropout参数在训练该LoRA适配器模型时,会向低秩矩阵引入随机dropout机制。该参数能有效防止模型过拟合。通过将lora_dropout设置为0,unsloth框架可自动为我们选择最佳优化值。
    • target_modules参数用于指定模型中需要应用LoRA适配的具体类或模块名称列表。




    06

    加载数据集
    现在,我们已经在预训练的 LLM 上设置了 LoRA 适配器,可以着手构建用于训练模型的数据了。为了使数据结构化,我们必须以包含指令和响应的方式指定提示。
    • Instructions: 表示向LLM提出的主要问题。
    • Response: 表示 LLM 的输出。它用于说明如何根据具体指令调整 LLM 的响应。
    提示词的模版如下:
    human_prompt = """Below is an instruction that describes a task. Write a response that appropriately completes the request.### Instruction:{}### Response:{}"""
    接着,我们创建如下函数,该函数将对 human_prompt 中的所有数据进行适当的结构化处理。
    EOS_TOKEN = tokenizer.eos_token # Must add EOS_TOKENdef formatting_human_prompts_func(examples):    instructions = examples["prompt"]    outputs      = examples["chosen"]    texts = []    for instruction, output in zip(instructions, outputs):        # Must add EOS_TOKEN, otherwise your generation will go on forever!        text = human_prompt.format(instruction, output) + EOS_TOKEN        texts.append(text)    return { "text" : texts, }
    现在,我们必须加载用于微调模型的数据集,在我们的例子中,数据集是来自HuggingFace的 "HumanLLMs/Human-Like-DPO-Dataset"。代码如下:
    from datasets import load_datasetdataset = load_dataset("HumanLLMs/Human-Like-DPO-Dataset", split = "train")dataset = dataset.map(formatting_human_prompts_func, batched = True,)



    07
    训练模型
    有了结构化数据和带有 LoRA 适配器的模型,我们就可以开始训练模型了。
    为了训练模型,我们必须初始化某些超参数,这将有助于训练过程,同时也会在一定程度上影响模型的准确性。
    代码如下:
    from trl import SFTTrainerfrom transformers import TrainingArgumentsfrom unsloth import is_bfloat16_supportedtrainer = SFTTrainer(    model = model, # The model with LoRA adapters    tokenizer = tokenizer, # The tokenizer of the model    train_dataset = dataset, # The dataset to use for training    dataset_text_field = "text", # The field in the dataset that contains the structured data    max_seq_length = 2048, # Max length of input sequence that the model can process    dataset_num_proc = 2, # Noe of processes to use for loading and processing the data    packing = False, # Can make training 5x faster for short sequences.    args = TrainingArguments(        per_device_train_batch_size = 2, # Batch size per GPU        gradient_accumulation_steps = 4, # Step size of gradient accumulation        warmup_steps = 5,        # num_train_epochs = 1, # Set this for 1 full training run.        max_steps = 120, # Maximum steps of training        learning_rate = 2e-4, # Initial learning rate        fp16 = not is_bfloat16_supported(),        bf16 = is_bfloat16_supported(),        logging_steps = 1,        optim = "adamw_8bit", # The optimizer that will be used for updating the weights        weight_decay = 0.01,        lr_scheduler_type = "linear",        seed = 3407,        output_dir = "outputs",        report_to = "none", # Use this for WandB etc    ),)
    现在,要开始训练模型,使用该训练器,代码如下:
    trainer_stats = trainer.train()
    这将启动模型的训练,并记录所有步骤的训练损失。



    08
    模型推理
    现在,我们已经完成了模型的训练,我们要做的就是推理微调后的模型,以评估其效果。
    对模型进行推理的代码如下:
    FastLanguageModel.for_inference(model) # Enable native 2x faster inferenceinputs = tokenizer([    human_prompt.format(        "Oh, I just saw the best meme - have you seen it?", # instruction        "", # output - leave this blank for generation!    )], return_tensors = "pt").to("cuda")outputs = model.generate(**inputs, max_new_tokens = 1024, use_cache = True)tokenizer.batch_decode(outputs)
    在上述代码中:
    • 我们使用 unsloth 软件包中的 FastLanguageModel 来加载微调模型进行推理。这种方法能产生更快的结果。
    • 为了推理模型,我们必须首先将查询转换为结构化提示,然后对提示进行Token化处理。
    • 我们还设置了 return_tensors="pt",表明返回 PyTorch 张量,然后使用 .to("cuda") 将该张量加载到 GPU,以提高处理速度。
    • 然后,我们调用 model.generate() 为查询生成响应。
    • 在生成时,我们提到了 max_new_tokens=1024,它设置了模型可以生成的最大Token数。
    • use_cache=True 有助于加快生成速度,尤其是对于较长的序列。
    • 最后,我们将微调模型的输出从张量解码为文本。
    微调模型输出



    09
    测试微调模型
    文章的这一部分包含了微调模型的一些其他结果。

    Query1:  I love reading and writing,what are your hobbies?

    Output corresponding to Query 1

    Query2: What’s your favourite type of cuisine to cook or eat?

    Output corresponding to Query 2
    在这里,我们可以注意到所生成的答复的表现力水平。在保持答复实际质量的同时,答复也更加耐人寻味。



    10
    保存微调模型
    这一步完成了微调模型的整个过程,现在我们可以保存微调后的模型,以便今后推理或使用。
    代码如下:
    # Pushing with 4bit precisionmodel.push_to_hub_merged("<YOUR_HF_ID>/<MODEL_NAME>", tokenizer, save_method = "merged_4bit", token = "<YOUR_HF_TOKEN>")# Pushing with 16 bit precision 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 矩阵一起上传到hub上。



    11
    结论
    微调是一个过程,通过这个过程,我们可以让大型语言模型按照我们想要的方式做出反应。特别是要使响应具有特定领域和良好的结构。我们讨论了一些影响微调模型生成的响应质量的超参数,并尝试对它们进行初始化,以实现我们的特定用例。

    最后,大家可以在这里找到本文微调后的权重:


    链接:

    https://huggingface.co/krishanwalia30/DeepSeek-R1-Distill-HumanLikeDPO-FineTuned-16bit






    欢迎大家持续关注!

    一起学习,共同进步!!!

    参考:

    [1] DeepSeekV2:   https://arxiv.org/abs/2405.04434

    [2] DeepSeekV3:   https://arxiv.org/abs/2412.19437

    [3] DeepSeekR1:   https://arxiv.org/abs/2501.12948





    点击上方小卡片关注我




    添加个人微信,进专属粉丝群!


    【声明】内容源于网络
    0
    0
    AI算法之道
    一个专注于深度学习、计算机视觉和自动驾驶感知算法的公众号,涵盖视觉CV、神经网络、模式识别等方面,包括相应的硬件和软件配置,以及开源项目等。
    内容 573
    粉丝 0
    AI算法之道 一个专注于深度学习、计算机视觉和自动驾驶感知算法的公众号,涵盖视觉CV、神经网络、模式识别等方面,包括相应的硬件和软件配置,以及开源项目等。
    总阅读436
    粉丝0
    内容573