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

TensorFlow脑肿瘤CNN模型与Kaggle同功能模型表现差异排查求助

脑肿瘤分类CNN模型问题排查:数据管道差异分析

核心问题

使用tf.keras.utils.image_dataset_from_directory替代原Kaggle自定义数据管道后,模型出现异常:所有样本预测同一值,但评估显示90%准确率,与原模型表现差距极大,核心问题集中在数据管道的多个关键差异上。

关键差异与问题点

1. 验证/测试集的使用逻辑错误

  • 你的代码:将独立的Testing目录直接作为验证集使用,且训练阶段未传入任何验证数据(model.fit无validation_data参数);同时从Training目录拆分出的20%验证集被完全闲置。
  • 原代码:用Training全量数据训练,Testing仅作为最终测试集,训练过程无额外验证集,但自定义生成器仅对训练数据做增强。
  • 影响:所谓的“90%验证准确率”实际是测试集准确率,若数据集存在类别不平衡(某类样本占比90%),模型只需全预测该类就能得到高准确率,但完全丧失分类能力。

2. 数据增强的时机与实现错误

  • 你的代码:将增强层嵌入模型,导致验证/测试阶段也会应用随机增强(如RandomBrightness),且Rescaling(1./255)放在增强之后——原始图像为0-255范围,增强后像素值可能超出范围,再做归一化会破坏数据分布。
  • 原代码:仅在训练阶段的自定义生成器中做增强,验证/测试时无增强;且基于0-255图像做增强后再归一化到0-1。
  • 影响:测试数据的随机变换会导致评估结果不可靠,数据分布异常则会让模型无法学习有效特征,最终只能偏向占比最高的类别。

3. 预训练模型的预处理缺失

  • 你的代码:仅用Rescaling(1./255)做归一化,未遵循VGG16预训练时的输入要求(需将像素值转换为符合ImageNet数据集的分布,通常是减去均值并缩放)。
  • 原代码:虽未显式使用VGG16的预处理函数,但自定义的归一化逻辑(除以255)与原模型训练时的输入更匹配。
  • 影响:VGG16的预训练特征无法有效复用,模型只能从头学习,且数据分布不匹配会导致特征提取失效,最终出现随机预测或偏向多数类的情况。

4. 类别编码顺序不一致

  • 你的代码:image_dataset_from_directory默认按字母顺序编码类别。
  • 原代码:按os.listdir(train_dir)的系统遍历顺序编码类别。
  • 影响:若两类编码顺序不同,模型预测的索引会对应错误的类别,进一步干扰准确率的判断,甚至让你误以为模型有效。

修复建议

1. 修正验证集与测试集的使用

从Training目录拆分出验证集用于训练监控,Testing目录仅作为最终测试:

# 训练集(80%)
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "C:\\data\\MRI Images\\Training",
    labels="inferred",
    color_mode="rgb",
    batch_size=BATCH_SIZE,
    seed=123,
    image_size=(IMG_SIZE, IMG_SIZE),
    subset="training",
    validation_split=0.2
)

# 验证集(20%,来自Training目录)
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "C:\\data\\MRI Images\\Training",
    labels="inferred",
    color_mode="rgb",
    batch_size=BATCH_SIZE,
    seed=123,
    image_size=(IMG_SIZE, IMG_SIZE),
    subset="validation",
    validation_split=0.2
)

# 独立测试集
test_ds = tf.keras.preprocessing.image_dataset_from_directory(
    "C:\\data\\MRI Images\\Testing",
    labels="inferred",
    color_mode="rgb",
    batch_size=BATCH_SIZE,
    seed=123,
    image_size=(IMG_SIZE, IMG_SIZE)
)

2. 调整数据增强的应用时机

将增强移出模型,仅在训练阶段应用,同时使用VGG16的官方预处理:

# 定义增强层(仅训练时使用)
data_augmentation = Sequential([
    layers.RandomBrightness(0.2),
    layers.RandomContrast(0.2),
])

# 训练数据:预处理+增强
def train_preprocess(image, label):
    image = tf.keras.applications.vgg16.preprocess_input(image)
    image = data_augmentation(image, training=True)
    return image, label

# 验证/测试数据:仅预处理
def val_test_preprocess(image, label):
    image = tf.keras.applications.vgg16.preprocess_input(image)
    return image, label

train_ds = train_ds.map(train_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.map(val_test_preprocess, num_parallel_calls=tf.data.AUTOTUNE)
test_ds = test_ds.map(val_test_preprocess, num_parallel_calls=tf.data.AUTOTUNE)

3. 修正模型结构

移除模型内的增强层,确保输入符合VGG16要求:

base_model = VGG16(input_shape=(IMG_SIZE, IMG_SIZE, 3), weights='imagenet', include_top=False)
for layer in base_model.layers:
    layer.trainable = False
# 解冻最后3层
base_model.layers[-2].trainable = True
base_model.layers[-3].trainable = True
base_model.layers[-4].trainable = True

model = Sequential([
    base_model,
    layers.Flatten(),
    layers.Dropout(0.3),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(4, activation='softmax')
])

model.compile(
    loss='sparse_categorical_crossentropy',
    metrics=['sparse_categorical_accuracy'],
    optimizer=Adam(learning_rate=0.0001)
)

4. 监控训练过程并处理类别不平衡

  • 训练时传入验证集,观察损失与准确率变化:
epochs=10  # 适当增加轮次
history = model.fit(
    train_ds,
    epochs=epochs,
    validation_data=val_ds
)
  • 检查数据集类别分布,若不平衡,在fit中加入class_weight参数:
# 统计各类样本数,计算权重
class_counts = [len(os.listdir(f"C:\\data\\MRI Images\\Training\\{cls}")) for cls in os.listdir("C:\\data\\MRI Images\\Training")]
total_samples = sum(class_counts)
class_weight = {i: total_samples / count for i, count in enumerate(class_counts)}

history = model.fit(
    train_ds,
    epochs=epochs,
    validation_data=val_ds,
    class_weight=class_weight
)

最终评估

训练完成后,用独立测试集评估模型性能:

print("测试集评估结果:", model.evaluate(test_ds))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 10:15:34