My Blog
Agent 学习

Agent 学习第 6 周:文本分类,以及 LoRA 为什么赢了全参微调

在 TNEWS 15 分类上做了七组对照实验,最反直觉的结果是只训 0.22% 参数的 LoRA 赢了全参微调。

发布于 2026/9/11更新于 2026/9/11阅读约 11 分钟
只问这篇文章 →

第六周是文本分类。课程内容不算难,但作业让我做了七组对照实验——BERT 三种池化方式、加权损失、LLM 零样本、LoRA 微调、全参微调。

跑完之后有一个结果和我预期完全相反:LoRA 赢了全参微调。这篇主要讲这个。


一、为什么 Agent 时代还要学文本分类

这是我这周第一个意外收获。我原以为有了大模型,分类这种「老任务」就没意义了。课上给的答案很有说服力:

在 Agent 系统里,文本分类无处不在——

  • 多 Agent 路由:用户输入 → 分类判断意图 → 分发到搜索/代码/数据 Agent
  • 中控调度:子任务类型分类,决定调用哪个工具
  • 输出安全过滤:对生成内容做合规分类
  • Query 路由:判断走 RAG 检索、长期记忆,还是直接回答

那为什么不让大模型自己判断? 四个理由:

维度轻量分类模型大模型
延迟<20ms>500ms
成本——高 2~3 个数量级
行为输出固定枚举,不会幻觉可能跑偏
监控置信度可记录难量化

这个视角挺重要的:不是所有事都该交给大模型,能用小模型确定性解决的,就别用大模型概率性解决。


二、课程主线

从 Token 序列到句子向量

BERT 输出的是每个 token 一个向量,但分类需要一个固定维度的句子向量。三条路:

  • 取 [CLS] 位置的向量
  • 对所有 token 做 Mean Pooling
  • 对所有 token 做 Max Pooling

这三种我都跑了,结果在下面。

单标签 vs 多标签

单标签 → Softmax(概率和为 1,选最大的)
多标签 → Sigmoid(每个类独立判断,可多选)

这个区别看似简单,但输出层选错了训练会完全学不动。


三、实验:七组对照

数据集是 CLUE / TNEWS 今日头条中文新闻标题,15 分类,训练集 53,360 条。

先看数据:两个必须注意的事实

① 类别极度不均衡

最多类   科技  5,955 条(11.2%)
最少类   证券    257 条(0.5%)
不均衡比 23.2 倍

验证集里「证券」只有 45 条。 这个数字要牢记——后面所有关于证券类指标的讨论都建立在这 45 条上,波动天然很大。

② 文本极短,max_length 有优化空间

字符长度:均值 22.1,P95 = 32,P99 = 39
max_length=64 时截断比例:0.00%

默认的 max_length=64 一条都没截断,实际 48 就够。注意力复杂度是 O(L²),64→48 能省约 44% 的注意力计算量——这是个免费的优化点。

数据本身有噪声

我从数据里随手挑了几条,发现标签本身就不干净——有些标题从人的角度看也分不清该归哪一类。这解释了后面所有模型的准确率天花板:不是模型不够强,是数据的上限就在那。

这也是我这周学到的一条经验:跑模型之前先看数据。如果我一上来就调参,会一直纳闷为什么怎么调都上不去。


四、最反直觉的结果:LoRA 赢了全参微调

用 Qwen2-0.5B-Instruct 做 SFT,对比 LoRA 和全参微调:

LoRA全量微调
学习率2e-42e-5(必须比 LoRA 小 10 倍)
可训练参数0.22%100%
准确率0.5700(285/500)更低
格式错误率0.4%0.4%

全参微调输了。

这和「全参微调上限更高」的常识相反。我的理解是:

LoRA 只训 0.22% 的参数,这个约束本身就是一种强正则化。 它没有足够的自由度去背训练集,反而泛化得更好。

训练过程也能看出来——全参微调的 train_loss 掉得更快,但验证集表现更差,是典型的过拟合特征。

结论:LoRA 的价值不只是「省显存」。在小数据场景下,它本身就是效果更好的方法。

顺带一个对比:zero-shot 的格式问题

准确率格式错误率
zero-shot29.0%29.0%
LoRA SFT57.0%0.4%

zero-shot 的格式错误率高达 29%——模型经常不按要求输出类别名,而是加一堆解释。SFT 最直接的收益之一就是让输出格式变得可靠,这一点在做 Agent 时特别重要(工具调用最怕格式不稳定)。


五、三种池化方式的对比

池化方式表现
[CLS]基线
Mean Pooling略优
Max Pooling相近

差距不大。这类「选哪个更好」的问题,跑一遍比查资料快——而且结论只对你自己的数据成立。

另外我还跑了一组加权损失(按类别频率倒数加权)来对抗不均衡。效果是尾部类别的召回上来了,但整体准确率略降——这是个取舍,不是免费午餐。


这周的收获

1. 先看数据,再调模型。

如果不是先跑了数据探查,我不会知道:标签本身有噪声(决定了天花板)、max_length 可以砍掉 25%(免费优化)、验证集某个类只有 45 条(决定了哪些数字不可信)。

2. 「常识」要在自己的数据上验证。

「全参微调效果更好」是常识,但在我这个 5 万条数据的场景下不成立。方法的优劣依赖数据规模和任务特性。

3. 分类任务在 Agent 时代没有过时,只是换了位置。

它从「终端产品」变成了「系统里的一个组件」——路由、过滤、调度。延迟和成本上的两三个数量级差距,决定了这个位置大模型替代不了。

下周是序列标注(NER),要做 BERT + CRF。

相关文章