10.1 zero-shot 近随机


10.1 zero-shot 近随机

本节摘要:官方 README 里最显眼的一句诚实声明:底座检查点不做微调直接使用,效果接近随机猜。本节先解释成因——laya 的检查点是 BERT 级编码器(第 2 章),参数量与预训练目标决定了它没有大模型那种广域先验;再划定例外——简单二分类、选项语义差异极大的任务可能勉强可用,但「勉强可用」不是上线理由;然后给一份部署前的最小验证集自测清单:五十到两百道题、覆盖真实分布、按类型分桶判定;最后用两个误用案例说明「laya 是微调框架,不是开箱模型」这句话的分量。这一节是全书的守门员:跳过它,后面所有章节都建在流沙上。

学习目标

  • 从参数量与预训练目标两个角度解释 zero-shot 近随机的成因。
  • 说出「例外任务」的判断条件,以及为什么例外也不该免检。
  • 按最小验证集清单完成上线前自测。
  • 识别两个典型误用:当通用分类器上线、拿演示效果当生产效果。

一、成因:为什么底座接近随机猜

第 2 章介绍过三个检查点的底座:laya 421M 基于 ModernBERT-large,laya-multilingual 322M 基于 mmBERT。两个数字先摆出来(官方口径):421M 与 322M 的参数量,比主流生成式大模型小三个数量级。

角度 生成式大模型 laya 底座检查点
参数量 数十亿到数千亿 322M~421M(官方口径)
预训练目标 广域语言建模,见过海量任务形态 编码器表征,任务形态靠微调注入
zero-shot 表现 靠指令泛化,多数任务可用 近随机(官方诚实声明)
微调后表现 提升有限(已经很强) 质变:typed-decisions 0.362→0.766(官方口径)

关键在第二行:生成式大模型的广域先验是在预训练里「顺便」获得的,而 laya 的设计哲学是把这些先验全部让渡出去,换取毫秒级延迟与 CPU 可跑的部署形态(第 0.1 节的三轴)。所以近随机不是缺陷被藏起来了,而是架构选择的直接代价——官方把它写在 README 显眼处,本节只是把这句话翻译成工程语言。

两条能力曲线的分歧(示意,非精确数值) 效果 │ 生成式大模型(预训练即高峰) │ ─────────────────── │ ────┘ │ ────┘ laya(微调后才起飞) │ ──┘ ────────────── │ ──┘ ────┘ │随机线──┴──────────────────────▶ 投入(微调数据/轮次) └───────────────────────────── 结论:两条曲线的交叉点之后,laya 用小得多的算力拿到任务内的精度 ​

二、例外与「为什么例外也不该免检」

实践中确实存在底座勉强能用的任务,条件大致三条:输出空间极小(是/否两档);选项之间语义差异极大(「合规」与「涉嫌违法」而不是「较好」与「略好」);输入文本短且模式固定。三条全中的任务,底座可能略高于随机。

但「略高于随机」依然不够上线资格,原因有二:其一,略高于随机意味着错误仍然过半,而决策场景的错误是有业务代价的(第 7.3 节的代价矩阵);其二,你无法区分「模型懂这个任务」和「模型碰巧在这批样本上蒙对」——没有验证集,这两个假设不可分辨。所以例外任务也要走本节第三部分的清单,只是验证集可以小一号。

三、部署前的最小验证集自测清单

最小验证集的目标不是全面评测(那是《Evals 实战:LLM 评测工程》第 07 章《概率系统评测》的领域),而是在上线前用最小成本回答「微调后的 laya 在我的任务上及格了吗」。

# min_eval.py —— 最小验证集自测:按类型分桶统计准确率与弃权率 import json from collections import defaultdict def run_min_eval(model, eval_path, pass_threshold=0.85): buckets = defaultdict(lambda: {"hit": 0, "total": 0, "abstain": 0}) with open(eval_path, encoding="utf-8") as fh: for line in fh: item = json.loads(line) pred = model.predict(item["context"], item["question"], item["options"]) bucket = buckets[item["type"]] # 按问题类型分桶 bucket["total"] += 1 if pred.get("abstained"): # min_confidence 弃权单独计数 bucket["abstain"] += 1 elif pred["choice"] == item["label"]: bucket["hit"] += 1 report, all_pass = {}, True for type_name, stat in buckets.items(): acc = stat["hit"] / stat["total"] ok = acc >= pass_threshold # 阈值按业务代价定(第 7.3 节) all_pass &= ok report[type_name] = { "样本数": stat["total"], "准确率": round(acc, 3), "弃权率": round(stat["abstain"] / stat["total"], 3), "及格": "是" if ok else "否", } return {"分桶报告": report, "全部及格": all_pass} ​

清单本体(标注为工程建议,非官方要求):

清单项 规模建议(示意) 判定
题目总量 50~200 道 覆盖真实分布,别只挑难题
类型分桶 每桶至少 20 道 有任何一桶不及格就不上线
标注来源 业务标注而非模型生成 防止「模型考自己」
与微调集隔离 严格不重叠 重叠即作弊,分数无效
弃权率上限 按业务定(例如 10%) 弃权爆表说明校准或阈值有问题
位置偏差抽查 抽 10 道做打乱重测(第 10.2 节) 概率随位置剧烈漂移要预警

四、两个误用案例

案例一:当通用分类器上线。团队拿到 laya,没做任何微调,直接接进内容审核流,理由是「BERT 应该天然懂分类」。两周后抽检发现错误率过半——这正是底座近随机的表现。正确路径是:圈定审核流里最狭窄的一个子任务(例如「是否涉人身攻击」),构造验证集确认底座不行,微调(第 5 章),再过一遍本节清单。

案例二:拿演示效果当生产效果。演示时用十个精选样本,微调后全对,于是直接放量。问题在于十个样本说明不了分布——长尾问题、混合语言、奇怪措辞都没出现。最小验证集的 50~200 道就是为了把「精选」挤掉,让长尾有机会暴露。

两个案例的共同教训就是本节标题的另一半:laya 是微调框架,不是开箱模型。它的价值主张(第 5.3 节的两个案例)全部建立在「你的数据 + 它的速度」上,跳过第一步就没有后面的故事。

五、常见问题与排查

问题 排查顺序 处置
微调后验证集仍不及格 数据量是否太少(几百条以下,示意量级)→ 标注是否有冲突(同类样本不同标签)→ 题面是否歧义(人工重读 20 条错题) 先清标注再谈数据量;题面歧义的题拆改写
到底多少条微调数据起步 看任务封闭度:类目越少、措辞越规整,所需越少(数百条即可见效果,示意量级) 从封闭子任务起步攒数据,再逐步放开
能不能先拿底座跑着攒数据 可以,但只当「采集期」不当生产 底座判定结果落盘为弱标注候选,人工抽检后再入训练集
验证集为什么不能顺便看微调效果 微调集看效果等于开卷考试,分数无意义 验证集与微调集物理隔离,文件名与流程上都要隔离
简单二分类也不达标 检查是不是把多个判断塞进了一道题(先分情绪再分紧急度) 任务拆分:一道题只问一件事
及格线怎么定 不是拍 0.9:看错误代价(第 7.3 节代价矩阵)与人工兜底成本 代价高的桶线就高;个别难桶单独设线

排查的总原则与第 10.2、10.3 节一致:先怀疑数据与流程,再怀疑模型——微调框架的故障九成在喂数据的那一环。

本节要点回顾

  • 底座 zero-shot 近随机是官方明示的架构代价,不是隐藏缺陷。
  • 参数量与预训练目标是成因;微调是唯一的解药(第 5 章)。
  • 例外任务也要走最小验证集,50~200 道、分桶判定、与微调集隔离。
  • 两个误用——当通用分类器上线、拿演示当生产——的共同解法是先自测再放量。

下一节解决上线后的第一类可信度问题:同样的题目、同样的选项,只因为顺序不同,概率分布就变了——位置偏差怎么测、怎么补。


作者与出处
原作者: 灏天文库
整理: 灏天文库整理
本站整理收录,版权归原作者/开源协议所有;欢迎通过原文链接访问源仓库。
发布者: 作者: 灏天文库 转发
评论区 (0)
U