Type something to search...
人性化 Deepseek R1:在 Python 中进行微调!

人性化 Deepseek R1:在 Python 中进行微调!

DeepSeek | DeepSeek R1 | Python | 微调 | 人工智能 | 大语言模型 | 初学者友好 | 类人 LLM

学习如何微调 Deep Seek R1,使其像人类一样响应,通过这个适合初学者的教程!

让我们让 DeepSeek R1 像我们一样回应——人类!🚀

这是几乎所有 LLM(无论是 Gemini、Llama 还是 GPT)都尝试实现的任务之一,现在凭借惊人的性能指标,是时候让 DeepSeek-R1 证明自己了。

通过本文,您将学习如何使通用的 DeepSeek R1 模型,停止像机器一样响应,变得像我们——人类一样充满情感和吸引力

坚持到最后,您将能够为自己制作一个这样的模型!

介绍

DeepSeek R1 引入了一种全新的训练 LLMs 的方法,并在这些模型在思考和进行一系列推理后响应的方式上带来了显著的变化。

在响应之前进行思考和推理的这一小变化,在大多数指标上带来了真正显著的结果。这就是为什么 DeepSeek R1 成为几乎所有精明开发者和创始人的首选。

一些开发者和创始人也在探索如何将这个最佳可用模型应用于他们特定的项目和产品。本文也试图阐明微调 DeepSeek-R1 模型 的过程。

在本文中,您将微调 DeepSeek-R1 模型的精简版本,特别是为了使生成的响应尽可能富有情感和引人入胜,像我们——人类一样!

通过本文,您将学习如何以用于微调模型的方式构建数据集。调优后,将其合并并保存在 Hugging Face Hub 上。

尽管微调是一项计算密集型任务,但本文试图通过利用普遍可用的资源,使其变得尽可能可及,使用 Google 的 Colab Notebook

前提条件和设置

在我们实际开始微调LLM之前,先简要介绍一下技术前提或设置要求。

Python库和框架

用于微调LLM所需的Python库和框架包括:

  • unsloth,这个包使得微调大型语言模型如Llama-3、Mistral、Phi-4和Gemma的速度提高了2倍,内存使用减少了70%,而且没有准确度的下降!您可以在这里阅读更多信息。
  • torch,这个包是使用PyTorch进行深度学习的基本构建块。它提供了一个强大的张量库,类似于NumPy,但具有GPU加速的额外优势,这在处理LLM时至关重要。
  • transformers是一个强大且流行的开源自然语言处理(NLP)库。它提供了易于使用的接口,用于广泛的最先进的预训练模型。由于预训练模型构成了任何微调任务的基础,这个包有助于轻松访问训练模型。
  • Python中的trl包是一个专门用于**强化学习(RL)**与变换器模型的库。它建立在Hugging Face的transformers库之上,利用其优势使得与变换器的RL变得更加可访问和高效。

计算需求

微调模型是一种使LLM的响应更加结构化和领域特定的技术。为了微调模型,采用了许多技术,有些技术在不实际进行全面参数训练的情况下简化了这一过程。

然而,对于大多数普通计算机硬件而言,微调更大规模的LLM的过程仍然不可行,因为所有可训练参数以及实际的LLM都存储在GPU的vRAM(虚拟内存)中,而LLM的巨大规模在实现这一目标时构成了主要障碍。

因此,出于本文的目的,我们将微调DeepSeek-R1 LLM的精简版本,即DeepSeek-R1-Distill,具有47.4亿参数。该LLM至少需要8–12 GB的vRAM,为了让所有人都能使用,我们将使用Google Colab的免费T4 GPU,具有16 GB的vRAM。

数据准备策略

为了微调一个LLM,我们需要结构化和特定任务的数据。有许多数据准备策略,无论是抓取社交媒体平台、网站、书籍还是研究论文。

在本文中,我们将使用datasets库加载Hugging Face Hub中存在的数据。我们将使用来自Hugging Face的HumanLLMs/Human-Like-DPO-Dataset数据集,您可以在这里探索该数据集。

Python 实现

安装包

使用 Google Colab 进行此微调任务的一个主要好处是大多数包已经预装。我们只需要安装一个包,即 unsloth

安装该包的过程是, —

!pip install unsloth

初始化模型和分词器

我们将使用 unsloth 包来加载预训练模型,因为它提供了许多有用的技术,可以帮助我们更快地下载和微调 LLM。

加载模型和分词器的代码是,—

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,
    # token = "hf_...", # use one if using gated models like meta-llama/Llama-2-7b-hf
)
  • 这里我们指定了模型名称,'unsloth/DeepSeek-R1-Distill-Llama-8B-unsloth-bnb-4bit',用于访问预训练的 DeepSeek-R1-Distill 模型。
  • 我们将 max_seq_length 定义为 2048,这设置了模型可以处理的输入序列的最大长度。通过合理设置,我们可以优化内存使用和处理速度。
  • dtype 设置为 None,这有助于映射模型将要获取的数据类型,与可用的硬件兼容。通过使用这个,我们不需要明确检查和提及数据类型,unsloth 会处理所有相关内容。
  • load_in_4bit 提升了推理性能并减少了内存使用。基本上,我们将模型量化为 4bit 精度。

添加 LoRA 适配器

我们将向预训练的 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 重新初始化了 model,以使用 PEFT 技术。
  • 我们还需要传递在上一步中获取的预训练 model
  • 这里,r=64 参数定义了 LoRA 适配中的低秩矩阵的秩。这个秩通常在 8–128 范围内能产生最佳结果。
  • lora_dropout 参数在训练此 LoRA 适配器模型时引入了低秩矩阵的 dropout。该参数防止模型过拟合。unsloth 通过将其设置为 0 为我们提供了自动选择优化值的功能。
  • target_modules 指定了我们希望应用 LoRA 适配的模型中特定类或模块的名称列表。

数据准备

现在,我们已经在预训练的 LLM 上设置了 LoRA 适配器,我们可以开始构建用于训练模型的数据。

为了构建数据,我们必须以包含指令和响应的方式指定提示。

  • Instructions,表示对 LLM 的主要查询。这是我们向 LLM 提出的问询。
  • Response,表示来自 LLM 的输出。它用于说明如何将 LLM 的响应调整为特定的 instruction(查询)。

提示的结构是,—

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_TOKEN
def 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, }
pass

现在,我们必须加载将用于微调模型的数据集,在我们的案例中,它是来自 Hugging Face Hub 的“HumanLLMs/Human-Like-DPO-Dataset”。您可以在 这里 探索该数据集。

from datasets import load_dataset
dataset = load_dataset("HumanLLMs/Human-Like-DPO-Dataset", split = "train")
dataset = dataset.map(formatting_human_prompts_func, batched = True,)

训练模型

现在我们已经拥有了结构化数据和带有 LoRA 适配器或矩阵的模型,我们可以继续进行模型的训练。

为了训练模型,我们需要初始化某些超参数,这将有助于训练过程,并在一定程度上影响模型的准确性。

我们将使用 SFTTrainer 和超参数初始化一个 trainer

from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported

trainer = SFTTrainer(
    model = model, # 带有 LoRA 适配器的模型
    tokenizer = tokenizer, # 模型的分词器
    train_dataset = dataset, # 用于训练的数据集
    dataset_text_field = "text", # 数据集中包含结构化数据的字段
    max_seq_length = 2048, # 模型可以处理的输入序列的最大长度
    dataset_num_proc = 2, # 用于加载和处理数据的进程数量
    packing = False, # 可使短序列的训练速度提高 5 倍。
    args = TrainingArguments(
        per_device_train_batch_size = 2, # 每个 GPU 的批次大小
        gradient_accumulation_steps = 4, # 梯度累积的步长
        warmup_steps = 5,
        # num_train_epochs = 1, # 将此设置为 1 次完整训练运行。
        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", # 用于 WandB 等
    ),
)

现在要开始模型的训练,使用这个训练器,—

trainer_stats = trainer.train()

这将开始模型的训练,并将所有步骤及其各自的 训练损失 记录在内核上。

推理微调模型

现在,随着我们完成了模型的训练,我们需要做的就是对微调后的模型进行推理,以评估其响应。

进行模型推理的代码如下,—

FastLanguageModel.for_inference(model) # Enable native 2x faster inference
inputs = 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 来加载微调后的模型进行推理。此方法能提供更快的结果。
  • 为了对模型进行推理,我们首先需要将查询转换为结构化的提示,然后对提示进行标记化。
  • 我们还设置了 return_tensors="pt",以使标记器返回一个 PyTorch 张量,然后使用 .to("cuda") 将该张量加载到 GPU 中,以提高处理速度。
  • 然后我们调用 model.generate() 来生成查询的响应。
  • 在生成时,我们提到 max_new_tokens=1024,这表示模型可以生成的最大令牌数。
  • use_cache=True 有助于加快生成速度,特别是对于较长的序列。
  • 最后,我们将微调模型的输出从张量解码为文本。

微调模型的结果

本节文章包含了一些微调模型的其他结果。

查询 — 1: 我喜欢阅读和写作,你有什么爱好?

查询 — 2: 你最喜欢做或吃的菜系是什么?

在这里,可以注意到生成的响应的表现力水平。响应更具吸引力,同时保持了实际的响应质量。

保存微调后的模型

此步骤完成了微调模型的整个过程,现在我们可以保存微调后的模型以进行推理或在未来使用。

我们还需要与模型一起保存分词器。以下是将微调后的模型保存到 Hugging Face Hub 的方法。

## Pushing with 4bit precision
model.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
  • 可以以 4bit16bit 精度上传完整的合并模型。合并模型意味着预训练模型与 LoRA 矩阵一起上传到 Hub,而还有选项可以仅推送 LoRA 矩阵而不包括模型。
  • 您可以在 这里 获取您的 Hugging Face 令牌。

结论

没错!这篇文章就到这里。以下是本文讨论的主要主题——

  • 微调是一个过程,通过它我们可以使大型语言模型以我们希望的方式响应。特别是为了使响应具有特定领域的针对性和结构良好。
  • 我们定义了一个结构,用于以适合微调模型的方式排列数据集。
  • 我们使用的主要 Python 库和框架包括 unslothtorchtransformerstrl。此外,我们讨论了微调 LLM 的计算要求。
  • 我们讨论了多个影响微调模型生成的响应质量的超参数,并尝试为实现我们的特定用例初始化它们。
  • 我们还将 LoRA 适配器或矩阵与预训练模型合并,以便将其推送到 Hugging Face Hub

作者注

感谢您阅读本文。如果您有任何问题或建议,请随时在评论区留言。我非常欣赏反馈

Related Posts

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

AI 研究报告和论文写作 合并两个系统指令以获得两个模型的最佳效果 Perplexity AI 的 Deep Research 工具提供专家级的研究报告,而 OpenAI 的 ChatGPT-o3-mini-high 擅长推理。我发现你可以将它们结合起来生成令人难以置信的论文,这些论文比任何一个模型单独撰写的都要好。你只需要将这个一次性提示复制到 **

阅读更多
让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

Non members click here作为一名软件开发人员,多年来的一个发现总是让我感到惊讶,那就是人们还在 Excel

阅读更多
使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

10 个常见问题解答 本文是我推出的一个名为“10 个常见问题解答”的新系列的一部分。在本系列中,我旨在通过回答关于该主题的十个最常见问题来分解复杂的概念。我的目标是使用简单的语言和相关的类比,使这些想法易于理解。 图片来自 [Solen Feyissa](https://unsplash.com/@solenfeyissa?utm_source=medium&utm_medi

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

在AI军备竞赛中分辨事实与虚构 DeepSeek AI真的是它所宣传的游戏规则改变者,还是仅仅聪明的营销和战略炒作?👀 虽然一些人将其视为AI效率的革命性飞跃,但另一些人则认为它的成功建立在借用(甚至窃取的)创新和可疑的做法之上。传言称,DeepSeek的首席执行官在疫情期间像囤积卫生纸一样囤积Nvidia芯片——这只是冰山一角。 从其声称的550万美元培训预算到使用Open

阅读更多
Type something to search...