深度学习:从零开始的DeepSeek-R1-Distill有监督微调训练实战(SFT)

原文链接:从零开始的DeepSeek微调训练实战(SFT)

微调参考示例:由unsloth官方提供https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_(7B)-Alpaca.ipynbhttps://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Qwen2.5_(7B)-Alpaca.ipynb

本文使用modelscope社区提供的免费GPU示例进行复现。

魔搭社区汇聚各领域最先进的机器学习模型,提供模型探索体验、推理、训练、部署和应用的一站式服务。https://www.modelscope.cn/my/overview

基础概念

预训练模型 (Pre-trained Model): 预训练模型是指在大规模数据集上(如Wikipedia、书籍、网页等)进行过训练的模型。这些模型学习到了通用的语言知识和模式。你可以把它们想象成已经掌握了基本语法和常识的“学生”。常见的预训练模型有BERT、GPT、Llama、DeepSeek等。

微调 (Fine-tuning): 微调是指在预训练模型的基础上,使用特定任务的数据集继续训练模型,使其适应特定任务或领域。就像让一个已经掌握基本知识的学生,学习特定专业的知识。

为什么需要微调?: 预训练模型虽然强大,但它们是通用的。对于特定任务(如医疗问答、代码生成、情感分析等),预训练模型可能表现不佳。微调可以让模型更好地适应特定任务,提高性能。

SFT (Supervised Fine-Tuning): SFT是一种微调方法,它使用带有标签的数据集进行训练。例如,在医疗问答任务中,数据集会包含问题和对应的正确答案。模型通过学习这些问题和答案之间的关系,来提高在特定任务上的表现。

SFT vs. RLHF:
- SFT (Supervised Fine-tuning): 使用标注好的数据集进行训练。模型学习输入和输出之间的直接映射。简单高效,但依赖于高质量的标注数据。
- RLHF (Reinforcement Learning from Human Feedback): 通过人类反馈来训练模型。首先使用SFT,然后通过人类对模型输出进行打分,并使用强化学习算法来优化模型。可以更好地捕捉人类偏好,但更复杂,成本更高。
- 总结: SFT是基础,RLHF是进阶。通常先进行SFT,再根据需要进行RLHF。

高效微调 (Efficient Fine-tuning): 高效微调是指在有限的计算资源下,对大型模型进行微调的方法。例如,LoRA(Low-Rank Adaptation)只微调模型中的部分参数,从而减少计算量和内存需求。

环境准备

unsloth

  • Unsloth 是什么?

    Unsloth 是一个专为大型语言模型(LLM)微调和推理设计的框架。它的主要目标是提高训练速度和降低内存消耗,让用户能够在有限的硬件资源上更高效地进行 LLM 的操作。

  • Unsloth 的主要特点

    • 速度快:Unsloth 通过各种优化技术(如 Flash Attention、量化等)显著提高了 LLM 的训练和推理速度。在某些情况下,速度提升可达数倍。

    • 内存占用低:Unsloth 通过优化内存使用,使得在较小显存的 GPU 上也能微调大型模型。

    • 易于使用:Unsloth 提供了简洁的 API,方便用户快速上手。

    • 支持多种模型:Unsloth 支持多种流行的 LLM,如 Llama、Mistral、Phi、Qwen 等。

  • Unsloth 的安装

    • 直接使用pip命令安装即可

    • pip install unsloth
      pip install --force-reinstall --no-cache-dir --no-deps git+https://github.com/unslothai/unsloth.git

WandB (Weights & Biases) 安装 

  • WandB 是什么?

    WandB 是一个用于机器学习实验跟踪、可视化和协作的平台。它可以帮助你记录实验的各种指标、超参数、模型权重、数据集等,并提供交互式的可视化界面,方便你分析实验结果和比较不同实验的表现。

  • WandB 的主要特点

    • 实验跟踪:记录实验的各种指标(如损失、准确率、学习率等)、超参数、代码版本、数据集等。

    • 可视化:提供交互式的图表,方便你分析实验结果。

    • 协作:支持多人协作,方便团队成员共享实验结果和讨论。

    • 超参数优化:支持自动超参数搜索,帮助你找到最佳的超参数组合。

    • 模型管理:可以保存和版本控制模型权重。

    • 报告生成:可以自动生成实验报告。

  • WandB 的安装和注册

    • 安装:使用 pip 安装 WandB:

    • pip install wandb
    • 注册:
    • 访问 WandB 官网(https://wandb.ai/site)并注册账号。

    • 注册后,在你的个人设置页面找到 API Key,复制它。

    • WandB 在环境准备中的作用

      在 SFT 环境准备中,WandB 主要用于:

      • 监控训练过程:在训练过程中,WandB 会自动记录各种指标,如损失、学习率等,并提供实时更新的图表。

      • 记录超参数:WandB 会记录你使用的超参数,方便你后续复现实验和比较不同超参数的效果。

      • 保存模型:你可以使用 WandB 保存训练过程中的模型权重,方便后续加载和使用。

      • 分析实验结果:WandB 提供了丰富的可视化工具,可以帮助你分析实验结果,找出最佳的模型和超参数。

  • 模型下载

    ModelScope模型地址:https://www.modelscope.cn/models/deepseek-ai/DeepSeek-R1-Distill-Qwen-7B

       创建DeepSeek-R1-Distill-Qwen-7B文件夹,用于保存下载的模型权重:

  • mkdir ./DeepSeek-R1-Distill-Qwen-7B
    

       创建成功后,可使用如下命令下载模型:

  • modelscope download --model deepseek-ai/DeepSeek-R1-Distill-Qwen-7B --local_dir ./DeepSeek-R1-Distill-Qwen-7B
  • 模型权重文件  
  • config.json
  • 内容: 这个文件包含了模型的配置信息,它是一个 JSON 格式的文本文件。这些配置信息定义了模型的架构、层数、隐藏层大小、注意力头数等。
  • 重要性: 这是模型的核心配置文件,加载模型时会读取这个文件来构建模型的结构。
{"architectures": ["Qwen2ForCausalLM"  // 指定模型的架构类型为 Qwen2ForCausalLM,这是一个用于因果语言建模(生成文本)的 Qwen2 模型。],"attention_dropout": 0.0,  // 在注意力机制中使用的 dropout 比率。设置为 0.0 表示不使用 dropout。Dropout 是一种正则化技术,用于防止过拟合。"bos_token_id": 151646,  // 句子开头标记(Beginning of Sentence)的 ID。在分词器中,每个词或标记都有一个唯一的 ID。"eos_token_id": 151643,  // 句子结束标记(End of Sentence)的 ID。"hidden_act": "silu",  // 隐藏层的激活函数。SiLU(Sigmoid Linear Unit)是一种激活函数。"hidden_size": 3584,  // 隐藏层的大小(维度)。"initializer_range": 0.02,  // 用于初始化模型权重的标准差。"intermediate_size": 18944,  // 前馈网络(Feed-Forward Network)中间层的大小。"max_position_embeddings": 131072,  // 模型可以处理的最大序列长度(位置嵌入的数量)。"model_type": "qwen2",  // 模型类型为 qwen2。"num_attention_heads": 28,  // 注意力机制中注意力头的数量。"num_hidden_layers": 28,  // 模型中隐藏层(Transformer 层)的数量。"num_key_value_heads": 4,  //  键值头的数量。用于分组查询注意力(Grouped-Query Attention, GQA)。如果该值小于`num_attention_heads`,则表示启用了GQA, 否则为多头注意力(Multi-Head Attention, MHA)。"rms_norm_eps": 1e-06,  // RMSNorm(Root Mean Square Layer Normalization)中使用的 epsilon 值,用于防止除以零。"rope_theta": 10000.0,  // RoPE(Rotary Positional Embeddings)中使用的 theta 值。RoPE 是一种位置编码方法。"tie_word_embeddings": false,  // 是否将词嵌入矩阵和输出层的权重矩阵绑定(共享)。设置为 `false` 表示不绑定。"torch_dtype": "bfloat16",  // 模型使用的默认数据类型。`bfloat16` 是一种 16 位浮点数格式,可以提高计算效率并减少内存占用。"transformers_version": "4.48.3",  // 使用的 Transformers 库的版本。"use_cache": true,  // 是否使用缓存机制来加速推理。设置为 `true` 表示使用缓存。"vocab_size": 152064  // 词汇表的大小(不同词或标记的数量)。
}
  • configuration.json 
  • 内容: 这个文件和 config.json 类似,通常包含模型的配置信息。在某些模型中,这两个文件可能是同一个文件,或者 configuration.json 包含了更详细的配置。对于 DeepSeek-R1-Distill-7B 模型,你可以认为它和 config.json 作用相同。
  • generation_config.json
  • 内容: 这个文件包含模型生成文本时的配置参数,例如解码方法(beam search、top-k sampling 等)、最大生成长度、温度系数等。
{"_from_model_config": true,  // 表示这些配置中的大部分是从模型的配置文件(config.json)中继承的。"bos_token_id": 151646,    // 句子开头标记(Beginning of Sentence)的 ID。"eos_token_id": 151643,    // 句子结束标记(End of Sentence)的 ID。"do_sample": true,       // 是否使用采样(sampling)方法生成文本。如果设置为 `false`,则使用贪婪解码(greedy decoding)。"temperature": 0.6,      // 温度系数。温度系数用于控制生成文本的随机性。值越高,生成的文本越随机;值越低,生成的文本越确定。"top_p": 0.95,          // Top-p 采样(nucleus sampling)的阈值。Top-p 采样只从概率最高的、累积概率超过 `top_p` 的词中进行采样。"transformers_version": "4.39.3"  // 使用的 Transformers 库的版本。(原文档中是4.39.3,这与之前config.json里的版本号不同,但通常情况下,版本号应当以config.json里的为准)
}
  • LICENSE

    内容: 这是一个文本文件,包含了模型的许可证信息。许可证规定了你可以如何使用、修改和分发模型。
  • model-00001-of-00002.safetensors 和 model-00002-of-00002.safetensors

    内容: 这些文件是模型权重文件,它们以 Safetensors 格式存储。Safetensors 是一种安全且高效的张量存储格式。由于模型很大,权重被分成了多个文件。
  • model.safetensors.index.json

    内容: 这是一个索引文件,用于指示哪些权重存储在哪个 .safetensors 文件中。当模型权重被分成多个文件时,需要这个索引文件来正确加载权重。
  • README.md

    内容: 这是一个 Markdown 格式的文本文件,通常包含模型的介绍、使用说明、示例代码等。
  • tokenizer_config.json

    内容: 包含分词器(Tokenizer)的配置信息。
{"add_bos_token": true,  // 是否在输入序列的开头添加句子开头标记(BOS token)。设置为 `true` 表示添加。"add_eos_token": false, // 是否在输入序列的结尾添加句子结束标记(EOS token)。设置为 `false` 表示不添加。"__type": "AddedToken",           //这是一个内部使用的类型标记,表示这是一个"添加的token""content": "<|begin of sentence|>",  // 这是一个特殊标记的内容,表示句子的开始"lstrip": false,                    //在处理这个token时,是否移除左侧的空白符"normalized": true,                 // 是否对这个token进行标准化处理"rstrip": false,                     //是否移除右边的空白符"single_word": false,                // 是否将此token视为单个词"clean_up_tokenization_spaces": false, // 是否清理分词过程中的空格。设置为 `false` 表示不清理。"__type": "AddedToken","content": "<|end of sentence|>","lstrip": false,"normalized": true,"rstrip": false,"single_word": false,"legacy": true,                    // 是否使用旧版(legacy)的分词器行为。这里设置为`true`可能表示兼容旧版本。"model_max_length": 16384,      // 模型可以处理的最大序列长度。"__type": "AddedToken","content": "<|end of sentence|>","lstrip": false,"normalized": true,"rstrip": false,"single_word": false,"sp_model_kwargs": {},          // SentencePiece 模型的相关参数(这里为空)。"unk_token": null,            // 未知词标记(unknown token)。设置为 `null` 表示没有专门的未知词标记。"tokenizer_class": "LlamaTokenizerFast",  // 分词器的类名。`LlamaTokenizerFast` 表示这是一个快速版本的 Llama 分词器。"chat_template": "{% if not add_generation_prompt is defined %}{% set add_generation_prompt = false %}{% endif %}{% set ns = namespace(is_first=false, is_tool=false, is_output_first=true, system_prompt='') %}{%- for message in messages %}{%- if message['role'] == 'system' %}{% set ns.system_prompt = message['content'] %}{%- endif %}{%- endfor %}{{bos_token}}{{ns.system_prompt}}{%- for message in messages %}{%- if message['role'] == 'user' %}{%- set ns.is_tool = false -%}{{'<|User|>' + message['content']}}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is none %}{%- set ns.is_tool = false -%}{%- for tool in message['tool_calls']%}{%- if not ns.is_first %}{{'<|Assistant|><|tool calls begin|><|tool call begin|>' + tool['type'] + '<|tool sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments'] + '\n' + '```' + '<|tool call end|>'}}{%- set ns.is_first = true -%}{%- else %}{{'\n' + '<|tool call begin|>' + tool['type'] + '<|tool sep|>' + tool['function']['name'] + '\n' + '```json' + '\n' + tool['function']['arguments'] + '\n' + '```' + '<|tool call end|>'}}{{'<|tool calls end|><|end of sentence|>'}}{%- endif %}{%- endfor %}{%- endif %}{%- if message['role'] == 'assistant' and message['content'] is not none %}{%- if ns.is_tool %}{{'<|tool outputs end|>' + message['content'] + '<|end of sentence|>'}}{%- set ns.is_tool = false -%}{%- else %}{% set content = message['content'] %}{% if '</think>' in content %}{% set content = content.split('</think>')[-1] %}{% endif %}{{'<|Assistant|>' + content + '<|end of sentence|>'}}{%- endif %}{%- endif %}{%- if message['role'] == 'tool' %}{%- set ns.is_tool = true -%}{%- if ns.is_output_first %}{{'<|tool outputs begin|><|tool output begin|>' + message['content'] + '<|tool output end|>'}}{%- set ns.is_output_first = false %}{%- else %}{{'\n<|tool output begin|>' + message['content'] + '<|tool output end|>'}}{%- endif %}{%- endif %}{%- endfor -%}{% if ns.is_tool %}{{'<|tool outputs end|>'}}{% endif %}{% if add_generation_prompt and not ns.is_tool %}{{'<|Assistant|><think>\n'}}{% endif %}"// ↑这是一个 Jinja2 模板,定义了对话的格式。它根据消息的角色(用户、助手、工具)和内容,构建最终的输入文本。}

数据集准备

推理模型与通用模型相比,输出的回答包括了一段思考过程(Chain of Thoughts 思维链)。这个思考过程本质也是通过预测下一个token进行实现的,只不过DeepSeek系列模型输出时,会将思考过程放在一对特殊token <think>...</think>之间,</think>标签后的内容作为回答的正文。

微调推理模型时,同样需要包含思维链和最终回答两部份。因此,在围绕DeepSeek R1 Distill模型组进行微调的时候,微调数据集的回复部分文本也需要是包含推理 和最终回复两部分内容,才能使得DeepSeek R1模型组在保持既定回复风格的同时,强化模型能力,反之则会导致指令消融问题(模型回复不再包含think部分)。

modelscope社区提供了多样的推理数据集供开发者使用 。

原文采取由深圳大数据研究院发布的HuatuoGPT-o1模型的微调数据集—medical-o1-reasoning-SFT,地址:https://www.modelscope.cn/datasets/AI-ModelScope/medical-o1-reasoning-SFT。

本数据集将数据分为:

- Question:医疗问题

- Complex_CoT:进行诊疗的思维链

- Response:最终的答复

数据集中所有内容均为英文

模型演示

在进行微调前,我们可以了解一下模型的基本用法。

1. 加载已经下载到本地的模型

max_seq_length = 2048 # 指定输出的最大长度
dtype = None # 不指定模型精度,由unsloth框架自动检测
load_in_4bit = False # 采用int4量化,减少显存占用,但是会降低模型性能# 加载模型和分词器
model, tokenizer = FastLanguageModel.from_pretrained(model_name="./DeepSeek-R1-Distill-Qwen-7B", # 待微调的模型名称max_seq_length=max_seq_length, # 模型可以处理的最长序列长度dtype=dtype, # 限定模型浮点精度load_in_4bit=False # 是否使用int量化
)

2. 通过unsloth框架配置待微调的LoRA模型

'''
LoRA 的核心思想是,对于预训练模型的权重矩阵 W,不直接对其进行更新,
而是添加一个低秩分解矩阵 ΔW = A * B,
其中 A 和 B 是两个较小的矩阵。在微调过程中,只更新 A 和 B 的参数,而 W 的参数保持不变。
这样可以大大减少需要微调的参数数量,降低计算成本。
'''
model = FastLanguageModel.get_peft_model(model,r=8, # lora微调的秩  # 较小的 `r` 值会减少需要微调的参数数量,降低计算成本,但也可能降低模型的表达能力。# 较大的 `r` 值会增加参数数量,提高模型的表达能力,但也会增加计算成本。# 通常需要根据实际情况进行实验,选择合适的 `r` 值。一般来说,8、16、32、64 是常用的值。target_modules = ["q_proj", "k_proj", "v_proj", # 指定要应用 LoRA 的模块。这些模块通常是 Transformer 模型中的线性层。"o_proj", "gate_proj", "up_proj", "down_proj"], # 这里分别应用了注意力机制中的Wq, Wk, Wv, Wo线性投影层,FFN中的线性层lora_alpha=8, # lora缩放因子,决定模型权重的更新程度,建议设置为r或r的倍数lora_dropout=0,bias="none", # 不为LoRA层添加偏置use_gradient_checkpointing="unsloth", # 是否设置梯度检查点,# 梯度检查点是一种以时间换空间的技术,可以减少内存占用,但会增加计算时间。random_state=3407, # 设置随机种子,保证实验可以浮现use_rslora=False, # 是否使用Rank-Stabilized LoRA(rslora)。rslora 是一种改进的 LoRA 方法,可以自动调整 `lora_alpha`。loftq_config=None # 是否使用QLoRA,即将LoRA与量化技术结合
)

3. 进行简单推理

# 将模型切换为推理模式,可以进行简单的对话
FastLanguageModel.for_inference(model)question = "请介绍一下你自己!"
# 对输入进行分词
# 传入待分词的文本列表,最后返回一个PyTorch张量
input_ids = tokenizer([question], return_tensors="pt").to("cuda")
# input_ids返回token对应词表中的id,即将一个句子映射为一个token id序列
# attention_mask用于表示input_ids中哪些是为了填充序列长度而通过<pad>填充的token,1表示所有的 token 都是实际的词或标记,没有填充。
input_ids# 调用模型生成答复
'''
是否使用缓存机制来加速生成过程。设置为 True 表示使用缓存。缓存机制会存储先前计算的键/值对(key/value pairs),避免重复计算,从而提高生成速度。在自回归生成(逐个 token 生成)中,缓存机制非常有用。
'''
outputs_ids = model.generate(input_ids=input_ids.input_ids,max_new_tokens=1024,use_cache=True
)
# 模型的直接输出同样为token ids,需要通过tokenizer进行解码
outputs_idsresponse = tokenizer.batch_decode(outputs_ids)
print(response[0])

可以在prompt中添加<think>标签对引导模型进行思考。

question = "你好,好久不见!"
# 更完善的prompt
prompt_style_chat = """请写出一个恰当的回答来完成当前对话任务。### Instruction:
你是一名助人为乐的助手。### Question:
{}### Response:
"""# 使用tokenizer处理prompt
input_ids = tokenizer([prompt_style_chat.format(questionm '')], return_tensors="pt").to("cuda")outputs = model.generate(input_ids=input_ids.input_ids,use_cache=True,do_sample=True,          # 启用采样temperature=0.7,         # 较高的温度top_p=0.9,               # Top-p 采样repetition_penalty=1.2,  # 重复惩罚max_new_tokens=1024,     # 最大新token数量
)response = tokenizer.batch_decode(outputs, skip_special_tokens=True)[0]
print(response)

未添加<think>标签,模型有概率不思考。

prompt_style_chat = """请写出一个恰当的回答来完成当前对话任务。### Instruction:
你是一名助人为乐的助手。### Question:
{}### Response:
<think>{}
"""
question = "请你分析李朗笛和朗朗以及李云迪之间的关系"# 使用tokenizer处理prompt
input_ids = tokenizer([prompt_style_chat.format(question, "")], return_tensors="pt").to("cuda")outputs = model.generate(input_ids=input_ids.input_ids,use_cache=True,do_sample=True,          # 启用采样temperature=0.7,         # 较高的温度top_p=0.95,               # Top-p 采样repetition_penalty=1.2,  # 重复惩罚max_new_tokens=1024,     # 最大新token数量
)response = tokenizer.batch_decode(outputs, skip_special_tokens=False)[0]
print(response)

 添加<think>标签作为引导,模型更容易进行思考。

微调实操

微调请重新开一个notebook,清空缓存,从头进行。

1. 倒入依赖

# 导入依赖
from modelscope.msdatasets import MsDataset # modelscope数据集类
from trl import SFTTrainer # 微调训练器配置类
from transformers import TrainingArguments # 微调参数配置类
from unsloth import FastLanguageModel, is_bfloat16_supported # 检查GPU是否支持bf16
import wandb # 微调数据可视化

 2. 定义模板

因为数据集是英文的,所以promt也采用英文,保证语言一致性。

# 1. 定义prompt模板
finetune_template = '''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>
{}'''prompt_style_zh = '''以下是一个任务说明,配有提供更多背景信息的输入。
请写出一个恰当的回答来完成该任务。
在回答之前,请仔细思考问题,并按步骤进行推理,确保回答逻辑清晰且准确。### Instruction:
您是一位具有高级临床推理、诊断和治疗规划知识的医学专家。
请回答以下医学问题。### 问题:
{}### 问题:
<think>{}'''

3. 加载模型

# 2. 加载模型
model, tokenizer = FastLanguageModel.from_pretrained(model_name="./DeepSeek-R1-Distill-Qwen-7B",max_seq_length=2048,dtype=None,load_in_4bit=False
)
EOS_TOKEN = tokenizer.eos_token

4. 加载数据集

# 在模型微调时,给微调数据集加上 EOS_TOKEN 非常重要。它可以明确文本边界、保持训练目标一致性、控制生成过程、处理多轮对话,以及更好地利用 CoT 数据集。
EOS_TOKEN = tokenizer.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 = finetune_template.format(input, cot, output) + EOS_TOKENtexts.append(text)return {"text": texts,}ds = MsDataset.load('AI-ModelScope/medical-o1-reasoning-SFT', split = "train")
dataset = ds.map(formatting_prompts_func, batched = True,)
print(dataset["text"][0])

5. 配置微调模型

将LoRA模块加入模型,为微调做准备

'''
LoRA 的核心思想是,对于预训练模型的权重矩阵 W,不直接对其进行更新,
而是添加一个低秩分解矩阵 ΔW = A * B,
其中 A 和 B 是两个较小的矩阵。在微调过程中,只更新 A 和 B 的参数,而 W 的参数保持不变。
这样可以大大减少需要微调的参数数量,降低计算成本。
'''
model = FastLanguageModel.get_peft_model(model,r=16, # lora微调的秩  # 较小的 `r` 值会减少需要微调的参数数量,降低计算成本,但也可能降低模型的表达能力。# 较大的 `r` 值会增加参数数量,提高模型的表达能力,但也会增加计算成本。# 通常需要根据实际情况进行实验,选择合适的 `r` 值。一般来说,8、16、32、64 是常用的值。target_modules = ["q_proj", "k_proj", "v_proj", # 指定要应用 LoRA 的模块。这些模块通常是 Transformer 模型中的线性层。"o_proj", "gate_proj", "up_proj", "down_proj"], # 这里分别应用了注意力机制中的Wq, Wk, Wv, Wo线性投影层,FFN中的线性层lora_alpha=16, # lora缩放因子,决定模型权重的更新程度,建议设置为r或r的倍数lora_dropout=0,bias="none", # 不为LoRA层添加偏置use_gradient_checkpointing="unsloth", # 是否设置梯度检查点,# 梯度检查点是一种以时间换空间的技术,可以减少内存占用,但会增加计算时间。random_state=3407, # 设置随机种子,保证实验可以浮现use_rslora=False, # 是否使用Rank-Stabilized LoRA(rslora)。rslora 是一种改进的 LoRA 方法,可以自动调整 `lora_alpha`。loftq_config=None # 是否使用QLoRA,即将LoRA与量化技术结合
)

6. 配置微调参数

# 5. 配置微调参数
trainer = SFTTrainer(model=model,tokenizer=tokenizer,train_dataset=dataset,dataset_text_field="text", # 数据集中包含文本的字段的名称。# dataset_text_field="text", # 说明text列对应的是微调数据集max_seq_length=2048, # 模型能处理的最长序列dataset_num_proc=2, # 用于预处理数据的进程数。args=TrainingArguments(per_device_train_batch_size=2, # mini-batch-sizegradient_accumulation_steps=4, # 梯度累积,用于模型batch_size=2*4=8的情况,模型实际上经过 2 * 4 = 8 个batch之后才会更新参数(一个step),能缓解GPU无法放下大batch的问题num_train_epochs=3, # 训练轮数# max_steps = 60 # 如果要进行迅速严重微调可行性,可以只训练60个steps,训练的总步数(参数更新次数)。warmup_steps=5, # 模型热身步数,学习率会从 0 逐渐增加到设定的学习率。lr_scheduler_type="linear", # 学习率调度器类型。这里使用线性调度器,学习率会线性下降。learning_rate=2e-4, # 学习率fp16=not is_bfloat16_supported(), # 是否使用 FP16(16 位浮点数)混合精度训练。如果 GPU 不支持 bfloat16,则使用 fp16。bf16=is_bfloat16_supported(),logging_steps=10, # 多少个step打印一次信息optim="adamw_8bit", # 指定优化器weight_decay=0.01, # 权重衰退seed=3407, # 随机种子,保证结果可以复现output_dir="outputs" # 保存训练结果(模型、日志等)的目录。)
)

7. 进行微调

# 6. 进行微调
wandb.init()
trainer_stats = trainer.train()

看到如下输出即表示微调正在运行中。 

8. 将LoRA权重与原始矩阵合并,保存微调后的模型

# LoRA微调完成后,保存微调模型并合并矩阵
new_model_local = "DeepSeek-R1-Qwen-7B-Medical-Full"  # 定义一个字符串变量,表示保存模型的本地路径。
model.save_pretrained(new_model_local)          # 保存微调后的模型(包括 LoRA 权重)。
tokenizer.save_pretrained(new_model_local)      # 保存分词器。
model.save_pretrained_merged(new_model_local, tokenizer, save_method="merged_16bit")  # 合并 LoRA 权重到基础模型中,并保存合并后的模型。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 调优

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

Clion远程开发配置

代码开发环境&#xff1a;windows下&#xff0c;基于Clion 2024.3开发&#xff0c;标准为C20 代码运行环境&#xff1a;远程服务器&#xff0c;ubuntu&#xff0c;cmake版本3.12&#xff0c;gcc11.4&#xff0c;g11.4&#xff0c;gdb12.1 实现功能&#xff1a;在本地windows开…

男女搭配(数学思维)

#include <bits/stdc.h> using namespace std; int main() {// 请在此输入您的代码int t;cin>>t;while(t--){int n,m,k;cin>>n>>m>>k;int smin(n,2*m)/2;if(nm-k > 3*s) cout<<s<<endl;else cout<<(nm-k)/3<<endl;}r…

SakuraCat(1)整体架构概述 (完善中)

项目功能概述 支持Servlet组件可部署一个标准的Web App 项目架构总览 HTTP服务器&#xff1a;负责建立链接&#xff0c;处理请求的数据&#xff0c;并转发给Servlet容器。Servlet容器&#xff1a;将HttpServletRequest和HttpServletResponse对象传给对应的业务类进行相应的逻…

一种基于大规模语言模型LLM的数据分析洞察生成方法

从复杂数据库中提取洞察对数据驱动决策至关重要,但传统手动生成洞察的方式耗时耗力,现有自动化数据分析方法生成的洞察不如人工生成的有洞察力,且存在适用场景受限等问题。下文将介绍一种新的方法,通过生成高层次问题和子问题,并使用SQL查询和LLM总结生成多表数据库中的见…

单片机学完开发板,如何继续提升自己的技能?

很多人学完开发板后都会卡在一个尴尬的阶段&#xff1a;觉得自己会的东西不少&#xff0c;但又不知道下一步该干啥。会点C语言&#xff0c;能烧录程序&#xff0c;能点亮LED&#xff0c;玩转按键&#xff0c;搞定串口等等&#xff0c;能用开发板做点小玩意儿&#xff0c;但面对…

计算机网络——总结

01. 网络的发展及体系结构 网络演进历程 从1969年ARPANET的4个节点发展到如今覆盖全球的互联网&#xff0c;网络技术经历了电路交换到分组交换、有线连接到无线覆盖的革命性变革。5G时代的到来使得网络传输速度突破10Gbps&#xff0c;物联网设备数量突破百亿级别。 网络体系…

实验10决策树

实验10决策树 一、实验目的 &#xff08;1&#xff09;理解并熟悉决策树算法思想和原理&#xff1b; &#xff08;2&#xff09;熟悉决策树算法的数学推导过程&#xff1b; &#xff08;3&#xff09;能运用决策树算法解决实际问题并体会算法的效果&#xff1b; &#xff08;4…

【css酷炫效果】纯CSS实现悬浮弹性按钮

【css酷炫效果】纯CSS实现悬浮弹性按钮 缘创作背景html结构css样式完整代码效果图 想直接拿走的老板&#xff0c;链接放在这里&#xff1a;https://download.csdn.net/download/u011561335/90492020 缘 创作随缘&#xff0c;不定时更新。 创作背景 刚看到csdn出活动了&…

【模块化编程】制作、可视化不平衡数据(长尾数据)(以Cifar-10为例)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;《PyTorch科研加速指南&#xff1a;即插即用式模块开发》-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎…

Linux操作系统7- 线程同步与互斥1(POSIX互斥锁的使用详解)

上篇文章&#xff1a;Linux操作系统6- 线程4&#xff08;POSIX线程的简单封装&#xff09;-CSDN博客 本篇代码仓库:myLerningCode/l30 橘子真甜/Linux操作系统与网络编程学习 - 码云 - 开源中国 (gitee.com) 目录 一. 线程不互斥造成的结果 二. pthread_mutex_t 互斥…

深入 Linux 声卡驱动开发:核心问题与实战解析

1. 字符设备驱动如何为声卡提供操作接口&#xff1f; 问题背景 在 Linux 系统中&#xff0c;声卡被抽象为字符设备。如何通过代码让应用程序能够访问声卡的录音和播放功能&#xff1f; 核心答案 1.1 字符设备驱动的核心结构 Linux 字符设备驱动通过 file_operations 结构体定…

洛谷 [语言月赛 202503] 题解(C++)

本文为洛谷3月的语言月赛题目全部题解&#xff0c;难度为入门到普及-&#xff0c; 觉的有帮助或者写的不错的可以点个赞 题目链接为 题目列表 - 洛谷 | 计算机科学教育新生态 目录 题目A:长方形 解题思路: 代码(C): 题目B:水流 题目大意: 解题思路: 代码(C): 题目C:格…

算法每日一练 (15)

&#x1f4a2;欢迎来到张胤尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 算法每日一练 (15)第 N 个泰波那契数题目描述解题思路…

实验11 机器学习-贝叶斯分类器

实验11 机器学习-贝叶斯分类器 一、实验目的 &#xff08;1&#xff09;理解并熟悉贝叶斯分类器的思想和原理&#xff1b; &#xff08;2&#xff09;熟悉贝叶斯分类器的数学推导过程&#xff1b; &#xff08;3&#xff09;能运用贝叶斯分类器解决实际问题并体会算法的效果&a…

Matrix-breakout-2-morpheus靶机实战攻略

1.安装并开启靶机 2.获取靶机IP 3.浏览器访问靶机 4.扫描敏感目录文件和端口 gobuster dir -u http://192.168.52.135 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,html 5.访问文件和端口 发现在graffiti.php输入框输入内容后页面会返回内容…

【知识】Graph Sparsification、Graph Coarsening、Graph Condensation的详细介绍和对比

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 1. 理论基础&#xff08;Definitions & Theoretical Background&#xff09; 2. 算法方法&#xff08;Techniques & Algorithms&#x…

Java单元测试、Junit、断言、单元测试常见注解、单元测试Maven依赖范围、Maven常见问题解决方法

一. 测试 1. 测试&#xff1a;是一种用来促进鉴定软件的正确性、完整性、安全性和质量的过程 2. 阶段划分&#xff1a;单元测试、集成测试、系统测试、验收测试。 ① 单元测试&#xff1a;对软件的基本组成单位进行测试&#xff0c;最小测试单位&#xff1b;目的检验软件基本组…

【Notepad】Notepad优化笔记AutoHotkey语法高亮\设置替换默认的notepad程序\设置主题\增加返回上一个编辑地方插件

Npp使用优化笔记 AHK或自定义语法高亮设置替换系统默认的notepad设置主题返回上一次编辑的地方插件使用 AHK或自定义语法高亮 具体参考该论坛 https://www.autohotkey.com/boards/viewtopic.php?t50 设置替换默认的notepad程序 参考文章&#xff1a; https://www.winhelpo…

Mac:Maven 下载+安装+环境配置(详细讲解)

&#x1f4cc; 下载 Maven 下载地址&#xff1a;https://maven.apache.org/download.cgi &#x1f4cc; 无需安装 Apache官网下载 Maven 压缩包&#xff0c;无需安装&#xff0c;下载解压后放到自己指定目录下即可。 按我自己的习惯&#xff0c;我会在用户 jane 目录下新建…