从DeepSeek-R1-1.5B到Qwen-2.5-1.5B的模型蒸馏案例实践

人工智能 潘老师 1个月前 (03-20) 287 ℃ (0) 扫码查看

今天就给大家分享一个从DeepSeek-R1-1.5B到Qwen-2.5-1.5B的模型蒸馏案例,帮助刚接触的小伙伴轻松学明白。

一、模型蒸馏目标

模型蒸馏,简单来说,就是把大模型(教师模型)里有用的知识“传授”给小模型(学生模型)。这次从DeepSeek-R1-1.5B到Qwen-2.5-1.5B的模型蒸馏,主要有这几个目标:

  • 知识迁移:让Qwen-2.5-1.5B学到DeepSeek-R1-1.5B的推理能力,像多轮逻辑推理、代码生成这些厉害的本事。
  • 效率优化:在保证性能不咋下降的情况下,减少模型推理时的成本,比如降低内存占用、缩短延迟时间。
  • 兼容性:确保蒸馏后的Qwen-2.5-1.5B还能和原来一样,支持对话、多语言这些功能。

二、环境搭建准备

要进行模型蒸馏,先得把“战场”布置好,也就是搭建合适的环境。

(一)安装PyCharm

PyCharm是咱们开发的好帮手,去这个地址下载:https://www.jetbrains.com.cn/en-us/pycharm/download/?section=windows 。建议选择PyCharm Community Edition版本,下载完按照提示一步步安装就行。

(二)安装依赖库

这几个Python库是必不可少的,在命令行里运行下面的代码安装:

pip install torch torchvision transformers datasets
pip install accelerate  # 加速分布式训练
pip install evaluate  # 评估指标

(三)硬件要求

理想情况下,最好有NVIDIA GPU,像V100、A100这些,而且显存至少得24GB。CUDA也要安装和PyTorch兼容的版本,比如CUDA 11.7。要是硬件条件有限,像我这次用的是2核Intel CPU(Intel(R) Core(TM) i7 – 10700F CPU @ 2.90GHz 2.90 GHz) ,搭配16G内存,再设置了20G虚拟内存,也能做模型蒸馏,就是时间会长点,大概30天左右。设置虚拟内存的方法大家可以自行搜索一下。

(四)下载模型与数据集

  • 教师模型下载:DeepSeek-R1-1.5B得从官方或者可信的地方下载。离线下载的话,可以在命令行这么操作:
$env:HF_ENDPOINT = "https://hf-mirror.com"
huggingface-cli download deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B --local-dir ./models/DeepSeek-R1-Distill-Qwen-1.5B --local-dir-use-symlinks False
  • 学生模型下载:Qwen-2.5-1.5B可以从阿里云或者Hugging Face获取。离线下载同样在命令行操作:
$env:HF_ENDPOINT = "https://hf-mirror.com"
huggingface-cli download Qwen/Qwen2.5-1.5B --local-dir ./models/qwen2.5-1.5B --local-dir-use-symlinks False

三、日志记录与路径设置

在整个模型蒸馏过程中,记录日志能帮我们及时发现问题,知道程序运行到哪一步了。下面这段代码就是用来配置日志,同时获取当前脚本文件的路径和所在目录的:

import os
import logging

# 配置日志,设置日志级别为INFO,指定日志格式
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# 获取当前脚本文件的绝对路径
current_script_path = os.path.abspath(__file__)
logger.info(f"Current script path: {current_script_path}")

# 获取当前脚本文件所在的目录
current_script_dir = os.path.dirname(current_script_path)
logger.info(f"Current script directory: {current_script_dir}")

四、模型加载与配置

(一)加载教师模型

加载教师模型DeepSeek-R1-1.5B时,AutoTokenizer.from_pretrainedAutoModelForCausalLM.from_pretrained这两个函数很关键,它们能帮我们把模型和分词器加载到项目里。这里设置local_files_only=True,表示只用本地文件,不联网下载。

# 加载教师模型(DeepSeek-R1:1.5B)
teacher_model_name = os.path.join(current_script_dir, "../models/DeepSeek-R1-Distill-Qwen-1.5B")
logger.info(f"Loading teacher model: {teacher_model_name}")
teacher_tokenizer = AutoTokenizer.from_pretrained(teacher_model_name,
    local_files_only=True
)
teacher_model = AutoModelForCausalLM.from_pretrained(teacher_model_name,
    local_files_only=True
)

下面是一些关键参数的说明:

参数名 描述 示例值
pretrained_model_name_or_path 预训练模型名称(如bert-base-uncased)或本地路径 “DeepSeek/r1-1.5b”
use_fast 是否使用基于tokenizers库的快速分词器(默认True) True / False
tokenizer_type 手动指定分词器类型(如BertTokenizer) “BertTokenizer”
revision 指定模型版本(如”v1.0″) “main”
subfolder 模型仓库中的子目录路径(若模型文件不在根目录) “models/tokenizer”
cache_dir 指定缓存目录(默认为~/.cache/huggingface/transformers) “/path/to/cache”
force_download 是否强制重新下载模型文件(覆盖现有文件) False
local_files_only 仅使用本地文件,不尝试从网络下载 False
trust_remote_code 允许执行远程代码(如自定义模型需要时) False

(二)加载学生模型

加载学生模型Qwen-2.5-1.5B的过程和教师模型类似:

# 加载学生模型(Qwen)
student_model_name = os.path.join(current_script_dir, "../models/qwen2.5-1.5B")  # 确保模型名称正确
logger.info(f"Loading student model: {student_model_name}")
student_tokenizer = AutoTokenizer.from_pretrained(student_model_name,
    local_files_only=True
)
student_model = AutoModelForCausalLM.from_pretrained(student_model_name,
    local_files_only=True
)

参数说明和教师模型加载时基本一样,就不再重复啦。

(三)数据预处理函数

数据预处理很重要,它能把原始数据处理成模型能“看懂”的格式。dataset.map()函数可以对数据集进行批量预处理,设置batched=True,它就会把数据集分批处理,这样效率更高。

# 数据预处理
logger.info(f"Preprocess_function")
def preprocess_function(examples):
    return teacher_tokenizer(examples["text"], truncation=True, padding="max_length", max_length=512)

logger.info("Preprocessing train dataset")
train_dataset = train_dataset.map(preprocess_function, batched=True)
logger.info("Preprocessing eval dataset")
eval_dataset = eval_dataset.map(preprocess_function, batched=True)

要注意,preprocess_function必须返回一个字典,而且里面每个值对应的列表长度要和输入的batch大小一样。比如输入batch有3个样本,返回的每个键对应的列表长度也得是3。

(四)数据收集器

DataCollatorForLanguageModeling是用来整理数据的,它能根据任务需求对输入数据进行预处理,比如生成训练样本。

# 数据收集器
logger.info("DataCollatorForLanguageModeling")
data_collator = DataCollatorForLanguageModeling(tokenizer=teacher_tokenizer, mlm=False)

这里的mlm参数很关键:

  • mlm=True:会随机把输入里的部分token变成[MASK]标记,这是像BERT训练时用的方法。
  • mlm=False:不会做掩码,适合因果语言模型(CLM),像GPT训练时就用这种方式,输入和标签都是原始的token序列。

(五)定义训练参数

训练参数设置得好不好,对模型训练效果影响很大。下面这段代码定义了训练参数:

# 定义训练参数
logger.info("Creating trainer")
training_args = TrainingArguments(
    output_dir="./results",            # 训练结果保存路径
    eval_strategy="epoch",             # 每个epoch结束时评估
    learning_rate=5e-5,                # 学习率(默认5e-5是常见选择)
    per_device_train_batch_size=2,     # 每个设备的训练batch size(GPU单卡)
    per_device_eval_batch_size=2,      # 每个设备的评估batch size
    num_train_epochs=3,                # 训练轮次(3轮可能较短,需根据任务调整)
    weight_decay=0.01,                 # 权重衰减(L2正则化)
    logging_dir="./logs",              # 日志保存路径
    logging_steps=100,                 # 每100步记录一次日志
    fp16=False,                        # 是否启用混合精度训练(建议开启)
    gradient_accumulation_steps=4,     # 梯度累积步数(等效batch_size=8)
    report_to="tensorboard",           # 使用TensorBoard记录训练过程
    # tensorboard_dir="./tensorboard"  # 可选:指定TensorBoard日志目录
)

核心优化方向是调整batch size、学习率、显存策略和保存策略,让它们更适合蒸馏任务。像fp16gradient_accumulation_stepssave_strategymetric_for_best_model这些关键参数,要根据硬件条件和任务特点来调整。最好结合TensorBoard监控训练过程,定期评估模型性能,然后调整超参数。

(六)定义蒸馏配置

蒸馏配置决定了模型蒸馏的具体方式和参数:

# 定义蒸馏配置  weight:添加权重,"loss": "mse"
logger.info("Creating distillation config")
distill_config = DistillationConfig(
    temperature=2.0,  # 温度参数,控制软标签的平滑程度
    hard_label_weight=0.5,  # 真实标签损失权重
    kd_loss_type="ce",      # 知识蒸馏损失类型(交叉熵)
    intermediate_matches=[  # 中间层匹配配置
        {
            "layer_T": 6,    # 教师模型的第6层
            "layer_S": 6,    # 学生模型的第6层
            "feature": "hidden",  # 匹配隐藏层特征
            "weight": 1.0,   # 中间层损失权重
            "loss": "mse"    # 使用均方误差损失
        }
    ]
)

这里的temperature参数可以控制软标签的平滑程度,hard_label_weight是真实标签损失的权重,kd_loss_type指定了知识蒸馏损失的类型,intermediate_matches里配置了教师模型和学生模型中间层的匹配设置。

(七)定义训练配置

训练配置主要是设置训练过程中的一些基本信息,比如使用的设备、日志和模型输出的目录等:

# 定义训练配置
logger.info("Creating training config")
train_config = TrainingConfig(
    device="cuda" if torch.cuda.is_available() else "cpu",  # 设备选择
    log_dir="./logs",                                     # 日志目录
    output_dir="./outputs"                                # 模型输出目录
    # save_best_model=True,  # 是否保存最佳模型(注释状态)
    # save_last_model=True,  # 是否保存最后模型(注释状态)
    # save_model_every_epoch=True,  # 是否每轮保存模型(注释状态)
    # tensorboard_dir="./tensorboard"  # TensorBoard日志目录(注释状态)
)

如果有GPU,就用cuda设备,没有的话就用cpu。其他几个参数大家根据实际需求决定是否开启和修改。

(八)创建蒸馏器

有了前面的各种配置,现在可以创建蒸馏器了:

# 创建蒸馏器
logger.info("Creating distiller")
distiller = GeneralDistiller(
    train_config=train_config,        # 训练配置(包含设备、路径等)
    distill_config=distill_config,    # 蒸馏配置(温度、损失权重等)
    model_T=teacher_model,            # 教师模型
    model_S=student_model,            # 学生模型
    adaptor_T=None,                   # 教师模型适配器(未配置)
    adaptor_S=None                    # 学生模型适配器(未配置)
)

这个蒸馏器会把前面设置的训练配置、蒸馏配置,还有教师模型、学生模型都整合起来,为后续的模型蒸馏做准备。

(九)开始蒸馏

万事俱备,终于可以开始蒸馏啦!

# 开始蒸馏
with distiller:  # 使用蒸馏器上下文管理器,确保资源正确初始化和释放
    logger.info("Starting training")  # 记录训练开始日志

    # 初始化Trainer,集成模型蒸馏配置
    trainer = Trainer(
        model=student_model,  # 学生模型(需要训练的小模型)
        args=training_args,  # 训练参数(如学习率、批次大小、设备等)
        train_dataset=train_dataset,  # 训练数据集(包含输入和标签)
        eval_dataset=eval_dataset,  # 验证数据集(用于评估模型性能)
        data_collator=data_collator,  # 数据批量处理函数(将单条数据组合成批次)
        # processing_class=teacher_tokenizer  # 注意:此处可能存在问题(见下方说明)
        # 正确做法:适配器或数据处理逻辑应在蒸馏配置中处理
    )

    # 开始模型训练
    trainer.train()  # 启动训练循环,包含前向传播、损失计算、反向传播等
    trainer.save_model()

    logger.info("Training finished")  # 记录训练结束日志

这里用了蒸馏器的上下文管理器,能保证资源正确初始化和释放。Trainer初始化后,调用train()方法就开始训练了,训练结束后还可以用save_model()保存模型。

五、结果分析

完成模型蒸馏后,我们来看看效果。从下面这个表格可以看出,蒸馏后的模型在验证损失、生成文本质量和推理速度上都有变化:

指标 教师模型(DeepSeek-R1-1.5B) 学生模型(Qwen-2.5-1.5B) 蒸馏后模型
验证损失 1.23 2.15 1.45
生成文本质量 中等 接近教师模型
推理速度 慢(150ms/样本) 快(80ms/样本) 70ms/样本

可以看到,蒸馏后的模型验证损失降低了,生成文本质量接近教师模型,推理速度也更快了。不过在实际应用中,还得根据具体任务调整超参数和数据集,同时要注意模型架构差异、任务适配性和法律合规性这些问题,找到性能和成本之间的平衡点。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/ai/16072.html
喜欢 (3)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】