自然语言处理:第一百零九章 单卡4090微调DeepSeek-R1-32B

本人项目地址大全:Victor94-king/NLP__ManVictor: 优快云 of ManVictor


写在前面: 笔者更新不易,希望走过路过点个关注和赞,笔芯!!!

写在前面: 笔者更新不易,希望走过路过点个关注和赞,笔芯!!!

写在前面: 笔者更新不易,希望走过路过点个关注和赞,笔芯!!!


在 24G 显存的单卡 4090 上微调训练 deepseek-ai/DeepSeek-R1-Distill-Qwen-32B;即使该模型的权重文件大小已经达到 62G,这是因为 unsloth 和 lora 的量化微调和部分参数微调优化可以大幅节约显存占用。

因为设置了**max_steps=**60 限制了只执行60步以便快速完成实验。去掉这个参数后,SFTTrainer 即可根据数据量自动计算微调步数了。这次进行了 FreedomIntelligence/medical-o1-reasoning-SFT 数据集 24772 条数据的全量微调,epoch为默认值3,微调结果如下:

  • 训练总步数 (Total steps) : 9288 步
  • **训练总轮次 (Epochs) : 3.0 轮 **
  • 每轮数据量: 24,772 条数据
  • 训练时间: 总计 28小时28分37秒(102517.8411 秒)

本次训练在贝联云算力平台( https://cloud.lccomputing.com )上完成。

完整训练代码如下:

import wandb
# 登录 wandb.ai 用于实验跟踪
wandb.login(key="放置你的wandb.ai网站上的token")
# 初始化wandb项目
run = wandb.init(
    project='Lora-R1-Distill-Qwen on Medical COT Dataset',
    job_type="training",
    anonymous="allow"
)


####################################################################################################
# 1.加载模型


# 使用 unsloth 优化的 FastLanguageModel 加载模型
from unsloth import FastLanguageModel
max_seq_length = 4096 # 最大序列长度
dtype = None          # 数据类型,None表示自动选择
load_in_4bit = True   # 使用4bit量化加载模型以节省显存


# 加载预训练模型和分词器
model, tokenizer = FastLanguageModel.from_pretrained(
    #model_name = "unsloth/DeepSeek-R1-Distill-Qwen-7B",
    model_name = "/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-32B",
    local_files_only=True,  # 避免联网
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
    #token = hf_token, 
)
print(model)


####################################################################################################
# 2. 定义提示模板,并在微调前做一次推理


prompt_style = """以下是描述任务的指令,以及提供更多上下文的输入。
  请写出恰当完成该请求的回答。
  在回答之前,请仔细思考问题,并创建一个逐步的思维链,以确保回答合乎逻辑且准确。
  ### Instruction:
  你是一位在临床推理、诊断和治疗计划方面具有专业知识的医学专家。
  请回答以下医学问题。
  ### Question:
  {}
  ### Response:
  <think>{}"""
train_prompt_style = prompt_style + """
  </think>
  {}"""


# 测试用医学问题
question = "一名70岁的男性患者因胸痛伴呕吐16小时就医,心电图显示下壁导联和右胸导联ST段抬高0.1~0.3mV,经补液后血压降至80/60mmHg,患者出现呼吸困难和不能平卧的症状,体检发现双肺有大量水泡音。在这种情况下,最恰当的药物处理是什么?"


# 设置模型为推理模式
FastLanguageModel.for_inference(model) 
inputs = tokenizer([prompt_style.format(question, "")], return_tensors="pt").to("cuda")


# 生成回答
outputs = model.generate(
    input_ids=inputs.input_ids,
    attention_mask=inputs.attention_mask,
    max_new_tokens=1200,
    use_cache=True,
)
response = tokenizer.batch_decode(outputs)
print("### 微调前模型推理结果:")
print(response[0].split("### Response:")[1])


####################################################################################################
# 3. 处理数据集


EOS_TOKEN = tokenizer.eos_token  # 添加结束符标记
#格式化提示函数,用于处理数据集中的示例
def formatting_prompts_func(examples):
    # 从examples中提取问题、思维链和回答
    inputs = examples["Question"]      # 医学问题列表
    cots = examples["Complex_CoT"]     # 思维链列表 
    outputs = examples["Response"]     # 回答列表
    
    # 存储格式化后的文本
    texts = []
    
    # 遍历每个示例,将问题、思维链和回答组合成指定格式
    for input, cot, output in zip(inputs, cots, outputs):
        # 使用train_prompt_style模板格式化文本,并添加结束符
        text = train_prompt_style.format(input, cot, output) + EOS_TOKEN
        texts.append(text)
        
    # 返回格式化后的文本字典
    return {
        "text": texts,
    }


# 加载数据集并应用格式化
from datasets import load_dataset,load_from_disk
dataset = load_dataset(
    "json",  # 指定数据格式为 JSON
    data_files="/dat
<think>我们正在讨论如何微调 deepseek-r1-distill-qwen模型。根据引用[1]和引用[2],我们可以使用LLaMA-Factory来微调这个模型,并且可以使用vllm进行推理。微调完成后,我们需要合并LoRA权重才能用vllm进行推理。步骤概述: 1.准备环境:安装必要的库,包括LLaMA-Factory和vllm。2.准备数据集:根据任务需求准备训练和验证数据集。 3.配置微调参数:使用LLaMA-Factory提供的配置模板,设置模型路径、数据集路径、训练参数等。 4.开始微调:运行训练脚本。 5.合并权重:微调完成后,使用提供的脚本合并LoRA权重到基座模型中。6.使用vllm进行推理:加载合并后的模型进行推理服务。 详细步骤:###1.环境准备首先,确保已经安装了LLaMA-Factory和vllm。如果没有,可以通过以下命令安装:```bash#安装LLaMA-Factorygit clonehttps://github.com/hiyouga/LLaMA-Factory.gitcd LLaMA-Factorypipinstall -e .[metrics] #安装vllmpip installvllm``` ###2.准备数据集LLaMA-Factory支持多种数据集格式,如alpaca、json等。假设我们有一个名为`dataset.json`的文件,格式如下(以alpaca格式为例):```json[{"instruction":"解释深度学习。","input": "","output":"深度学习是机器学习的一个分支..."},...] ```将数据集放在合适的目录下,例如`data/dataset.json`。###3.配置微调参数LLaMA-Factory提供了训练脚本`src/train_bash.py`。我们可以通过命令行参数或配置文件来设置训练参数。以下是一个示例命令:```bashCUDA_VISIBLE_DEVICES=0 pythonsrc/train_bash.py\--stagesft \--do_train \--model_name_or_path/workspace/luoshiyong/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \--dataset dataset\--templatedefault \--finetuning_typelora\--lora_targetq_proj,v_proj\--output_dir saves/deepseek/lora/sft \--overwrite_cache \--per_device_train_batch_size4\--gradient_accumulation_steps4\--lr_scheduler_type cosine\--logging_steps10\--save_steps1000 \--learning_rate5e-5 \--num_train_epochs3.0 \--plot_loss\--fp16``` 参数说明:- `--stagesft`:使用监督微调- `--model_name_or_path`:基座模型路径。- `--dataset`:数据集名称(对应`data`目录下的文件名,不带后缀)。 -`--template`:模板,这里使用default。 -`--finetuning_typelora`:使用LoRA进行微调-`--lora_target`:指定要应用LoRA的模块,这里以QProj和VProj为例(具体目标模块需根据模型结构确定,对于DeepSeek-R1-Distill-Qwen-7B,可能需要参考其模型结构)。- `--output_dir`:输出目录,用于保存微调后的LoRA权重。 -其他训练参数如批次大小、学习率等可根据实际情况调整。注意:`lora_target`的设置需要根据模型结构来确定。对于DeepSeek-R1-Distill-Qwen-7B,我们可以查看其模型结构或参考类似模型(如Qwen)的设置。常见的设置是`q_proj, v_proj`,但具体可能需要尝试或查阅文档。 ###4.开始微调运行上述命令开始训练。训练过程中会输出日志,包括损失值等。 ###5.合并权重训练完成后,LoRA权重保存在`output_dir`指定的目录中。为了使用vllm进行推理,我们需要将LoRA权重合并到基座模型中。使用引用[2]中提供的脚本: ```pythonfrom peft importPeftModelfrom transformersimport AutoModelForCausalLM#加载基座模型base_model =AutoModelForCausalLM.from_pretrained("/workspace/luoshiyong/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B")#加载LoRA适配器并合并merged_model= PeftModel.from_pretrained(base_model, "/workspace/luoshiyong/LLaMA-Factory/saves/deepseek/lora/sft") merged_model =merged_model.merge_and_unload()#保存合并后的模型merged_model.save_pretrained("/workspace/luoshiyong/deepseek-ai/lora_sft") ```注意:合并后的模型将保存为一个完整的模型,可以直接加载。 ###6.使用vllm进行推理合并后的模型可以使用vllm进行推理服务。启动服务命令如下: ```bashpython -m vllm.entrypoints.openai.api_server \--model /workspace/luoshiyong/deepseek-ai/lora_sft\--tensor-parallel-size2\--max-model-len32768``` 参数说明:- `--model`:合并后的模型路径。 -`--tensor-parallel-size`:张量并行数,根据GPU数量设置。- `--max-model-len`:最大模型长度。然后就可以通过OpenAIAPI的格式进行调用。 ###注意事项-微调需要大量计算资源,确保有足够的GPU内存。 -微调前,建议先在小批量数据上测试,确保配置正确。-对于`lora_target`的设置,如果不确定,可以尝试使用`all`(如果LLaMA-Factory支持)或者参考类似模型的设置。 以上步骤提供了一个完整的微调流程。根据具体任务,可能需要调整训练参数和数据集。§§相关问题§§1.如何为DeepSeek-R1-Distill-Qwen-7B模型准备数据集? 2.微调DeepSeek-R1-Distill-Qwen-7B模型时,如何选择合适的学习率和批次大小?3.除了LoRA,还有哪些微调方法适用于DeepSeek-R1-Distill-Qwen-7B模型? 4.如何评估微调后的DeepSeek-R1-Distill-Qwen-7B模型性能?</think>### 微调 DeepSeek-R1-Distill-Qwen-7B 模型指南 #### 1. 环境准备 - 安装核心库: ```bash pip install vllm transformers peft accelerate datasets ``` - 确保 GPU 环境(建议 NVIDIA A100 80GB 或更高) - 准备模型权重: ```python from transformers import AutoModelForCausalLM model = AutoModelForCausalLM.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-7B") ``` #### 2. 数据准备(示例) ```python from datasets import load_dataset dataset = load_dataset("json", data_files="your_data.json") # 自定义数据集格式 dataset = dataset.map(lambda x: {"text": f"指令: {x['instruction']}\n响应: {x['output']}"}) ``` #### 3. LoRA 微调(使用 LLaMA-Factory) ```bash # 克隆仓库 git clone https://github.com/hiyouga/LLaMA-Factory.git cd LLaMA-Factory ``` ```bash # 启动微调 (单卡示例) CUDA_VISIBLE_DEVICES=0 python src/train_bash.py \ --stage sft \ --model_name_or_path deepseek-ai/DeepSeek-R1-Distill-Qwen-7B \ --do_train \ --dataset your_dataset \ --template default \ --finetuning_type lora \ --lora_target q_proj,v_proj \ --output_dir saves/lora_sft \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 4 \ --lr_scheduler_type cosine \ --logging_steps 10 \ --save_steps 1000 \ --learning_rate 5e-5 \ --num_train_epochs 3.0 \ --fp16 ``` **关键参数说明**: - `lora_target`:指定适配层(根据模型结构调整) - `per_device_train_batch_size`:根据 GPU 显存调整 - `learning_rate`:推荐 1e-5 到 5e-5 #### 4. 权重合并(微调后必需步骤) ```python from peft import PeftModel from transformers import AutoModelForCausalLM base_model = AutoModelForCausalLM.from_pretrained("deepseek-ai/DeepSeek-R1-Distill-Qwen-7B") merged_model = PeftModel.from_pretrained(base_model, "saves/lora_sft") merged_model = merged_model.merge_and_unload() # 合并LoRA权重 merged_model.save_pretrained("merged_model") # 保存完整模型[^2] ``` #### 5. 使用 vLLM 部署 ```bash python -m vllm.entrypoints.openai.api_server \ --model merged_model \ --tensor-parallel-size 2 \ --max-model-len 32768 \ --enforce-eager ``` **部署参数**: - `tensor-parallel-size`:GPU 并行数量 - `max-model-len`:最大上下文长度(需匹配训练长度) - `enforce-eager`:优化内存使用[^1] #### 6. 验证微调效果 ```python from vllm import LLM llm = LLM("merged_model") outputs = llm.generate(["你的测试指令"]) print(outputs[0].outputs[0].text) ``` ### 注意事项 1. **显存优化**: - 使用 `fp16` 或 `bf16` 精度 - 启用梯度检查点:`--gradient_checkpointing` 2. **数据格式**: - 确保指令-响应对格式统一 - 推荐使用 Alpaca 格式 3. **灾难性遗忘**: - 添加 10-20% 原始预训练数据 - 控制学习率不超过 5e-5 > 微调效果取决于数据质量和超参数调整,建议先用 5% 数据做测试训练[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曼城周杰伦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值