# 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[官方比赛数据
train.csv / test dicom] --> B[图像预处理数据集
256 / 512 / 1024 PNG]
B --> C[yolov5-chest-512.ipynb
主检测流程]
A --> C
B --> D[vinbigdata-2-class-classifier-complete-pipeline.ipynb
normal / abnormal 二分类]
A --> D
C --> E[14 类异常检测结果]
D --> F[test_pred.csv / valid_pred.csv
整图 normal 概率]
E --> G[后处理逻辑
Keep / Add / Replace]
F --> G
G --> H[submission.csv]
H --> I[ensemble-of-best-public-notebooks.ipynb
轻量 2-class 再过滤]
F --> I
I --> J[postprocessed submission.csv]
H --> K[ensembling-approach.ipynb
多 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
保留检测结果]
B -->|low_threshold <= p < high_threshold| D[Add
保留检测结果并追加 class 14]
B -->|p >= high_threshold| E[Replace
替换为 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 流程。