(小白0基础) 微调deepseek-8b模型参数详解以及全流程——训练篇

news2025/4/17 15:28:07


本篇参考bilibili如何在本地微调DeepSeek-R1-8b模型_哔哩哔哩_bilibili

上篇:(小白0基础) 租用AutoDL服务器进行deepseek-8b模型微调全流程(Xshell,XFTP) —— 准备篇

初始变量

max_seq_length = 2048
dtype = None
load_in_4bit = True
  • 单批次最大处理模型大小
  • dype 参数的数据精度,包括各种矩阵中的数据的精例如 float32(高精度)、float16(半精度),选择None则是自动选择精度
  • 4bit量化,可以将模型部署在消费级的显卡上,而不损失大量的精度
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/DeepSeek-R1-Distill-Llama-8B",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
    token = hf_token,
)
  • 解包操作,对于该方法复制给两个变量
question = "A 61-year-old woman with a long history of involuntary urine loss during activities like coughing or sneezing but no leakage at night undergoes a gynecological exam and Q-tip test. Based on these findings, what would cystometry most likely reveal about her residual volume and detrusor contractions?"

## 模型输入
FastLanguageModel.for_inference(model)  # Unsloth has 2x faster inference!
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(response[0].split("### Response:")[1])
  • input_ids这里是将字符转换为token
  • max_new_tokens 生成的最大长度
  • use_cache 缓存开启,也就是保存之前的键值对(这里还不太懂)
  • attention_mask 指的是 Padding Mask 指的是忽略输入文本长度,针对样本不同的token填充例如[PAD],在矩阵中赋值为0
model = FastLanguageModel.get_peft_model(
    model,
    r=16,
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
    ],
    lora_alpha=16,
    lora_dropout=0,
    bias="none",
    use_gradient_checkpointing="unsloth",  # True or "unsloth" for very long context
    random_state=3407,
    use_rslora=False,
    loftq_config=None,
)
  • Lora的基本概念,通过分解detw的值ΔW=A⋅B

  • r 分解矩阵的秩的大小:d×r+r×k

  • lora_alpha, LoRA缩放因子(ΔW = α * A*B)通常为r的倍数

  • lora_dropout 丢弃率,防止过拟合

  • bias 偏置项,减少训练量 wx+b的b

  • andom_state,用来确保实验可以复现(保存初始化元素)

  • use_rslora lora变体

  • use_gradient_checkpointing 梯度检查点
    Forward: [Layer1-5 → 检查点 → Layer6-10 → 检查点 → …] 仅存储检查点激活
    Backward:

    1. 从最后一个检查点重计算 Layer6-10

    2. 计算 Grad10-6

    3. 从中间检查点重计算 Layer1-5

    4. 计算 Grad5-1

      具体来说,就是删除其中一些向量a,我们在反向传播的时候要用到的a通过再次前向传输进行计算输出

      用空间换时间
      在这里插入图片描述

trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=max_seq_length,
    dataset_num_proc=2,
    args=TrainingArguments(
        per_device_train_batch_size=2,
        gradient_accumulation_steps=4,
        # Use num_train_epochs = 1, warmup_ratio for full training runs!
        warmup_steps=5,
        max_steps=60,
        learning_rate=2e-4,
        fp16=not is_bfloat16_supported(),
        bf16=is_bfloat16_supported(),
        logging_steps=10,
        optim="adamw_8bit",
        weight_decay=0.01,
        lr_scheduler_type="linear",
        seed=3407,
        output_dir="outputs",
    ),
)

  • SFTTrainertrl 库中专门用于对语言模型进行监督式微调(Supervised Fine-Tuning)的训练器,通常用于指令微调(Instruction Tuning)。

  • dataset_num_proc=2

作用: 指定在预处理数据集(例如,进行分词)时使用的 CPU 进程数量。

  • per_device_train_batch_size=2 Batch Size 是指在单次模型权重更新前,模型处理的样本数量。

  • gradient_accumulation_steps=4 小批次反向传播

  • warmup_steps 在训练开始的前 warmup_steps 步(这里是 5 步),学习率会从一个很小的值(通常是 0)逐渐线性增加到设定的 learning_rate。这有助于在训练初期稳定模型,避免因初始梯度过大导致训练发散。

    • max_steps=60 训练将在执行了 60 次权重更新后停止,无论处理了多少数据或完成了多少轮(Epoch)。如果同时设置了 num_train_epochsmax_steps 会覆盖它。这里设置为 60,表明这是一个非常短的训练过程,可能用于快速验证代码或流程是否正常。注释提示完整训练应使用 num_train_epochs
  • num_train_epochs = 1 删除 max_steps=60,设置 num_train_epochs = 1 作为

  • fp16=not is_bfloat16_supported(), 数据精度问题
    bf16=is_bfloat16_supported(),

  • logging_steps=10 设置记录训练指标(如损失、学习率等)的频率

  • optim=“adamw_8bit” adam优化器
    -在这里插入图片描述

  • weight_decay=0.01 权重衰减是一种正则化技术,通过在损失函数中添加一个与权重平方和成正比的惩罚项,来防止模型权重变得过大,有助于减少过拟合。区别(L2)

  • lr_scheduler_type=“linear” 学习率调度器负责在训练过程中动态调整学习率,这里是线性增加

这里的学习处理的一些参数设置关系

训练开始 (Step 0 -> Step 5):

  • Warmup 控制: warmup_steps=5 生效。
  • Scheduler (Linear) 配合: 学习率从 0 开始线性增加。
  • Optimizer (AdamW_8bit) 执行: 在每一步使用这个逐渐增大的学习率和计算出的梯度来更新模型权重。

预热结束 (Step 5):

  • 学习率达到峰值 learning_rate=2e-4

训练继续 (Step 6 -> Step 60):

  • Scheduler (Linear) 控制: lr_scheduler_type="linear" 生效。学习率从 2e-4 开始线性下降,目标是在第 60 步时降到 0。
  • Optimizer (AdamW_8bit) 执行: 在每一步使用这个逐渐减小的学习率和计算出的梯度来更新模型权重。

训练结束 (Step 60):

  • 学习率理论上降到 0,训练停止。

wandb图标观察

  1. train/loss (训练损失)
  • X 轴: train/global_step - 训练进行的全局步数(优化器更新次数),从 10 到 60。

  • Y 轴: Loss (损失值) - 模型在训练数据上计算出的损失函数值。这个值越低通常表示模型拟合训练数据越好。

  • 曲线解读: 图表显示损失值从训练开始(第 10 步之后)的较高值(约 1.9)迅速下降,然后在后续步骤中(20 到 60 步)下降速度减缓,最终达到约 1.35 左右。
    在这里插入图片描述

    1. train/learning_rate (训练学习率)
    • X 轴: train/global_step - 全局步数 (10 到 60)。
    • Y 轴: Learning Rate (学习率) - 优化器在每一步实际使用的学习率。
    • 曲线解读: 学习率从第 10 步时的一个较高值(接近你设置的峰值 2e-4,这里显示约 1.6e-4 可能是因为记录点和实际峰值点略有偏差或 warmup 刚结束)开始,随着步数增加线性下降,在第 60 步接近 0。
    • 意义: 这个图完美地验证了你的学习率调度设置:warmup_steps=5 (前 5 步预热,图中未完全显示,因为 x 轴从 10 开始) 和 lr_scheduler_type="linear" 以及 max_steps=60。学习率在预热后达到峰值,然后线性衰减至训练结束。

在这里插入图片描述

  1. train/grad_norm (训练梯度范数)
    • X 轴: train/global_step - 全局步数 (10 到 60)。
    • Y 轴: Grad Norm (梯度范数) - 模型所有参数梯度组成的向量的长度(范数)。它衡量了梯度的大小。
    • 曲线解读: 梯度范数在训练早期(第 10 步)相对较高(约 0.58),然后迅速下降到 0.3 左右(第 20 步),之后趋于稳定,最后略有回升到 0.35 左右。
    • 意义: 梯度范数可以帮助诊断训练稳定性。初始值较高表明模型离最优解较远,需要较大调整。迅速下降表明模型快速进入损失较低的区域。后续稳定或轻微波动是正常的。需要警惕的是梯度范数爆炸(变得非常大)或消失(变得非常接近 0),这两种情况都可能阻碍训练。你图中的值看起来在合理范围内。

在这里插入图片描述

  1. train/epoch (训练轮数)
    • X 轴: train/global_step - 全局步数 (10 到 60)。
    • Y 轴: Epoch - 当前训练进度相当于遍历了整个训练数据集的多少比例。
    • 曲线解读: Epoch 值随着全局步数的增加而线性增加,从第 10 步的约 0.15 增加到第 60 步的约 0.9。

在这里插入图片描述
完整代码

pip install unsloth  # 安装unsloth库
pip install bitsandbytes unsloth_zoo # 安装工具库
 
import torch # 加载torch库
from unsloth import FastLanguageModel 
 
# ############## 加载模型和分词器#####################
# 超参数设置
max_seq_length = 2048 #模型的上下文长度,可以任意选择,内部提供了RoPE Scaling 技术支持
dtype = None  # 通常设置为None,使用Tesla T4, V100等GPU时可用Float16,使用Ampere+时用Bfloat16
load_in_4bit = True  # 以4位量化进行微调
 
# 基于unsloth加载deepseek的蒸馏模型
model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/DeepSeek-R1-Distill-Llama-8B",
    max_seq_length = max_seq_length,
    dtype = dtype,
    load_in_4bit = load_in_4bit,
    token = hf_token, 
)
 
# ################# 提示模板 #######################
prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. 
Write a response that appropriately completes the request. 
Before answering, think carefully about the question and create a step-by-step chain of thoughts to ensure a logical and accurate response.
### Instruction:
You are a medical expert with advanced knowledge in clinical reasoning, diagnostics, and treatment planning. 
Please answer the following medical question. 
### Question:
{}
### Response:
<think>{}"""
 
# ##################### 微调前推理示例 #######################
question = "一个患有急性阑尾炎的病人已经发病5天,腹痛稍有减轻但仍然发热,在体检时发现右下腹有压痛的包块,此时应如何处理?"
 
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(response[0].split("### Response:")[1])
 
# ###################### 更新提示模板 #######################
train_prompt_style = """Below is an instruction that describes a task, paired with an input that provides further context. 
Write a response that appropriately completes the request. 
Before answering, think carefully about the question and create a step-by-step chain of thoughts to ensure a logical and accurate response.
### Instruction:
You are a medical expert with advanced knowledge in clinical reasoning, diagnostics, and treatment planning. 
Please answer the following medical question. 
### Question:
{}
### Response:
<think>
{}
</think> 
{}"""
 
# ####################### 处理函数 #########################
EOS_TOKEN = tokenizer.eos_token  # 末尾必须加上 EOS_TOKEN
 
def formatting_prompts_func(examples):
    inputs = examples["Question"]
    cots = examples["Complex_CoT"]
    outputs = examples["Response"]
    texts = []
    for input, cot, output in zip(inputs, cots, outputs):
        text = train_prompt_style.format(input, cot, output) + EOS_TOKEN
        texts.append(text)
    return {
        "text": texts,
    }
 
 
# ################### 加载数据集 ##########################
from datasets import load_dataset
dataset = load_dataset("FreedomIntelligence/medical-o1-reasoning-SFT", 'zh', split = "train[0:500]", trust_remote_code=True)
print(dataset.column_names)
 
dataset = dataset.map(formatting_prompts_func, batched = True)
print(dataset["text"][0])
 
# ################## 微调参数设置 #####################
model = FastLanguageModel.get_peft_model(
    model,
    r=16,   # 选择任何数字 > 0 !建议 8、16、32、64、128微调过程的等级。
        #数字越大,占用的内存越多,速度越慢,但可以提高更困难任务的准确性。太大也会过拟合
    target_modules=[
        "q_proj",
        "k_proj",
        "v_proj",
        "o_proj",
        "gate_proj",
        "up_proj",
        "down_proj",
    ],  # 选择所有模块进行微调
 
    lora_alpha=16, # 微调的缩放因子,建议将其等于等级 r,或将其加倍。
    lora_dropout=0,  # 将其保留为 0 以加快训练速度!可以减少过度拟合,但不会那么多。
    bias="none",  # 将其保留为 0 以加快训练速度并减少过度拟合!
    use_gradient_checkpointing="unsloth",  # True or "unsloth" for very long context
    random_state=3407, # 随机种子数
    use_rslora=False,  # 支持等级稳定的 LoRA,高级功能可自动设置 lora_alpha = 16
    loftq_config=None, # 高级功能可将 LoRA 矩阵初始化为权重的前 r 个奇异向量。
                        #可以在一定程度上提高准确性,但一开始会使内存使用量激增。
)
 
# ################# 训练参数设置 #######################
from trl import SFTTrainer
from transformers import TrainingArguments
from unsloth import is_bfloat16_supported
 
trainer = SFTTrainer(
    model=model,
    tokenizer=tokenizer,
    train_dataset=dataset,
    dataset_text_field="text",
    max_seq_length=max_seq_length,
    dataset_num_proc=2,
    args=TrainingArguments(
        per_device_train_batch_size=2,
        gradient_accumulation_steps=4,
        # Use num_train_epochs = 1, warmup_ratio for full training runs!
        warmup_steps=5,
        max_steps=60,
        learning_rate=2e-4,
        fp16=not is_bfloat16_supported(),
        bf16=is_bfloat16_supported(),
        logging_steps=10,
        optim="adamw_8bit",
        weight_decay=0.01,
        lr_scheduler_type="linear",
        seed=3407,
        output_dir="outputs",
    ),
)
 
# ################### 模型训练 #################
trainer_stats = trainer.train()
 
# ################### 模型保存 ##################
new_model_local = "DeepSeek-R1-Medical-COT"
model.save_pretrained(new_model_local)  # 本地模型保存
tokenizer.save_pretrained(new_model_local) # 分词器保存
 
# 将模型和分词器以合并的方式保存到指定的本地目录
model.save_pretrained_merged(new_model_local, tokenizer, save_method = "merged_16bit",) 
 
 
# model.push_to_hub("your_name/lora_model", token = "...") # Online saving
# tokenizer.push_to_hub("your_name/lora_model", token = "...") # Online saving

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2335921.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于汽车辅助驾驶不同等级、技术对比、传感器差异及未来发展方向的详细分析

以下是关于汽车辅助驾驶不同等级、技术对比、传感器差异及未来发展方向的详细分析&#xff1a; 一、汽车辅助驾驶等级详解 根据SAE&#xff08;国际自动机工程师学会&#xff09;的标准&#xff0c;自动驾驶分为 L0到L5 六个等级&#xff1a; 1. L0&#xff08;无自动化&…

mongodb7日志特点介绍:日志分类、级别、关键字段(下)

#作者&#xff1a;任少近 上篇《mongodb7日志特点介绍&#xff1a;日志分类、级别、关键字段(上)》 链接: link 文章目录 4.日志会输出F/E/W/I四种情况5.日志关键字段6.日志量验证情况7.总结 4.日志会输出F/E/W/I四种情况 在MongoDB7中&#xff0c;日志输出按照严重性分为四种…

word中插入图片显示不完整,怎么处理让其显示完整?

在WORD里插入图片后&#xff0c;选择嵌入式发现插入的图片显示不正常&#xff0c;只能显示底部一部分&#xff0c;或者遮住文字。出现此故障的原因有可能是设置为固定值的文档行距小于图形的高度&#xff0c;从而导致插入的图形只显示出了一部分。 1.选中图片&#xff0c;然后点…

SAP S4HANA embedded analytics

SAP S4HANA embedded analytics

JavaWeb开发 Servlet底层 Servlet 过滤器 过滤器和拦截器 手写一个限制访问路径的拦截器

目录 万能图 过滤器自我理解 案例 实现Filter 接口 配置文件 web.xml 将过滤器映射到 servlet 用处 拦截器 手写案例 重写 preHandle() 方法 拦截处理 重写 postHandle() 方法 后处理 重写 afterHandle() 方法 完成处理 代码 如何配置拦截器 万能图 还是看一下这张…

【leetcode hot 100 72】编辑距离

解法一&#xff1a;递归 解法二&#xff1a;&#xff08;动态规划&#xff09;①定义&#xff1a;dp[i][j]为word1中前i个字符转化为word2中前j个字符所需操作数;dp[m1][n1] ②初始状态&#xff1a;dp[0][j]j(0变为j&#xff0c;需要j步)&#xff0c;dp[i][0]i(i变为0&#xff…

Java练习——day1(反射)

文章目录 练习1练习2练习3思考封装原则与反射合理使用反射“破坏”封装的场景 练习1 编写代码&#xff0c;通过反射获取String类的所有公共方法名称&#xff0c;并按字母顺序打印。 示例代码&#xff1a; import java.lang.reflect.Method; import java.util.Arrays;public …

Docker 安装 Elasticsearch 8.x

Docker 安装 Elasticsearch 8.x 前言一、准备工作二、设置容器的目录结构三、启动一个临时的容器来复制配置文件四、复制配置文件到本地目录五、删除临时容器六、创建并运行容器&#xff0c;挂载本地目录七、修改文件配置监听端口八、端口配置&#xff1a;Host 网络模式 vs Por…

Vue工程化开发脚手架Vue CLI

开发Vue有两种方式 核心包传统开发模式&#xff1a;基于html / css / js 文件&#xff0c;直接引入核心包&#xff0c;开发 Vue。工程化开发模式&#xff1a;基于构建工具&#xff08;例如&#xff1a;webpack&#xff09;的环境中开发Vue。 脚手架Vue CLI Vue CLl 是 Vue 官方…

开源智慧巡检——无人机油田AI视频监控的未来之力

油田巡检&#xff0c;关乎能源命脉&#xff0c;却常受困于广袤地形、高危环境和人工效率瓶颈。管道泄漏、设备故障、非法闯入——这些隐患稍有疏忽&#xff0c;便可能酿成大患。传统巡检已无法满足现代油田对安全与效率的需求&#xff0c;而无人机油田巡检系统正以智能化之力重…

Django从零搭建卖家中心登陆与注册实战

在电商系统开发中&#xff0c;卖家中心是一个重要的组成部分&#xff0c;而用户注册与登陆则是卖家中心的第一步。本文将详细介绍如何使用Django框架从零开始搭建一个功能完善的卖家注册页面&#xff0c;包括前端界面设计和后端逻辑实现。 一、项目概述 我们将创建一个名为sel…

MySQL表的使用(4)

首先回顾一下之前所学的增删查改&#xff0c;这些覆盖了平时使用的80% 我们上节课中学习到了MySQL的约束 其中Primary key 是主键约束&#xff0c;我们今天要学习的是外键约束 插入一个表 外键约束 父表 子表 这条记录中classid为5时候&#xff0c;不能插入&#xff1b; 删除…

ollama修改配置使用多GPU,使用EvalScope进行模型压力测试,查看使用负载均衡前后的性能区别

文章目录 省流结论机器配置不同量化模型占用显存1. 创建虚拟环境2. 创建测试jsonl文件3. 新建测试脚本3. 默认加载方式&#xff0c;单卡运行模型3.1 7b模型输出213 tok/s3.1 32b模型输出81 tok/s3.1 70b模型输出43tok/s 4. 使用负载均衡&#xff0c;多卡运行4.1 7b模型输出217t…

Dijkstra算法求解最短路径—— 从零开始的图论讲解(2)

前言 在本系列第一期:从零开始的图论讲解(1)——图的概念,图的存储,图的遍历与图的拓扑排序-CSDN博客 笔者给大家介绍了 图的概念,如何存图,如何简单遍历图,已经什么是图的拓扑排序 按照之前的学习规划&#xff0c;今天笔者将继续带大家深入了解图论中的一个核心问题&#x…

[连载]Transformer架构详解

Transformer: Attention Is All You Need Paper 地址&#xff1a;https://arxiv.org/abs/1706.03762 Paper 代码&#xff1a;https://github.com/tensorflow/tensor2tensor Paper 作者&#xff1a;Ashish Vaswani,Noam Shazeer,Niki Parmar,Jakob Uszkoreit,Llion Jones,Aidan…

LVGL Video控件和Radiobtn控件详解

LVGL Video控件和Radiobtn控件详解 一、 Video控件详解1. 概述2. 创建和初始化3. 基本属性设置4. 视频控制5. 回调函数6. 高级功能7. 注意事项 二、Radiobtn控件详解1. 概述2. 创建和初始化3. 属性设置4. 状态控制5. 组管理6. 事件处理7. 样式设置8. 注意事项 三、效果展示四、…

组合数哭唧唧

前言&#xff1a;手写一个简单的组合数&#xff0c;但是由于长期没写&#xff0c;导致一些细节没处理好 题目链接 #include<bits/stdc.h> using namespace std; #define endl "\n"#define int long longconst int N (int)2e510; const int Mod (int)1e97;int…

NLP高频面试题(四十二)——RAG系统评估:方法、指标与实践指南

1. 引言:RAG系统概述与评估挑战 检索增强生成(Retrieval-Augmented Generation,简称 RAG)是近年来自然语言处理领域的一个重要进展。RAG系统在大型语言模型生成文本的过程中引入了外部检索模块,从外部知识库获取相关信息,以缓解纯生成模型可能出现的幻觉和知识盲点。通过…

Linux路漫漫

目录 Vim模式 基本操作 文本编辑 更多功能 1. 直接启动 Vim 2. 打开一个已存在的文件 3. 打开多个文件 4. 以只读模式打开文件 5. 从指定行号开始编辑 6. 快速打开并执行命令 7. 检查是否安装了 Vim 8. 退出 Vim 前提条件 SCP 命令格式 具体操作 1. Windows 命…

游戏引擎学习第227天

今天的计划 今天的工作重点是进行吸引模式&#xff08;attract mode&#xff09;的开发&#xff0c;主要是处理游戏的进出和其他一些小的细节问题&#xff0c;这些是之前想要整理和清理的部分。我做了一些工作&#xff0c;将游戏代码中的不同部分分离到逻辑上独立的区域&#…