Files
vinbigdata-cxr-kaggle-pipeline/VINBIGDATA_REVIEW.md
T

14 KiB
Raw Blame History

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

其中:

  • 013 表示 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.csvtest_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 职责,以及后处理决策逻辑。

总体流水线

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 职责图

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[同类框平均融合]

后处理决策图

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
  • 默认 backboneresnet18
  • 5-fold StratifiedKFold
  • 训练轮数:epoch=15
  • 调度器:CosineAnnealingWarmRestarts
  • 支持 mixuplabel_smoothingEMA
  • 输出:
    • 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=640conf=0.15iou=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.csvYOLO 标签目录
vinbigdata-cxr-ad-yolov5-14-class-infer.ipynb submission.csv
vinbigdata-2-class-classifier-complete-pipeline.ipynb valid_pred.csvtest_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 流程。