120 lines
6.1 KiB
Markdown
120 lines
6.1 KiB
Markdown
# SparseFocus 项目约定
|
||
|
||
## 项目理解
|
||
|
||
SparseFocus 面向自动对焦中的离焦预测问题。
|
||
|
||
基础任务是根据显微图像内容预测离焦程度。当前工作的核心判断是:内容稀疏视野会削弱离焦预测的稳定性。当视野中缺少足够有效结构时,直接从整图或任意局部区域回归离焦量,容易引入不可靠信号。
|
||
|
||
因此,项目目标中的主要流程应当是两阶段:
|
||
|
||
1. 先预测区域重要度,也就是判断每个局部区域是否包含有用信息。
|
||
2. 再使用重要区域作为有效证据进行离焦预测。
|
||
|
||
当前代码结构中:
|
||
|
||
- `RINet` 用于从输入图像预测 `9x9` 的区域重要度图。
|
||
- `DPNet` 用于预测离焦距离。
|
||
- `train_rin.py` 是当前较清晰的区域重要度训练入口。
|
||
- `train_dpn.py` 是当前离焦回归任务的训练入口。
|
||
- `old_datasets.py` 仍然承载了较多历史数据入口逻辑和本地路径假设。
|
||
- `datasets.py` 中已有较干净的 RIN 任务专用数据集和同步变换实现。
|
||
- TOML 配置文件用于将训练超参数从训练脚本中分离出来。
|
||
|
||
后续重构应当保留这个研究意图,同时让任务边界、数据契约和实验产物更加明确。
|
||
|
||
## 重构边界
|
||
|
||
`old_proj/` 是只读参考区域。
|
||
|
||
具体规则:
|
||
|
||
- `old_proj/` 下的代码、数据、笔记和产物只能读取参考。
|
||
- 重构过程中不得在 `old_proj/` 下创建、编辑、移动、重命名、格式化或删除任何文件。
|
||
- 所有实现变更都必须发生在 `old_proj/` 之外。
|
||
- 如果需要借鉴 `old_proj/` 中的历史逻辑,只能将思路手动迁移到主项目结构中,并在主项目内重新整理实现。
|
||
- 不要从 `old_proj/` 直接导入运行时代码;它不应成为当前工程依赖图的一部分。
|
||
|
||
这条边界用于保留旧快速迭代项目的历史上下文,同时避免旧结构和误操作继续泄漏到新的工程重构中。
|
||
|
||
## 代码风格约定
|
||
|
||
### 模块职责
|
||
|
||
- 模型、数据集、训练循环、工具函数、配置文件和实验输出应当分离。
|
||
- 当标签形状或返回值契约不同的时候,优先使用任务专用的数据集类。
|
||
- 除非共享契约已经明确,否则不要让同一个数据集辅助函数同时服务区域重要度分类和离焦回归。
|
||
- 路径发现和标签解析应放在数据层,不应放进模型逻辑或训练循环。
|
||
|
||
### 命名
|
||
|
||
- 任务名称应保持一致:
|
||
- `RIN` / `RINet` 表示区域重要度预测。
|
||
- `DP` / `DPNet` 表示离焦预测。
|
||
- 优先使用能表达含义的变量名,例如 `train_image_paths`、`valid_labels`、`run_dir` 和 `best_valid_loss`。
|
||
- 新代码中如果领域含义已经明确,应避免使用 `type`、`data`、`label`、`imag` 这类过于泛化的命名。
|
||
|
||
### 训练脚本
|
||
|
||
- 训练脚本应保持稳定顺序:
|
||
1. 读取配置。
|
||
2. 创建运行目录。
|
||
3. 初始化日志、TensorBoard writer、随机种子和设备。
|
||
4. 构建数据集和 dataloader。
|
||
5. 构建模型、损失函数、优化器和学习率调度器。
|
||
6. 执行训练和验证循环。
|
||
7. 保存最佳权重和最后权重。
|
||
- 单轮训练函数和单轮验证函数应与 `main()` 分离。
|
||
- 验证阶段应使用 `torch.no_grad()`。
|
||
- 日志中应记录配置路径、运行目录、数据集规模、优化器、调度器、每轮损失、最佳损失和权重保存事件。
|
||
- 每次实验运行都应将配置文件复制到对应运行目录中。
|
||
|
||
### 配置与实验
|
||
|
||
- 超参数应放在 TOML 配置文件中,不应硬编码在训练脚本中。
|
||
- 实验输出应写入带时间戳的运行目录,并保持被 Git 忽略。
|
||
- checkpoint、TensorBoard event 文件和训练日志属于运行时产物,不属于源码。
|
||
- 如果配置中的数据路径指向本机特定绝对路径,应先视为临时约定,直到引入更可移植的数据根目录机制。
|
||
|
||
### 模型代码
|
||
|
||
- 神经网络模块应保持小而可组合。
|
||
- 对有明确语义的模型组件,优先使用显式的 `nn.Module` 类。
|
||
- 当张量形状不明显时,应在模块边界附近记录形状预期,尤其是 `9x9` 区域重要度图和展平后的回归输出。
|
||
- 如果构造函数已经提供通道数参数,辅助模块内部应避免再次硬编码通道数。
|
||
|
||
### 数据契约
|
||
|
||
- 数据集 `__getitem__` 的返回值应稳定,并且与具体任务匹配。
|
||
- 图像张量在进入模型前应完成一致的归一化和形状整理。
|
||
- 除非模型明确设计为其他通道契约,否则读取图像时应显式转换为 RGB。
|
||
- 从文件名、Excel 或 JSON 中解析标签的逻辑,应与训练循环隔离,并适合单独测试。
|
||
- 数据加载函数中应避免隐藏依赖本机绝对路径。
|
||
|
||
### 编码与注释
|
||
|
||
- 新文件应使用 UTF-8 编码。
|
||
- 现有乱码中文注释应在聚焦重构时修复或删除,不应复制到新代码中。
|
||
- 绝大多数时候应使用 ASCII 字符,尤其是代码标识、短字符串、运行时输出、表格字段名、Sheet 名和指标枚举值。
|
||
- 较长的大段文档、代码注释可以并且应该使用中文描述,便于直接理解。
|
||
- 保存到结果文件中的字段名、Sheet 名、指标枚举值等应使用英文,例如 `image_path`、`sparsity_level`、`dense`。
|
||
- 注释应简短并解释真实背景,优先说明领域假设、张量形状、数据格式和不明显的训练选择。
|
||
- 不要用注释重复解释简单代码本身。
|
||
|
||
### 执行检查
|
||
|
||
- 代码运行、训练、测试和静态检查默认由用户执行。
|
||
- 除非用户明确要求,助手不主动运行代码检查、训练脚本或测试脚本。
|
||
|
||
### 导入与格式
|
||
|
||
- 导入顺序应按标准库、第三方库、本地模块分组。
|
||
- 新代码中优先使用 `pathlib.Path` 处理文件系统路径。
|
||
- 格式应兼容常见 Python 工具;窄范围改动时避免引入无关格式化变更。
|
||
|
||
### Git 卫生
|
||
|
||
- `old_proj/`、`.vscode/`、`__pycache__/` 和带时间戳的实验目录应保持被忽略。
|
||
- 不要提交生成的 checkpoint、TensorBoard 日志、训练日志或 Python 字节码。
|
||
- 重构时应保持改动范围清晰,并围绕有明确含义的工程节点进行提交。
|