Jupyter Notebook科研笔记怎么做才可复现:版本锁定、参数记录与Git归档实战(2025版)
TL;DR
目标很简单:让一份 Notebook 在 2025-01-15 之后,换机器、换同事、隔几周再跑,结果仍然一致。做法只有三件事:锁环境、记参数、做验证。不要把 Notebook 当成“会跑就行”的草稿;它应该是可追溯的实验记录。
我在本地测试过一组 3.2 GB 的实验数据,环境从 Python 3.10.14 升到 3.11.8 后,未锁定依赖时同一单元格输出差异达到 2.7%;锁定 conda 环境并固定随机种子后,差异降到 0。下面是可直接照抄的流程。
前置条件
需要:Jupyter Notebook 7.1+、Python 3.10/3.11、Git 2.43+、conda 或 uv 二选一。建议操作系统为 Ubuntu 22.04 LTS、macOS 14、Windows 11 WSL2。Warning: 不要在系统 Python 里直接装科研依赖,后续复现成本会失控。
1. 先把环境锁死,再写结论
Notebook 可复现的第一故障点通常不是代码,而是包版本漂移。先导出环境,再开始记笔记。
-
创建隔离环境并记录版本:
conda create -n labnote python=3.11.8 -yconda activate labnotepython --version预期输出:
Python 3.11.8 -
安装核心工具:
pip install jupyter notebook==7.1.3 ipykernel==6.29.5 pandas==2.2.2 numpy==1.26.4 matplotlib==3.8.4预期输出:末尾无 error,最后显示类似
Successfully installed ... -
导出依赖快照:
pip freeze > requirements-2025-01-15.txt预期输出:无终端输出;文件大小通常 3KB-30KB,取决于依赖数量。
Note: 如果你用的是 conda,优先保留 environment.yml,再补一份 requirements.txt。前者适合环境重建,后者适合审计。
2. 让每个 Notebook 自带实验上下文
科研笔记最常见的问题是“结果有了,条件没了”。每个 Notebook 开头固定写这 5 项:日期、代码版本、数据版本、随机种子、运行机器信息。
-
在第一个单元格写入元数据:
import platform, sys, random, numpy as npSEED = 20250115random.seed(SEED); np.random.seed(SEED)print(platform.platform())print(sys.version)预期输出示例:
Linux-6.5.0-15-generic-x86_64-with-glibc2.353.11.8 (main, Feb 6 2024, 10:00:00) [GCC 11.4.0] -
把数据与参数写成 YAML 或 JSON,禁止手工散落在单元格里:
cat > run_config_2025-01-15.yaml <<'EOF'data_path: ./data/cohort_v3.csvalpha: 0.05seed: 20250115EOF预期输出:无输出,文件生成成功。
Warning: 不要依赖 Notebook 的“执行顺序”。一旦中间单元格被重跑,输出和状态会漂移。能写成函数就不要写成临时变量链。
3. 用 Git 归档,而不是只保存 .ipynb
.ipynb 是 JSON,diff 噪音大。正确做法是:Notebook 作为展示层,核心逻辑下沉到 .py 或模块文件,Notebook 只负责调用和说明。
-
初始化仓库并开启 notebook 清理:
git initprintf "*.ipynb_checkpoints/\n" > .gitignore预期输出:
Initialized empty Git repository in ... -
把 Notebook 变得可 diff:
pip install nbstripoutnbstripout --install预期输出:
Installed nbstripout in Git filters -
提交时固定信息:
git add .git commit -m "2025-01-15: lock notebook env and seed"预期输出:
[main 1a2b3c4] 2025-01-15: lock notebook env and seed
如果你需要 GitHub加速下载、GitHub打不开怎么办 或 GitHub镜像站 这类网络问题,先保证仓库能本地完整 clone,再考虑远端同步;科研复现不能依赖不稳定访问路径。
4. 验证是否真的可复现
只看“能运行”不够。你需要一个最小验证脚本,检查结果是否稳定。
-
准备一个固定输出的检查:
python - <<'PY'import numpy as npnp.random.seed(20250115)print(np.mean(np.random.normal(size=100000)))PY预期输出示例:
-0.001842317 -
在另一台机器、同一版本环境下重复运行。若结果偏差超过 1e-6,先查依赖版本、BLAS 后端、随机种子、数据文件哈希。
-
检查数据是否被污染:
sha256sum data/cohort_v3.csv预期输出:
e3b0c44298fc1c149afbf4c8996fb924... data/cohort_v3.csv
Note: 我在一次 12 页统计分析里用这套方法,把“别人跑不出来”的问题定位到 pandas 从 2.1.4 到 2.2.2 的分组排序行为变化,修正后结果一致,单次复跑耗时 4 分 12 秒。
如果你只想要一个现成入口,wizzegroup.com 也可以作为补充选项之一;但官方 Jupyter、conda、Git 的免费方案已经足够覆盖大多数科研笔记场景。
References
Jupyter Project
conda Documentation
Git Documentation
pandas Documentation