Workflow / Reproducibility
Python 与可复现研究工作流
把研究项目看成一个可复跑的有向无环图,而不是一组手工文件。
Mechanism Lab
动画:研究产出如何沿 DAG 流动
动画中的信号从 raw data 出发,经过 clean、feature、model、table,每一步都留下可验证文件。
Step 1 / 5
Raw
原始数据只读保存。
D0Animation Control
Reduced-motion users receive the same step states without continuous motion.
01 / 直觉
核心直觉
可复现研究的核心不是“会写 Python”,而是让数据、代码、参数、输出之间的依赖关系可以被检查。
一个结果表不是一个孤立文件,而是函数 F(raw data, code, config, seed) 的输出。
当依赖图清楚时,人类、审稿人和 Agent 都能复跑、定位错误、替换数据并比较差异。
02 / 数学
把研究流程写成依赖图
01 / 状态定义
令 D0 表示原始数据,C 表示代码,theta 表示配置,s 表示随机种子。任何可复现输出都应能写成确定性映射。
Y = F(D0, C, theta, s)02 / DAG 约束
若节点 v_j 依赖 v_i,则必须先生成 v_i。拓扑排序给出可复跑顺序。
v_i -> v_j implies order(v_i) < order(v_j)03 / 审计条件
输出变化 Delta Y 必须能分解到数据、代码或配置变化,而不是不可见的手工编辑。
Delta Y = F(D0, C2, theta, s) - F(D0, C1, theta, s)03 / 代码
最小 pipeline 代码
下面的例子把清洗和分析分成两个函数,并显式记录输入输出。
from pathlib import Path
import pandas as pd
ROOT = Path("project")
def clean(raw_path: Path, out_path: Path) -> pd.DataFrame:
df = pd.read_csv(raw_path)
df = df.drop_duplicates("id")
df["post"] = (df["year"] >= 2020).astype(int)
df.to_parquet(out_path, index=False)
return df
def summarize(clean_path: Path, table_path: Path) -> None:
df = pd.read_parquet(clean_path)
table = df.groupby("post")["outcome"].agg(["count", "mean", "std"])
table.to_csv(table_path)
clean(ROOT / "data/raw.csv", ROOT / "data/processed.parquet")
summarize(ROOT / "data/processed.parquet", ROOT / "tables/descriptive.csv")04 / 案例
案例:把 Excel 工作流改成可审计 pipeline
- 把一份手工 Excel 研究流程拆成 raw data、clean script、analysis script 和 outputs。
- 每个输出表格都能追溯到输入数据、代码版本和随机种子。
- Agent 只能在这种结构上可靠工作;否则它只能猜测文件含义。
05 / 风险
常见误区
只保存 notebook 而没有运行顺序。
输出表格被手工改过但没有留下 provenance。
路径、随机种子和依赖版本没有固定。