临床级医疗AI:从多模态模型到智能体合规部署的实战体系(三)
第8章:2D影像分类实战——胸片疾病诊断胸片(Chest X-ray, CXR)是世界上最常见的医学影像检查,也是医疗AI最经典的起点。一个能自动检测肺炎、气胸、肺水肿、心脏肥大等常见疾病的AI,直接具有巨大的临床筛查价值。本章我们以CheXpert或MIMIC-CXR这样的多标签胸片数据集为蓝本,带你构建一个可落地的2D多标签分类器,并重点突破类别不平衡、不确定性标签等核心难题。8.1 数据加载:构建多标签胸片数据集CheXpert数据集包含224,316张胸片,标记了14种放射学发现,每个标签有三个取值:1(阳性)、0(阴性)、-1(不确定)。这种设计反映了临床报告中普遍存在的模糊性。我们首先要决定如何处理这些“不确定”标签。标签策略选择:忽略不确定:将-1视为缺失值,训练时跳过该样本的该标签维度。这最严谨,但实现复杂。全填0:将不确定视为阴性,这是CheXpert论文中使用的“U-Zeros”策略,简单有效,被广泛采用。全填1:将不确定视为阳性,更保守,适合筛查场景。软标签:将不确定视为0.5概率的软标签,体现不确定性。这符合第4章的软标签思想。# U-Zeros策略:将-1替换为0defconvert_labels(label_df):returnlabel_df.fillna(0).replace(-1,0)MONAI数据加载器构建:我们使用MONAI的ImageDataset,配合自定义的数据列表。frommonai.dataimportImageDatasetimportpandasaspd# 假设有一个dataframe: 'image_path', 'Atelectasis', 'Cardiomegaly', ...train_df=pd.read_csv('chexpert_train.csv')# 获取图像路径列表和标签矩阵 (n_samples, 14)image_paths=train_df['image_path'].tolist()labels=train_df.iloc[:,1:].values.astype(np.float32)# 定义图像增强变换train_transforms=Compose([LoadImaged(keys=['img']),EnsureChannelFirstd(keys=['img']),ScaleIntensityd(keys=['img'],minv=0.0,maxv=1.0),# 归一化到[0,1]RandRotated(keys=['img'],range_x=15,prob=0.5),RandZoomd(keys=['img'],min_zoom=0.9,max_zoom=1.1,prob=0.5),RandFlipd(keys=['img'],spatial_axis=0,prob=0.5),Resized(keys=['img'],spatial_size=(224,224)),EnsureTyped(keys=['img']),])# 因为ImageDataset期望(image, label)格式,我们可以使用列表推导构建数据train_data=[{'img':img,'label':label}forimg,labelinzip(image_paths,labels)]train_ds=Dataset(data=train_data,transform=train_transforms)train_loader=DataLoader(train_ds,batch_size=64,shuffle=True,num_workers=8)8.2 类别不平衡的终极武器:从Focal Loss到Asymmetric Loss胸片数据中,疾病标签是典型的长尾分布。“无发现”(No Finding)占一半以上,而“气胸”等急症只占不到1%。普通二元交叉熵损失(BCE)在这种严重不平衡下会直接崩溃:模型只需把所有样本都预测为阴性,就能获得很低的loss,但毫无意义。Focal Loss (FL):何恺明提出的Focal Loss通过添加调节因子(1 - p_t)^γ来降低易分样本的损失贡献,强制模型聚焦于难分样本。FL(pt)=−αt(1−pt)γlog(pt) FL(p_t) = -\alpha_t (1 - p_t)^\gamma \log(p_t)FL(pt)=−αt(1−p