用 Unsloth 训练自己的决策模型:微调 Qwen3.8 与 Gemma 4
Train your own Decision Model with Unsloth
Unsloth 发布教程,介绍如何用 LoRA 微调 Qwen3.8、Gemma 4 等 LLM,将其转为输出选项与概率的决策模型,而非生成文本。官方称用 Clef head 加 LoRA(r=64)训练一个 epoch,下游准确率从 30–37% 提升到最高 78%,Qwen3.5-0.8B 与 2B 分别达到 78% 和 81%。
⌘Ctrlk
用 Unsloth 训练你自己的决策模型
微调 Qwen 和 Gemma 等 LLM,使其以校准后的概率做出决策。
你现在可以用 Unsloth 训练自己的决策模型,就像 Jev、Laya 和 Clef 一样。微调 Qwen3.8 和 Gemma 4 LLM,将它们转化为决策模型,让它们做出决策,而不是生成文本。微调后的模型会读取你的输入,为你提供的选项打分,并返回一个带有概率的选择。训练后的基准测试见下表:
Qwen3.5-0.8B
36% -> 73%
7% -> 74%
19% -> 76%
78%
Qwen3.5-2B
33% -> 78%
1% -> 58%
1% -> 62%
81%
我们用 LoRA(r=64)为 LLM 微调了一个 Clef 头,仅训练一个 epoch,就将下游准确率从 30–37%(大致相当于随机水平)提升到高达 78%。
训练使用与 Laya 和 Clef 相同的数据集格式。测试集已针对训练数据进行了去污染处理。
所有模型都同样有效——你还可以进一步微调 Laya / Clef 等决策模型。
Qwen3.5-0.8B
78%
4GB
42 分钟
Qwen3.5-2B
81%
8GB
40 分钟
Llama 3.2 3B
79%
4.1GB
30 分钟
Gemma 4 E4B
77%
14.4GB
49 分钟
Laya(微调后)
77%
2.5GB
10 分钟
我们使用了 12 个来源的混合数据,外加 typed-decisions:ag_news、arc、banking77、boolq、clinc150、commonsense_qa、mmlu、mnli、prompt_injections、snli、sst5 和 wanli。测试集包含 3,000 行:2000 行来自 typed-decisions,500 行来自 BANKING77,500 行来自 CLINC150。
🦥 在 Unsloth 中训练
设置 Unsloth
最简单的入门方式是下载 Unsloth 桌面应用。支持 macOS、Windows 和 Linux。
或者,如果你更喜欢手动安装:
MacOS、Linux、WSL:
curl -fsSL https://unsloth.ai/install.sh | shWindows PowerShell:
irm https://unsloth.ai/install.ps1 | iex选择你的模型和数据集
打开 Train 选项卡并选择一个 LLM,例如 unsloth/Qwen3.5-4B。然后将 Train as 设置为 Decision model。Unsloth 会自动填入效果良好的设置。要匹配我们的结果,请将 epochs 设为 2,LoRA rank 设为 16,学习率设为 2e-4。
上传文件或从 Hugging Face 选择数据集,使用该数据集格式。对于 typed-decisions,将 Subset 设置为 all。

开始训练

点击 Start Training。Unsloth 会报告训练前后在留出决策上的准确率,并校准模型的置信度。
在 Decision API 中运行
点击 Use in Decision API。使用 laya、default 或 jev-latest 的请求现在会转到你的模型。

你的模型也会以其运行名称显示在 Settings → API 下的 Decision API → Model 中。

你还可以通过 Decision API 中的“Try It”选项来试用训练好的决策模型:


📒 使用我们的免费 notebook
你可以完全免费地使用我们的 Google Colab 或 Kaggle notebook 训练自己的决策模型。只要你拥有 Google 账号,Colab 和 Kaggle 都提供慷慨的免费 GPU 算力。这些 notebook 中有分步工作流程,你可以逐步操作,我们会向你展示如何进行数据准备、训练实际模型(此处为 Qwen3.5-4B)并将其导出。
通过我们的免费 notebook 将 Qwen3.5-4B 微调为决策模型:
你也可以使用我们免费的 Unsloth Studio notebook,通过 UI 界面训练决策模型:
🐍 用代码训练
用 pip install --upgrade unsloth, and use the following code to train your own decision model. 安装或更新 Unsloth
要使用 Llama 或 Gemma 4,请将 model_name 改为 unsloth/Llama-3.2-3B-Instruct 或 unsloth/gemma-4-E4B-it。Unsloth 可以微调的其他 LLM 应该也能以相同方式工作。
对于你自己的数据,请参阅数据集格式。每一行包含一个 state、要决策的问题以及标准答案。
校准并保存
在留出的 split_holdout 行上进行校准,使模型的概率与其正确频率相匹配:
然后保存。save_pretrained 保存 LoRA 适配器和 head。save_pretrained_merged 保存完整的 16 位模型:
像加载基础模型一样再次加载它:
🎯 做出决策
给 predict 一个输入和要决策的问题,格式与你的数据集相同:
answer 是 choice 的选项键,True 或 False 用于 noul,score 则用级别数字。每个答案还具有与 Decision API 答案相同的字段。
要在有标签的测试集上检查准确率,请使用 evaluate:
在 Decision API 中使用它
你可以阅读我们的详细指南来了解如何服务/运行决策模型,否则请阅读下面的快速摘要。你在 Unsloth 中训练的模型会显示在 Settings → API 中。对于你用代码训练的模型,请用你保存的合并文件夹启动 Unsloth:
在 Settings → API 中打开 Decision API。使用 laya、default 或 jev-latest 的请求现在会转到你的模型,答案格式与 Laya 的相同。该模型需要 GPU,并在首次请求时加载,这可能需要几分钟。当训练任务正在使用 GPU 时,Decision API 会等待,并在训练结束后重新开始回答。
工作原理
Unsloth 将你的输入放在一个提示中,后面跟着每个问题及其选项。LLM 读取一次。一个小的 head(设计与 Cloudflare 的 Clef 相同)查看 LLM 对每个问题和选项的输出,为每个选项打分,并一起决定所有问题。它从不写文本,因此不会把内存花在 LLM 的词语预测上。
⚙️ 推荐设置
从 rank 16 的 4 位 LoRA 和学习率 2e-4 开始。新 head 默认以 1e-4 训练。你可以在
DecisionTrainer中用head_learning_rate更改它。我们在 typed-decisions 上使用了 2 个 epoch。数据较少时,可以尝试 3 或 4 个。
如果想快速试一下,请设置
max_steps = 60。Qwen3.5-4B 在 L4 上 10 分钟内达到了 76%。如果内存不足,请将 batch size 减半,并将梯度累积加倍。
max_seq_length设置训练期间的最长输入。长输入会保留问题和选项,并截断输入末尾以适配。预测最多读取 16,384 个 token。
最后更新于 2 分钟前
这有帮助吗?
这有帮助吗?
from unsloth import FastDecisionModel, DecisionTrainer, is_bfloat16_supported
from datasets import load_dataset
from transformers import TrainingArguments
model, tokenizer = FastDecisionModel.from_pretrained(
model_name = "unsloth/Qwen3.5-4B",
max_seq_length = 2048,
load_in_4bit = True,
)
model = FastDecisionModel.get_peft_model(
model,
r = 16,
lora_alpha = 16,
lora_dropout = 0,
use_gradient_checkpointing = "unsloth",
random_state = 3407,
)
dataset = load_dataset("LocalLLaMA/typed-decisions", "all", split = "train")
items, report = FastDecisionModel.build_dataset(dataset, tokenizer, model)
print(f"Skipped {report['skipped']} of {report['total']} decisions")
train_items, eval_items = FastDecisionModel.split_holdout(items, seed = 3407)
trainer = DecisionTrainer(
model = model,
processing_class = tokenizer,
train_dataset = train_items,
eval_dataset = eval_items,
args = TrainingArguments(
per_device_train_batch_size = 8,
gradient_accumulation_steps = 4,
num_train_epochs = 2,
learning_rate = 2e-4,
lr_scheduler_type = "cosine",
warmup_steps = 10,
weight_decay = 0.01,
bf16 = is_bfloat16_supported(),
fp16 = not is_bfloat16_supported(),
eval_strategy = "epoch",
logging_steps = 10,
output_dir = "outputs",
report_to = "none",
seed = 3407,
),
)
trainer.train()metrics = FastDecisionModel.calibrate(model, tokenizer, eval_items)
print(metrics) # held-out accuracy, calibration error (ece) and lossmodel.save_pretrained("qwen-decisions")
model.save_pretrained_merged("qwen-decisions-merged")
# model.push_to_hub("hf_username/qwen-decisions", token = "hf_...")model, tokenizer = FastDecisionModel.from_pretrained("qwen-decisions", load_in_4bit = True)FastDecisionModel.for_inference(model)
answers = FastDecisionModel.predict(
model,
tokenizer,
"Hi, I was charged twice for invoice #4411. Please refund the duplicate today.",
{
"team": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "invoices, payments, refunds",
"technical": "bugs, outages, errors",
"sales": "pricing, new plans",
},
},
"refund": {"type": "noul", "instructions": "Does the customer ask for a refund?"},
},
)
print(answers["team"]["answer"]) # "billing"
print(answers["team"]["probabilities"]) # {"billing": ..., "sales": ..., "technical": ...}test = load_dataset("LocalLLaMA/typed-decisions", "all", split = "test")
test_items, _ = FastDecisionModel.build_dataset(test, tokenizer, model)
print(FastDecisionModel.evaluate(model, tokenizer, test_items))UNSLOTH_SYSTEMONE_MODEL=/path/to/qwen-decisions-merged unsloth studio -H 0.0.0.0 -p 8888来源:Hacker News · unsloth.ai