1. 为什么我会盯上“rerank + 小模型”这条路线
先说结论:这 16 个实验跑完,我认输了,但不是那种“这条路走不通”的认输,而是“用我最初设想的那种最省事的方式走不通”的认输。这个区别很重要,因为它直接决定了你后面要不要继续投入时间。
事情的起点很朴素。我手上有一个判定类任务,输入是一段文本,输出是一个离散标签,比如“是/否”“合规/不合规”“相关/不相关”这种二选一或者三选一的判断。任务本身不算复杂,但标注数据很少,满打满算几百条,而且正负样本还不太均衡。我第一反应是:这种活儿,用一个大模型直接做 zero-shot 或者 few-shot 判定,效果应该凑合,但成本和延迟都下不来;那能不能用一个小模型来扛推理,再用 rerank 的思路去提升判定质量?
这个想法在逻辑上是成立的。rerank 的本质是“先粗排再精排”,在检索场景里用得最多:先用向量召回一批候选,再用一个更强的交叉编码器对候选重新打分排序。我把它迁移到判定任务上的思路是:让小模型先给出一个初步判定和置信度,然后用一个 rerank 模型对“判定结果 + 原始输入”做二次打分,把那些小模型拿不准的样本挑出来重新决策。听起来很合理,对吧?我一开始也这么觉得。
但两天 16 个实验跑下来,我发现问题不在“思路对不对”,而在于几个非常具体的工程细节上:小模型的判定边界不稳定、rerank 的打分和判定标签之间没有天然对齐、小样本下微调极易过拟合、以及我低估了“判定”和“排序”这两个任务在目标函数上的本质差异。下面我把这 16 个实验拆开讲,重点不是告诉你“我失败了”,而是把每一步的坑和背后的原因说清楚,让你少走两天弯路。
2. 先把任务和方案拆清楚:判定模型到底在判什么
2.1 判定任务和排序任务的本质差异
很多人会把判定和排序混为一谈,因为它们都输出一个分数。但这两者的目标函数完全不一样。排序任务关心的是“相对顺序”,只要正样本排在负样本前面就行,分数的绝对值不重要;判定任务关心的是“绝对边界”,你需要一个明确的阈值把样本切成正负两类,阈值稍微偏一点,准确率就掉一大截。
我最初的设计是:小模型输出一个 logit 或者概率,rerank 模型输出一个相关性分数,然后把两个分数加权融合,再卡一个阈值做判定。问题就出在这里——rerank 模型的分数分布和小模型的概率分布根本不在一个量纲上。rerank 模型在训练时见到的正负样本比例、分数区间,和我的判定任务完全不是一回事。我试过直接加权,也试过先做归一化再融合,效果都不稳定。
提示:如果你要做类似的事,先别急着融合分数。先分别画出小模型分数和 rerank 分数的分布直方图,看看它们的重叠区域在哪里。如果重叠区域很大,说明两个信号本身区分度就不够,融合只会互相拖累。
2.2 小模型选型的现实约束
现在开源小模型确实有不少能用的,但“能用”和“适合你的任务”是两码事。我这次试了几个不同规模的小模型,参数量从 1 亿多到 7 亿左右。选型的核心约束有三个:一是显存,我得保证在单卡上能同时跑小模型和 rerank 模型;二是延迟,判定任务通常要求实时或者准实时;三是小样本微调的稳定性,数据少的时候,模型越大越容易过拟合,但太小又学不动。
我实测下来,参数量在 3 亿到 5 亿之间的模型,在这个任务上是一个比较舒服的区间。再小,语义理解能力明显不够,判定边界很粗糙;再大,微调时 loss 震荡得厉害,几百条数据根本喂不饱它。这里没有绝对标准,你得根据自己的数据量和硬件条件去试。
2.3 rerank 模型在判定任务里的角色定位
我一开始把 rerank 模型当成“第二意见”来用,后来发现它更适合的角色其实是“边界样本的仲裁者”。也就是说,不要让 rerank 参与所有样本的判定,而是只让它处理小模型置信度处于中间地带的那部分样本。这样既能控制延迟,又能把 rerank 的价值集中在最难的那批样本上。
这个思路的转变很关键。我前 8 个实验基本都在尝试“全量融合”,效果一直上不去;后 8 个实验改成“分层决策”,才看到一点希望。虽然最后整体指标还是没有达到我预期的水平,但至少证明了 rerank 在这个任务里不是完全没用,只是用法得对。
3. 16 个实验的完整记录与关键发现
3.1 实验分组与变量设计
我把 16 个实验分成了四组,每组 4 个,变量分别是:小模型是否微调、rerank 是否参与、融合策略、阈值选择方法。这样分组是为了尽量隔离变量,避免“改了三个地方结果变好了但不知道是哪个起的作用”这种常见错误。
| 组别 | 小模型状态 | rerank 参与方式 | 融合策略 | 阈值方法 |
|---|---|---|---|---|
| A 组 | 未微调 | 不参与 | 无 | 固定 0.5 |
| B 组 | 未微调 | 全量参与 | 加权平均 | 固定 0.5 |
| C 组 | 微调 | 不参与 | 无 | 验证集搜索 |
| D 组 | 微调 | 分层参与 | 分层决策 | 验证集搜索 |
A 组基本是 baseline,用来确认“不微调的小模型到底能做到什么程度”。B 组是验证“rerank 全量融合有没有用”。C 组是看“微调能带来多少提升”。D 组是我最后收敛到的方案。
3.2 A 组:不微调的小模型比想象中脆弱
A 组的四个实验,我换了不同的小模型和不同的 prompt 模板。结果很一致:不微调的小模型在判定任务上,准确率大概在 60% 到 70% 之间晃。这个水平意味着什么?意味着它比随机猜好一点,但离可用还差得远。
更麻烦的是,它的错误分布很不均匀。对于表述清晰的样本,它判得还行;但只要输入稍微绕一点、或者出现训练时没见过的表达方式,它就会给出一个非常自信但完全错误的判定。这种“自信的错误”在后续融合时特别致命,因为如果你用置信度做加权,这些错误样本的权重反而很高。
注意:不要只看整体准确率。一定要把错误样本单独拉出来看,按置信度分桶统计。如果高置信度桶里的错误率也很高,说明模型的校准很差,这时候任何基于置信度的融合策略都会出问题。
3.3 B 组:rerank 全量融合为什么反而拖后腿
B 组是我最寄予厚望的一组,结果也是最让我意外的。rerank 全量参与之后,整体准确率不仅没升,反而比 A 组还低了几个点。我一开始以为是融合权重没调好,后来把 rerank 分数单独拿出来看,才发现问题所在。
rerank 模型在排序任务上训练时,见到的负样本大多是“语义相关但不完全匹配”的样本,所以它对“部分相关”的样本会给一个中等偏高的分数。但在我的判定任务里,这些“部分相关”的样本恰恰是应该被判为负类的。也就是说,rerank 模型的分数和我的判定标签之间存在系统性的偏移。
我试过对 rerank 分数做线性变换去对齐,但小样本下拟合出来的变换参数很不稳定,换一批验证数据就失效。这让我意识到,rerank 模型不是不能用在判定任务里,而是不能直接把它当成一个“判定分数”来用。
3.4 C 组:微调有效,但过拟合来得很快
C 组的结果是四组里最好的,微调之后小模型的准确率能到 80% 左右。但这个提升是有代价的。我用了几百条数据做微调,训练集上 loss 很快就降到很低,但验证集上的 loss 在几个 epoch 之后就开始往上走。典型的过拟合曲线。
我试过几种缓解手段:降低学习率、加 dropout、早停、数据增强。其中早停最有效,基本上在验证集 loss 最低的那个 checkpoint 停下来,效果最稳。数据增强也有帮助,但增强方式得贴合任务,不能随便同义词替换,否则会改变判定标签。
提示:小样本微调时,验证集的划分要特别小心。如果验证集太小,早停的时机很容易选偏。我建议至少留出 20% 的数据做验证,并且做多次随机划分取平均,看看早停的 epoch 是否稳定。
3.5 D 组:分层决策是唯一看到希望的方案
D 组的思路是:小模型先对全量样本做判定,同时输出置信度;置信度高于某个上界的,直接采纳小模型结果;低于某个下界的,直接判为负类或者进入人工复核;只有中间地带的样本,才交给 rerank 模型做二次判定。
这个方案的关键在于两个阈值的选取。我一开始用固定阈值,效果一般;后来改成在验证集上搜索,让整体指标最优,效果明显好一些。最终 D 组的准确率比 C 组高了大概两个点,虽然提升不大,但至少证明了 rerank 在边界样本上是有价值的。
不过这里有个隐患:中间地带的样本比例如果太高,延迟就会上去;如果太低,rerank 又发挥不了作用。我实测下来,中间地带占比在 15% 到 25% 之间比较合理,具体取决于你的延迟预算。
4. 我踩过的坑和对应的排查方法
4.1 分数融合的陷阱:量纲不对齐
这是我最开始踩的坑。小模型输出的是概率,rerank 输出的是相关性分数,两者量纲完全不同。我试过直接加权、先归一化再加权、先排序再融合,效果都不稳定。后来我放弃了分数融合,改成“分层决策”,才绕开了这个问题。
如果你非要做分数融合,我的建议是:先把两个分数分别转换成“在该分数区间内的百分位”,再做融合。这样至少能保证两个信号在同一个尺度上。但即便如此,小样本下百分位的估计也很不稳定,慎用。
4.2 小模型置信度校准:别信它说的“我很确定”
小模型的置信度普遍偏高,尤其是微调之后,模型会变得过度自信。我做过一个统计:在验证集上,小模型给出 0.9 以上置信度的样本里,仍然有大约 15% 是错的。这个错误率在融合时会被放大。
校准的方法有几种:温度缩放、Platt scaling、isotonic regression。我试了温度缩放,实现简单,效果也还行。但校准参数同样需要验证集来拟合,小样本下要注意别过拟合校准参数。
4.3 rerank 模型的选择:不是越大越好
我试过不同规模的 rerank 模型,发现参数量大的 rerank 模型在这个任务上并没有明显优势,反而因为分数分布更“平滑”,边界样本的区分度更差。中等规模的 rerank 模型,分数分布更“陡”,反而更适合做边界仲裁。
这个结论可能和具体任务有关,但至少说明一点:rerank 模型不是越大越好,你得看它的分数分布是否适合你的判定边界。
4.4 数据标注质量:小样本下每个样本都很贵
几百条数据里,如果有几十条标错了,对最终效果的影响是致命的。我在实验中途重新检查了一遍标注,发现大概有 5% 的样本存在歧义或者错误。修正之后,C 组和 D 组的指标都有明显提升。
小样本场景下,数据质量比数据数量重要得多。与其花时间去找更多数据,不如先把现有数据清洗一遍。
4.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决思路 |
|---|---|---|---|
| 融合后指标下降 | 分数量纲不对齐 | 分别画分数分布直方图 | 改用分层决策或百分位融合 |
| 微调后验证集 loss 上升 | 过拟合 | 看训练/验证 loss 曲线 | 早停、降学习率、加正则 |
| 高置信度样本错误率高 | 置信度未校准 | 按置信度分桶统计错误率 | 温度缩放或 Platt scaling |
| rerank 分数区分度差 | 模型规模不匹配 | 看分数分布的重叠区域 | 换中等规模 rerank 模型 |
| 中间地带样本过多 | 阈值选取不当 | 统计各区间样本占比 | 在验证集上搜索阈值 |
5. 如果重新来过,我会怎么调整方案
5.1 先做数据清洗,再谈模型选型
我这次是先选模型再洗数据,顺序反了。小样本场景下,数据质量是天花板,模型只是逼近这个天花板的手段。如果数据本身有 5% 的错误,你再怎么调模型,上限也就那样。所以如果重新来过,我会先把数据过一遍,把歧义样本和错误样本清理掉,再开始选模型。
5.2 把 rerank 定位成“边界仲裁”,而不是“第二意见”
全量融合的思路听起来很美,但实际做下来,rerank 在简单样本上带来的噪声大于收益。把它限制在边界样本上,既能控制延迟,又能让它的优势发挥出来。这个定位的转变,是我这 16 个实验里最有价值的收获。
5.3 阈值搜索要用交叉验证,不要只切一次验证集
我一开始只切了一次验证集,阈值搜出来的结果换一批数据就失效。后来改成 5 折交叉验证,每折都搜一次阈值,取平均,稳定性好很多。虽然计算量上去了,但小样本下这点计算量换来的稳定性是值得的。
5.4 接受“小模型 + rerank”不是万能方案
最后说点实在的。小模型加 rerank 这套组合,在检索和排序场景里很成熟,但迁移到判定任务上,并不是即插即用的。它需要你对任务目标、分数分布、阈值选取有比较深的理解,还需要足够的数据来支撑微调和校准。如果你的数据只有几十条,或者你的判定边界非常模糊,那这套方案可能不适合你,老老实实上大模型或者规则引擎可能更划算。
我这次认输,认的是“用最省事的方式复现一个判定模型”这个想法。但如果把问题拆细,把每一步的假设都验证一遍,这条路还是能走通的,只是需要的时间和精力比预期多得多。希望这篇记录能帮你少走一点弯路。