443 lines
14 KiB
Markdown
443 lines
14 KiB
Markdown
# VinBigData 项目说明
|
||
|
||
## 1. 文档目的
|
||
|
||
本文档用于说明本仓库中 `VinBigData Chest X-ray Abnormalities Detection` Kaggle 比赛项目的目标、组成、运行链路和复现注意事项。
|
||
|
||
该仓库本质上是一个 **以 Kaggle Notebook 为中心的比赛归档项目**,重点在于提交策略验证,而不是可直接安装和运行的标准工程包。因此,本文档的定位是:
|
||
|
||
- 说明项目主线与各 notebook 的职责
|
||
- 记录关键输入、输出和依赖关系
|
||
- 为后续回看、迁移或局部复现提供导航
|
||
|
||
## 2. 项目概述
|
||
|
||
### 2.1 比赛任务
|
||
|
||
比赛输入为胸部 X-ray 影像,输出为 Kaggle 要求的 `PredictionString`,每 6 个值表示一条预测:
|
||
|
||
`class_id score x_min y_min x_max y_max`
|
||
|
||
其中:
|
||
|
||
- `0` 到 `13` 表示 14 类胸片异常
|
||
- `14` 表示 `No finding`
|
||
|
||
因此,该任务不仅是目标检测任务,还包含明显的图像级正常/异常判别需求。仓库中的方案围绕这一点构建,核心并非单一模型,而是以下组合:
|
||
|
||
1. 14 类异常检测
|
||
2. normal / abnormal 二分类
|
||
3. `No finding` 的规则化后处理
|
||
4. 多个 submission 的结果级融合
|
||
|
||
### 2.2 仓库定位
|
||
|
||
从当前文件内容看,该项目的主要价值不在于“训练脚本工程化”,而在于保留一套完整的比赛思路:
|
||
|
||
- 检测模型负责输出异常框
|
||
- 二分类模型负责判断整图是否更接近正常
|
||
- 后处理阶段决定保留框、追加 `class 14`,或直接替换为 `No finding`
|
||
- 在此基础上尝试进一步 ensemble
|
||
|
||
## 3. 仓库文件说明
|
||
|
||
| 文件 | 作用 | 说明 |
|
||
| --- | --- | --- |
|
||
| `yolov5-chest-512.ipynb` | 主流程 notebook | 包含数据整理、fold 划分、YOLO 标签生成、检测推理、图像级分类辅助后处理 |
|
||
| `vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb` | 纯检测推理 | 使用训练好的 YOLOv5 权重生成检测结果并导出 `submission.csv` |
|
||
| `vinbigdata-2-class-classifier-complete-pipeline.ipynb` | 二分类完整流程 | 训练 normal / abnormal 分类器,并导出 `valid_pred.csv`、`test_pred.csv` |
|
||
| `ensembling-approach.ipynb` | submission 级融合 | 对多个检测 submission 做启发式融合与平均 |
|
||
| `ensemble-of-best-public-notebooks.ipynb` | 轻量后处理 | 对已有 submission 再应用一次 2-class filter |
|
||
| `VINBIGDATA_REVIEW.md` | 项目说明文档 | 当前文档 |
|
||
|
||
## 4. 方案架构
|
||
|
||
### 4.1 总体流程
|
||
|
||
该项目可以概括为以下流水线:
|
||
|
||
1. 使用检测模型生成 14 类异常框
|
||
2. 使用二分类模型估计图像为 normal 的概率
|
||
3. 根据 normal 概率对检测结果做后处理
|
||
4. 必要时对多个 submission 再进行融合
|
||
|
||
可简化表示为:
|
||
|
||
`Detection -> 2-class probability -> Post-process No finding -> Ensemble`
|
||
|
||
为了便于快速把握整体关系,下面补充三张结构图,分别对应总体流水线、各 notebook 职责,以及后处理决策逻辑。
|
||
|
||
**总体流水线**
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
A[官方比赛数据<br/>train.csv / test dicom] --> B[图像预处理数据集<br/>256 / 512 / 1024 PNG]
|
||
B --> C[yolov5-chest-512.ipynb<br/>主检测流程]
|
||
A --> C
|
||
B --> D[vinbigdata-2-class-classifier-complete-pipeline.ipynb<br/>normal / abnormal 二分类]
|
||
A --> D
|
||
|
||
C --> E[14 类异常检测结果]
|
||
D --> F[test_pred.csv / valid_pred.csv<br/>整图 normal 概率]
|
||
|
||
E --> G[后处理逻辑<br/>Keep / Add / Replace]
|
||
F --> G
|
||
G --> H[submission.csv]
|
||
|
||
H --> I[ensemble-of-best-public-notebooks.ipynb<br/>轻量 2-class 再过滤]
|
||
F --> I
|
||
I --> J[postprocessed submission.csv]
|
||
|
||
H --> K[ensembling-approach.ipynb<br/>多 submission 融合]
|
||
J --> K
|
||
K --> L[final submission.csv]
|
||
```
|
||
|
||
**Notebook 职责图**
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[yolov5-chest-512.ipynb] --> A1[读取比赛数据]
|
||
A --> A2[MultilabelStratifiedKFold 分 fold]
|
||
A --> A3[生成 YOLO 标签]
|
||
A --> A4[调用检测模型推理]
|
||
A --> A5[结合整图分类做后处理]
|
||
A --> A6[导出 submission.csv]
|
||
|
||
B[vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb] --> B1[加载 best.pt]
|
||
B --> B2[运行 detect.py]
|
||
B --> B3[YOLO 坐标转回比赛格式]
|
||
B --> B4[纯检测 baseline submission]
|
||
|
||
C[vinbigdata-2-class-classifier-complete-pipeline.ipynb] --> C1[构造 normal / abnormal 标签]
|
||
C --> C2[StratifiedKFold 训练]
|
||
C --> C3[导出 valid_pred.csv]
|
||
C --> C4[导出 test_pred.csv]
|
||
C --> C5[按阈值修正检测 submission]
|
||
|
||
D[ensemble-of-best-public-notebooks.ipynb] --> D1[读取已有 submission]
|
||
D --> D2[读取 2-class 概率]
|
||
D --> D3[Keep / Add / Replace]
|
||
|
||
E[ensembling-approach.ipynb] --> E1[读取多个 submission]
|
||
E --> E2[按图片拆分 PredictionString]
|
||
E --> E3[top-n 保留]
|
||
E --> E4[同类框平均融合]
|
||
```
|
||
|
||
**后处理决策图**
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
A[输入: 一张图的检测结果 + class0 概率] --> B{normal 概率阈值}
|
||
B -->|p < low_threshold| C[Keep<br/>保留检测结果]
|
||
B -->|low_threshold <= p < high_threshold| D[Add<br/>保留检测结果并追加 class 14]
|
||
B -->|p >= high_threshold| E[Replace<br/>替换为 14 1 0 0 1 1]
|
||
```
|
||
|
||
### 4.2 检测主线
|
||
|
||
`yolov5-chest-512.ipynb` 是最接近“总控台”的 notebook。根据 notebook 中保留的代码,其主线包括:
|
||
|
||
- 读取官方比赛数据与预处理后的 PNG 数据
|
||
- 将原始标注缩放到训练尺寸
|
||
- 使用 `MultilabelStratifiedKFold` 划分 5-fold
|
||
- 生成 YOLO 训练目录及标签文件
|
||
- 以 512 尺度作为主要检测输入
|
||
- 调用 YOLOv5 `detect.py` 做推理
|
||
- 结合图像级分类结果生成最终 `submission.csv`
|
||
|
||
需要说明的是,该 notebook 中保留了部分历史实验痕迹,例如 EfficientDet / EfficientNet 相关配置、硬编码阈值和样本过滤列表。它更像比赛过程中的工作 notebook,而不是整理后的单一职责脚本。
|
||
|
||
### 4.3 二分类补偿分支
|
||
|
||
`vinbigdata-2-class-classifier-complete-pipeline.ipynb` 负责训练整图二分类器,用于回答“这张图是否正常”。
|
||
|
||
其主要配置和行为包括:
|
||
|
||
- 输入图像目录:`vinbigdata-chest-xray-resized-png-256x256`
|
||
- 默认 backbone:`resnet18`
|
||
- 5-fold `StratifiedKFold`
|
||
- 训练轮数:`epoch=15`
|
||
- 调度器:`CosineAnnealingWarmRestarts`
|
||
- 支持 `mixup`、`label_smoothing`、`EMA`
|
||
- 输出:
|
||
- `valid_pred.csv`
|
||
- `test_pred.csv`
|
||
|
||
该分支不负责检测框位置,只输出 normal / abnormal 概率,供后处理阶段使用。
|
||
|
||
### 4.4 后处理策略
|
||
|
||
当前仓库中的后处理逻辑高度一致,核心思想为:
|
||
|
||
1. 若 normal 概率较低,则保留检测结果
|
||
2. 若 normal 概率处于中间区间,则保留检测结果并追加 `class 14`
|
||
3. 若 normal 概率较高,则直接替换为 `14 1 0 0 1 1`
|
||
|
||
在 `vinbigdata-2-class-classifier-complete-pipeline.ipynb` 中,保存下来的阈值示例为:
|
||
|
||
- `low_threshold = 0.0`
|
||
- `high_threshold = 0.976`
|
||
|
||
在 `ensemble-of-best-public-notebooks.ipynb` 中,轻量后处理版本使用:
|
||
|
||
- `low_threshold = 0.0`
|
||
- `high_threshold = 0.90`
|
||
|
||
这说明项目后期的主要增分手段之一,是利用二分类模型修正检测器在正常样本上的误报。
|
||
|
||
### 4.5 多模型融合
|
||
|
||
`ensembling-approach.ipynb` 不是模型层面的联合训练,而是 **submission 级别** 的结果融合。
|
||
|
||
它的做法是:
|
||
|
||
1. 读取多个模型导出的 `PredictionString`
|
||
2. 将每个 submission 拆分成按图像组织的预测字典
|
||
3. 每个模型仅保留 top-n 预测,默认 `n=3`
|
||
4. 找出相同类别的重复预测
|
||
5. 对重复类别的分数和框坐标做平均
|
||
6. 重新拼接为新的 `submission.csv`
|
||
|
||
该方法更接近启发式 averaging,而不是标准训练期融合。
|
||
|
||
## 5. 各 Notebook 的正式说明
|
||
|
||
### 5.1 `yolov5-chest-512.ipynb`
|
||
|
||
用途:
|
||
|
||
- 项目主流程梳理
|
||
- 训练前数据准备
|
||
- YOLO 标签生成
|
||
- 检测结果读取与后处理
|
||
- 结合图像级分类器生成最终提交
|
||
|
||
关键实现:
|
||
|
||
- `split_df(...)`
|
||
- 使用 `MultilabelStratifiedKFold` 做检测任务分层划分
|
||
- `Preprocess_wbf(...)`
|
||
- 对训练标注做 WBF 风格整理
|
||
- `create_file(...)`
|
||
- 生成 YOLO 所需目录结构和标签文件
|
||
- `Predict_process.fit(...)`
|
||
- 读取 YOLO 检测结果
|
||
- 执行 NMS
|
||
- 调用 `EfficientnetCus` 进行整图分类
|
||
- 根据分类概率决定最终 `PredictionString`
|
||
|
||
说明:
|
||
|
||
- notebook 中提供了 YOLOv5 训练命令示例,但训练命令本身是注释状态
|
||
- 检测推理阶段调用的是外部 `best.pt`
|
||
- 部分阈值和过滤列表属于比赛调参产物,保留了明显经验化特征
|
||
|
||
### 5.2 `vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb`
|
||
|
||
用途:
|
||
|
||
- 以最小流程生成纯检测提交
|
||
|
||
关键行为:
|
||
|
||
- 读取已训练好的 `best.pt`
|
||
- 调用 `detect.py`
|
||
- 使用 `img=640`、`conf=0.15`、`iou=0.4`
|
||
- 保存 `txt` 和置信度
|
||
- 将 YOLO 输出转换回比赛要求的原图坐标
|
||
- 对无检测框图像填充 `14 1 0 0 1 1`
|
||
|
||
适用场景:
|
||
|
||
- 快速恢复纯检测 baseline
|
||
- 对比二分类后处理前后的差异
|
||
|
||
### 5.3 `vinbigdata-2-class-classifier-complete-pipeline.ipynb`
|
||
|
||
用途:
|
||
|
||
- 训练二分类器
|
||
- 导出验证集和测试集概率
|
||
- 演示如何将 2-class 结果作用到检测 submission
|
||
|
||
关键行为:
|
||
|
||
- 数据标签定义为:
|
||
- 无异常标注 -> normal
|
||
- 有异常标注 -> abnormal
|
||
- 使用 `StratifiedKFold` 保持 normal / abnormal 比例
|
||
- 导出:
|
||
- `valid_pred.csv`
|
||
- `test_pred.csv`
|
||
- 支持最后一步 2-class filter 后处理
|
||
|
||
适用场景:
|
||
|
||
- 单独复现 normal / abnormal 分支
|
||
- 为现有检测 submission 追加后处理信号
|
||
|
||
### 5.4 `ensembling-approach.ipynb`
|
||
|
||
用途:
|
||
|
||
- 对多个已有 submission 做结果融合
|
||
|
||
关键行为:
|
||
|
||
- 按图像读取多个 `PredictionString`
|
||
- 对每个模型保留高置信度 top-n 结果
|
||
- 对重复类别做概率和框坐标平均
|
||
- 导出新的融合 submission
|
||
|
||
适用场景:
|
||
|
||
- 比较不同检测方案或不同公开 notebook 的互补性
|
||
|
||
### 5.5 `ensemble-of-best-public-notebooks.ipynb`
|
||
|
||
用途:
|
||
|
||
- 对已有 submission 快速再施加一层 2-class filter
|
||
|
||
关键行为:
|
||
|
||
- 读取检测 submission
|
||
- 读取 2-class 预测 csv
|
||
- 按阈值执行 `Keep / Add / Replace`
|
||
- 导出新的 `submission.csv`
|
||
|
||
适用场景:
|
||
|
||
- 不重新训练模型,只做最后一步规则修正
|
||
|
||
## 6. 输入、输出与依赖
|
||
|
||
### 6.1 运行环境
|
||
|
||
该项目基于 Kaggle Notebook 环境编写,当前仓库 **不包含完整可离线执行的依赖清单和脚本封装**。大部分 notebook 默认假设以下前提成立:
|
||
|
||
- 运行环境为 Kaggle
|
||
- 数据、模型权重和外部代码位于 `../input/...`
|
||
- 图像已提前转换为 PNG 或已存在预处理版本
|
||
|
||
### 6.2 主要外部输入
|
||
|
||
从 notebook 中能确认的主要依赖包括:
|
||
|
||
- 官方比赛数据:
|
||
- `vinbigdata-chest-xray-abnormalities-detection`
|
||
- 预处理图像数据:
|
||
- `vinbigdata-chest-xray-resized-png-256x256`
|
||
- `vinbigdata-chest-xray-resized-png-1024x1024`
|
||
- `vinbigdata-512-image-dataset` 或同类 512 PNG 数据
|
||
- 测试元数据:
|
||
- `vinbigdata-testmeta/test_meta.csv`
|
||
- 2-class 预测结果:
|
||
- `vinbigdata-2class-prediction/2-cls test pred.csv`
|
||
- 或 `vinbigdata2classpred/test_pred.csv`
|
||
- 外部模型/代码:
|
||
- `yolov5`
|
||
- 已训练检测权重 `best.pt`
|
||
- 二分类模型权重
|
||
|
||
### 6.3 主要输出
|
||
|
||
| Notebook | 主要输出 |
|
||
| --- | --- |
|
||
| `yolov5-chest-512.ipynb` | `submission.csv`,YOLO 标签目录 |
|
||
| `vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb` | `submission.csv` |
|
||
| `vinbigdata-2-class-classifier-complete-pipeline.ipynb` | `valid_pred.csv`、`test_pred.csv`、后处理后的 `submission.csv` |
|
||
| `ensembling-approach.ipynb` | 融合后的 `submission.csv` |
|
||
| `ensemble-of-best-public-notebooks.ipynb` | 追加 2-class filter 后的 `submission.csv` |
|
||
|
||
## 7. 推荐阅读顺序
|
||
|
||
### 7.1 理解项目主线
|
||
|
||
建议顺序:
|
||
|
||
1. `VINBIGDATA_REVIEW.md`
|
||
2. `yolov5-chest-512.ipynb`
|
||
3. `vinbigdata-2-class-classifier-complete-pipeline.ipynb`
|
||
|
||
目标:
|
||
|
||
- 先理解最终提交的构成方式
|
||
- 再理解检测和二分类分别提供什么信号
|
||
|
||
### 7.2 只恢复纯检测 baseline
|
||
|
||
建议优先阅读:
|
||
|
||
1. `vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb`
|
||
2. `yolov5-chest-512.ipynb` 中的检测后处理部分
|
||
|
||
### 7.3 只恢复后处理与提分思路
|
||
|
||
建议优先阅读:
|
||
|
||
1. `vinbigdata-2-class-classifier-complete-pipeline.ipynb`
|
||
2. `ensemble-of-best-public-notebooks.ipynb`
|
||
3. `ensembling-approach.ipynb`
|
||
|
||
## 8. 复现注意事项
|
||
|
||
### 8.1 本仓库不是完整的本地工程
|
||
|
||
当前仓库仅保留 notebook 与说明文档,没有:
|
||
|
||
- 独立的 `requirements.txt`
|
||
- 统一的训练入口脚本
|
||
- 完整的本地路径配置
|
||
- 明确的最终线上提交版本记录
|
||
|
||
因此,仓库更适合做以下用途:
|
||
|
||
- 回顾比赛策略
|
||
- 迁移部分 notebook 逻辑
|
||
- 抽取后处理与 ensemble 思路
|
||
|
||
不适合直接视为“一键复现实验”的标准工程。
|
||
|
||
### 8.2 路径和参数存在 Kaggle 绑定
|
||
|
||
多数 notebook 直接写死了 `../input/...` 路径,说明原始运行环境依赖 Kaggle Dataset / Notebook Output。若迁移到本地,需要自行重建:
|
||
|
||
- 原始数据目录
|
||
- 预处理 PNG 目录
|
||
- 测试元数据
|
||
- 模型权重目录
|
||
- YOLOv5 代码目录
|
||
|
||
### 8.3 存在比赛期经验化规则
|
||
|
||
项目中保留了较多比赛调参痕迹,例如:
|
||
|
||
- `list_remove`
|
||
- `image_remove`
|
||
- 类别特定阈值
|
||
- `No finding` 的分段规则
|
||
|
||
这些逻辑对理解历史提交有价值,但不应直接视为可泛化的医学影像检测最佳实践。
|
||
|
||
### 8.4 最终最佳提交版本无法仅凭仓库唯一确认
|
||
|
||
从当前仓库可以清楚恢复整体方案,但无法仅凭现有文件 100% 唯一确认最终线上提交是哪一个 notebook 产物或哪个 ensemble 版本。原因包括:
|
||
|
||
- 缺少 leaderboard 版本记录
|
||
- 缺少 commit 级说明
|
||
- 仓库中同时保留了多条尝试路线
|
||
|
||
## 9. 结论
|
||
|
||
本项目的核心不是单一检测模型,而是一套围绕 VinBigData 比赛构建的提交工程:
|
||
|
||
1. 用检测模型识别 14 类异常
|
||
2. 用二分类模型判断 normal / abnormal
|
||
3. 用后处理规则显式处理 `No finding`
|
||
4. 视情况再对多个 submission 进行融合
|
||
|
||
如果只保留一个最值得回看的文件,应优先查看 `yolov5-chest-512.ipynb`;如果要理解本项目为什么能进一步提分,应重点查看 `vinbigdata-2-class-classifier-complete-pipeline.ipynb` 中的 2-class filter 流程。
|