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

基于胸片的COVID-19检测CNN模型过拟合问题求助

问题描述

我正在构建一个基于CNN的胸片COVID-19检测模型,使用包含约27000张图像的数据集,仅选用其中的COVID和NORMAL两类。参考Keras图像分类教程调整后得到代码如下:

batch_size = 16
img_height = 160
img_width = 160
img_size = (img_height, img_width)
seed_train_validation = 1
shuffle_value = True
validation_split = 0.3
train_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    image_size = img_size,
    validation_split = validation_split,
    subset = "training",
    seed = seed_train_validation,
    color_mode = "grayscale",
    shuffle = shuffle_value
)
val_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    image_size = img_size,
    validation_split = validation_split,
    subset = "validation",
    seed = seed_train_validation,
    color_mode = "grayscale",
    shuffle = shuffle_value
)
val_batches = tf.data.experimental.cardinality(val_ds)
test_ds = val_ds.take((2*val_batches) // 3)
val_ds = val_ds.skip((2*val_batches) // 3)
AUTOTUNE = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
val_ds = val_ds.cache().prefetch(buffer_size=AUTOTUNE)
resize_and_rescale = tf.keras.Sequential([
  layers.Resizing(img_height, img_width),
  layers.Rescaling(1./255)
])
data_augmentation = tf.keras.Sequential([
  layers.RandomFlip("horizontal_and_vertical"),
  layers.RandomRotation(0.2),
  layers.RandomZoom(0.1)
])
num_classes = len(class_names)

model_1 = Sequential([
    resize_and_rescale,
    data_augmentation,
    layers.Conv2D(16, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(64, 3, padding='same', activation='relu'),
    layers.MaxPooling2D(),
    layers.Dropout(0.2),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(num_classes)
])
model_1.compile(optimizer="adam",
                loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])
epochs = 75
history = model_1.fit(
    train_ds,
    validation_data = val_ds,
    epochs = epochs
)

训练轮数较少(如10轮)时,准确率和损失曲线表现正常;但训练75轮时曲线出现异常,已加入数据增强和Dropout层但效果不佳,怀疑是过拟合问题,寻求解决建议。


解决建议
  • 提前停止训练(Early Stopping)
    直接避免模型过度训练,当验证集性能连续多轮无提升时自动停止,并恢复到最优权重:

    early_stopping = tf.keras.callbacks.EarlyStopping(
        monitor='val_loss',
        patience=10,
        restore_best_weights=True
    )
    # 训练时加入回调
    history = model_1.fit(
        train_ds,
        validation_data=val_ds,
        epochs=75,
        callbacks=[early_stopping]
    )
    
  • 强化正则化
    现有正则化力度不足,可从两方面优化:

    • 提升Dropout比例至0.3-0.5
    • 给卷积层和全连接层添加L2正则化,限制权重规模:
      from tensorflow.keras import regularizers
      
      model_1 = Sequential([
          resize_and_rescale,
          data_augmentation,
          layers.Conv2D(16, 3, padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.001)),
          layers.MaxPooling2D(),
          layers.Conv2D(32, 3, padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.001)),
          layers.MaxPooling2D(),
          layers.Conv2D(64, 3, padding='same', activation='relu', kernel_regularizer=regularizers.l2(0.001)),
          layers.MaxPooling2D(),
          layers.Dropout(0.3),
          layers.Flatten(),
          layers.Dense(128, activation='relu', kernel_regularizer=regularizers.l2(0.001)),
          layers.Dense(num_classes)
      ])
      
  • 优化数据增强策略
    胸片垂直翻转无医学意义,反而引入噪声,同时可增加更多有效扰动:

    data_augmentation = tf.keras.Sequential([
      layers.RandomFlip("horizontal"),
      layers.RandomRotation(0.15),
      layers.RandomZoom(0.15),
      layers.RandomContrast(0.1),
      layers.RandomTranslation(height_factor=0.1, width_factor=0.1)
    ])
    
  • 精简模型结构
    降低模型容量减少过拟合风险:

    • 把全连接层的128个神经元缩减至64
    • 在卷积层后添加BatchNormalization层,稳定训练同时抑制过拟合:
      model_1 = Sequential([
          resize_and_rescale,
          data_augmentation,
          layers.Conv2D(16, 3, padding='same', activation='relu'),
          layers.BatchNormalization(),
          layers.MaxPooling2D(),
          layers.Conv2D(32, 3, padding='same', activation='relu'),
          layers.BatchNormalization(),
          layers.MaxPooling2D(),
          layers.Conv2D(64, 3, padding='same', activation='relu'),
          layers.BatchNormalization(),
          layers.MaxPooling2D(),
          layers.Dropout(0.3),
          layers.Flatten(),
          layers.Dense(64, activation='relu'),
          layers.Dense(num_classes)
      ])
      
  • 调整学习率策略
    降低初始学习率或添加学习率衰减,避免训练后期震荡:

    lr_scheduler = tf.keras.optimizers.schedules.ExponentialDecay(
        initial_learning_rate=0.001,
        decay_steps=1000,
        decay_rate=0.96,
        staircase=True
    )
    optimizer = tf.keras.optimizers.Adam(learning_rate=lr_scheduler)
    model_1.compile(optimizer=optimizer,
                    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                    metrics=['accuracy'])
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 09:02:34