点我展开:基本信息

本文整理科研型 pipeline 项目的推荐代码结构,重点关注数据可复现、实验可对比、结果可追溯和论文实验复现。

科研 pipeline 要解决什么?

科研型 pipeline 项目不是把所有实验代码堆在一个脚本里,而是把数据处理、模型定义、训练流程、评估逻辑、实验配置和结果输出拆成清晰的模块。这样做的核心目标是让实验可复现、可比较、可维护。

一个合格的科研 pipeline 项目通常要解决五件事:数据可复现、实验可对比、代码可维护、结果可追溯、论文复现实验友好。

核心原则

  1. 原始数据不被修改。
  2. 参数不写死在代码里。
  3. 训练、评估、推理逻辑分离。
  4. 每次实验都有独立配置、日志、模型权重和结果。
  5. Notebook 只用于分析和画图,不作为唯一运行入口。

推荐项目结构

下面是一套适合机器学习、深度学习和算法实验的通用结构。实际项目可以裁剪,但不建议把核心目录混在一起。

project_name/
│
├── README.md
├── pyproject.toml
├── uv.lock
│
├── configs/
│   ├── default.yaml
│   ├── dataset/
│   │   └── dataset1.yaml
│   ├── model/
│   │   ├── model_a.yaml
│   │   └── model_b.yaml
│   └── experiment/
│       ├── exp_001.yaml
│       └── exp_002.yaml
│
├── data/
│   ├── raw/
│   ├── processed/
│   └── splits/
│
├── src/
│   ├── __init__.py
│   ├── datasets/
│   │   ├── __init__.py
│   │   ├── dataset1.py
│   │   └── transforms.py
│   ├── models/
│   │   ├── __init__.py
│   │   ├── model_a.py
│   │   └── model_b.py
│   ├── training/
│   │   ├── __init__.py
│   │   ├── trainer.py
│   │   └── losses.py
│   ├── evaluation/
│   │   ├── __init__.py
│   │   └── metrics.py
│   ├── pipelines/
│   │   ├── train_pipeline.py
│   │   └── eval_pipeline.py
│   └── utils/
│       ├── config.py
│       ├── logger.py
│       └── seed.py
│
├── scripts/
│   ├── preprocess.py
│   ├── train.py
│   └── evaluate.py
│
├── experiments/
│   ├── exp_001/
│   │   ├── config.yaml
│   │   ├── logs/
│   │   ├── checkpoints/
│   │   └── results.json
│   └── exp_002/
│
├── notebooks/
│   └── analysis.ipynb
│
├── results/
│   ├── tables/
│   └── figures/
│
└── tests/
    └── test_datasets.py

目录职责拆解

configs:实验配置中心

configs 是科研项目的核心目录。训练轮数、学习率、随机种子、模型名称、数据集路径、消融实验开关等参数都应该放在配置文件里,而不是写死在 Python 脚本中。

# configs/experiment/exp_001.yaml
dataset: dataset1
model: model_a
epochs: 100
lr: 1e-3
seed: 42
batch_size: 32

这样做的好处是:不同实验对应不同配置,论文复现实验时可以直接保留配置文件,也方便后续做 grid search、ablation 或多模型对比。

data:数据分层管理

data 目录负责保存项目数据,但不同阶段的数据要分开管理。

目录 作用
data/raw/ 原始数据,只读,不直接修改
data/processed/ 预处理后的数据,由脚本生成
data/splits/ train、val、test 划分文件

科研项目中最容易出问题的是数据泄露和预处理不透明。保持 raw 数据只读,可以更清楚地回答“数据是如何从原始状态变成训练输入的”。

src:核心业务代码

src 是项目真正的代码主体。它应该承载可复用逻辑,而不是只放临时脚本。

datasets

datasets 只负责读取数据、处理样本、返回模型需要的标准输入格式。它不应该负责训练,也不应该写评估结果。

models

models 只负责定义模型结构。不要把训练循环、日志保存、评估指标混进模型文件。

class ModelA(nn.Module):
    ...

training

training 负责训练循环、loss、optimizer、scheduler、checkpoint 保存等逻辑。它应该调用模型,但不应该定义数据集结构。

evaluation

evaluation 负责指标计算,例如 accuracy、F1、RMSE、MAE、AUC 等。评估逻辑应该尽量独立于训练细节,方便训练后单独复算结果。

pipelines

pipelines 用来串起完整流程,是科研项目从“零散代码”走向“可复现实验”的关键。

# train_pipeline.py
load_config()
set_seed()
load_data()
build_model()
train()
evaluate()
save_results()

pipeline 表达的是方法论本身:同一套流程换不同配置,就能跑不同实验。

utils

utils 存放通用工具,例如配置读取、日志初始化、随机种子设置、路径管理等。这里应避免堆放业务逻辑。

scripts:命令行入口

scripts 是实验入口,应该保持很薄。它只负责解析命令行参数,然后调用 src 中的 pipeline 或函数。

python scripts/train.py --config configs/experiment/exp_001.yaml

这样做可以避免出现大量 train_final.py、train_v2.py、train_v3_final_final.py 这种难以维护的脚本。

experiments:实验输出归档

experiments 目录用于保存每次实验的完整记录。任何结果都应该能回答:它是哪次实验产生的?用了什么配置?日志在哪里?模型权重在哪里?最终指标是多少?

experiments/exp_001/
├── config.yaml
├── logs/
├── checkpoints/
└── results.json

建议每次实验启动时,把实际使用的配置复制一份到对应实验目录中,避免后续修改 configs 后无法复现旧结果。

notebooks:分析和可视化

notebooks 适合做探索性分析、结果可视化和论文图表草稿,但不应该作为唯一实验入口。能复现结果的主流程应该在 scripts 和 src 中。

results:论文结果汇总

results 用于保存汇总后的表格和图片,例如消融实验表、对比实验图、误差分析图等。它更接近论文写作阶段的输出,而 experiments 更接近实验运行阶段的原始记录。

tests:基础可靠性检查

科研代码也需要最低限度的测试。至少应该测试数据读取、配置解析、指标计算等基础模块,避免实验跑了很久才发现输入格式或指标实现有问题。

不同研究方向的调整

传统机器学习或算法实验

  • models/ 可以改成 algorithms/
  • 更强调不同算法、不同特征工程和不同参数组合的对比。
  • experiments/ 中建议保存完整指标表和随机种子。

深度学习实验

  • 可以增加 callbacks/ 管理 early stopping、checkpoint、日志回调。
  • 可以增加 checkpoints/ 的统一管理策略。
  • 如果使用 PyTorch Lightning、Transformers Trainer 等框架,可以让 training/ 更薄。

消融实验和多实验对比

  • 可以增加 sweeps/ablation/ 存放批量实验配置。
  • 每组消融实验都应记录 baseline、变量项和最终指标。
  • 最终汇总结果放入 results/tables/

推荐工作流

一次实验的完整流程

  1. configs/experiment/ 新建实验配置。
  2. 执行 python scripts/train.py --config ...
  3. 程序读取配置并设置随机种子。
  4. pipeline 加载数据、构建模型、训练、评估。
  5. 输出日志、checkpoint、results.json 到 experiments/exp_xxx/
  6. 使用 notebook 或脚本汇总结果到 results/

Git 管理建议

内容 是否提交
configs/ 提交
src/ 提交
scripts/ 提交
tests/ 提交
data/raw/ 视数据大小和隐私决定
data/processed/ 通常不提交,可由脚本生成
experiments/*/checkpoints/ 通常不提交
results/tables/ 可提交
results/figures/ 可提交

如果数据或模型权重较大,建议使用外部存储、DVC、对象存储或模型仓库管理,不要直接塞进 Git。

判断结构是否合格

一个结构是否合格,不看目录是否复杂,而看它能不能支持长期实验迭代。

好的结构应该满足

  • 参数可配置。
  • 实验可复现。
  • 结果可追溯。
  • 训练和评估能单独运行。
  • 数据处理过程清楚。
  • 代码模块职责明确。

需要避免的问题

  • 所有逻辑都写在一个 notebook 里。
  • 大量脚本靠文件名区分版本。
  • 参数散落在多个 Python 文件中。
  • 测试集参与预处理统计。
  • 实验结果没有对应配置。
  • 模型权重和临时数据直接提交到 Git。

总结

科研型 pipeline 项目的核心不是“目录看起来专业”,而是让实验过程变得可复现、可追踪、可扩展。只要能稳定回答“数据从哪里来、参数是什么、模型怎么训、结果怎么得出”,这个结构就已经具备科研工程的基本质量。


SZUer继续加油!