Lora微调关键指标和实战

一、标准 LLM 指令微调(SFT 场景)

例如:

  • 问答
  • 对话
  • 文本改写
  • 总结
  • 代码生成

这种属于 token-level 生成任务

不推荐作为核心指标

  • Accuracy
  • F1

为什么?
因为生成任务:

  • 输出长度不固定
  • 同义表达很多
  • 只要一个 token 不同,accuracy 就是 0

例如:

参考答案:

北京是中国的首都
模型输出:
中国的首都是北京
语义完全正确,但 token 级 accuracy 可能不高。
所以 F1/Accuracy 在生成任务里会严重失真。

最少需要:

①train/loss

交叉熵(Cross-Entropy)是衡量两个概率分布差异的指标。
在深度学习里,它通常表示:模型预测的概率分布 与 真实标签分布 之间的距离。

这是 LoRA 微调的第一判断指标
原因:

  • LoRA 本质是低秩参数更新
  • 是否学到任务,本质反映在交叉熵是否下降
  • 过拟合、学习率过大、r 过高都会体现在 loss 曲线上

你要关注:

现象 结论
loss 快速 → 0 LoRA 容量过大 / lr 过高 / 过拟合
loss 下降很慢 lr 太小 / LoRA 容量太小(r 太小 / target module 太少)/ 数据不够
loss 震荡剧烈 lr 太大
loss 稳定下降并趋平 正常

如何区分“lr 太小”和“容量太小”?

操作 结果
提高 lr loss 下降明显加快 → lr 原因
提高 lr 几乎无变化 → 容量不足

②.eval/loss

和 train/loss 是同一种指标,只不过数据换成了验证集。

一、正常的 eval/loss 特征

1️⃣ 下降趋势与 train/loss 一致

  • train/loss 下降 → eval/loss 也下降
  • 说明模型不仅在记忆训练数据,也在泛化到验证集

2️⃣ 数值平稳,无剧烈波动

  • 小幅波动正常(验证集较小或 batch size 小)
  • 没有大幅上跳或异常跳变

3️⃣ 与训练阶段匹配

  • 初期:eval/loss 下降快
  • 中期:下降趋缓
  • 后期:达到平台期,但仍略高于 train/loss(train < eval)

典型曲线:train/loss 平滑下降 → eval/loss 同步下降 → 最终平台轻微高于 train/loss


二、异常的 eval/loss 特征

1️⃣ eval/loss 快速上升

  • train/loss 下降 → eval/loss 却快速上升

  • 原因

    • 模型过拟合训练集(train loss 很低,但泛化差)
    • LoRA 容量太大(r 太大 / target modules 太多)
    • dropout 太低,正则化不足
  • 提示

    • 提前停止训练(early stopping)
    • 或降低 r / 增加 dropout

2️⃣ eval/loss 波动剧烈

  • 每轮验证差异很大

  • 原因

    • 验证集太小 / batch size 太小
    • 随机性太大(训练不稳定)
    • lr 太高导致训练不稳定
  • 提示

    • 稳定训练 → 减小 lr 或增加 eval batch size
    • 多跑几次取平均

3️⃣ eval/loss 与 train/loss 差距过大

  • train/loss 很低,eval/loss 很高

  • 原因

    • 过拟合
    • 数据分布不一致(训练集 vs 验证集)
  • 提示

    • 检查数据质量
    • 调整容量 / dropout / α

4️⃣ eval/loss 不下降,长期平台

  • train/loss 正常下降,eval/loss 长期停滞

  • 原因

    • LoRA 容量不足(r 太小)
    • lr 太低 → 学不到泛化能力
    • 数据噪声大
  • 提示

    • 考虑提高 r 或增加 target module
    • 调整 lr

三、判断 eval/loss 正常与异常的参考表

eval/loss 特征 可能原因 结论 / 建议
平滑下降,略高于 train/loss 正常 模型泛化良好
快速上升,train/loss 很低 过拟合 降低 r / 增加 dropout / early stopping
长期平台,train/loss 下降 容量不足或 lr 太小 提高 r / lr
剧烈波动 lr 太高 / 验证集小 减小 lr / 增大 eval batch / 多次验证平均
突然爆炸 梯度异常 降低 lr,检查 α 和 dropout

在Wandb生成val/loss

W&B 本身不会“生成” val/loss
它只会记录你在代码里 主动计算并 log 的验证指标

所以要让 W&B 出现 val/loss(或 eval/loss),本质上要完成三件事:

必须同时满足:

  1. 有验证集(eval_dataset)
  2. 训练过程中执行验证(evaluation loop)
  3. 把验证 loss 记录到 W&B

少任何一步,都不会出现。


如果你用 HuggingFace Trainer(最常见 LoRA 场景)

第一步:准备验证集

dataset = dataset.train_test_split(test_size=0.1)

train_dataset = dataset["train"]
eval_dataset = dataset["test"]

第二步:开启 evaluation

training_args = TrainingArguments(
    output_dir="./output",
    evaluation_strategy="steps",   # 关键
    eval_steps=200,                # 每 200 step 验证一次
    logging_steps=50,
    report_to="wandb",             # 确保开启 wandb
)

如果你写的是:

evaluation_strategy="no"

那永远不会出现 val/loss。


第三步:传入 eval_dataset

trainer = Trainer(
    model=model,
    args=training_args,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,   # 必须传
)

只要满足以上条件,W&B 会自动出现:

eval/loss

注意:HF 默认字段名是 eval/loss,不是 val/loss


三、如果你用 SFTTrainer(TRL 场景)

原理一样:

trainer = SFTTrainer(
    model=model,
    train_dataset=train_dataset,
    eval_dataset=eval_dataset,
    args=TrainingArguments(
        evaluation_strategy="steps",
        eval_steps=200,
        report_to="wandb"
    )
)

四、如果你是自写训练循环

那就需要手动 log:

wandb.log({
    "val/loss": val_loss
}, step=global_step)

并且你必须写一个 validation forward:

model.eval()
with torch.no_grad():
    for batch in val_loader:
        outputs = model(**batch)
        loss = outputs.loss

否则不会有。


五、常见为什么“开了也没有”

检查这几个点:

1️⃣ eval_dataset 是 None

→ 不会触发 evaluation

2️⃣ eval_steps 大于总 step

→ 训练结束前根本没执行 eval

3️⃣ 没设置 report_to="wandb"

→ 指标没上传

4️⃣ eval_accumulation_steps 配错导致没执行

六、工业推荐配置(LoRA 微调)

evaluation_strategy="steps"
eval_steps=200
logging_steps=50
load_best_model_at_end=True
metric_for_best_model="eval_loss"
greater_is_better=False

这样:

  • 每 200 步验证
  • 自动根据 eval_loss 保存最好模型
  • 防止过拟合

train/grad_norm ——梯度向量整体大小 --- 稳定性指标 ⭐⭐⭐⭐

LoRA 很容易在:

  • r 太大
  • α 太大
  • lr 太高

时出现梯度爆炸。
典型危险信号:

  • grad_norm 突然飙升
  • 波动剧烈
  • loss 同时震荡

正常 LoRA 微调:

  • 初期较高
  • 然后缓慢下降
  • 波动范围稳定

它是你判断是否需要:

  • 降 lr
  • 加 gradient clipping
  • 降 LoRA rank

的关键指标。

train/entropy —— 过拟合预警指标 ⭐⭐⭐⭐

很多人忽略这个,但其实在 LLM 微调中非常重要。

熵下降代表模型越来越“自信”。

危险信号:

现象 说明
entropy 急速下降 过拟合
entropy 接近 0 模型开始塌缩
entropy 和 loss 同时快速下降 过度记忆

LoRA 容量过大时特别容易出现。

它比 accuracy 更早暴露问题。

理想情况下:
perplexity

当是 “结构化分类/抽取” 微调任务的时候

用 loss 做 early stopping
用 macro-F1 选最优模型

主指标(业务指标) → F1(macro-F1 优先)
优化指标(训练稳定性) → eval/loss

  1. 意图识别(Intent Classification):≤10 个分类
  2. 动作分类(Action Classification):几十个分类

不同任务类别数和数据量对 F1 的期望是不同的,我给你一个系统分析:


一、意图识别(≤10 类)

  • 类别少,数据量通常充足
  • Macro-F1 相对容易达到高值
  • 参考期望值
数据量 类别数 macro-F1 合理范围
小数据集 (<5k 样本) ≤10 0.80–0.88
中等数据集 (5k–50k) ≤10 0.85–0.92
大数据集 (>50k) ≤10 0.88–0.95

说明

  • 少数类权重影响较小,Macro-F1 容易靠近 Accuracy
  • 如果你看到 <0.75,说明模型还没学到规律 → 检查容量 / lr / 数据

二、动作分类(几十个类别)

  • 类别多,数据不平衡可能严重
  • 少数类 F1 往往拉低 Macro-F1
  • 参考期望值
数据量 类别数 macro-F1 合理范围
小数据集 (<5k 样本) 20~50 0.65–0.75
中等数据集 (5k–50k) 20~50 0.70–0.80
大数据集 (>50k) 20~50 0.75–0.85

说明

  • Macro-F1 相对意图识别低一些是正常的
  • 业务上少数类的识别可以结合 Precision / Recall / top-k Accuracy 做辅助指标

三、微调策略建议

1️⃣ 先保证训练稳定

  • 关注 train/eval loss,确保 LoRA 容量 + lr 合理
  • 梯度正常 → loss 平稳下降

2️⃣ Macro-F1 作为业务指标

  • 意图识别:F1 0.85–0.90 → 可以上线
  • 动作分类:F1 0.70–0.80 → 可以接受,少数类可额外加权或做规则补偿

3️⃣ Early Stopping

  • eval loss + macro-F1 联合监控
  • 当 loss 平稳,macro-F1 不再明显提升 → 停训练

4️⃣ 类别不平衡处理

  • 动作分类少数类可:

    • 加权 loss(CrossEntropyLoss weight)
    • 数据增强
    • 重采样

四、总结

任务 类别数 数据量 期望 Macro-F1
意图识别 ≤10 小→大 0.80–0.95
动作分类 20~50 小→大 0.65–0.85

F1 越高越好,但要结合 loss 曲线看训练是否健康。
动作分类低一些是正常现象,不必焦虑。

参考

F1和准确率
https://www.cnblogs.com/aibi1/p/19530491

posted @ 2026-02-08 20:24  向着朝阳  阅读(39)  评论(0)    收藏  举报