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

CNN验证准确率不提升求助:EyePACs视网膜图像分类任务

眼部视网膜图像分类问题分析与优化

问题背景

尝试构建简易CNN区分不同严重程度的眼部视网膜扫描图像,初始为5类多分类任务,采用Kaggle EyePACs缩放后数据集。训练时预期训练与验证准确率同步上升,但实际验证准确率毫无提升;转为0和4两类二分类任务后,曲线仍无明显改善。未做图像预处理,原计划先实现基础学习再用CLAHE等优化,但模型初始准确率达0.75且后续无提升,验证集完全无学习迹象。

当前代码与输出

数据集构建代码

import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "/content/drive/MyDrive/Colab Notebooks/resized train 15/Binary 0-4",
    labels="inferred",
    label_mode="binary",
    validation_split=0.2,
    seed=1337,
    subset="training",
)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "/content/drive/MyDrive/Colab Notebooks/resized train 15/Binary 0-4",
    labels="inferred",
    label_mode="binary",
    validation_split=0.2,
    seed=1337,
    subset="validation",
)

test_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "/content/drive/MyDrive/Colab Notebooks/resized test 15/0-4/",
    labels="inferred",
    label_mode="binary",
)

数据集输出

Found 26518 files belonging to 2 classes.

Using 21215 files for training.

Found 26518 files belonging to 2 classes.

Using 5303 files for validation.

Found 36759 files belonging to 2 classes.

模型与训练代码

# 加速处理
train_ds = train_ds.prefetch(buffer_size=32)
val_ds = val_ds.prefetch(buffer_size=32)
test_ds = test_ds.prefetch(buffer_size=32)

# 模型架构:
from keras.models import Sequential
from keras.layers import Dense, Rescaling, Conv2D, MaxPool2D, Flatten

model = Sequential()
model.add(Rescaling(1.0 / 255))
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(256,256,3)))
model.add(MaxPool2D(pool_size=(2, 2), strides=2))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(MaxPool2D(pool_size=(2, 2), strides=2))
model.add(Flatten())
model.add(Dense(units=2, activation='sigmoid'))

# 编译模型:
from keras import optimizers

model.compile(optimizer=keras.optimizers.Adam(1e-3), loss='sparse_categorical_crossentropy', metrics=['accuracy'])

# 训练:
history = model.fit(
          x=train_ds,
          epochs=30,
          validation_data=val_ds,
)

# 测试评估:
loss, acc = model.evaluate(test_ds)
print("Accuracy", acc)

训练输出

1149/1149 [==============================] - 278s 238ms/step - loss: 0.1408 - accuracy: 0.9672

Accuracy 0.9671916961669922

核心问题分析

  1. 损失函数与输出层不匹配:二分类任务中label_mode="binary"对应单值标签(0/1),但当前输出层设为2个单元+sigmoid激活,搭配sparse_categorical_crossentropy损失,完全不符合二分类配置逻辑,导致模型学习信号混乱,无法有效更新权重。
  2. 类别不平衡嫌疑:初始准确率0.75大概率是某类样本占比75%,模型仅靠输出占比高的类别就能达到该准确率,后续无提升说明模型未学到有效特征。
  3. 模型容量不足:仅两层卷积的简易CNN,无法捕捉视网膜图像中区分病理特征(如血管、渗出物)的精细信息,特征提取能力太弱。
  4. 缺乏图像预处理:视网膜图像普遍存在光照不均、对比度低的问题,直接输入原始图像会让模型难以聚焦于有效病理特征,阻碍基础学习。

优化方向与修正代码

关键优化点

  1. 修正模型与损失函数的二分类适配配置
  2. 处理类别不平衡问题
  3. 增强模型特征提取能力
  4. 添加图像预处理与数据增强

修正后的核心代码

# 修正模型架构
model = Sequential()
model.add(Rescaling(1.0 / 255))
# 添加数据增强
model.add(layers.RandomFlip("horizontal"))
model.add(layers.RandomRotation(0.1))
# 增加卷积层并加入BatchNormalization
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=(256,256,3)))
model.add(layers.BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2), strides=2))
model.add(Conv2D(64, kernel_size=(3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2), strides=2))
model.add(Conv2D(128, kernel_size=(3, 3), activation='relu'))
model.add(layers.BatchNormalization())
model.add(MaxPool2D(pool_size=(2, 2), strides=2))
model.add(Flatten())
# 添加Dropout防止过拟合
model.add(layers.Dropout(0.5))
# 二分类正确输出层:1个单元+ sigmoid
model.add(Dense(units=1, activation='sigmoid'))

# 修正编译配置
model.compile(optimizer=keras.optimizers.Adam(1e-4), # 降低学习率提升稳定性
              loss='binary_crossentropy', 
              metrics=['accuracy'])

# 计算类别权重(假设类别0占比75%,类别4占比25%,权重反比于类别占比)
class_weights = {0: 1.0, 4: 3.0}

# 训练时加入类别权重
history = model.fit(
          x=train_ds,
          epochs=30,
          validation_data=val_ds,
          class_weight=class_weights
)

额外建议

  • 先统计数据集各类别样本数量,确认是否存在类别不平衡问题
  • 可视化训练/验证的损失与准确率曲线,直观观察模型学习状态
  • 尝试预训练模型(如ResNet50)做迁移学习,这是医学图像分类任务中快速提效的常用方法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 10:39:16