686. PhysioNet - Digitization of ECG Images | physionet-ecg-image-digitization
本解决方案针对 PhysioNet 挑战,旨在将 ECG 图像数字化——将打印/拍摄的 ECG 记录转换回数值波形数据。该方法使用三阶段深度学习流程,逐步将原始 ECG 图像转换为高保真数字波形。
最终公共排行榜得分:21.56 SNR
最终私有排行榜得分:21.37 SNR
来自各种来源的 ECG 图像(打印记录、手机照片、损坏文档的扫描件)需要转换回数字波形。挑战涉及:

目的:检测导联标记并校正图像方向
注意:对于此阶段,我使用了 原始基线 中提供的预训练阶段 0 检查点。
目的:检测并校正网格失真
注意:与阶段 0 类似,我使用了 原始基线 中的预训练阶段 1 检查点。
目的:从校正后的图像中提取 ECG 波形
这是主要的预测阶段,大部分创新在于此。

HRNet-W48 骨干网络:通过并行分支在整个网络中保持高分辨率表示,对于精确的像素级波形预测至关重要
CoordConv 解码器:在每个解码器块注入归一化的 2D 坐标,实现位置感知预测,这对于 ECG 布局理解至关重要
RGB 跳跃连接:从输入图像到预测头的直接连接保留了可能在编码器压缩中丢失的精细空间细节
PixelShuffle 上采样:使用子像素卷积进行内存高效的可学习上采样,代替转置卷积
GroupNorm:支持 batch size 为 1 的稳定训练(对于有限 GPU 内存上的高分辨率 1696×4352 图像是必要的)
模型使用带正类加权的二元交叉熵 (BCE) 进行像素级监督:
loss = F.binary_cross_entropy_with_logits(
pixel_logit,
target_mask,
pos_weight=10.0 # 处理稀疏的 ECG 线条像素
)
发现此方法优于基于回归的损失(MSE, SNR)。
开发了全面的 segment 感知的增强流程 以匹配多样的训练数据分布:
| 增强 | 概率 | 目的 |
|---|---|---|
| Perlin 噪声 | 85% | 模拟扫描仪噪声、纸张纹理 |
| 纹理噪声 | 70% | 网格状伪影、扫描线 |
| 颜色抖动 | 80% | 亮度、对比度、饱和度、色调变化 |
| 高斯噪声 | 50% | 扫描仪 ISO 噪声 |
| 高斯模糊 | 35% | 低质量扫描、失焦照片 |
| 阴影叠加 | 35% | 不均匀照明 |
| 纸张纹理 | 30% | 物理纸张颗粒模拟 |
| JPEG 伪影 | 30% | 压缩伪影 |
| 水平翻转 | 50% | 数据增强(带标签翻转) |
训练数据包含 12 种具有不同特征的 segment 类型。增强流程根据 segment 类型应用针对性的退化:
| Segment | 特征 | 应用的增强 |
|---|---|---|
| 0003 | 标准彩色扫描 | 仅基线增强 |
| 0004 | 黑白扫描 | 灰度转换 + 纸张色调 |
| 0005 | 手机照片 | 暗角 + 阴影渐变 |
| 0006 | 屏幕照片 | 摩尔纹 + 屏幕 glare |
| 0009 | 水损 | 水渍 + 颜色渗色 |
| 0010 | 严重损坏 | 折叠褶皱 + 重度噪声 |
| 0011, 0012 | 发霉扫描 | 霉斑 + 灰度 |
为避免昂贵的实时增强操作(尤其是 Perlin 噪声生成),内存映射缓存系统 预计算增强掩码:
| 参数 | 值 |
|---|---|
| Batch Size | 1 (4352×1696 全分辨率) |
| 优化器 | AdamW |
| 学习率 | 1e-4 |
| 权重衰减 | 0.05 |
| Epochs | 80 |
| EMA 衰减 | 0.999 |
| 训练/验证 分割 | 100/0 (完整训练集) |
| 混合精度 | FP16 (AMP) |
| 梯度检查点 | 为解码器启用 |
水平翻转 TTA 提高鲁棒性:
基于物理的后处理步骤强制实施心电图约束:
爱因托芬定律: 导联 II = 导联 I + 导联 III
校正将违规错误重新分配到所有三个肢体导联:
error = II - (I + III)
I_corrected = I + α × error
III_corrected = III + α × error
II_corrected = II - α × error # α = 0.33
4 条带的像素预测通过以下方式转换为波形:
注意:这些分数是近似值。更改未单独隔离,以加快迭代速度并节省计算成本。
| 配置 | 公共 LB 得分 |
|---|---|
| 基线 (BCE 损失 + 全面增强,90/10 分割) | ~15.31 |
| + 高分辨率 (1696×4352) | ~18.22 |
| + HRNet-W48 骨干网络 (替换 ResNet) | ~20.90 |
| + 100/0 训练/验证 分割 (使用所有训练数据) | ~21.01 |
| + 水平翻转 TTA | ~21.28 |
| + 爱因托芬定律校正 | ~21.32 |
| + RGB Skip + PixelShuffle + 融合头 | ~21.56 |
分辨率很重要:从标准分辨率增加到 1696×4352 提供了最大的单一改进 (~3 SNR)
HRNet 优势:多分辨率并行分支比传统编码器 - 解码器架构更好地保留空间精度
完整训练数据:通过全面增强,使用 100% 数据进行训练优于保留验证集
物理约束有帮助:爱因托芬校正通过强制已知的 ECG 关系提供一致的小幅改进
在 batch size 为 1 的情况下训练高分辨率图像 (1696×4352) 需要仔细的内存管理:
├── stage0_model.py # 阶段 0:标记检测与标准化
├── stage1_model.py # 阶段 1:网格检测与校正
├── stage2_model.py # 阶段 2:波形预测 (主模型)
├── predictor_dataset.py # 训练数据加载与预处理
├── predictor_trainer.py # 带 EMA、指标的训练循环
├── augmentations.py # 全面增强流程
├── augmentation_cache.py # 内存映射增强缓存
├── demo-submission.py # 端到端推理与提交生成
├── config_predictor.yaml # 训练配置
└── archive/
├── stage0-last.checkpoint.pth # 阶段 0 预训练权重
└── stage1-last.checkpoint.pth # 阶段 1 预训练权重
该解决方案通过以下方式在 ECG 数字化方面实现了强劲性能:
希望你喜欢我的报告。感谢阅读!
该解决方案建立在 Kaggle 社区分享的出色工作之上: