SemIf 校准指南为直接评分器逐工作负载拟合温度缩放Temperature Scaling的完整方法与复现【免费下载链接】SemIfSemantic ifs from open models, on a 3090 at home. Independent; not affiliated with Jev or TypeSafe.项目地址: https://gitcode.com/gh_mirrors/op/SemIfSemIf 是一个用开源模型在本地如 RTX 3090实现语义 if 判断的研究项目其直接评分器direct scorer一次前向传播即可读出运行时定义选项的类型化概率。但正如 docs/METHOD.md 明确指出的那样Softmax over allowed tokens is conditional on the supplied alternatives; it is not calibrated operational confidence——这些概率是条件于给定选项且未校准的置信度数字本身不能直接当作可信度使用。本文以 docs/CALIBRATION.md 为核心完整讲解 SemIf 如何通过一个每工作负载的后验温度缩放层per-workload post-hoc temperature scaling让概率阈值真正具有操作意义并给出源码级实现原理、实验证据与可直接运行的复现命令。校准在整个管线中的定位一个独立的标注层在 SemIf 中校准不是对评分模型的修改而是一个完全独立的额外步骤原生评分器native scorer、其提示词以及所有已提交的原始预测committed raw predictions一律保持不变校准层只消费预测文件中已携带的option_logits字段拟合一个温度标量T并输出校准后的概率校准后的预测文件如results/raw/calibration/direct-wanli256.calibrated.jsonl是新增产物不会回写原始预测。这一点在 benchmarks/calibrate.py 的模块文档中有明确表述A separate labeled layer: it never touches the native scorer. It reads committed prediction logits, fits a single scalar T against gold labels, and reports honest group-disjoint out-of-fold calibration.方法单个标量 T 的最小化 NLL 拟合校准公式每个工作负载workload只拟合一个标量T校准后的概率为calibrated_probability softmax(option_logits / T)其中T在该工作负载的所有标注行上通过最小化平均负对数似然mean NLL来拟合。在 benchmarks/calibrate.py 中fit_temperature使用黄金分割搜索golden-section search在[0.05, 20.0]区间内迭代 60 次求解NLL对1/T是凸的因此搜索是安全的def fit_temperature(pairs, bounds(0.05, 20.0), iterations60) - float: # golden-section search minimizing mean NLL over T为什么 argmax 永远不会移动单调性保证除以T是单调变换所以对任意两个选项的 logit 相对排序保持不变if logit_a logit_b, then logit_a / T logit_b / T (T 0)因此校准不会改变任何一行被选中的选项——accuracy、balanced accuracy 以及所有决策类指标在校准前后完全一致唯一改变的是置信度。这个性质在代码里被显式保护check_temperature要求温度必须是有限且为正的benchmarks/calibrate.py否则除以温度可能翻转 argmax测试 tests/test_calibrate.py 会拒绝0、负数、inf、nan四种非法温度。为什么是单标量而不是逐类校准器SemIf 的选项是运行时定义且数量可变的每次请求的 options 可以不同因此逐类的 Platt scaling、vector scaling、matrix scaling 等方法在这里不适用类集合不固定在这些样本量下144256 行单个标量也是数据效率最高的选择——参数越少过拟合风险越低。数据合约gold 与 predictions 如何配对校准的输入是两组 JSONL 文件通过id关联benchmarks/calibrate.py 的load_pairsgold 文件如benchmarks/data/authored144.jsonl每行包含id、family、group_id、options、label、state、question等字段其中label是正确选项在options中的整数下标group_id用于分组不泄漏的交叉验证predictions 文件如results/raw/predictions/direct-authored144.jsonl每行包含id、option_ids、option_logits以及模型信息Qwen/Qwen3.5-4B、revision、dtype 等和时序字段。load_pairs会做严格的合法性校验校验项行为gold 中出现重复id抛出ValueErrorgold 行缺少label或携带target_distribution跳过该行软标签/分布标签需要分布感知处理不做标量缩放gold 的选项 id 重复或label越界抛出ValueError预测的选项 id 与 gold 的选项集合不一致抛出ValueErroroption_logits与option_ids长度不匹配或含非有限值抛出ValueError两个文件没有共享的硬标签行抛出ValueError对应测试覆盖了这些拒绝路径tests/test_calibrate.py例如选项集不匹配、重复 gold 行、非有限 logits。校准效果三个工作负载的实验证据主结果表校准在三个已冻结的工作负载上评估ECEExpected Calibration Error期望校准误差采用等宽 bin、top-label定义benchmarks/calibrate.pyWorkloadRowsModel accFittedTECET1ECE own-T(out-of-fold)CI-separated?authored (owned)1440.8061.230.0680.038noWANLI (NLI)2560.6372.500.2080.069yesEvery (labeled)1540.9421.710.0500.047no这些数字与已提交的数据文件逐一对应results/raw/calibration/authored144.json中shipped_temperature1.2342、ece_uncalibrated.value0.0678、ece_calibrated_out_of_fold.value0.0384results/raw/calibration/summary.json 中wanli256的own_temperature2.4990、ece_own_temperature_out_of_fold0.0691every154的own_temperature1.7086。关键发现WANLI 的强过度自信被显著修正最重要的结论在 WANLI 上模型报告高置信度但实际正确率只有约 64%T≈2.5。而且这个温度在 5 折交叉验证中稳定在2.42.68见 results/raw/calibration/wanli256.json 的fold_temperatures2.517、2.487、2.395、2.677、2.427说明不是对特定折的过拟合。温度缩放把 WANLI 的 ECE 从0.208 降至 0.069且两者的 95% bootstrap 区间完全不重叠improvement_ci_separated: true——这是一个真实、有统计依据的改进。authored 与 Every本来就近校准收益有限authored拟合出的T1.23相对温和ECE 本来就低0.068校准后区间与未校准区间重叠improvement_ci_separated: false改进不显著Every注意其T1.71并不接近 1但让它几乎没有收益的是极小的起点 ECE0.050而不是温度本身——置信度与准确率已经高度一致没什么可修。评估协议组不相交的 5 折交叉验证需要特别强调 ECE 是如何诚实地报告的拟合用全部标注行shippedT是部署值但ECE 报告的是 out-of-foldOOF值——每个折只用训练折拟合T再在留出折上评分折按group_id划分组不相交这样保持语义的变体same group 的行不会泄漏进拟合——fold_map用固定种子217做确定性分配benchmarks/calibrate.pyECE 的 95% 区间通过对源组做 1000 次有放回重采样bootstrap得到bootstrap_eceseed217而不是对单行重采样每个报告文件results/raw/calibration/{authored144,wanli256,every154}.json都完整提交了fold_groups精确的group_id → fold映射、逐折温度、reliability bins、per-family ECE 与 caveats可独立审计无需依赖种子重推。为什么是每工作负载一个温度而不是一个合并温度拟合温度差异悬殊三个工作负载的拟合温度差异很大authored 1.23、WANLI 2.50不存在一个单一标量能同时匹配两者——这就是逐工作负载而非全局一个 T的直接理由。负控制实验合并温度pooled temperature为了验证每工作负载拟合确实优于合并拟合项目设计了严格的负控制合并侧在全部工作负载的行上拟合温度而不是每个工作负载各拟合一个关键设计两侧使用完全相同的已提交逐工作负载折分配fold_groups因此每一行的 own-T与 pooled-T评分只在训练范围上有差异仅自己工作负载 vs 所有工作负载绝不会因为落在不同的折里而不同合并侧也是按折拟合的5 个折温度 ≈1.922.02若被迫在所有行上拟合单个值则为 ≈1.97见 results/raw/calibration/summary.json所以这是合并的逐折温度而非全局固定 1.97。结果如下均 OOFWorkloadECE own-TECE pooled-T(fold-wise, OOF)paired Δ 95% CIauthored0.0380.081[-0.012, 0.073]WANLI0.0690.067[-0.043, 0.047]Every0.0470.053[-0.018, 0.030]配对 Δ 的 95% 区间由paired_bootstrap_delta计算按共享组重采样行级配对差值benchmarks/calibrate.pysummary.json中的pooled_temperature_significantly_worse标志只有在区间完全排除 0 时才为 true。诚实性说明三个配对区间都包含 0所以在当前样本量下合并温度并没有被证明显著更差——这个控制是证据不足而不是证明了合并有害更值得注意的是 WANLI 的 pooled ECE0.067甚至略低于其 own-TECE0.069因为NLL 拟合最小化的是 log-loss而不是 OOF ECE所以逐工作负载拟合并不能保证在 ECE 上必胜逐工作负载拟合的论据是① 它本来就是预期的部署方式在决策真正运行的工作负载上校准② 拟合温度差异悬殊1.23 vs 2.50。这不是一个 OOF-ECE 优势的声明文档对此保持了明确的自律。校准启用了什么让阈值真正有意义校准的价值在于置信度阈值只有在置信度≈准确率时才具有操作意义。以 WANLI 风格的原始得分为例设置0.8的截断阈值是无意义的——模型声称 90% 置信度时实际正确率只有约 64%。经过每工作负载的温度缩放后置信度与准确率紧密贴合于是自动决策 vs 人工复核auto-decide-versus-review这类门控就有了真实可用的操作点。需要明确边界校准并没有接入 benchmarks/evaluate.py 的screening_gate——那个门被冻结在 96 行的 authored 伪造筛查集上每组四个变体、三个特定 family不运行于 WANLI 或 Every其语义保持不变为其他工作负载提供通用的校准阈值门是未来工作。已知上限与未来工作单标量只能修正整体过/欠置信不能修正工作负载内部误校准的形状authored 的小 familyn48在校准后没有可靠的改进results/raw/calibration/authored144.json 显示candidate_selection的 per-family ECE 甚至从 0.124 升到 0.131范围仅限于硬标签行WANLI 与 Every 的 gold 由固定的、经哈希校验的上游源重建不在本仓库重新分发需先执行获取步骤见下节Every 工作负载混合了类别判断与检索两类行检索行目前在其单个相关/不相关标签上被校准但其置信度本质上是排序风格的一个 per-family 的T才能将两类分离分布标签distribution-labeled的 TypeSafe 行被明确排除——它们需要分布感知的处理而不是标量缩放load_pairs中target_distribution非空的行会被跳过。完整复现从源数据到校准报告第一步获取并重建固定上游数据WANLI 与 Every 的 gold 由固定版本、哈希校验过的上游源重建见 benchmarks/README.md 与 THIRD_PARTY.md不在仓库内重分发python benchmarks/fetch_sources.py --output build/sources python benchmarks/build_wanli.py --source build/sources/wanli-test.jsonl --selection benchmarks/manifests/source-selection.jsonl --output build/gold-wanli256.jsonl python benchmarks/build_every.py --archive build/sources/every-source.zip --experiments build/sources/every-experiments.json --selection benchmarks/manifests/source-selection.jsonl --output-dir build/everybenchmarks/build_wanli.py 从固定的 WANLI test 集按 benchmarks/manifests/source-selection.jsonl 的选择清单重建恰好 256 行脚本内置len(rows) ! 256断言并把 WANLI 的三分类标签映射为 SemIf 的三选项entailment→supported、neutral→insufficient、contradiction→contradicted保留source_id、source_seed_id、revision等 provenancebenchmarks/build_every.py 从上游 zip 与实验 JSON 中重建204 条推理行 154 条作者标注行同样内置数量断言len(inference) ! 204 or len(gold) ! 154即报错。第二步对每个工作负载拟合温度并生成报告与校准预测python benchmarks/calibrate.py --gold benchmarks/data/authored144.jsonl --predictions results/raw/predictions/direct-authored144.jsonl --report build/authored144.json --calibrated-out build/direct-authored144.calibrated.jsonl python benchmarks/calibrate.py --gold build/gold-wanli256.jsonl --predictions results/raw/predictions/direct-wanli256.jsonl --report build/wanli256.json --calibrated-out build/direct-wanli256.calibrated.jsonl python benchmarks/calibrate.py --gold build/every/gold154.jsonl --predictions results/raw/predictions/direct-every204.jsonl --report build/every154.json --calibrated-out build/direct-every204.calibrated.jsonl第三步生成跨工作负载汇总含合并温度负控制python benchmarks/calibrate.py --manifest results/raw/calibration/workloads.json --summary build/summary.jsonresults/raw/calibration/workloads.json 是复现所用的 manifest它以{name: {gold: ..., predictions: ...}}的形式声明三个工作负载的路径其中build/gold-wanli256.jsonl、build/every/gold154.jsonl等build/路径由上面的构建步骤产生。--manifest模式会调用cross_workload_reportbenchmarks/calibrate.py输出每工作负载的 own-T与 pooled-T对比及配对 Δ 95% 区间。第四步可选不重拟合直接应用已选定的温度如果已经有选定的温度、且不需要 gold 数据或重拟合可直接应用python benchmarks/calibrate.py --predictions predictions.jsonl --temperature 1.23 --calibrated-out calibrated.jsonl--temperature分支会跳过build_report测试 tests/test_calibrate.py 验证了这一点调用apply逐行把probabilities重算为softmax(logits / T)并为每行附加calibration: {method: temperature_scaling, temperature: T}字段见 results/raw/calibration/direct-wanli256.calibrated.jsonl 的实际输出。apply会先验证所有输入行再创建输出文件benchmarks/calibrate.py避免留下看似完整实则残缺的中间产物。自检argmax 不变性与 OOF 改进对已提交的 authored 数据做内建自检断言温度未改变任何 argmax且 OOF ECE 确有下降python -c import sys; sys.path.insert(0,benchmarks); import calibrate; calibrate.demo()demo()benchmarks/calibrate.py在已提交的benchmarks/data/authored144.jsonl与results/raw/predictions/direct-authored144.jsonl上执行完整流程并打印类似ok: T1.234 ECE 0.068 - 0.038 (out-of-fold) acc unchanged0.806的结果对应的单元测试 tests/test_calibrate.py 也独立断言了T前后的correct序列完全一致。关于已提交产物的说明文档中提到的报告与summary.json是上述命令的冻结输出frozen outputs仓库中已提交的对应文件为逐工作负载报告results/raw/calibration/authored144.json、results/raw/calibration/wanli256.json、results/raw/calibration/every154.json跨工作负载汇总results/raw/calibration/summary.json校准后的预测文件results/raw/calibration/direct-{authored144,wanli256,every204}.calibrated.jsonl。校准层只依赖 numpy离线在 CPU 上运行已提交的预测本身就带有option_logits因此不会加载任何模型从 benchmarks/calibrate.py 的依赖可以看到这一点。小结SemIf 的温度校准是一个小而完整的工程样本单一标量 最小化 NLL 组不相交 OOF 评估 bootstrap 区间 配对负控制 冻结产物把模型置信度变成有操作语义的概率阈值。核心要点可归纳为独立性校准层不触碰原生评分器只消费已提交的option_logits单调性softmax(logits/T)不改变 argmax所有决策指标前后一致只有置信度移动证据WANLI 的 ECE 从 0.208 降到 0.069 且 bootstrap 区间分离是统计上站得住的改进authored 与 Every 收益有限且诚实标注边界单标量修正不了工作负载内部的形状误校准分布标签行需分布感知处理通用校准阈值门仍属未来工作可复现从fetch_sources到calibrate.py再到demo()自检全部命令与冻结产物一一对应。如需了解校准层所服务的直接评分器本身条件概率如何产生、提示词与指标口径可继续阅读 docs/METHOD.md 与 docs/RESULTS.md完整的基准套件说明见 benchmarks/README.md。【免费下载链接】SemIfSemantic ifs from open models, on a 3090 at home. Independent; not affiliated with Jev or TypeSafe.项目地址: https://gitcode.com/gh_mirrors/op/SemIf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
