Chest X-ray14数据集实战指南:从数据预处理到模型训练全流程解析

1次阅读
没有评论

共计 2607 个字符,预计需要花费 7 分钟才能阅读完成。

image.webp

Chest X-ray14 数据集实战指南:从数据预处理到模型训练全流程解析

背景介绍

Chest X-ray14 数据集是医学影像分析领域的重要基准数据集,包含 112,120 张标注了 14 种常见胸部疾病的 X 光图像。该数据集由美国国立卫生研究院 (NIH) 发布,具有以下特点:

Chest X-ray14 数据集实战指南:从数据预处理到模型训练全流程解析

  1. 规模大且标注全面:覆盖 14 种病理标签,包括肺不张、心脏肥大、肺实变等
  2. 多标签特性:单张图像可能同时存在多个病理状态
  3. 现实世界数据:包含不同医院采集的图像,存在设备差异
  4. 类别不平衡:某些疾病样本量较少

数据准备

数据下载

使用 wget 命令下载数据集(约 40GB):

wget https://nihcc.app.box.com/v/ChestXray-NIHCC/file/219427872344

解压数据集

unzip images_001.zip -d chest_xray14
# 重复解压所有分卷

数据集目录结构

chest_xray14/
├── images/               # 所有 DICOM 格式图像
│   ├── 00000001_000.png
│   └── ...
└── Data_Entry_2017.csv  # 包含图像路径和标签

图像加载示例

from PIL import Image
import pandas as pd

# 加载标注文件
df = pd.read_csv('chest_xray14/Data_Entry_2017.csv')

# 图像加载函数
def load_image(img_path):
    try:
        img = Image.open(f'chest_xray14/images/{img_path}')
        return img.convert('RGB')  # 统一转换为 RGB 格式
    except Exception as e:
        print(f"Error loading {img_path}: {e}")
        return None

数据预处理

医学影像标准化

  1. 像素值归一化:DICOM 图像通常有 12-16 位深度,需要归一化到 0 - 1 范围
  2. 尺寸统一:将图像 resize 到统一尺寸(如 224×224)
  3. 窗宽窗位调整:增强特定组织的可视性
import cv2
import numpy as np

def preprocess_image(img, target_size=(224,224)):
    # 转换为 numpy 数组
    img_array = np.array(img)

    # 归一化
    img_normalized = (img_array - img_array.min()) / (img_array.max() - img_array.min())

    # 调整大小
    img_resized = cv2.resize(img_normalized, target_size)

    return img_resized

处理类别不平衡

from sklearn.utils.class_weight import compute_class_weight

# 计算类别权重
labels = df['Finding Labels'].str.get_dummies(sep='|')
class_weights = compute_class_weight('balanced', classes=np.unique(labels), y=labels.values.argmax(axis=1))

模型训练

基础 CNN 模型

import torch
import torch.nn as nn
import torch.optim as optim

class ChestXrayCNN(nn.Module):
    def __init__(self, num_classes=14):
        super().__init__()
        self.features = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.classifier = nn.Sequential(nn.Linear(64*56*56, 128),
            nn.ReLU(),
            nn.Linear(128, num_classes)
        )

    def forward(self, x):
        x = self.features(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        return torch.sigmoid(x)  # 多标签分类使用 sigmoid

训练循环

model = ChestXrayCNN()
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 自定义数据加载器
class ChestXrayDataset(torch.utils.data.Dataset):
    # 实现__len__和__getitem__方法
    pass

dataset = ChestXrayDataset(df)
train_loader = torch.utils.data.DataLoader(dataset, batch_size=32, shuffle=True)

for epoch in range(10):
    for images, labels in train_loader:
        outputs = model(images)
        loss = criterion(outputs, labels.float())

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

避坑指南

  1. 数据加载优化:
  2. 使用多进程数据加载
  3. 预加载部分数据到内存
  4. 考虑使用 LMDB 等高效存储格式

  5. 内存不足处理:

  6. 减小 batch size
  7. 使用梯度累积
  8. 尝试混合精度训练

  9. 标签噪声处理:

  10. 使用标签平滑(Label Smoothing)
  11. 采用鲁棒损失函数
  12. 考虑半监督学习方法

进阶建议

  1. 迁移学习:
  2. 使用预训练的 ImageNet 模型作为特征提取器
  3. 尝试医学专用预训练模型如 CheXNet

  4. 多标签处理:

  5. 使用二元交叉熵而非交叉熵损失
  6. 考虑标签相关性建模
  7. 尝试图神经网络捕获标签关系

  8. 模型解释性:

  9. 使用 Grad-CAM 生成热力图
  10. 分析模型关注区域是否合理

思考题

  1. 如何处理 X 光图像中不同设备导致的域偏移问题?
  2. 当某些疾病样本极少时,除了重采样还有哪些数据增强策略?
  3. 如何设计一个能同时预测疾病和定位病灶的端到端模型?
正文完
 0
评论(没有评论)