如果GPU能跑推理,那也应该能微调。[P]
摘要
USAF(超稀疏自适应微调)是一种新方法,允许在消费级GPU(包括AMD硬件)上微调MoE模型,仅需12GB VRAM。与无法做到的LoRA/QLoRA不同,USAF只训练最重要的稀疏权重和路由器。
查看缓存全文
缓存时间: 2026/07/04 22:54
tsuyu122/usaf
来源:https://github.com/tsuyu122/usaf
USAF — 极致稀疏自适应微调
许可协议 Python (https://python.org) CUDA (https://developer.nvidia.com/cuda-downloads) 状态
在几乎只能运行推理的硬件上微调 MoE 模型。
Qwen3-30B-A3B 在 fp16 精度下需要 60GB 显存。全参数微调需要 120GB 以上。USAF 在 12GB GPU 上训练了 4.8B 参数中的 26M——这是唯一能在 AMD 显卡上运行的方法,也是唯一同时训练专家权重和路由器的方案。
为什么需要这个项目
我没有 A100、H100,甚至连 RTX 4090 都没有。我只有一块 Radeon RX 6750 XT,12GB 显存,运行 Windows。
现有的微调方法要么无法在这块硬件上加载,要么根本不会触及 MoE 模型真正重要的部分。所以我构建了一个两者都能兼顾的方案。
对比
以 Qwen3-30B-A3B 为例,训练 180 步。LoRA/QLoRA/DoRA 的数值为估算值——目前没有针对该模型、该规模下这些方法的公开基准测试。如果某方法无法运行,我会说明原因。
| USAF | LoRA | QLoRA | DoRA | 全参数微调 | |
|---|---|---|---|---|---|
| 在 12GB 显卡上运行 | 是 | 否 | 否 | 否 | 否 |
| 在 24GB 显卡上运行 | 是 | 否 | 可能 | 否 | 否 |
| 在 AMD 显卡上运行 | 是 | 否 | 否 | 否 | 否 |
| 最小显存需求(NVIDIA) | 12GB | ~60GB | ~24GB | ~60GB | ~120GB |
| 训练专家权重 | 是 | 否 | 否 | 否 | 是 |
| 训练路由器 | 是 | 否 | 否 | 否 | 是 |
| 耗时(RX 6750 XT) | 7.8h | 无法加载 | 无法加载 | 无法加载 | 无法加载 |
| 耗时(A100) | ~20min | ~8min | ~15min | ~10min | ~40min |
| 域内困惑度 | 2.76 | ~2.80 | ~2.90 | ~2.78 | ~2.60 |
LoRA 和 QLoRA 在冻结权重上训练适配器矩阵。USAF 则训练实际的专家权重和路由器——它只是挑选出哪些权重是重要的。对于 MoE 模型,门控网络对模型行为的决定性作用超过任何单个专家权重。
为什么在大 GPU 上 USAF 耗时更长
在 A100 上,USAF 每步耗时更长,因为它做了更多工作:
| 操作 | USAF | LoRA |
|---|---|---|
| 前向传播 | ~3ms/层(相同) | ~3ms/层 |
| 反向传播 | ~30ms/层(26M 参数) | ~0.5ms/层(100K 参数) |
| RigL 密集传播(每 50 步) | 每次 ~60s | 不适用 |
| 优化器 | SparseAdam (26M) | AdamW (100K) |
USAF 每步计算 2600 万参数的梯度,而 LoRA 只计算约 10 万——梯度计算量高出 260 倍。但它仅比 LoRA 慢 2-3 倍,这正是稀疏训练的精髓所在。
在消费级硬件上,对比更简单:USAF 能跑,LoRA 跑不了。
结果
在 Qwen3-30B-A3B 上训练 180 步,RX 6750 XT 12GB (AMD),DirectML。
| 指标 | 训练前 | 训练后 |
|---|---|---|
| 损失 | 1.43 | 1.00(下降 30%) |
| 域内困惑度 | 2.83 | 2.76 |
| 保留集困惑度 | 4.52 | 4.24(下降 6%) |
| 因 NaN 跳过的步数 | — | 0 / 180 |
保留集仓库(Flecs,SFML,EnTT,Box2D)的指标与训练数据一同改善——这是泛化能力提升,而非记忆。
为什么稀疏训练对 MoE 有效
并非所有权重都重要。 MoE 模型将每个 token 路由到少数几个专家。对于给定输入,大多数权重从未被激活。重要性阶段会找出梯度幅度最大的 0.5%。
路由器是杠杆点。 训练门控网络(200 万参数)会改变哪些专家被激活。仅一步就能使损失下降 0.65。适配器方法无法触及路由器。
稀疏性是自适应的。 RigL 重选机制每 50 步替换表现不佳的权重。活跃集不断演变——初始轮换率约 92%,随着模型收敛而降低。
驻留缓存消除了瓶颈。 在 CPU 上进行 4 位反量化速度很慢(每张张量 400ms)。可训练层在 RAM 中保留 fp16 副本——只需反量化一次,永久使用。
快速开始
pip install transformers safetensors psutil
# AMD GPU (DirectML)
python train.py
# NVIDIA GPU (CUDA)
USE_CUDA=1 USE_AMP=1 python train.py
# 多 GPU
USE_CUDA=1 USE_MULTI_GPU=1 MICROBATCH=4 python train.py
无需配置文件。一切通过环境变量配置。
性能
| 硬件 | 后端 | token/秒 | 180 步耗时 |
|---|---|---|---|
| RX 6750 XT 12GB | DirectML | 9 | 7.8h |
| T4 16GB | CUDA | ~30 | ~2h |
| 2× T4 16GB | CUDA | ~50 | ~1.2h |
| RTX 4090 24GB | CUDA | ~80 | ~45min |
CUDA 数据为估算值,需实际硬件基准测试确认。
支持的模型
自动检测适用于 HuggingFace 上的任何 MoE 模型——只需 config.json 即可。已在 Qwen3-30B-A3B 上测试通过。
| 模型系列 | 已测试 |
|---|---|
| Qwen3-MoE | 是 (30B-A3B) |
| Mixtral | 否 |
| DeepSeek-MoE | 否 |
| OLMoE | 否 |
我希望能测试的模型
以下这些模型是 USAF 的设计目标。我只是没有对应的 GPU。
| 模型 | 总参数 | 激活参数 | 已验证 | 原因 |
|---|---|---|---|---|
| DeepSeek-V4 Pro | 1.6T | 49B | 是 | 最新 DeepSeek,MIT 许可,2026 年 4 月 |
| Kimi K2.5 (Moonshot) | 1T | 32B | 是 | 原生多模态(视觉+文本),2026 年 2 月 |
| Mistral Large 3 | 675B | 41B | 是 | Apache 2.0,2025 年 12 月 |
| Qwen3-235B-A22B | 235B | 22B | 是 | 与已测试模型相同架构,规模 8 倍 |
| Mixtral-8x22B | 141B | 39B | 是 | 非融合专家投影 |
所需硬件:每个模型需要 4-8 块 A100 80GB 或同等规格。如果您有硬件并希望看到 USAF 在这些模型上的结果,请通过 GitHub Discussions (https://github.com/tsuyu122/usaf/discussions) 联系我。我来编写训练代码——您提供 GPU。
通用 CLI
python -m usaf.train --model Qwen/Qwen3-30B-A3B --dataset data.jsonl --steps 180
python -m usaf.train --model mistralai/Mixtral-8x7B --dataset data.jsonl
特性
| 特性 | 状态 |
|---|---|
| 稀疏训练(0.5% 活跃) | 正式 |
| RigL 动态重选 | 正式 |
| 路由器协同训练 | 正式 |
| 4 位量化权重 | 正式 |
| 驻留专家缓存 | 正式 |
| CUDA + AMP | 正式 |
| 多 GPU (DataParallel) | 正式 |
| DirectML (AMD) | 正式 |
| Vulkan 加速 | 实验性 |
| 保留集评估 | 正式 |
硬件要求
- 12GB 以上显存 GPU 或 32GB 内存(仅 CPU)
- AMD:DirectML(Windows,内置)
- NVIDIA:CUDA 11.8+
- Python 3.10+,PyTorch 2.0+
使用自定义模型
第一步:准备数据集
创建一个 JSONL 文件,包含分词后的序列。每行必须包含 input_ids 和 labels:
{"input_ids": [1, 2, 3, ..., 512], "labels": [1, 2, 3, ..., 512]}
使用模型的分词器对自定义文本进行分词:
from transformers import AutoTokenizer
tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen3-30B-A3B")
text = "您的训练文本..."
tokens = tokenizer.encode(text)
# 切分成 512 token 的片段
for i in range(0, len(tokens) - 512, 512):
chunk = tokens[i:i+512]
sample = {"input_ids": chunk, "labels": chunk[1:] + [tokenizer.eos_token_id]}
# 将 sample 写入 JSONL
第二步:量化专家权重
USAF 需要将专家权重以 4 位 HQQ 格式存储。目前默认支持 Qwen3-MoE。对于其他模型,您需要生成 experts_q4.pt 文件:
from usaf.quantization import quantize_4bit
import torch
# 加载模型的专家张量(每层的 gate_up_proj 和 down_proj)
q_dict = {}
for layer_idx in range(num_layers):
for param_name in ["gate_up_proj", "down_proj"]:
# 加载融合后的专家张量 [num_experts, intermediate, hidden]
weights = load_expert_weights(model_path, layer_idx, param_name)
q4_entry = quantize_4bit(weights, group_size=128)
q_dict[f"model.layers.{layer_idx}.mlp.experts.{param_name}"] = q4_entry
torch.save(q_dict, "my-model-q4/experts_q4.pt")
第三步:配置并运行
# 为您的模型设置以下环境变量
QUANT_PATH="my-model-q4/experts_q4.pt" # 量化权重路径
TRAIN_FROM=36 # 第一个可训练层(保留顶部层)
STEPS=360 # 对于约 190K token 进行 2 个 epoch
FRAC=0.005 # 0.5% 稀疏度
MICROBATCH=2 # 批大小(若显存充足可增大)
python train.py
环境变量参考
| 变量 | 默认值 | 描述 |
|---|---|---|
DATASET_PATH | data/train_dataset_12h.jsonl | 包含训练样本的 JSONL 文件 |
QUANT_PATH | 自动检测 | experts_q4.pt 的路径 |
TRAIN_FROM | 40 | 第一个可训练层(0-39 冻结) |
FRAC | 0.005 | 要训练的参数比例(0.5%) |
STEPS | 180 | 训练步数 |
MICROBATCH | 2 | 每个微批的序列数 |
LR_PEAK | 2e-4 | 峰值学习率(余弦衰减) |
RESELECT_EVERY | 50 | RigL 重选频率 |
USE_CUDA | 0 | 设置为 1 以使用 NVIDIA GPU |
USE_AMP | 1 | 混合精度(仅 CUDA) |
USE_MULTI_GPU | 1 | DataParallel(仅 CUDA) |
FROZEN_CACHE_N | 0 | 要缓存的样本数(0=全部) |
支持的 GPU 配置
| 设置 | 命令 |
|---|---|
| AMD GPU (RX 6000/7000) | python train.py |
| NVIDIA 单 GPU | USE_CUDA=1 python train.py |
| NVIDIA 双 GPU | USE_CUDA=1 USE_MULTI_GPU=1 MICROBATCH=4 python train.py |
| CPU 回退 | python train.py(自动) |
故障排除
“CUDA out of memory”:将 MICROBATCH 减少至 1,或增加 TRAIN_FROM 以冻结更多层。
NVIDIA 上出现 “No module named torch_directml”:这是预期的。代码会自动检测并使用 CUDA。设置 USE_CUDA=1。
损失不下降:确保 FRAC 足够高(>0.001)。尝试使用 EPOCHS=3 进行 2-3 个 epoch。检查数据集质量。
冻结缓存耗时过长:设置 FROZEN_CACHE_N=50 仅缓存前 50 个样本。或通过 USE_FROZEN_CACHE=0 禁用。
未来工作
- 在 A100 级别硬件上与 LoRA/QLoRA/DoRA 进行基准测试
- 完整的 Vulkan 注意力流水线,实现跨厂商加速
- 分布式训练(FSDP)
- 在 DeepSeek-V4 Pro、Kimi K2.5、Mistral Large 3 上进行测试——需要硬件支持
许可协议
相似文章
@_vmlops:在单GPU上微调12B模型已成现实 大多数人以为需要庞大的GPU集群才能微调大型语言模型…
Hugging Face 的 PEFT 库实现了在单张 GPU 上对大型模型进行参数高效微调,在降低计算和存储成本的同时保持性能。
单GPU微调的高效异构协同设计
SlideFormer 提出了一种异构协同设计,用于在单GPU上进行全参数LLM微调,利用GPU/CPU/RAM/NVMe及其层滑动引擎和优化的Triton内核,在单张RTX 4090上实现对123B+模型的微调,吞吐量显著提升。
@Suryanshti777: NVIDIA刚刚揭秘了它们用来让LLM微调显著加速的隐藏技巧。不是新GPU。不是大…
NVIDIA和Unsloth发布了一篇技术指南,详细介绍了三种底层优化方法,可将LLM微调速度提升高达25%,包括打包序列缓存、双缓冲检查点存储和优化的MoE路由。该指南提供了深入的系统级解释和基准测试,面向机器学习工程师和开发者。
@0x0SojalSec: 想象一下,在Kaggle上免费微调一个31B参数的多模态模型。现在你可以训练这个庞大的31B密集型多模态模型……
Unsloth 使得在Kaggle上免费微调31B参数的多模态模型成为可能,采用4位量化,本地运行仅需22-24GB VRAM。
@che_shr_cat: 1/ 我们一直误解了GPU内存的使用方式。如果GPU根本不需要存储你的模型呢?MegaTrain 实现了…
MegaTrain 通过将 VRAM 视为瞬时无状态缓存,反转内存层次结构,在单张 GPU 上实现了 100B 以上大语言模型的全精度训练。