ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

16个实验后,我为何放弃rerank+小模型做判定任务

16个实验后,我为何放弃rerank+小模型做判定任务

1. 为什么我会盯上“rerank + 小模型”这条路线

先说结论:这 16 个实验跑完,我认输了,但不是因为方向错了,而是因为我把“判定模型”这件事想得太简单了。标题里说的“判定模型”,说白了就是一个能对输入内容做二分类或者多分类判断的模型,比如判断一条评论是不是垃圾信息、判断一段文本属于哪个意图、判断一个工单该不该升级。这类任务在业务里遍地都是,需求量大、迭代频繁,所以大家都想找一个又便宜又快的方案。

我一开始的算盘打得很精:用一个开源小模型做粗筛,再用 rerank 模型做精排,两者配合起来,理论上既能控制成本,又能把准确率拉上去。rerank 这个词这两年热度一直很高,核心思路就是先召回一批候选,再用一个更强的模型对候选重新打分排序。把它用在判定任务上,直觉上完全说得通——小模型先给出一个初步判断,rerank 再对边界样本做二次确认。

但现实给我上了一课。我花了两天时间,跑了 16 组实验,从模型选型、数据构造、阈值调优到误差分析,几乎把能试的组合都试了一遍。最后我发现,这条路不是不能走,而是有几个隐藏的坑,如果不提前想清楚,跑再多实验也是白费。这篇文章就是把这 16 个实验的完整过程、核心发现和踩坑记录摊开来聊,适合正在做判定类任务、考虑用小模型加 rerank 方案的同行参考。

2. 方案整体设计与思路拆解

2.1 判定任务的本质是什么

判定任务和生成任务最大的区别在于,它不需要模型“说人话”,只需要模型给出一个稳定的判断。这听起来简单,但恰恰是这种简单,让很多人低估了它的难度。生成任务你可以容忍一定的多样性,但判定任务不行,同一个输入两次跑出不同结果,业务方直接就会质疑你的系统可靠性。

我在设计实验之前,先把判定任务拆成了三个层次:第一层是特征提取,模型需要从输入里抓到关键信号;第二层是决策边界,模型需要知道什么情况下判正、什么情况下判负;第三层是置信度校准,模型不仅要给判断,还要知道自己有多确定。小模型通常在第二层和第三层上吃亏,因为参数量有限,它对边界样本的区分能力天然弱于大模型。

rerank 的介入点,理论上应该是在第二层和第三层之间。小模型先给出一个粗略的判断和置信度,rerank 对置信度处于中间区间的样本做二次打分。这个思路本身没问题,问题在于 rerank 模型的设计初衷是排序,不是分类。排序和分类虽然数学上有关联,但在实际使用中,两者的输出分布和阈值语义完全不同。

2.2 为什么选小模型而不是直接上大模型

成本是最直接的原因。大模型跑一次推理的成本,小模型能跑几十次。对于判定任务这种需要高频调用的场景,成本差异会被放大到无法忽视的程度。另外,小模型的响应延迟更低,对于实时性要求高的业务,这一点比准确率还重要。

但小模型的问题也很明显。我实测下来,同一个开源小模型在不同判定任务上的表现波动很大。有些任务它能做到 85% 以上的准确率,有些任务连 70% 都费劲。这种不稳定性让它在生产环境里很难直接上线,必须配合某种兜底机制。

我选小模型的时候主要看三个指标:参数量、推理速度和微调成本。参数量决定了它能不能在消费级显卡上跑起来,推理速度决定了它能不能满足实时要求,微调成本决定了它能不能快速适配新任务。这三个指标往往是互相矛盾的,参数量小的模型推理快但准确率低,参数量大的模型准确率高但推理慢。我最后选的是一个 1B 到 3B 区间的模型,这个区间在速度和效果之间相对平衡。

2.3 rerank 在判定任务里的角色定位

rerank 模型通常比小模型大,但比通用大模型小,它的训练目标是对候选列表做精细排序。在搜索场景里,rerank 的效果非常明显,因为它能捕捉到 query 和 document 之间的细粒度交互。但在判定任务里,rerank 面对的不是一个候选列表,而是一个单独的输入,这就导致它的优势很难发挥出来。

我试过两种用法:一种是把 rerank 当成二分类器用,直接看它的打分;另一种是把 rerank 当成置信度校准器用,只对小模型不确定的样本做二次判断。第一种用法的问题在于,rerank 的打分分布和小模型的输出分布不在同一个尺度上,直接比较没有意义。第二种用法的问题在于,你需要先定义什么叫“不确定”,而这个定义本身就需要调参。

提示:如果你打算在判定任务里用 rerank,先想清楚它到底是替代小模型做决策,还是只做置信度校准。这两个定位对应的实验设计和评估指标完全不同。

3. 核心细节解析与实操要点

3.1 数据构造:判定任务的命门

判定任务的数据质量比模型选型重要十倍。我这次实验最大的教训就是,前 8 个实验之所以失败,根本原因不是模型不行,而是数据构造有问题。判定任务的数据通常有两个特点:一是类别不平衡,正样本可能只占 5% 到 10%;二是边界样本多,很多样本人类标注员自己都拿不准。

我一开始用的是公开数据集,跑出来的结果看着还行,但一换到业务数据上就崩了。后来我才意识到,公开数据集的分布和业务数据的分布差异太大,模型在公开数据集上学到的决策边界,在业务数据上完全不适用。这个问题在小模型上尤其明显,因为小模型的泛化能力本来就弱。

我后来自己构造了一批数据,核心思路是分层采样加边界增强。先把样本按置信度分成高、中、低三档,高置信度样本直接用作训练,低置信度样本人工复核后决定去留,中置信度样本做数据增强。数据增强的手段包括同义词替换、句式改写和负样本挖掘。负样本挖掘这一步特别关键,因为判定任务的假阳性往往比假阴性更致命。

数据构造策略优点缺点适用场景
公开数据集直接使用省时省力分布不匹配快速验证
业务数据分层采样分布匹配标注成本高生产上线
边界样本增强提升边界区分度可能引入噪声准确率瓶颈期
负样本挖掘降低假阳性需要额外计算风控类任务

3.2 小模型微调的关键参数

小模型微调看起来简单,但有几个参数直接决定了成败。第一个是学习率,小模型对学习率非常敏感,太大容易过拟合,太小收敛太慢。我实测下来,1B 到 3B 的模型,学习率在 1e-5 到 5e-5 之间比较合适,具体取值要看数据量和任务难度。

第二个是 batch size。小模型的显存占用低,理论上可以用大 batch,但判定任务的数据量通常不大,大 batch 反而容易导致梯度更新不够精细。我最后用的是 16 到 32 的 batch size,配合梯度累积来模拟更大的 batch。

第三个是训练轮数。小模型在判定任务上很容易过拟合,我试过跑 10 轮,第 3 轮之后验证集指标就开始下降。后来改成早停策略,patience 设为 2,效果稳定了很多。

# 小模型微调的核心参数配置示例 training_args = { "learning_rate": 2e-5, "per_device_train_batch_size": 16, "gradient_accumulation_steps": 2, "num_train_epochs": 5, "early_stopping_patience": 2, "warmup_ratio": 0.1, "weight_decay": 0.01, "fp16": True, }

注意:小模型微调时一定要留出独立的验证集,而且验证集的分布要和测试集一致。我见过太多人用训练集的一部分当验证集,结果上线后指标暴跌。

3.3 rerank 模型的接入方式

rerank 模型的接入有两种方式:一种是离线批量打分,一种是线上实时打分。离线批量打分适合对延迟不敏感的场景,可以一次性处理大量样本;线上实时打分适合对延迟敏感的场景,但需要控制 rerank 的调用频率。

我这次实验用的是线上实时打分,因为判定任务通常要求低延迟。但实测下来,rerank 的推理延迟比小模型高出一个数量级,如果每个样本都过 rerank,整体延迟会直接超标。后来我改成只对置信度处于中间区间的样本调用 rerank,调用比例控制在 20% 左右,延迟才降下来。

rerank 的打分需要做归一化,否则和小模型的输出没法比较。我试过 min-max 归一化和 z-score 归一化,最后发现 z-score 更稳定,因为它对异常值不敏感。归一化之后,还需要确定一个融合策略,是把两个分数加权平均,还是用 rerank 的分数直接覆盖小模型的分数。我试过加权平均,权重需要调参;也试过直接覆盖,但覆盖的阈值很难定。

4. 16 个实验的完整实操过程

4.1 实验一到四:基线验证

前四个实验的目的是建立基线。实验一用原始小模型直接推理,不做任何微调,准确率 72.3%。实验二对小模型做全量微调,准确率提升到 81.5%。实验三在实验二的基础上加入 rerank,但 rerank 对所有样本都打分,准确率提升到 83.1%,但延迟增加了 3 倍。实验四只对置信度低于 0.7 的样本调用 rerank,准确率 82.8%,延迟只增加了 40%。

这四个实验让我确认了两件事:第一,小模型微调是有效的,但提升幅度有限;第二,rerank 确实能提升准确率,但全量调用不现实,必须做样本筛选。

4.2 实验五到八:数据策略对比

实验五到八聚焦数据策略。实验五用公开数据集训练,业务数据测试,准确率只有 65.2%,直接崩盘。实验六用业务数据训练,但没做分层采样,准确率 78.4%。实验七加入分层采样,准确率 83.7%。实验八在实验七的基础上加入边界样本增强,准确率 85.1%,但训练时间增加了 60%。

这一轮实验让我意识到,数据策略的收益远大于模型策略。同样的模型,换一套数据构造方法,准确率能差 20 个百分点。边界样本增强虽然费时,但收益是实打实的。

4.3 实验九到十二:rerank 融合策略

实验九到十二专门调 rerank 的融合策略。实验九用简单加权平均,权重 0.5 比 0.5,准确率 84.3%。实验十用网格搜索找最优权重,最后找到 0.3 比 0.7,准确率 85.6%。实验十一用 rerank 分数直接覆盖小模型分数,但只在 rerank 置信度高于 0.9 时覆盖,准确率 85.2%。实验十二用 stacking 方式,把两个分数作为特征训练一个逻辑回归,准确率 86.1%。

stacking 的效果最好,但工程复杂度也最高。它需要额外训练一个元模型,而且元模型的训练数据需要单独构造。如果团队没有成熟的 MLOps 流程,我不建议一上来就用 stacking。

4.4 实验十三到十六:阈值调优与误差分析

最后四个实验聚焦阈值调优和误差分析。实验十三用固定阈值 0.5,准确率 86.1%,但假阳性率偏高。实验十四用 ROC 曲线找最优阈值,准确率 86.8%,假阳性率下降了 30%。实验十五用代价敏感学习,给假阳性更高的惩罚权重,准确率 86.5%,但假阴性率上升。实验十六做误差分析,发现 70% 的错误集中在边界样本上,而且这些样本的 rerank 分数和小模型分数差异很大。

误差分析的结果让我很意外。我原本以为错误主要来自模型能力不足,但实际上,大部分错误来自两个模型的判断不一致。当小模型和 rerank 给出相反判断时,融合策略很难做出正确决策。这个问题不是调参能解决的,它涉及到两个模型的训练目标不一致。

实验编号核心变量准确率延迟增幅关键发现
1原始小模型72.3%基准基线偏低
2小模型微调81.5%基准微调有效
3全量 rerank83.1%+200%延迟不可接受
4筛选 rerank82.8%+40%性价比最高
5公开数据65.2%基准分布不匹配
6业务数据78.4%基准数据质量关键
7分层采样83.7%基准收益明显
8边界增强85.1%+60%训练成本高
9加权平均84.3%+40%权重敏感
10网格搜索85.6%+40%调参耗时
11直接覆盖85.2%+40%阈值难定
12Stacking86.1%+50%工程复杂
13固定阈值86.1%+50%假阳性高
14ROC 阈值86.8%+50%综合最优
15代价敏感86.5%+50%偏保守
16误差分析86.8%+50%边界样本是瓶颈

5. 常见问题与排查技巧实录

5.1 小模型和 rerank 判断不一致怎么办

这是我在实验里遇到的最头疼的问题。两个模型给出相反判断时,融合策略往往失效。我的解决思路是引入第三个信号,比如规则引擎或者人工审核。规则引擎可以覆盖一些明确的边界情况,人工审核则用于处理规则也搞不定的样本。

另一个思路是让两个模型共享部分训练数据,减少它们的判断分歧。我试过用同一批数据分别微调小模型和 rerank,分歧率从 18% 降到了 11%。但这样做有个副作用,就是两个模型的多样性下降,融合的收益也会变小。

5.2 阈值调优为什么总是过拟合

阈值调优过拟合是判定任务的经典问题。你在验证集上找到的最优阈值,换到测试集上往往就不是最优了。根本原因是验证集和测试集的分布有差异,而且这种差异在边界样本上被放大了。

我的应对方法是交叉验证加阈值平滑。先用交叉验证找到多个阈值,然后取这些阈值的平均值或者中位数,而不是直接取验证集上的最优值。另外,阈值不要设得太精细,比如 0.523 这种精度没有意义,取 0.5 或者 0.55 这种粗粒度反而更稳定。

5.3 小模型选型有哪些坑

小模型选型最大的坑是只看参数量不看训练数据。同样是 1B 参数的模型,有的在中文任务上表现很好,有的连基本的中文理解都费劲。选型的时候一定要看模型的训练数据构成,特别是中文数据的占比和质量。

第二个坑是忽略推理框架的兼容性。有些小模型在 HuggingFace 上跑得好好的,换到 vLLM 或者 TensorRT 上就各种报错。选型的时候要提前确认推理框架的支持情况,否则后期迁移成本很高。

第三个坑是低估微调的数据需求。小模型虽然参数量小,但微调仍然需要足够的数据。我实测下来,判定任务至少需要 2000 到 5000 条标注数据,才能让微调效果稳定。数据量低于 1000 条时,微调很容易过拟合。

提示:小模型选型时,先跑一个零样本测试,看看模型在没有微调的情况下能到什么水平。如果零样本准确率低于 60%,说明这个模型的基础能力不够,微调也很难救回来。

5.4 rerank 调用比例怎么定

rerank 调用比例直接决定了成本和延迟。比例太高,成本和延迟都上去了;比例太低,准确率提升有限。我的经验是,先用小模型的置信度分布来确定调用比例。如果置信度低于 0.7 的样本占比 30%,那就先按 30% 调用 rerank,然后逐步调整。

调整的时候要看边际收益。比如从 20% 调到 30%,准确率提升了 1 个百分点,但延迟增加了 50%,那就不划算。从 10% 调到 20%,准确率提升了 2 个百分点,延迟只增加了 30%,那就划算。边际收益递减是必然的,关键是找到那个拐点。

6. 我最后为什么认输了

认输的原因不是方案完全不可行,而是投入产出比不划算。16 个实验跑下来,最好的方案准确率 86.8%,比单纯微调小模型的 81.5% 高了 5.3 个百分点。但这 5.3 个百分点是用双倍的计算资源、三倍的工程复杂度和两倍的维护成本换来的。对于大多数业务场景来说,这个交换不划算。

更关键的是,我意识到判定任务的瓶颈不在模型融合,而在数据质量。同样的融合策略,换一批更干净的标注数据,准确率可能直接提升 10 个百分点。与其在模型融合上死磕,不如把精力花在数据清洗和标注规范上。

另外,rerank 模型的选择也很受限。开源 rerank 模型大多是为搜索场景设计的,直接迁移到判定任务上,效果打折扣。如果要自己训练 rerank 模型,那成本又上去了,还不如直接微调一个大一点的小模型。

我最后的建议是:如果你的判定任务准确率要求不超过 85%,直接用微调后的小模型就够了,简单可靠。如果要求超过 90%,那 rerank 加小模型的组合也很难达到,需要考虑更大的模型或者更复杂的数据策略。如果要求介于 85% 到 90% 之间,可以试试 rerank,但要做好投入产出比的评估。

这个方向我暂时搁置了,但没完全放弃。等开源小模型的能力再上一个台阶,或者 rerank 模型有专门针对判定任务的版本出来,我会再试一次。现在的话,还是先把数据质量搞上去,那个才是真正的杠杆。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进