You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Chestxray数据集训练ResNet50时验证精度劣于训练精度的问题排查

解决方案:Chestxray多标签分类ResNet50训练不收敛问题

你的核心问题是训练精度持续上升但验证精度波动下降,属于典型的过拟合+指标误用结合的场景,以下是针对性解决步骤:

1. 修正多标签任务的评价指标

你使用的默认accuracy在多标签任务中完全不适用——它要求样本的13个标签预测全对才算正确,这在医学影像多标签场景里几乎不可能实现,导致你看到的精度数值极低且无参考性。必须替换为适配多标签的指标:

# 替换为binary_accuracy,适配多标签逐样本评判
model.compile(optimizer=adam_optimizer, 
              loss='binary_crossentropy', 
              metrics=['binary_accuracy'])

如果需要更贴合医学任务的指标,可加入精度、召回率或自定义F1-score:

from tensorflow.keras.metrics import Precision, Recall

model.compile(optimizer=adam_optimizer, 
              loss='binary_crossentropy', 
              metrics=['binary_accuracy', Precision(name='precision'), Recall(name='recall')])

这一步是基础,先把评价指标改对,才能正确判断模型是否真的在收敛。

2. 调整预训练模型的训练策略(解冻+微调)

你冻结了ResNet50的所有层,仅训练最后一个全连接层,模型容量严重不足,极易拟合训练集噪声。正确做法是分阶段训练:

  • 第一阶段:冻结ResNet50大部分层,只训练顶部自定义全连接层,让模型先适配任务标签分布;
  • 第二阶段:解冻ResNet50后10-20层,用极小学习率微调,让预训练特征适配当前任务。

示例代码:

# 第一阶段:冻结预训练层,训练顶部
resnet50 = ResNet50(input_shape=(256, 256, 3), weights='imagenet', include_top=False)
for layer in resnet50.layers:
    layer.trainable = False

x = Flatten()(resnet50.output)
x = Dropout(0.5)(x)  # 添加Dropout抑制过拟合
prediction = Dense(13, activation='sigmoid')(x)

model = Model(inputs=resnet50.input, outputs=prediction)
model.compile(optimizer=Adam(learning_rate=0.001), 
              loss='binary_crossentropy', 
              metrics=['binary_accuracy'])
history = model.fit(train_dataset, epochs=10, validation_data=val_dataset)

# 第二阶段:解冻后20层,微调
for layer in resnet50.layers[-20:]:
    layer.trainable = True

# 微调使用极小学习率,避免破坏预训练特征
model.compile(optimizer=Adam(learning_rate=1e-5), 
              loss='binary_crossentropy', 
              metrics=['binary_accuracy'])
history_fine = model.fit(train_dataset, epochs=30, validation_data=val_dataset, initial_epoch=history.epoch[-1])

3. 处理标签不平衡问题

Chestxray数据集普遍存在标签不平衡(正常样本多、罕见病变样本少),会导致模型偏向多数类,验证集表现差。解决方法:

  • 计算类别权重,在损失函数中加入权重惩罚:
# 假设已统计每个标签的样本数counts
import numpy as np
total_samples = len(train_dataset)
class_weights = {i: total_samples / (2 * counts[i]) for i in range(13)}

# 训练时传入类别权重
history = model.fit(train_dataset, epochs=10, validation_data=val_dataset, class_weight=class_weights)
  • 对少数类样本进行过采样,或针对性增强少数类样本的数据增强。

4. 优化数据预处理与增强

Chestxray是灰度图转3通道输入没问题,但需确保预处理与ImageNet一致:

  • 归一化:将像素值缩放到[0,1],或用ImageNet均值[0.485, 0.456, 0.406]和方差[0.229, 0.224, 0.225]做标准化;
  • 数据增强贴合医学影像特点:保留左右翻转(胸部X光有意义),避免上下翻转,可加入随机裁剪、亮度微调、高斯噪声等,避免过度增强导致样本失真。

5. 调整学习率与训练回调

  • 当前学习率0.001在全冻结训练时可能偏高,建议加入学习率调度器:
from tensorflow.keras.callbacks import ReduceLROnPlateau

reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-7)
callbacks = [early_stopping, reduce_lr]
  • EarlyStopping建议监控val_loss而非val_accuracy,损失是更稳定的收敛指标,尤其在多标签任务中。

6. 检查数据集划分与加载

确认训练/验证集划分无数据泄露(验证集样本未出现在训练集);检查batch_size是否合理,过大易过拟合,过小会导致训练不稳定。


内容的提问来源于stack exchange,提问作者Hamza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 00:50:56