深度学习模型已经彻底改变了人工智能领域,但它们庞大的规模和计算需求可能成为实际应用的瓶颈。模型蒸馏是一种强大的技术,通过将知识从一个大型、复杂的模型(教师模型)转移到一个较小、更高效的模型(学生模型)来应对这一挑战。
在本博客中,我们将介绍如何使用诸如LoRA(低秩适配)等专业技术,将DeepSeek-R1的推理能力蒸馏到像微软的Phi-3-Mini这样的更小模型中。
什么是蒸馏?
蒸馏是一种机器学习技术,其中较小的模型(“学生”)被训练来模仿较大、预训练模型(“教师”)的行为。其目标是在显著降低计算成本和内存占用的同时,保留教师模型的大部分性能。
这一概念最早在Geoffrey Hinton关于知识蒸馏的开创性论文[1]中提出。与其直接在原始数据上训练学生模型,不如让学生模型学习教师模型的输出或中间表示。这实际上是受人类教育的启发。
为什么这很重要:
•成本效益:较小的模型需要更少的计算资源。•速度:适用于对延迟敏感的应用(例如API、边缘设备)。•专业化:无需重新训练大型模型即可将模型定制到特定领域。
蒸馏的类型
模型蒸馏有几种方法,每种方法都有其自身的优势:
1. 数据蒸馏
在数据蒸馏中,教师模型生成合成数据或伪标签,然后这些数据用于训练学生模型。这种方法可以应用于广泛的任务,即使是在logits信息较少的任务(例如开放式推理任务)中也能发挥作用。
2. Logits蒸馏
Logits是神经网络在应用softmax函数之前的原始输出分数。在logits蒸馏中,学生模型被训练来匹配教师模型的logits,而不仅仅是最终的预测。这种方法保留了更多关于教师模型置信水平和决策过程的信息。
3. 特征蒸馏
特征蒸馏涉及将教师模型中间层的知识转移到学生模型中。通过对齐两个模型的隐藏表示,学生模型可以学习到更丰富和更抽象的特征。
DeepSeek的蒸馏模型
为了让更多人能够使用,DeepSeek AI发布了六个基于流行架构(如Qwen和Llama)的蒸馏变体。他们直接使用DeepSeek-R1整理的80万样本对开源模型进行了微调。
尽管这些蒸馏模型比DeepSeek-R1小得多,但它们在各种基准测试中表现出色,常常匹配甚至超越许多大型模型的能力。如下图所示:
Deepseek蒸馏模型基准[2]
为什么要蒸馏你自己的模型?
1. 任务特定优化
预蒸馏模型在广泛的数据集上训练,以在各种任务中表现良好。然而,实际应用通常需要专业化。
示例场景:
你正在构建一个金融预测聊天机器人。
在这种情况下,使用DeepSeek-R1为金融数据集(例如股票价格预测、风险分析)生成推理轨迹,并将这些知识蒸馏到一个已经了解金融细微差别的较小模型中(例如:finance-LLM)。
2. 大规模成本效率
虽然预蒸馏模型效率较高,但对于你的特定工作负载而言,它们可能仍然过于庞大。蒸馏你自己的模型可以让你针对精确的资源限制进行优化。
3. 基准性能 ≠ 实际性能
预蒸馏模型在基准测试中表现出色,但基准测试通常并不代表实际任务。因此,你往往需要一个在实际场景中表现优于任何预蒸馏模型的模型。
4. 持续改进
预蒸馏模型是静态的——它们不会随着时间的推移而改进。通过蒸馏你自己的模型,你可以随着新数据的出现不断优化它。
代码教程:将DeepSeek-R1知识蒸馏到自定义小型模型中
步骤1:安装库
pip install -q torch transformers datasets accelerate bitsandbytes flash-attn --no-build-isolation
步骤2:生成和格式化数据集
你可以通过在你的环境中使用ollama[3]或任何其他部署框架部署DeepSeek-R1来生成自定义领域相关的数据集。但在本教程中,我们将使用Magpie-Reasoning-V2[4]数据集,该数据集包含由DeepSeek-R1生成的25万条链式思考(CoT)推理样本。这些样本涵盖了数学推理、编码和一般问题解决等多种任务。
数据集结构
每个样本包括:
•Instruction:任务描述(例如,“解决这个数学问题”)。•Response:DeepSeek-R1的逐步推理(CoT)。
示例:
{` `"instruction": "Solve for x: 2x + 5 = 15",` `"response": "<think>First, subtract 5 from both sides: 2x = 10. Then, divide by 2: x = 5.</think>"``}``
from datasets import load_dataset`` ``# 加载数据集``dataset = load_dataset("Magpie-Align/Magpie-Reasoning-V2-250K-CoT-Deepseek-R1-Llama-70B", token="YOUR_KEY")``dataset = dataset["train"]`` ``# 格式化数据集``def format_instruction(example):` `return {` `"text": (` `"<|user|>\n"` `f"{example['instruction']}\n"` `"<|end|>\n"` `"<|assistant|>\n"` `f"{example['response']}\n"` `"<|end|>"` `)` `}`` ``# 直接使用 dataset.column_names``formatted_dataset = dataset.map(format_instruction, batched=False, remove_columns=dataset.column_names)`` ``# 训练-测试集划分``formatted_dataset = formatted_dataset.train_test_split(test_size=0.1) # 90% 训练集, 10% 测试集`` ``# 输出数据集信息``print(formatted_dataset)
将数据集构建为Phi-3的聊天模板格式:
•<|user|>
:标记用户查询的开始。•<|assistant|>
:标记模型响应的开始。•<|end|>
:标记回合的结束。
每个大语言模型(LLM)在指令遵循任务中使用特定的格式。将数据集与此结构对齐可确保模型学习正确的对话模式。因此,请确保根据你希望蒸馏的模型格式化数据。
步骤3:加载模型和分词器
向分词器添加特殊标记<think>
和</think>
。
为了增强模型的推理能力,我们引入了这些标记。
•<think>
:标记推理的开始。•</think>
:标记推理的结束。
这些标记有助于模型学习生成结构化的逐步解决方案。
from transformers import AutoTokenizer, AutoModelForCausalLM``import torch # ✅ 添加 PyTorch 导入`` ``model_id = "microsoft/phi-3-mini-4k-instruct"``tokenizer = AutoTokenizer.from_pretrained(model_id, trust_remote_code=True)`` ``# 添加自定义标记``CUSTOM_TOKENS = ["<think>", "</think>"]``tokenizer.add_special_tokens({"additional_special_tokens": CUSTOM_TOKENS})``tokenizer.pad_token = tokenizer.eos_token`` ``# 使用flash attention加载模型``model = AutoModelForCausalLM.from_pretrained(` `model_id,` `trust_remote_code=True,` `device_map="auto",` `torch_dtype=torch.float16,` `attn_implementation="flash_attention_2"``)``model.resize_token_embeddings(len(tokenizer)) # 调整以适应自定义标记``
步骤4:配置LoRA[5]以实现高效微调
LoRA通过冻结基础模型,仅训练小的适配层来减少内存使用。
from peft import LoraConfig`` ``peft_config = LoraConfig(` `r=8, # 低秩矩阵的秩` `lora_alpha=16, # 缩放因子` `lora_dropout=0.2, # dropout率` `target_modules=["q_proj", "k_proj", "v_proj", "o_proj"], # 目标注意力层` `bias="none", # 无偏置项` `task_type="CAUSAL_LM" # 任务类型``)``
步骤5:设置训练参数
from transformers import TrainingArguments`` ``training_args = TrainingArguments(` `output_dir="./phi-3-deepseek-finetuned",` `num_train_epochs=3,` `per_device_train_batch_size=2,` `per_device_eval_batch_size=2,` `gradient_accumulation_steps=4,` `eval_strategy="epoch",` `save_strategy="epoch",` `logging_strategy="steps",` `logging_steps=50,` `learning_rate=2e-5,` `fp16=True,` `optim="paged_adamw_32bit",` `max_grad_norm=0.3,` `warmup_ratio=0.03,` `lr_scheduler_type="cosine"``)``
步骤6:训练模型
SFTTrainer简化了指令遵循模型的监督微调过程。数据整理器对示例进行批处理,peft_config
启用基于LoRA的训练。
from trl import SFTTrainer``from transformers import DataCollatorForLanguageModeling`` ``# 数据整理器``data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm=False)`` ``# 训练器``trainer = SFTTrainer(` `model=model,` `args=training_args,` `train_dataset=formatted_dataset["train"],` `eval_dataset=formatted_dataset["test"],` `data_collator=data_collator,` `peft_config=peft_config``)`` ``# 开始训练``trainer.train()``trainer.save_model("./phi-3-deepseek-finetuned")``tokenizer.save_pretrained("./phi-3-deepseek-finetuned")``
步骤7:合并并保存最终模型
训练完成后,必须将LoRA适配器与基础模型合并以进行推理。此步骤确保模型可以独立使用,无需PEFT。
final_model = trainer.model.merge_and_unload()``final_model.save_pretrained("./phi-3-deepseek-finetuned-final")``tokenizer.save_pretrained("./phi-3-deepseek-finetuned-final")``
步骤8:推理
from transformers import pipeline`` ``# 加载微调后的模型``model = AutoModelForCausalLM.from_pretrained(` `"./phi-3-deepseek-finetuned-final",` `device_map="auto",` `torch_dtype=torch.float16``)`` ``tokenizer = AutoTokenizer.from_pretrained("./phi-3-deepseek-finetuned-final")``model.resize_token_embeddings(len(tokenizer))`` ``# 创建聊天流程``chat_pipeline = pipeline(` `"text-generation",` `model=model,` `tokenizer=tokenizer,` `device_map="auto"``)`` ``# 生成响应``prompt = """<|user|>``What's the probability of rolling a 7 with two dice?``<|end|>``<|assistant|>``"""`` ``output = chat_pipeline(` `prompt,` `max_new_tokens=5000,` `temperature=0.7,` `do_sample=True,` `eos_token_id=tokenizer.eos_token_id``)`` ``print(output[0]['generated_text'])``
以下是蒸馏前后Phi模型的响应:
问题: what’s the probability of rolling a 7 with two dice?
蒸馏前的推理: 响应简洁明了,直接提供了计算答案的步骤。
蒸馏后的推理: 蒸馏后的响应引入了更详细和结构化的方法,包括明确的“think”部分,概述了思考过程和推理,这对于生成复杂问题的准确响应非常有帮助。
总结
本文通过介绍利用LoRA等技术,将DeepSeek‑R1的强大推理能力迁移到较小模型中,实现了在显著降低计算资源和延迟的同时保留核心性能,并针对真实任务和特定领域进行优化,为实际应用中的大规模模型轻量化提供了全面且实用的指导。
如何学习大模型 AI ?
由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。
但是具体到个人,只能说是:
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
第一阶段(10天):初阶应用
该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。
- 大模型 AI 能干什么?
- 大模型是怎样获得「智能」的?
- 用好 AI 的核心心法
- 大模型应用业务架构
- 大模型应用技术架构
- 代码示例:向 GPT-3.5 灌入新知识
- 提示工程的意义和核心思想
- Prompt 典型构成
- 指令调优方法论
- 思维链和思维树
- Prompt 攻击和防范
- …
第二阶段(30天):高阶应用
该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。
- 为什么要做 RAG
- 搭建一个简单的 ChatPDF
- 检索的基础概念
- 什么是向量表示(Embeddings)
- 向量数据库与向量检索
- 基于向量检索的 RAG
- 搭建 RAG 系统的扩展知识
- 混合检索与 RAG-Fusion 简介
- 向量模型本地部署
- …
第三阶段(30天):模型训练
恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。
到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?
- 为什么要做 RAG
- 什么是模型
- 什么是模型训练
- 求解器 & 损失函数简介
- 小实验2:手写一个简单的神经网络并训练它
- 什么是训练/预训练/微调/轻量化微调
- Transformer结构简介
- 轻量化微调
- 实验数据集的构建
- …
第四阶段(20天):商业闭环
对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。
- 硬件选型
- 带你了解全球大模型
- 使用国产大模型服务
- 搭建 OpenAI 代理
- 热身:基于阿里云 PAI 部署 Stable Diffusion
- 在本地计算机运行大模型
- 大模型的私有化部署
- 基于 vLLM 部署大模型
- 案例:如何优雅地在阿里云私有部署开源大模型
- 部署一套开源 LLM 项目
- 内容安全
- 互联网信息服务算法备案
- …
学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。
如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。