如果GPU能跑推理,那也应该能微调。[P]

Reddit r/MachineLearning 工具

摘要

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 的数值为估算值——目前没有针对该模型、该规模下这些方法的公开基准测试。如果某方法无法运行,我会说明原因。

USAFLoRAQLoRADoRA全参数微调
在 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 每步耗时更长,因为它做了更多工作:

操作USAFLoRA
前向传播~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.431.00(下降 30%)
域内困惑度2.832.76
保留集困惑度4.524.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 12GBDirectML97.8h
T4 16GBCUDA~30~2h
2× T4 16GBCUDA~50~1.2h
RTX 4090 24GBCUDA~80~45min

CUDA 数据为估算值,需实际硬件基准测试确认。

支持的模型

自动检测适用于 HuggingFace 上的任何 MoE 模型——只需 config.json 即可。已在 Qwen3-30B-A3B 上测试通过。

模型系列已测试
Qwen3-MoE是 (30B-A3B)
Mixtral
DeepSeek-MoE
OLMoE

我希望能测试的模型

以下这些模型是 USAF 的设计目标。我只是没有对应的 GPU。

模型总参数激活参数已验证原因
DeepSeek-V4 Pro1.6T49B最新 DeepSeek,MIT 许可,2026 年 4 月
Kimi K2.5 (Moonshot)1T32B原生多模态(视觉+文本),2026 年 2 月
Mistral Large 3675B41BApache 2.0,2025 年 12 月
Qwen3-235B-A22B235B22B与已测试模型相同架构,规模 8 倍
Mixtral-8x22B141B39B非融合专家投影

所需硬件:每个模型需要 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_idslabels

{"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_PATHdata/train_dataset_12h.jsonl包含训练样本的 JSONL 文件
QUANT_PATH自动检测experts_q4.pt 的路径
TRAIN_FROM40第一个可训练层(0-39 冻结)
FRAC0.005要训练的参数比例(0.5%)
STEPS180训练步数
MICROBATCH2每个微批的序列数
LR_PEAK2e-4峰值学习率(余弦衰减)
RESELECT_EVERY50RigL 重选频率
USE_CUDA0设置为 1 以使用 NVIDIA GPU
USE_AMP1混合精度(仅 CUDA)
USE_MULTI_GPU1DataParallel(仅 CUDA)
FROZEN_CACHE_N0要缓存的样本数(0=全部)

支持的 GPU 配置

设置命令
AMD GPU (RX 6000/7000)python train.py
NVIDIA 单 GPUUSE_CUDA=1 python train.py
NVIDIA 双 GPUUSE_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 上进行测试——需要硬件支持

许可协议

Apache 2.0。LICENSE。贡献:CLA

相似文章

单GPU微调的高效异构协同设计

Papers with Code Trending

SlideFormer 提出了一种异构协同设计,用于在单GPU上进行全参数LLM微调,利用GPU/CPU/RAM/NVMe及其层滑动引擎和优化的Triton内核,在单张RTX 4090上实现对123B+模型的微调,吞吐量显著提升。