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

ResNet50瓶颈层迁移学习准确率极低(仅6%)问题排查求助

排查瓶颈层迁移学习准确率极低的问题

看起来你遇到的核心问题是瓶颈特征和标签的对应关系错位,以及一处可能的变量名拼写错误,导致模型完全无法学习到有效的分类特征。下面一步步拆解问题并给出修复方案:

1. 变量名拼写错误:num_class vs num_classes

你的代码中定义标签时用的是num_classes=num_classes(对应120个犬种),但在构建顶层模型时写成了:

model.add(Dense(num_class, activation='softmax'))

如果num_class是未正确定义的变量(比如误写了num_classes),输出层的神经元数量会和实际类别数不匹配——比如如果num_class被默认赋值为1,模型只能输出1类,自然无法正确分类120个犬种。优先修正这个笔误:

# 把num_class改为num_classes,和标签定义保持一致
model.add(Dense(num_classes, activation='softmax'))

2. 瓶颈特征与标签的样本数量不匹配

当使用flow_from_directory+predict_generator时,如果数据集的样本总数不是batch_size的整数倍,predict_generator默认只会返回floor(样本数/batch_size)批数据,剩余的样本会被丢弃。但train_generator.classes会包含所有样本的标签,这就导致bottleneck_features_train的样本数少于train_labels,训练时模型会循环复用特征,最终特征和标签完全错位,模型学不到任何有效信息。

修复方案:

手动指定predict_generator的steps参数,确保覆盖所有样本:

# 计算训练集和验证集的完整步数
train_steps = train_generator.samples // train_generator.batch_size
# 如果有剩余样本,加1步
if train_generator.samples % train_generator.batch_size != 0:
    train_steps += 1

val_steps = validation_generator.samples // validation_generator.batch_size
if validation_generator.samples % validation_generator.batch_size != 0:
    val_steps += 1

# 生成瓶颈特征时指定steps
bottleneck_features_train = tr_model.predict_generator(train_generator, steps=train_steps)
bottleneck_features_validation = tr_model.predict_generator(validation_generator, steps=val_steps)

同时可以添加断言,确保特征和标签样本数一致:

assert bottleneck_features_train.shape[0] == train_labels.shape[0], "特征与标签样本数不匹配!"
assert bottleneck_features_validation.shape[0] == validation_labels.shape[0], "验证特征与标签样本数不匹配!"

3. 顶层模型的训练策略优化

仅用Flatten+Dense的结构可能容易过拟合,而且rmsprop的学习率可能不适合小模型。可以尝试:

  • 添加Dropout层抑制过拟合
  • 改用Adam优化器,设置合适的学习率

示例修正后的顶层模型:

model = Sequential()
model.add(Flatten(input_shape=bottleneck_features_train.shape[1:]))
model.add(Dropout(0.5))  # 添加Dropout层缓解过拟合
model.add(Dense(num_classes, activation='softmax'))

# 改用Adam优化器,设置较小的学习率
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),
              loss='categorical_crossentropy',
              metrics=['accuracy'])

修正后的完整代码片段

from tensorflow.keras.applications import ResNet50
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.utils import to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Flatten, Dense, Dropout
from tensorflow.keras.optimizers import Adam
import tensorflow as tf

# 假设已定义这些变量
train_data_dir = "path/to/train"
validation_data_dir = "path/to/val"
image_size = 224
batch_size = 32
num_classes = 120

# 加载预训练ResNet50,不包含顶层
tr_model = ResNet50(include_top=False, weights='imagenet', input_shape=(224, 224, 3))
datagen = ImageDataGenerator(rescale=1. / 255)

#### Training ####
train_generator = datagen.flow_from_directory(
    train_data_dir,
    target_size=(image_size, image_size),
    class_mode=None,
    batch_size=batch_size,
    shuffle=False
)
# 计算完整步数
train_steps = train_generator.samples // batch_size
if train_generator.samples % batch_size != 0:
    train_steps += 1
bottleneck_features_train = tr_model.predict_generator(train_generator, steps=train_steps)
train_labels = to_categorical(train_generator.classes, num_classes=num_classes)
# 确保特征和标签样本数一致
assert bottleneck_features_train.shape[0] == train_labels.shape[0], "特征与标签样本数不匹配!"

#### Validation ####
validation_generator = datagen.flow_from_directory(
    validation_data_dir,
    target_size=(image_size, image_size),
    class_mode=None,
    batch_size=batch_size,
    shuffle=False
)
val_steps = validation_generator.samples // batch_size
if validation_generator.samples % batch_size != 0:
    val_steps += 1
bottleneck_features_validation = tr_model.predict_generator(validation_generator, steps=val_steps)
validation_labels = to_categorical(validation_generator.classes, num_classes=num_classes)
assert bottleneck_features_validation.shape[0] == validation_labels.shape[0], "验证特征与标签样本数不匹配!"

#### Model creation ####
model = Sequential()
model.add(Flatten(input_shape=bottleneck_features_train.shape[1:]))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.compile(
    optimizer=Adam(learning_rate=1e-4),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)

history = model.fit(
    bottleneck_features_train,
    train_labels,
    epochs=30,
    batch_size=batch_size,
    validation_data=(bottleneck_features_validation, validation_labels)
)

按照上面的修正,你的模型应该能学习到有效的特征,准确率会接近带顶层的ResNet50水平。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 06:49:42