21.5 稳健性检验与产出自动化

面向经管学生、研究者与从业者的 AI 智能体设计教材

作者

李学恒、林建浩、严翊歆

发布于

2026-05-11

配图:稳健性矩阵与多子代理协作

主回归跑出来后,项目进入八阶段流水线的阶段 6 与阶段 7——稳健性检验矩阵和表格图形生成。这两个阶段的共同特征是工作量大、规则化程度高、容错空间小:一份合格的稳健性矩阵动辄几十格,每格都要按统一的聚类规范、星号标准、表头格式跑出可比结果。本节把这两段流水线交给多子代理并行协作,再用 Hooks 在文件写入的瞬间做质量门禁。estimator-agent 按矩阵配置逐格执行,reviewer-agent 汇总并核查格式,PreToolUsePostToolUse 钩子拦截缺失的随机种子和未声明的聚类层级。整套机制把稳健性从耗时活变成常态检查。

稳健性检验是学术论文的防守线。审稿人不会只看主回归,而是要看结果在不同估计量、不同样本、不同控制变量下是否一致。传统工作流里,研究者要手工写几十个 do 文件,反复调整参数,跑完一轮往往要几天。把这条防守线交给智能体并行执行,研究者只需说明矩阵的边界,剩下的工作由代码自动化完成,最后由人做方向判断。

稳健性矩阵的四个维度

一个合格的稳健性矩阵至少覆盖四个维度:估计量、控制变量集、样本范围、结果变量。每个维度给出 2-3 个选项,笛卡尔积就是完整矩阵。以最低工资 DID 为例:

维度 选项 A 选项 B 选项 C
估计量 TWFE(reghdfe CS(csdid SDID(sdid
控制变量集 无控制 基准(州 GDP、失业率) 扩展(加行业结构)
样本范围 全样本 2000-2019 排除加州、纽约、德州 排除 2008-2009 金融危机年份
结果变量 水平值 emp 对数值 log_emp IHS 变换 asinh(emp)

四个维度各三档,理论上有 81 个格子。实务中不必每格都跑,研究者挑 10-15 个关键组合覆盖主要威胁即可。选择原则:优先覆盖每个维度的极端值(最简规范和最复杂规范),保证估计量×样本的 2×2 交叉格至少都有,最后补入审稿人最可能追问的格子(如排除危机年份、排除人口大州)。矩阵配置写在 config/robustness-matrix.yaml 中,estimator-agent 按此文件逐格执行:

# config/robustness-matrix.yaml
estimators: [twfe, csdid, sdid]
controls:
  none: []
  baseline: [log_gdp, unemployment_rate]
  extended: [log_gdp, unemployment_rate, industry_share]
samples:
  full: "year >= 2000 & year <= 2019"
  excl_large: "!inlist(state_id, 6, 36, 48)"   # 排除加州、纽约、得州
  excl_crisis: "!inlist(year, 2008, 2009)"
outcome: log_emp

估计量维度检验方法论选择是否稳健,控制变量维度检验遗漏变量偏误,样本维度检验异常州或异常时期的影响,结果变量维度检验函数形式假设。

稳健性矩阵避免选择性报告

稳健性检验最大的诱惑是只报告支持主结论的列。AI 并行跑完所有格子后,研究者应把全部结果放进附录表,再在正文选 3-4 列展示。若某格符号翻转或显著性消失,不要删除,要在正文中说明可能原因。完整矩阵本身就是诚信证明。

多子代理并行协作

稳健性矩阵适合用多子代理并行执行。一条自然语言指令下去,三类子代理各司其职:

  • estimator-agent:按矩阵配置跑每个格子,输出系数、标准误、样本量到中间文件
  • reviewer-agent:汇总全部格子结果,检查系数方向一致性、样本量是否符合预期;同时做对抗式审阅,核查表格星号是否统一、标准误格式是否一致、事件研究图轴标签是否规范

研究者只需发出一条触发指令:

▶ Claude Code
请按 robustness-matrix.yaml 里定义的配置跑完整稳健性矩阵。estimator-agent 负责执行,reviewer-agent 汇总结果并检查一致性和表格格式。跑完后把汇总表放到 output/tables/tab_robustness.tex,异常格子单独列一份报告给我看。

下面是 estimator-agent 的 agent.md 定义:

▶ Agent
---
name: estimator-agent
description: 稳健性矩阵执行子代理。按 YAML 配置文件指定的估计量、样本、控制变量组合,逐一调用 Stata 脚本并收集系数、标准误、样本量。
model: sonnet
tools: Read, Write, Bash
---

你是稳健性矩阵的执行方。你的任务是按矩阵配置跑每一个格子,不做方向判断。

**工作流:**
1. 读取 `config/robustness-matrix.yaml`,解析每个格子的参数组合
2. 对每个格子,生成临时 do 文件并调用 `stata-mp -b do tmp_cell_XX.do`
3. 从 `.log` 文件中提取:系数、聚类稳健标准误、样本量、R²、估计量名称
4. 写入 `output/robustness/cell_XX.json`,字段齐全且数值未做任何筛选
5. 所有格子跑完后,在 `output/robustness/summary.json` 里给出索引

**关键原则:**
- 不合并格子结果,不评判系数方向,这是 reviewer-agent 的事
- 任何一个格子执行失败要立即上报,不跳过
- 每个 do 文件首行必须 `set seed 20260417`、`version 18.0`
- 禁止修改 `code/02_clean.do` 生成的清洗面板

两个子代理通过文件系统通信:estimator-agent 写出 JSON,reviewer-agent 读 JSON 生成汇总 LaTeX 并检查格式。文件接口让子代理解耦,任何一个出问题都可以单独重跑。

表格与图形自动化

Stata 侧用 esttab 生成期刊格式的 LaTeX 表,用 csdid_plot 画事件研究图。下面是 06_tables_figs.do 的核心片段:

* 合成 DID(sdid)稳健性规范
sdid log_emp state_id year treat_indicator, ///
    vce(bootstrap) seed(20260417) reps(200)
estimates store sdid_main

* 主表:三种估计量并排
esttab twfe_main cs_main sdid_main ///
    using "output/tables/tab_main.tex", replace ///
    keep(treat_indicator) ///
    b(3) se(3) ///
    star(* 0.1 ** 0.05 *** 0.01) ///
    booktabs label nonotes ///
    mtitles("TWFE" "CS" "SDID") ///
    stats(N r2, fmt(%9.0fc %9.3f) labels("Obs." "R\$^2\$")) ///
    title("主回归结果:最低工资对低薪就业的影响") ///
    addnotes("括号内为聚类在州层级的标准误。")

* 事件研究图(csdid 专用命令)
estimates restore cs_main
estat event
csdid_plot, title("事件研究:最低工资调整对低薪就业") ///
    xtitle("相对处理年份") ytitle("ATT 估计量")
graph export "output/figures/fig_event_study.pdf", replace

R 用户可以用更紧凑的三行代码得到对照结果:

library(fixest); library(modelsummary)
m_twfe <- feols(log_emp ~ treat | state_id + year, cluster = "state_id", data = panel)
modelsummary(list(TWFE = m_twfe), output = "output/tables/tab_main_r.tex", stars = TRUE)
iplot(m_twfe, main = "Event Study")

两种工具链的输出可以互相校验。若 Stata 的 reghdfe 和 R 的 fixest::feols 在同样规范下给出不同系数,基本可以锁定代码错误而非理论差异。

词条:esttabcoefplot

esttab 是 Jann 的 estout 包(首发 2005 年)内的核心命令,把 estimates store 暂存的回归结果组合成单张 LaTeX/RTF/CSV 表,支持多列并排、星号自定义、统计量脚注。coefplot 是同作者的系数可视化工具,常用于事件研究图的绘制。两者都是 AEA 期刊复现包的标配。

Hooks 做质量门禁

Skills 和子代理让 AI 把事做完,Hooks 则让 AI 把事做对。在实证项目里,Hooks 可以在文件写入或工具调用的关键节点自动触发检查,把容易被遗漏的规范强制兑现。下面这份 .claude/settings.json 里的 hooks 字段示例覆盖了三类典型场景:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/check-seed.sh \"$CLAUDE_FILE_PATH\""
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write|Edit",
        "hooks": [
          {
            "type": "command",
            "command": "bash .claude/hooks/check-cluster.sh \"$CLAUDE_FILE_PATH\""
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "echo '主回归已生成,请在继续稳健性前人工审阅 output/tables/tab_main.tex'"
          }
        ]
      }
    ]
  }
}

三个 Hook 覆盖三类典型风险。PreToolUse(Write) 在新 do 文件写入前扫描内容,若缺 set seedexit 2 拦截,避免 bootstrap 结果每次不同。PostToolUse(Write|Edit) 在修改任何 do 文件后扫描回归命令是否带聚类或稳健标准误选项,缺了就把提示回灌给模型。Stop 在会话终止前打印提示,要求研究者人工确认主表再进入稳健性。三个 Hook 合起来构成一道自动化检查流水线。

Hooks 是提示层,不能替代人审

Hook 检测的都是”规则能表达的事”——种子有没有、聚类选项有没有、文件有没有生成。它检测不了”规范合不合理”——聚类层级选得对不对、样本边界合不合适、事件窗口够不够长。Hook 可以拦下明显的遗漏,但研究者仍要亲自核对主回归的规范与方向。把 Hook 当作协作者而非审查者,效果最好。