多输入尺寸图像分类集成模型训练精度异常求助
集成模型训练精度异常的解决方法
核心问题定位
- 输入名称不匹配:构建集成模型时,输入被命名为
input_0、input_1,但喂数据时用的是inputmobilenet_v2_100_96等名称,导致模型无法正确接收对应输入。 - 损失函数与输出激活不兼容:使用
CategoricalCrossentropy(from_logits=True)但输出层用了sigmoid激活,from_logits=True要求输出为未经过激活的原始logits。 - 分类任务激活函数选择错误:200类分类任务应使用
softmax而非sigmoid,sigmoid更适合多标签任务。
具体修复步骤
1. 修正输入名称匹配
先通过model.summary()查看模型实际的输入名称,再在构建数据集时使用对应key:
# 查看模型输入名称 print("模型输入名称:", [inp.name.split(':')[0] for inp in model.inputs]) # 用正确的key构建输入数据集 model_inputs = tf.data.Dataset.zip(( {"input_0": train_x_96, "input_1": train_x_224}, train_y_96 )) model_vals = tf.data.Dataset.zip(( {"input_0": val_x_96, "input_1": val_x_224}, val_y_96 ))
2. 修正损失函数与输出层
将输出层改为softmax激活(适配多分类任务),同时调整损失函数参数:
# 输出层改用softmax激活 merge = tf.keras.layers.concatenate(ensemble_outputs) merge = tf.keras.layers.Dense(200, activation='relu')(merge) output = tf.keras.layers.Dense(200, activation='softmax')(merge) model = tf.keras.models.Model(inputs=ensemble_visible, outputs=output) # 损失函数设置from_logits=False(输出已通过softmax激活) model.compile( optimizer=tf.keras.optimizers.SGD(learning_rate=0.005, momentum=0.9), loss=tf.keras.losses.CategoricalCrossentropy(from_logits=False, label_smoothing=0.1), metrics=['accuracy'] )
如果任务是多标签分类,可保留sigmoid激活,但需确保损失函数的from_logits=False。
3. 简化数据处理流程
去掉不必要的unbatch().batch()操作,避免潜在的样本顺序错乱:
def gen_datasets(image_size): train_ds, val_ds = build_dataset(image_size) class_names = tuple(train_ds.class_names) train_size = train_ds.cardinality().numpy() # 移除冗余的unbatch再batch操作 train_ds = train_ds.repeat() normalization_layer = tf.keras.layers.Rescaling(1. / 255) preprocessing_model = tf.keras.Sequential([normalization_layer]) do_data_augmentation = False if do_data_augmentation: preprocessing_model.add(tf.keras.layers.RandomRotation(40)) preprocessing_model.add(tf.keras.layers.RandomTranslation(0, 0.2)) preprocessing_model.add(tf.keras.layers.RandomTranslation(0.2, 0)) preprocessing_model.add(tf.keras.layers.RandomZoom(0.2, 0.2)) preprocessing_model.add(tf.keras.layers.RandomFlip(mode="horizontal")) train_ds = train_ds.map(lambda images, labels: (preprocessing_model(images), labels)) valid_size = val_ds.cardinality().numpy() # 同样移除val_ds的unbatch操作 val_ds = val_ds.map(lambda images, labels: (normalization_layer(images), labels)) return train_ds, val_ds, train_size, valid_size, class_names
4. 验证数据一致性
随机抽取样本确认两个数据集的标签完全对应:
# 验证标签一致性 sample_y_96 = next(train_y_96.as_numpy_iterator()) sample_y_224 = next(train_y_224.as_numpy_iterator()) print("标签是否一致:", (sample_y_96 == sample_y_224).all())
额外优化建议
- 调整学习率:若修正后学习缓慢,可尝试将SGD学习率调整为
0.01,或改用Adam优化器。 - 微调预训练层:若集成效果仍不理想,可解冻预训练模型的最后几层,同时将学习率降至
0.0001左右进行微调。 - 添加Dropout层:在拼接后的Dense层之间添加
tf.keras.layers.Dropout(0.5),防止过拟合。
内容的提问来源于stack exchange,提问作者0x7477
相关产品推荐
相关产品推荐

