在《昇思 + 昇腾开发板:软硬结合玩转 DeepSeek 开发实战》课程学习中,《模型LoRA微调》是第二部分内容,在这部分中我通过视频学习和代码实践学习了LoRA 微调的核心流程,接下来我将对我学习到的经验进行分享。
首先,我们需要明白,什么是LoRA 微调,LoRA(Low-Rank Adaptation)是一种高效的参数微调方法,属于参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)的范畴。它的核心思想是在不改变原始模型大部分参数的情况下,对模型的关键部分进行小幅度的调整,从而让模型更好地适应新的任务或数据。
具体来说,LoRA 的方法是在模型的注意力层(Attention Layer)中引入一种特殊的结构。注意力层是模型中用来处理信息的关键部分,它通过 Query(查询)、Key(键)、Value(值)这三个模块来理解输入数据。LoRA 的巧妙之处在于,它在这些模块中添加了一个低秩旁路结构,这个旁路由两个可训练的低维矩阵 A 和 B 组成。这两个矩阵 A 和 B 的作用是替代对原始大矩阵的直接更新。换句话说,我们不需要重新训练整个模型的所有参数(这会非常耗时和耗资源),而是只更新这两个小矩阵。这样一来,训练的参数量大幅减少,计算和内存开销也大大降低,但模型的性能依然可以保持接近全参数微调的水平。
我们在进行 LoRA 微调之前,可以先把一个预训练好的基础模型加载进来。这种模型一般都用海量数据训练过,就像 DeepSeek 那种。加载它主要是想用上那些预训练好的权重。
在代码实现环节,教程基于昇思 MindSpore 框架,对 DeepSeek-R1-Distill-Qwen-1.5B 模型进行了 LoRA 微调。微调的目标是让模型能够模仿《甄嬛传》中甄嬛的语气和风格进行对话。
这段代码基于昇思MindSpore框架,实现了对DeepSeek-R1-Distill-Qwen-1.5B模型的LoRA微调,目标是让模型模仿《甄嬛传》中甄嬛的语气风格进行对话。以下是LoRA微调的全流程详解,按代码执行逻辑拆解:
一、环境准备:搭建基础依赖
代码首先完成微调所需的环境配置,确保工具链兼容昇腾开发板和LoRA微调需求:
- 安装MindSpore框架:指定安装
mindspore==2.6.0,这是支持LoRA微调及昇腾硬件的核心框架,提供模型训练、推理的基础能力。 - 安装MindNLP库:安装
mindnlp==0.4.1,这是昇思生态下的NLP工具库,提供预训练模型加载、数据集处理、LoRA适配等功能,已适配昇腾开发板的Qwen系列模型。 - 安装openmind_hub:用于从魔乐社区下载专用数据集(如
huanhuan.json,包含甄嬛风格对话数据)。
二、数据集下载与处理:适配模型输入格式
数据集是微调的“教材”,需处理成模型可理解的格式,具体步骤如下:
1. 下载数据集
通过om_hub_download从魔乐社区下载huanhuan.json,该数据集包含大量模仿甄嬛语气的对话样本(如“User: 你是谁? Assistant: 本宫是钮祜禄·甄嬛”),为模型学习风格提供数据基础。
2. 加载与格式化数据
实例化Tokenizer:使用DeepSeek-R1-Distill-Qwen-1.5B-FP16模型对应的分词器,统一文本到token的转换规则;设置pad_token = eos_token(因该模型中填充符与结束符一致),并将padding方向设为右侧,避免影响文本语义。
定义数据处理逻辑(process_func):
核心是将原始对话格式化为模型训练所需的“输入-标签”对,具体规则:
- 输入文本格式:
User: {问题}\n\nAssistant: {回答}<eos>(用eos_token标记结束); - 标签(
labels)设置:仅对“Assistant: 回答”部分计算损失(标签为对应token),“User: 问题”部分不参与训练(标签设为-100,MindSpore会忽略该值); - 长度处理:统一序列长度为64(超过则截断,不足则用
pad_token填充),确保批量训练时输入维度一致。
数据集裁剪:为加速演示,仅取前3条数据用于训练(实际场景需用完整数据集)。
三、基础模型加载:准备预训练“底座”
LoRA微调的核心是“冻结预训练模型参数,仅训练新增的低秩矩阵”,因此需先加载预训练模型作为“底座”:
- 加载基础模型:通过
AutoModelForCausalLM.from_pretrained加载DeepSeek-R1-Distill-Qwen-1.5B-FP16模型,该模型是DeepSeek-R1的轻量蒸馏版,参数规模1.5B,适合在昇腾开发板等边缘设备运行。 - 配置生成参数:加载模型默认的生成配置(如
pad_token_id、eos_token_id),并将pad_token_id与eos_token_id对齐(因模型设计中两者共享token),避免生成时格式混乱。
四、LoRA配置与模型构建:实现参数高效微调
这是LoRA微调的核心环节,通过插入低秩矩阵实现“少参数微调”:
1. LoRA参数配置(LoraConfig)
task_type=TaskType.CAUSAL_LM:指定任务为因果语言模型(适用于对话生成场景)。 target_modules:指定在模型的哪些层插入LoRA低秩矩阵,这里选择注意力层的q_proj(Q投影)、k_proj(K投影)、v_proj(V投影)、o_proj(输出投影)及前馈层的gate_proj、up_proj、down_proj,这些是影响模型语义表达的关键模块。 r=8:低秩矩阵的秩(矩阵维度),控制参数规模(秩越小,参数越少,这里仅需训练0.5%的参数)。 lora_alpha=32:缩放因子,用于调整低秩矩阵的更新强度(alpha/r决定有效学习率)。 lora_dropout=0.1: dropout层,防止过拟合。
2. 构建LoRA模型
通过get_peft_model(base_model, config)将基础模型与LoRA配置结合,生成可训练的LoRA模型。此时模型的原始参数被冻结,仅新增的低秩矩阵(矩阵A和B)可训练。代码中model.print_trainable_parameters()验证了这一点:可训练参数仅占总参数的0.5%,体现了LoRA“参数高效”的特点。
五、训练设置与回调:控制训练过程
为确保训练稳定进行并保存关键结果,需配置训练参数和回调函数:
1. 训练超参数(TrainingArguments)
output_dir:指定模型权重保存路径(./output/DeepSeek-R1-Distill-Qwen-1.5B)。 per_device_train_batch_size=1:单设备batch size(昇腾开发板内存有限,设为1避免溢出)。 logging_steps=1:每1步打印训练日志(便于监控损失变化)。 num_train_epochs=1:训练轮次(演示用,实际需根据数据量调整)。 save_steps=3:每3步保存一次权重(便于中断后续训)。 learning_rate=1e-4:学习率(LoRA微调的学习率通常高于全量微调,因仅更新少量参数)。
2. 自定义回调函数(SavePeftModelCallback)
LoRA微调仅需保存新增的“适配器权重”(低秩矩阵参数),无需保存完整基础模型(节省空间)。该回调函数的作用是:
- 在训练到
save_steps指定的步数时,将LoRA适配器权重保存到adapter_model目录; - 自动删除保存路径中额外生成的基础模型权重文件(如
model.safetensors),避免冗余存储。
六、启动训练:模型学习风格特征
通过Trainer实例化训练器,传入模型、训练参数、数据集和回调函数,调用trainer.train()启动微调。训练过程中,模型仅更新LoRA低秩矩阵的参数,通过学习huanhuan.json中甄嬛的对话风格(如用词、语气),逐步调整对“宫廷语境”的响应模式。
总结:LoRA微调的核心优势
- 参数高效:仅训练0.5%的参数,大幅降低昇腾开发板的内存和计算开销;
- 风格可控:通过特定数据集(
huanhuan.json)定向优化模型的对话风格; - 部署灵活:微调后仅需保存小体积的适配器权重(而非全量模型),便于在边缘设备部署。
在《昇思 + 昇腾开发板:软硬结合玩转 DeepSeek 开发实战》课程学习中,《模型LoRA微调》是第二部分内容,在这部分中我通过视频学习和代码实践学习了LoRA 微调的核心流程,接下来我将对我学习到的经验进行分享。
首先,我们需要明白,什么是LoRA 微调,LoRA(Low-Rank Adaptation)是一种高效的参数微调方法,属于参数高效微调(Parameter-Efficient Fine-Tuning, PEFT)的范畴。它的核心思想是在不改变原始模型大部分参数的情况下,对模型的关键部分进行小幅度的调整,从而让模型更好地适应新的任务或数据。
具体来说,LoRA 的方法是在模型的注意力层(Attention Layer)中引入一种特殊的结构。注意力层是模型中用来处理信息的关键部分,它通过 Query(查询)、Key(键)、Value(值)这三个模块来理解输入数据。LoRA 的巧妙之处在于,它在这些模块中添加了一个低秩旁路结构,这个旁路由两个可训练的低维矩阵 A 和 B 组成。这两个矩阵 A 和 B 的作用是替代对原始大矩阵的直接更新。换句话说,我们不需要重新训练整个模型的所有参数(这会非常耗时和耗资源),而是只更新这两个小矩阵。这样一来,训练的参数量大幅减少,计算和内存开销也大大降低,但模型的性能依然可以保持接近全参数微调的水平。
我们在进行 LoRA 微调之前,可以先把一个预训练好的基础模型加载进来。这种模型一般都用海量数据训练过,就像 DeepSeek 那种。加载它主要是想用上那些预训练好的权重。
在代码实现环节,教程基于昇思 MindSpore 框架,对 DeepSeek-R1-Distill-Qwen-1.5B 模型进行了 LoRA 微调。微调的目标是让模型能够模仿《甄嬛传》中甄嬛的语气和风格进行对话。
这段代码基于昇思MindSpore框架,实现了对
DeepSeek-R1-Distill-Qwen-1.5B模型的LoRA微调,目标是让模型模仿《甄嬛传》中甄嬛的语气风格进行对话。以下是LoRA微调的全流程详解,按代码执行逻辑拆解:一、环境准备:搭建基础依赖
代码首先完成微调所需的环境配置,确保工具链兼容昇腾开发板和LoRA微调需求:
mindspore==2.6.0,这是支持LoRA微调及昇腾硬件的核心框架,提供模型训练、推理的基础能力。mindnlp==0.4.1,这是昇思生态下的NLP工具库,提供预训练模型加载、数据集处理、LoRA适配等功能,已适配昇腾开发板的Qwen系列模型。huanhuan.json,包含甄嬛风格对话数据)。二、数据集下载与处理:适配模型输入格式
数据集是微调的“教材”,需处理成模型可理解的格式,具体步骤如下:
1. 下载数据集
通过
om_hub_download从魔乐社区下载huanhuan.json,该数据集包含大量模仿甄嬛语气的对话样本(如“User: 你是谁? Assistant: 本宫是钮祜禄·甄嬛”),为模型学习风格提供数据基础。2. 加载与格式化数据
实例化Tokenizer:使用
DeepSeek-R1-Distill-Qwen-1.5B-FP16模型对应的分词器,统一文本到token的转换规则;设置pad_token = eos_token(因该模型中填充符与结束符一致),并将padding方向设为右侧,避免影响文本语义。定义数据处理逻辑(
process_func):核心是将原始对话格式化为模型训练所需的“输入-标签”对,具体规则:
User: {问题}\n\nAssistant: {回答}<eos>(用eos_token标记结束);labels)设置:仅对“Assistant: 回答”部分计算损失(标签为对应token),“User: 问题”部分不参与训练(标签设为-100,MindSpore会忽略该值);pad_token填充),确保批量训练时输入维度一致。数据集裁剪:为加速演示,仅取前3条数据用于训练(实际场景需用完整数据集)。
三、基础模型加载:准备预训练“底座”
LoRA微调的核心是“冻结预训练模型参数,仅训练新增的低秩矩阵”,因此需先加载预训练模型作为“底座”:
AutoModelForCausalLM.from_pretrained加载DeepSeek-R1-Distill-Qwen-1.5B-FP16模型,该模型是DeepSeek-R1的轻量蒸馏版,参数规模1.5B,适合在昇腾开发板等边缘设备运行。pad_token_id、eos_token_id),并将pad_token_id与eos_token_id对齐(因模型设计中两者共享token),避免生成时格式混乱。四、LoRA配置与模型构建:实现参数高效微调
这是LoRA微调的核心环节,通过插入低秩矩阵实现“少参数微调”:
1. LoRA参数配置(
LoraConfig)task_type=TaskType.CAUSAL_LM:指定任务为因果语言模型(适用于对话生成场景)。target_modules:指定在模型的哪些层插入LoRA低秩矩阵,这里选择注意力层的q_proj(Q投影)、k_proj(K投影)、v_proj(V投影)、o_proj(输出投影)及前馈层的gate_proj、up_proj、down_proj,这些是影响模型语义表达的关键模块。r=8:低秩矩阵的秩(矩阵维度),控制参数规模(秩越小,参数越少,这里仅需训练0.5%的参数)。lora_alpha=32:缩放因子,用于调整低秩矩阵的更新强度(alpha/r决定有效学习率)。lora_dropout=0.1: dropout层,防止过拟合。2. 构建LoRA模型
通过
get_peft_model(base_model, config)将基础模型与LoRA配置结合,生成可训练的LoRA模型。此时模型的原始参数被冻结,仅新增的低秩矩阵(矩阵A和B)可训练。代码中model.print_trainable_parameters()验证了这一点:可训练参数仅占总参数的0.5%,体现了LoRA“参数高效”的特点。五、训练设置与回调:控制训练过程
为确保训练稳定进行并保存关键结果,需配置训练参数和回调函数:
1. 训练超参数(
TrainingArguments)output_dir:指定模型权重保存路径(./output/DeepSeek-R1-Distill-Qwen-1.5B)。per_device_train_batch_size=1:单设备batch size(昇腾开发板内存有限,设为1避免溢出)。logging_steps=1:每1步打印训练日志(便于监控损失变化)。num_train_epochs=1:训练轮次(演示用,实际需根据数据量调整)。save_steps=3:每3步保存一次权重(便于中断后续训)。learning_rate=1e-4:学习率(LoRA微调的学习率通常高于全量微调,因仅更新少量参数)。2. 自定义回调函数(
SavePeftModelCallback)LoRA微调仅需保存新增的“适配器权重”(低秩矩阵参数),无需保存完整基础模型(节省空间)。该回调函数的作用是:
save_steps指定的步数时,将LoRA适配器权重保存到adapter_model目录;model.safetensors),避免冗余存储。六、启动训练:模型学习风格特征
通过
Trainer实例化训练器,传入模型、训练参数、数据集和回调函数,调用trainer.train()启动微调。训练过程中,模型仅更新LoRA低秩矩阵的参数,通过学习huanhuan.json中甄嬛的对话风格(如用词、语气),逐步调整对“宫廷语境”的响应模式。总结:LoRA微调的核心优势
huanhuan.json)定向优化模型的对话风格;