使用Hugging Face微调开源LLM(2025年)

大型语言模型(LLMs)在2024年继续发挥其重要作用,多个重大进展完全超越了之前的模型。重点继续放在像Meta、Qwen或Google这样的公司开发的更小、更强大的模型上。这些模型不仅变得更加强大,而且更加高效。我们得到了参数量小至1B的Llama模型,其性能甚至超越了Llama 2 13B。

LLMs 现在可以通过提示来处理许多任务,包括聊天机器人、问答和摘要生成。然而,对于需要高准确度或领域专业知识的特殊应用,微调仍然是实现比单纯提示更好的结果、通过训练更小更高效的模型来降低成本,并确保特定用例的可靠性和一致性的强大方法。

与去年的指南不同如何在2024年用Hugging Face微调LLMs本指南更注重优化、分布式训练和更高的可定制性。这意味着支持从全微调到QLoRA和Spectrum的不同PEFT方法,优化更快、更高效的训练,使用Flash AttentionLiger Kernels,以及如何使用DeepSpeed将训练扩展到多个GPU。

本指南是使用脚本而不是笔记本创建的。如果你是完全的新手,我建议你先从2024年使用Hugging Face进行LLM微调指南开始,然后再回来查看本指南。

你将学习如何:

  1. 定义一个用于微调的好用例
  2. 设置开发环境
  3. 创建和准备数据集
  4. 使用 trl 和 SFTTrainer 通过QLoRA微调模型
  5. 使用GSM8K测试和评估模型
  6. 将模型部署到生产环境

什么是Qlora?

QLoRA(量化低秩适应) 通过使用4位量化和最小参数更新,使LLM的高效微调成为可能,减少了资源需求,但由于量化权衡,可能会影响性能。

什么是频谱?

Spectrum 是一种微调方法,通过信噪比(SNR)分析识别出LLM中最具信息量的层,并选择性地对这些层进行微调,提供与完全微调相当的性能,同时减少资源使用,特别是在分布式训练设置中。

注意:本指南是为消费者级GPU(24GB+)如NVIDIA RTX 4090/5090或A10G设计的,但也可以适应更大的系统。

1. 定义一个用于微调的好用例

2024年,开放的大语言模型变得更加强大且更加小巧。这通常意味着微调可能不是解决你问题的首选方法。在你考虑微调之前,你应该始终评估是否可以通过提示或已经微调的模型来解决你的问题。创建一个评估设置,并比较现有开放模型的性能。

然而,微调在几种情况下特别有价值。当您需要:

  • 在特定任务上持续提升表现
  • 控制模型输出的风格和格式(例如,强制执行公司的语气)
  • 教授模型领域特定的知识或术语
  • 减少关键应用中的幻觉
  • 通过创建更小、更专业的模型来优化延迟
  • 确保一致地遵守特定的指南或限制

作为一个例子,我们将使用以下用例:

我们希望微调一个模型,该模型可以解决高中数学问题,以教学生如何解决数学问题。

这是一个很好的微调用例,因为它需要大量的数学领域的知识以及如何解决数学问题。

注意:这是一个虚构的例子,因为现有的开放模型已经可以解决这个任务。

2. 设置开发环境

我们的第一步是安装 Hugging Face 库和 Pyroch,包括trl、transformers 和 datasets。如果你还没有听说过trl,别担心。trl 是一个基于 transformers 和 datasets 的新库,它使微调、rlhf、对齐开放 LLM 变得更容易。

# Install Pytorch & other libraries
%pip install "torch==2.4.1" tensorboard flash-attn "liger-kernel==0.4.2" "setuptools<71.0.0" "deepspeed==0.15.4" openai "lm-eval[api]==0.4.5"

# Install Hugging Face libraries
%pip install  --upgrade \
  "transformers==4.46.3" \
  "datasets==3.1.0" \
  "accelerate==1.1.1" \
  "bitsandbytes==0.44.1" \
  "trl==0.12.1" \
  "peft==0.13.2" \
  "lighteval==0.6.2" \
  "hf-transfer==0.1.8"

3. 创建和准备数据集

一旦你确定微调是正确的解决方案,你将需要一个数据集。大多数数据集现在是使用带有LLM的自动化合成工作流程创建的,尽管有几种方法:

  • 使用LLM进行合成生成:使用Distilabel等框架的最常见方法大规模生成高质量的合成数据
  • 现有数据集:使用来自Hugging Face Hub的公共数据集
  • 人工标注:对于最高质量但最昂贵的选择

LLM 数据集 提供了用于为各种目的微调 LLM 的高质量数据集概述。在我们的示例中,我们将使用Orca-Math 数据集,包含 200,000 个数学世界问题。

现代微调框架如trl支持标准格式:

// Conversation format
{
    "messages": [
        {"role": "system", "content": "You are..."},
        {"role": "user", "content": "..."},
        {"role": "assistant", "content": "..."},
    ]
}
// Instruction format
{"prompt": "<prompt text>", "completion": "<ideal generated text>"}

注意:如果你对如何创建高质量数据集的指南感兴趣,请告诉我。

为了准备我们的数据集,我们将使用Datasets库,然后将其转换为对话格式,在其中包含助手的系统消息中的模式定义。然后我们将数据集保存为jsonl文件,然后我们可以使用它来微调我们的模型。

注意:此步骤可能因您的使用案例而异。例如,如果您已经从 OpenAI 等渠道获得了一个数据集,您可以跳过此步骤并直接进行微调步骤。

from datasets import load_dataset

# Create system prompt
system_message = """这是一套针对解决高中数学问题的指导说明,具体内容如下:
整体要求:解决给定的高中数学问题时,要对每一步进行清晰解释,从而得出最终答案。在计算过程中,从对问题的解释开始,详细说明每个公式、数值或结论的推导过程,通过逻辑连贯且层层递进的步骤,系统地得出最终答案。
# 具体步骤:
1. 理解问题:重新阐述给定的数学问题,明确指出核心问题以及任何重要的已知数值。例如,对于 “已知三角形两边长分别为 3 和 4,夹角为 60°,求第三边长” 这一问题,核心问题是求第三边长,重要已知值为两边长 3 和 4 以及夹角 60°。
2. 设定思路:确定有助于解决问题的关键公式或概念,比如代数运算、几何公式、三角恒等式等。对于上述三角形问题,可能会想到余弦定理这一关键公式。
3. 逐步求解:逐步推进数学问题的每一步求解过程,解释为什么每一步操作能让我们更接近答案。例如在使用余弦定理求第三边长时,先说明余弦定理的表达式,再代入已知数值,解释代入的原因及计算过程。
4. 双重检查:如果可行,对解题过程进行准确性和合理性检查,并提及可能存在的其他解题方法。比如检查计算是否有误,思考是否能用向量法等其他方法解决该三角形问题。
5. 最终答案:清晰地给出数值或代数形式的解决方案,如果涉及单位,要一并给出。如上述三角形问题,最终答案可能是第三边长为√13(单位:厘米,若题目设定了长度单位)。
# 注意事项:
- 始终要清晰定义所使用的任何变量或术语。例如在解题中设三角形第三边为 c,就要说明 c 代表的意义。
- 在适用的情况下,要包含单位换算或结合题目背景说明选择每个公式或步骤的原因。比如在计算面积问题时,如果题目给的长度单位是分米,而最终要求的面积单位是平方厘米,就需要进行单位换算,并说明换算原因。
- 假设数学水平为高中程度,除非是高中常见的,否则避免使用过于高深的数学技巧。
"""

# convert to messages
def create_conversation(sample):
    return {
        "messages":[
            {"role": "system", "content": system_message},
            {"role": "user", "content": sample["question"]},
            {"role": "assistant", "content": sample["answer"]}
        ]
    }

# Load dataset from the hub
dataset = load_dataset("microsoft/orca-math-word-problems-200k", split="train")
print("map之前dataset")
print(dataset[0])

# Convert dataset to OAI messages
dataset = dataset.map(create_conversation, remove_columns=dataset.features, batched=False)
print("map之后dataset")
print(dataset[345]["messages"])

# save datasets to disk 
dataset.to_json("train_dataset.json", orient="records")
map之前dataset
{
  'question': 'Jungkook is the 5th place. Find the number of people who crossed the finish line faster than Jungkook.',
  'answer': 'If Jungkook is in 5th place, then 4 people crossed the finish line faster than him.'
} map之后dataset [
  {'content': '这是一套针对解决高中数学问题的指导说明,具体内容如下:\n整体要求:解决给定的高中数学问题时,要对每一步进行清晰解释,从而得出最终答案。在计算过程中,从对问题的解释开始,详细说明每个公式、数值或结论的推导过程,通过逻辑连贯且层层递进的步骤,系统地得出最终答案。\n# 具体步骤:\n1. 理解问题:重新阐述给定的数学问题,明确指出核心问题以及任何重要的已知数值。例如,对于 “已知三角形两边长分别为 3 和 4,夹角为 60°,求第三边长” 这一问题,核心问题是求第三边长,重要已知值为两边长 3 和 4 以及夹角 60°。\n2. 设定思路:确定有助于解决问题的关键公式或概念,比如代数运算、几何公式、三角恒等式等。对于上述三角形问题,可能会想到余弦定理这一关键公式。\n3. 逐步求解:逐步推进数学问题的每一步求解过程,解释为什么每一步操作能让我们更接近答案。例如在使用余弦定理求第三边长时,先说明余弦定理的表达式,再代入已知数值,解释代入的原因及计算过程。\n4. 双重检查:如果可行,对解题过程进行准确性和合理性检查,并提及可能存在的其他解题方法。比如检查计算是否有误,思考是否能用向量法等其他方法解决该三角形问题。\n5. 最终答案:清晰地给出数值或代数形式的解决方案,如果涉及单位,要一并给出。如上述三角形问题,最终答案可能是第三边长为√13(单位:厘米,若题目设定了长度单位)。\n# 注意事项:\n- 始终要清晰定义所使用的任何变量或术语。例如在解题中设三角形第三边为 c,就要说明 c 代表的意义。\n- 在适用的情况下,要包含单位换算或结合题目背景说明选择每个公式或步骤的原因。比如在计算面积问题时,如果题目给的长度单位是分米,而最终要求的面积单位是平方厘米,就需要进行单位换算,并说明换算原因。\n- 假设数学水平为高中程度,除非是高中常见的,否则避免使用过于高深的数学技巧。\n', 'role': 'system'},
  {'content': 'There is a machine that makes 32 toys per hour. Find how many boxes are needed to put 4 of the toys the machine made for 3 hours into each box.', 'role': 'user'},
  {'content': "First, let's calculate the total number of toys made by the machine in 3 hours:\n\n32 toys/hour * 3 hours = 96 toys\n\nNow, if we want to put 4 toys into each box, we need to divide the total number of toys by the number of toys per box:\n\n96 toys / 4 toys/box = 24 boxes\n\nTherefore, 24 boxes are needed to put 4 toys into each box.", 'role': 'assistant'}
] Creating json from Arrow format: 100%|██████████| 201/201 [00:09<00:00, 20.17ba/s]
1138676509

4. 使用 trl 和 SFTTrainer 通过QLoRA微调模型

我们现在已经准备好微调我们的模型。我们将使用 SFTTrainer 从 trl 来微调我们的模型。 SFTTrainer 使监督开放LLM的微调变得简单。 SFTTrainer 是 Trainer 的一个子类 transformers 库,并支持所有相同的功能,包括日志记录、评估和检查点,但增加了额外的生活质量功能,包括:

  • 数据集格式化,包括对话和指令格式
  • 仅对完成进行训练,忽略提示
  • 打包数据集以实现更高效的训练
  • PEFT(参数高效微调)支持,包括Q-LoRA,或Spectrum
  • 为对话微调准备模型和分词器(例如添加特殊标记)
  • 分布式训练与accelerate和FSDP/DeepSpeed

我们准备了一个run_sft.py脚本,它支持提供一个yaml配置文件来运行微调。这允许您轻松更改模型、数据集、超参数和其他设置。这是通过使用TrlParser来实现的,它解析yaml文件并将其转换为TrainingArguments参数。这样我们就可以用同一个脚本来支持Q-LoRA、Spectrum和其他PEFT方法。见附录A,了解不同模型和PEFT方法以及分布式训练的执行示例。

问题:我们为什么不使用像axolotl这样的框架?

这是一个很好的问题!Axolotl是一个很棒的框架,许多开源构建器都在使用它,并且经过了充分的测试。然而,了解如何手动操作也是很重要的。这将使你更好地理解其内部运作以及如何进行定制。特别是在你遇到问题或想扩展脚本并添加新功能时。

在我们开始训练之前,让我们先看看我们的训练脚本。脚本非常简单,易于理解。这应该有助于您理解、定制和扩展脚本来满足您的使用需求。我们为dataclasses定义了参数。每个参数可以通过命令行或提供yaml配置文件来提供。这样我们有更好的类型安全性和智能感知支持。

# ....

@dataclass
class ScriptArguments:
dataset_id_or_path:str...# ....     
    

我们可以为不同的训练方法定制行为,并在我们的脚本中使用它们script_args。训练脚本通过#######块来区分脚本的不同部分。主要的训练函数:

  1. 记录所有超超参数
  2. 从 Hugging Face Hub 或本地磁盘加载数据集
  3. 加载我们的训练策略(例如 Q-LoRA,Spectrum)的分词器和模型
  4. 初始化SFTTrainer
  5. 启动训练循环(可选地从检查点继续训练)
  6. 保存模型,并可选择将其推送到Hugging Face Hub

以下是使用 Q-LoRA 调整 Llama-3.1-8B 模型的一个示例.

# 模型参数
model_name_or_path: Meta-Llama/Meta-Llama-3.1-8B
tokenizer_name_or_path: Meta-Llama/Meta-Llama-3.1-8B-Instruct
model_revision: main
torch_dtype: bfloat16
attn_implementation: flash_attention_2
use_liger: true
bf16: true
tf32: true
output_dir: runs/llama-3-1-8b-math-orca-qlora-10k-ep1

# 数据集参数
dataset_id_or_path: train_dataset.json
max_seq_length: 1024
packing: true

# LoRA arguments
use_peft: true
load_in_4bit: true
lora_target_modules: "all-linear"
# important as we need to train the special tokens for the chat template of llama 
lora_modules_to_save: ["lm_head", "embed_tokens"] # you might need to change this for qwen or other models
lora_r: 16
lora_alpha: 16

# Training arguments
num_train_epochs: 1
per_device_train_batch_size: 8
gradient_accumulation_steps: 2
gradient_checkpointing: true
gradient_checkpointing_kwargs:
  use_reentrant: false
learning_rate: 2.0e-4 
lr_scheduler_type: constant
warmup_ratio: 0.1

# Logging arguments
logging_strategy: steps
logging_steps: 5
report_to:
- tensorboard
save_strategy: "epoch"
seed: 42

# Hugging Face Hub 
push_to_hub: true
# hub_model_id: llama-3-1-8b-math-orca-qlora-10k-ep1 # if not defined same as output_dir
hub_strategy: every_save

修改scripts/run_sft.py

def train_function(model_args: ModelConfig, script_args: ScriptArguments, training_args: SFTConfig):
    # 先调整嵌入层大小,否则会报错size mismatch for base_model.model.lm_head.modules_to_save.default.weight
    model.resize_token_embeddings(len(tokenizer))  # len(tokenizer)是新的词汇表大小
    # 再应用PEFT
    trainer = SFTTrainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
        tokenizer=tokenizer,
        peft_config=peft_config,
    )

此配置适用于单GPU训练和使用DeepSpeed的多GPU训练(详见附录以获取完整的命令)。如果您想使用Spectrum,请参阅附录以获取更多信息。

!python3 scripts/run_sft.py --config receipes/Qwen2.5-3b-qlora.yaml
{'loss': 0.1699, 'grad_norm': 0.30702558159828186, 'learning_rate': 0.0002, 'epoch': 0.1}
{'loss': 0.1593, 'grad_norm': 0.23631243407726288, 'learning_rate': 0.0002, 'epoch': 0.2}
{'loss': 0.1541, 'grad_norm': 0.2333337366580963, 'learning_rate': 0.0002, 'epoch': 0.3}
{'loss': 0.1694, 'grad_norm': 0.23603564500808716, 'learning_rate': 0.0002, 'epoch': 0.4}
{'loss': 0.1587, 'grad_norm': 0.20989495515823364, 'learning_rate': 0.0002, 'epoch': 0.5}
{'loss': 0.1496, 'grad_norm': 0.20045948028564453, 'learning_rate': 0.0002, 'epoch': 0.6}
{'loss': 0.146, 'grad_norm': 0.22607915103435516, 'learning_rate': 0.0002, 'epoch': 0.7}
{'loss': 0.1456, 'grad_norm': 0.1976633071899414, 'learning_rate': 0.0002, 'epoch': 0.8}
{'loss': 0.1423, 'grad_norm': 0.1997857391834259, 'learning_rate': 0.0002, 'epoch': 0.9}
{'train_runtime': 3791.7109, 'train_samples_per_second': 2.042, 'train_steps_per_second': 0.128, 'train_loss': 0.16703282739997896, 'epoch': 1.0}
100%|███████████████████████████████████████| 484/484 [1:03:11<00:00,  7.83s/it]
***** train metrics *****
  epoch                    =         1.0
  total_flos               = 138051217GF
  train_loss               =       0.167
  train_runtime            =  1:03:11.71
  train_samples            =       10000
  train_samples_per_second =       2.042
  train_steps_per_second   =       0.128
2025-08-09 16:36:01,719 - __main__ - INFO - *** Save model ***
INFO:__main__:*** Save model ***
2025-08-09 16:36:04,238 - __main__ - INFO - Model saved to qwen2.5-3b-math
INFO:__main__:Model saved to qwen2.5-3b-math
2025-08-09 16:36:04,444 - __main__ - INFO - Tokenizer saved to qwen2.5-3b-math
INFO:__main__:Tokenizer saved to qwen2.5-3b-math
2025-08-09 16:36:04,516 - __main__ - INFO - *** Training complete! ***
INFO:__main__:*** Training complete! ***
模型训练样本硬件方法训练序列长度每设备批次大小 梯度积累packing Flash AttentionLiger Kernels预计优化步骤预计训练时间
qwen2.5-3B 10,000 1x L4 24GB Q-LoRA 1024 1 2 5000 ~360 分钟
qwen2.5-3B 10,000 1x L4 24GB Q-LoRA 1024 2 2 1352 ~290 分钟
qwen2.5-3B 10,000 1x L4 24GB Q-LoRA 1024 2 4 676 ~220 分钟
qwen2.5-3B 10,000 1x L4 24GB Q-LoRA 1024 4 4 338 ~135 分钟
qwen2.5-3B 10,000 4x L4 24GB Q-LoRA 1024 8 2 84 ~33 分钟
qwen2.5-3B 10,000 8x L4 24GB Q-LoRA 1024 8 2 42 ~18 分钟
qwen2.5-3B 10,000 8x L4 24GB Spectrum (30%) 1024 8 2 42 ~21 分钟

笔记:

  • Q-Lora 包括训练嵌入层和lm_head,因为我们使用了Llama 3.1聊天模板,并且在基础模型中特殊标记没有经过训练。
  • 用于分布式训练的Deepspeed(0.15.4)结合了ZeRO3和Hugging Face Accelerate。
  • 具有30%信噪比层的Spectrum比Q-Lora稍慢,但在GSM8K数据集上实现了58%的准确率,比Q-Lora高4%。

仅使用 Q-LoRA 只会保存训练好的适配器权重。如果你想将模型作为独立模型使用,例如用于推理,你可能希望合并适配器和基础模型。这可以通过以下命令完成:

!python3 scripts/merge_adapter_weights.py --peft_model_id qwen2.5-3b-math --push_to_hub False

5. 测试模型并运行推理

训练完成后,我们希望评估和测试我们的模型。由于我们在解决数学问题上训练了模型,因此我们将在GSM8K数据集上评估模型。GSM8K(小学数学8K)是一个包含8500个高质量、语言多样化的 elementary school math word problems 数据集。该数据集的创建是为了支持在基本数学问题上的问答任务,这些任务需要多步推理。

评估生成式人工智能模型不是一件容易的事,因为一个输入可以有多个正确的输出。如果你想了解更多关于评估生成模型的信息,请查看:

我们将使用EvaluationHarness一个开源框架,用于在各种任务和基准上评估语言模型。该框架支持评估OpenAI兼容API端点后面的模型,这些模型可以是本地的或远程的。这非常有帮助,因为我们可以在与生产相同的环境中评估我们的模型。

我们将使用文本生成推理(TGI)来测试和部署我们的模型。TGI是一个为部署和提供服务大型语言模型(LLMs)而设计的解决方案。TGI使用张量并行性和连续 batching来实现高性能文本生成。如果您是或想要使用vLLM,您可以查看附录以了解如何启动推理服务器。

注意:确保你有足够的GPU内存来运行容器。重启内核以从笔记本中移除所有已分配的GPU内存。

我们将以1个GPU detached开始。这意味着容器运行时我们可以继续使用笔记本电脑。如果你有更多的GPU,你可以更改--gpus--num-shard标志为GPU的数量。

%%bash

num_gpus=1
model_id=philschmid/llama-3-1-8b-math-orca-spectrum-10k-ep1 # replace with your model id

docker run --name tgi --gpus ${num_gpus} -d -ti -p 8080:80 --shm-size=2GB \
  -e HF_TOKEN=$(cat ~/.cache/huggingface/token) \
  ghcr.io/huggingface/text-generation-inference:3.0.1 \
  --model-id ${model_id} \
  --num-shard ${num_gpus}

我们的容器现在将在后台启动,并从Hugging Face Hub下载模型。我们可以使用docker logs -f tgi查看日志以跟踪进度。

一旦我们的容器运行起来,我们就可以使用openaihuggingface_hub sdk 发送请求。这里我们将使用openai sdk 向我们的推理服务器发送请求。如果你没有安装openai sdk,你可以使用pip install openai进行安装。

from openai import OpenAI
# create client 
client = OpenAI(base_url="http://localhost:8080/v1",api_key="-")

system_message = """这是一套针对解决高中数学问题的指导说明,具体内容如下:
整体要求:解决给定的高中数学问题时,要对每一步进行清晰解释,从而得出最终答案。在计算过程中,从对问题的解释开始,详细说明每个公式、数值或结论的推导过程,通过逻辑连贯且层层递进的步骤,系统地得出最终答案。
# 具体步骤:
1. 理解问题:重新阐述给定的数学问题,明确指出核心问题以及任何重要的已知数值。例如,对于 “已知三角形两边长分别为 34,夹角为 60°,求第三边长” 这一问题,核心问题是求第三边长,重要已知值为两边长 34 以及夹角 60°。
2. 设定思路:确定有助于解决问题的关键公式或概念,比如代数运算、几何公式、三角恒等式等。对于上述三角形问题,可能会想到余弦定理这一关键公式。
3. 逐步求解:逐步推进数学问题的每一步求解过程,解释为什么每一步操作能让我们更接近答案。例如在使用余弦定理求第三边长时,先说明余弦定理的表达式,再代入已知数值,解释代入的原因及计算过程。
4. 双重检查:如果可行,对解题过程进行准确性和合理性检查,并提及可能存在的其他解题方法。比如检查计算是否有误,思考是否能用向量法等其他方法解决该三角形问题。
5. 最终答案:清晰地给出数值或代数形式的解决方案,如果涉及单位,要一并给出。如上述三角形问题,最终答案可能是第三边长为√13(单位:厘米,若题目设定了长度单位)。
# 注意事项:
- 始终要清晰定义所使用的任何变量或术语。例如在解题中设三角形第三边为 c,就要说明 c 代表的意义。
- 在适用的情况下,要包含单位换算或结合题目背景说明选择每个公式或步骤的原因。比如在计算面积问题时,如果题目给的长度单位是分米,而最终要求的面积单位是平方厘米,就需要进行单位换算,并说明换算原因。
- 假设数学水平为高中程度,除非是高中常见的,否则避免使用过于高深的数学技巧。
"""

messages = [
    {"role": "system", "content": system_message},
    {"role": "user", "content": "Natalia sold clips to 48 of her friends in April, and then she sold half as many clips in May. How many clips did Natalia sell altogether in April and May?"},
]
expected_answer = "72"

# Take a random sample from the dataset and remove the last message and send it to the model
response = client.chat.completions.create(
    model="orca",
    messages=messages,
    stream=False, # no streaming
    max_tokens=256,
)
response = response.choices[0].message.content

# Print results
print(f"Query:\n{messages[1]['content']}")
print(f"Original Answer:\n{expected_answer}")
print(f"Generated Answer:\n{response}")

太棒了,看起来很棒!现在我们可以用评估工具来评估我们的模型。

注意:请确保将模型ID更改为您的微调模型。

!lm_eval --model local-chat-completions \
  --tasks gsm8k_cot \
  --model_args model=philschmid/llama-3-1-8b-math-orca-spectrum-10k-ep1,base_url=http://localhost:8080/v1/chat/completions,num_concurrent=8,max_retries=3,tokenized_requests=False \
  --apply_chat_template \
  --fewshot_as_multiturn

哇,仅仅使用10k样本就能达到54%的准确率已经相当不错了!我们成功地验证了我们的模型可以解决数学问题。现在,完成后别忘了停止你的容器。

!docker stop tgi
!docker rm tgi

附录

附录包含有关如何运行分布式训练、推理以及如何使用Spectrum的附加命令和文档。

分布式训练

Deepspeed + Q-LoRA

注意:num_processes将此更改为您希望使用的GPU数量。

accelerate launch --config_file configs/accelerate_configs/deepspeed_zero3.yaml --num_processes 8 scripts/run_sft.py --config receipes/llama-3-1-8b-qlora.yaml

推理

vLLM

注意:将模型ID替换为您的微调模型。

docker run --runtime nvidia --gpus all \
-p 8000:8000 \    vllm/vllm-openai --model philschmid/llama-3-1-8b-math-orca-qlora-10k-ep1-merged     

Spectrum

Spectrum使用信噪比(SNR)分析来选择最有助于微调的层。它为不同的模型提供了脚本和预运行扫描。如果你的模型没有被扫描,它会提示你使用哪个批次大小进行扫描。对于70b模型,批次大小为4需要8xH100。但是像Llama 3.1 8B这样的流行模型已经扫描过了。你可以在这里找到已扫描的模型here.

脚本将在model_snr_results生成一个yaml配置文件,文件名包含模型名称和顶级百分比,例如对于meta-llama/Llama-3.1-8B30,它将生成在snr_results_meta-llama-Meta-Llama-3.1-8B_unfrozenparameters_30percent.yaml

  • --model-name指定本地模型路径或Hugging Face仓库。
  • --top-percent指定您希望检索的SNR层的最高百分比。
# 克隆spectrum
git clone https://github.com/cognitivecomputations/spectrum.git
cd spectrum
# 生成yaml配置
python3 spectrum.py --model-name meta-llama/Meta-Llama-3.1-8B --top-percent 30
# 前30%的SNR层保存到snr_results_meta-llama-Meta-Llama-3.1-8B_unfrozenparameters_30percent.yaml
cd ..

在生成 yaml 配置后,我们可以使用它来微调我们的模型。我们需要在我们的 train config yaml 文件中定义 yaml 配置文件,并提供 yaml 文件的路径作为 spectrum_config_path。查看 receipes/llama-3-1-8b-spectrum.yaml 以获取示例。

然后我们可以使用以下命令开始单 GPU 训练:

CUDA_VISIBLE_DEVICES=0 python scripts/run_sft.py --config receipes/llama-3-1-8b-spectrum.yaml

注意:Spectrum 比 Q-Lora 需要更多的内存。根据论文,在单个 GPU 上需要约 30-50GB。

对于使用FSDP和Deepspeed进行多GPU训练,您可以使用以下命令:

accelerate launch --config_file configs/accelerate_configs/deepspeed_zero3.yaml --num_processes 8 scripts/run_sft.py --config receipes/llama-3-1-8b-spectrum.yaml

注意:在8个L4 GPU上使用Spectrum进行训练需要约21分钟。在相同配置下,使用Q-Lora需要18分钟。

结果:

  • 在GSM8K数据集上训练了1个epoch的Spectrum模型,使用了30%的SNR层,达到了58%的准确率,比Q-Lora高4%。
  • 在GSM8K数据集上训练了3个epoch的Spectrum模型,带有30%的SNR层,达到了60%的准确率。
posted @ 2025-08-09 17:54  有何m不可  阅读(93)  评论(0)    收藏  举报