LLM 分析数据集时,代码执行、统计假设、结果解读任一环节出错都会输出错误结论且无报错,其中解释层最危险——模型会用流畅的语言为错误结果辩护。
让模型分析一个数据集,它会写代码、代码会运行、真实数字会出来,然后一段文字解释这些数字的含义。这三件事必须同时做对——但只有其中一件会在出错时告诉你。
代码可能出错。如果崩溃了你会立即发现,这是良性的情况。危险的情况是代码干净地运行了,但算的不是你要求的东西。
统计可能出错。代码忠实地执行了一个数据违反其假设的程序,或者回答的问题跟你要的不是同一个。没有任何报错;数字本身就不是你想要的证据。
解读可能出错。这是模型最擅长的领域,也是最危险的领域——因为生成一段流畅的结果解释正是它擅长的事,无论结果是否支持这个解释,它都会以同样的自信生成出来。
下面列出的是那些不产生错误但会改变答案的情况。每一种都很常见,没有一种是模型特有的——但人写代码时通常了解数据集,模型则不然。
静默丢行。缺失值在某个环节被默认丢弃了,导致分析跑在一个与结果并非随机相关的子集上。
连接改变了基数。预期的一对一合并实际变成了一对多,静默地复制了行,并使下游的每个计数和显著性检验都膨胀了。
类型强制转换。一列因为一个异常值被当作文本读取,然后被强制转为数字,转换失败的值变成缺失值,被上一条静默丢弃。
分组丢弃了键。缺失的分组标签被默认丢弃,导致某个类别从分组中消失,输出中却没有任何痕迹。
单位和编码。模型以为是百分比的列实际上是比例;像 -999 这样的哨兵值被当作测量值处理;日期在每月前十二天被以错误的日月顺序解析。
对付所有这些问题最高收益的习惯是要求行数。在每个过滤、连接和聚合前后打印行数,并认真查看。大多数问题立即可见,每步只需一行。
多重比较。在宽表中寻找"有趣的东西",模型会测试很多项并报告哪些显著了。这是教科书级别的假阳性配方,除非你要求,否则不会做任何校正。
独立性被违反。最常见的严重错误。对同一对象的重复测量、每个站点的多个样本、自相关的时间序列——都用假设独立观测的检验来分析,这会膨胀有效样本量并将 p 值压向虚无。
糟糕的对照。因为有就加上协变量。对中介变量条件化会移除你试图测量的效应;对碰撞变量条件化会创造一个不存在的关联。两者看起来都像是在谨慎行事。
聚合反转。辛普森悖论并不罕见——只要组大小不同且分组与结果相关就会发生。模型拿到一张扁平表,无法知道哪种分层是重要的。
把显著性读作重要性。大数据集中的微小效应是显著的,但可能无关。除非要求,否则效应量和区间会被省略。
built into the dataset。幸存者、响应者、到达诊所的患者。模型看到的是列,而不是行是如何产生的,而且它无法提问。
算术和分母。以错误的基数计算比率、百分比嵌套、普通的数值失误(参见模型在算术上不可靠的原因)。代码执行在这里有帮助但不能消除它,因为错误的分母也能完美计算出结果。
这是损害最大但被讨论最少的一种失败。你问一个问题。你得到了一个意想不到的答案。你说"换一种方式试试"。你得到了另一个答案。你一直试到某个看起来对的东西出现,然后你就写报告了。
这就是 p-hacking。这种做法一直都有可能,但以前每次尝试要花一个小时的工作量,这种摩擦在认识论上是有实际作用的。聊天界面把成本降到了一句话,所以可以在思考第一个分析是否合适的时间内跑十几个分析。最终报告中不会记录其他十一个曾经存在过。
防御是程序性的而非技术性的:在看结果之前决定分析方案,写下来,并记录每一次偏离。如果跑了十二个分析,诚实的报告应该这么说,而且十二个远不如一个令人印象深刻——这才是关键。
提前写出问题和分析方案,包括用什么检验、哪些协变量、以及什么算作零结果。把这个方案给模型,而不是数据集和一句邀请。
描述数据是如何产生的——采样方式、排除标准、单位、哨兵值。上面几乎每一种统计错误都是模型不知道某个你知道的、且从未被问过的东西。
在运行任何东西之前,让它陈述所提议检验的假设,以及如何检查每个假设。
用脚本而非对话工作。脚本是可审查、可重跑、可对比的;聊天记录三者都不是。
要求每一步都报告行数,以及开始时每列的缺失值数量。
审查代码,而非摘要。摘要是模型最擅长的部分,也是最不能说明正确性的部分。
让它写出相反结果的解读。如果那段话同样令人信服,那么原段落就不是由证据驱动的——这是一个快速而残酷的检查。
要求它给出反对该结论的最有力论据,以及什么样的混杂因素会在没有真实效应的情况下产生这种模式。
记录模型、版本、提示词和每一次分析运行,遵循可重复性的要求。