一块单独的显卡与一整排计算卡之间隔着一条画满误差带的通道

一、算力是真的省了,风险只是换了形态

公开报道里那组“一块显卡做完了几千块计算卡的活”的量级对照,我们的读法很固定:它说明被对照的那一侧是暴力式的直接求解,而这种求解在稍大一点的体系上就退化成无法用于工程的时间尺度。这个量级只用来定位瓶颈在哪里,据公开报道的数字不作为本篇任何判断的依据,更不能出现在给客户或内部立项的性能承诺里。

真正要在评审桌上说清楚的是另一件事。用统计模型替代精确求解,也就是通常所说的代理模型,省下的机时是实打实的;同时它把风险的性质换掉了。过去的问题是“算不完”,算不完没人签字,项目自然排队等机器。现在的问题是“算得出来,却不可信”。算得出来意味着会有人拿它做筛选,会有人把它写进汇报,会有人在没留参考值的地方把它当作结论。前者是排期问题,后者是责任问题,两种问题的处理方式完全不同。我们接受这类模型的理由和我们限制它的理由其实是同一条:它便宜。便宜到可以被大量调用,而大量调用恰恰是错误被放大的地方。

二、三类可用性前提,每一类都要配一个验证动作

代理模型能不能用,不取决于它在训练集上多准,而取决于下面三件事有没有被定义清楚。我们把它做成评审表,缺任何一行就不进入上线流程。

前提 必须写清的内容 配套验证动作
训练覆盖的输入分布 描述符的取值范围、体系规模的上下限、元素组合与结构族是否出现过 把待测输入投影到训练集的描述符分布上,统计落在边缘与外部区域的样本比例,并对边界样本做一次参考方法的短程对照
外推时的失效形态 是整体偏移、方差放大,还是对某类结构系统性给错方向 按体系规模与结构族分桶,逐桶出误差曲线,禁止只报一个全局平均偏差
误差能否用参考方法标定 在哪些输入位置上存在合理机时内可算出的参考值 每桶留出若干可标定格点,模型值与参考值成对存档,作为长期回归基准

三行里最容易糊过去的是第二行。失效形态不是“误差多大”,而是“误差往哪个方向、在什么区域偏”。方向性偏差在排序任务里不会被平均掉,它会把一整类候选系统性地压到后面,而这类候选恰好是模型没见过的类型。等人们发现漏斗底部少了东西,往往已经过了可以做实验验证的窗口。

三、“复杂度下降”这句话先问三件事

任何把某个计算复杂度显著降低的说法,落到自己的场景之前要过三道问题。

第一,比的是同一精度目标还是同一时间预算。同一时间预算下的对照只说明谁在给定机时里跑得更远,不说明谁更接近真值;同一精度目标下的对照才和结论可信度有关。两个口径的结论经常相反,而公开材料里通常只给一个,不说明是哪一种。

第二,被比较的传统方法有没有被认真优化过。直接求解的实现质量跨度很大,基组选择、截断策略、并行效率、是否用了行业内常见的加速手段,任何一项偷懒都会让“我们比传统方法快”变成比一个稻草人快。评审时要求把对照实现的运行环境与参数一并给出,写不清楚就当作未对照。

第三,两条成本曲线的形状各是什么。传统方法的成本随体系规模通常增长得很陡,模型侧的成本大致是先高后平。两条曲线会在某个规模处相交,相交点之前用传统方法更稳,之后代理模型才有性价比。这个问题的答案决定你日常处理的规模是否落在值得上模型的那一段,也决定它更适合做大体系的粗筛还是小体系的替代。

把速度数字翻译成决策语言,我们固定走三步。先问业务需要的到底是筛选还是终判,两者对误差的容忍度差一个量级。再问这个误差能否被容忍、由谁定容忍值,答案不能是“模型自己的指标”。最后问错判的下游代价:漏掉一个真正的好候选损失多大,多算一百个平庸候选损失多大。这两个代价一比,该把漏检压到什么程度就不是玄学了。

四、筛选与终判的分工,加上四条硬护栏

分工只有一句:筛选阶段可以用代理模型,终判阶段必须回到可复核方法。筛选允许它犯错,但要求我们清楚它以什么比例犯错;终判要求留下可追溯的输入、参数与方法档位,出错时有人能复查。把终判也交给模型,等于在最贵的一步上放弃了复核能力。

上线时我们只认四条硬护栏。

  • 输入域判定先行。描述符取值范围与体系规模上限写成可执行校验,域外输入直接拒绝,不给一个“看起来也能用”的结果。
  • 按档位给精度承诺并配抽检比例。精度不是一个数,而是“在这个输入域、这一档规模上偏差不超过某个量级”,且要在真实流量里定期用参考方法复查。
  • 每次输出附带不确定度或置信字段,字段不得为空,展示层不得省略它。没有这个字段,用户无法区分“模型很有把握”和“模型没见过这种东西”。
  • 拒绝要有出口。域外样本给一条降级到直接方法的排队路径,否则人们会去改输入绕过判定,这在实际使用中一定会发生,而且比想象中隐蔽。

四条里第三条最容易被工程侧砍掉,理由是“界面放不下”。砍掉的代价是把一个本该带置信度的系统改成不带置信度的系统,事后追责时拿不出证据。

五、验证集怎么分桶,标签成本怎么算

验证集设计最常见的错误是按样本随机划分。随机划分时,同一结构族的样本彼此高度相似,它们会同时出现在训练侧和验证侧,指标自然好看,而这恰恰高估了模型的域外能力,也就是它面对没见过的类型时的表现。正确做法是按桶划分:按体系规模分档,按结构族与元素组合分桶,同一族只出现在一侧;再留出一档高难样本,覆盖更大规模、更少见的组合与更极端的取值,这一档永远不进训练,只用于观察外推。改成分桶之后指标下降不是坏事,它只是把真实情况第一次显示出来。

另一本常被算漏的账是标签。这类模型的高精度标签不是人工标出来的,是算出来的,因此生成标签往往比训练模型本身更贵。要算三项:生成一批标签需要的机时与所用方法的精度档位;生成条件对输入域的覆盖度,它直接决定模型可用域的上限,覆盖不到的地方后面怎么补都补不回来;这批标签的可复用性,同一批标签能服务几代模型。如果换一次架构就要重算一批标签,这项成本得按代摊销,摊完之后经常发现数据侧的账比训练侧大。我们做算力核算时把标签生成单独列成一个科目,不允许混进训练成本,否则每一次架构试错的实际代价都被低估。

六、合同里怎么写,版本里存什么

对客户的一段诚实表述模板大致是这样:本系统在给定输入域内提供排序与预筛能力,在该域内以给定的漏检率与误筛率对候选集合做初筛,终判仍由可复核的直接方法完成。这里两个口径要提前定义清楚。漏检率指真实排序靠前的一定比例候选被模型筛掉的比例;误筛率指送入终判的候选中实际不占优的比例。两者都要写明用什么留出集、什么抽检方式测出,并在合同里约定复测频次。不要在合同里写“取代仿真”,这四个字我们不签,它把责任结构改变了,也把复验的必要性取消了。

组织侧最后一条建议:把这类模型当成模型资产来管,而不是当成一段脚本。三项内容必须进版本记录,分别是输入域定义、标定精度、失效行为。任何一次训练数据变更都要重跑分桶验证,并把新结果与上一版并排存档,两版差异要说得出来。洹拓内部把这三项加一次分桶复跑当作上线门禁,缺任何一项就不出评审。这不是保守,是因为代理模型最大的风险从来不是它算错,而是没有人知道它在哪些地方算错;上面这一整套做法,本质是把“哪些地方算错”变成一条有人长期维护的记录。