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

基于双视图与批量数据集,用Keras构建CNN分类模型报错解决

双视图CNN图像分类模型维度错误修复

问题概述

使用Keras构建双视图图像分类CNN时,训练阶段出现维度不兼容错误:

ValueError: Input 0 of layer is incompatible with the layer: expected shape=(None, 80, 80, 3), found shape=(32, 32, 80, 80, 3)

核心问题是数据加载和训练循环中出现了重复批次打包,导致多了一个不必要的维度。

错误原因

  1. 重复批次化:image_dataset_from_directory已经通过batch_size=32参数生成了批次数据,后续调用combined_dataset.batch(batch_size)会再次对批次进行打包,导致维度变成(32, 32, 80, 80, 3)(第一个32是新批次大小,内部每个元素是原32张图像的批次)。
  2. 数据集解构错误:tf.data.Dataset.zip((data_train_1, data_train_2))后的数据集元素结构是((view1_imgs, view1_labels), (view2_imgs, view2_labels)),原代码的循环解构(view1_batch, view2_batch), labels无法正确提取数据。
  3. 未定义变量:class_names未从数据集中获取,直接调用len(class_names)会报错。
  4. 损失函数不匹配:对比损失(contrastive loss)用于孪生网络的相似性判断任务,而当前是分类任务,应该使用分类专用损失函数。

修复步骤

  1. 移除combined_dataset.batch(batch_size)调用,直接使用原始批次化数据集。
  2. 修正训练循环的数据集解构逻辑,正确提取两个视图的图像和统一标签(确保双视图对应同一样本的标签一致)。
  3. 从数据集中获取class_names变量。
  4. 替换损失函数为适合分类任务的SparseCategoricalCrossentropy(因标签为整数类型),输出层激活改为softmax(多分类场景)。

完整修正代码

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

# 图像尺寸
img_width, img_height = 80, 80
batch_size = 32

# 加载视图1数据集
data_train_1 = tf.keras.preprocessing.image_dataset_from_directory(
    '_view_1', 
    labels='inferred', 
    label_mode='int', 
    color_mode='rgb', 
    batch_size=batch_size, 
    image_size=(img_width, img_height), 
    shuffle=True, 
    seed=123, 
    validation_split=0.2, 
    subset="training"
)
data_validation_1 = tf.keras.preprocessing.image_dataset_from_directory(
    '_view_1', 
    labels='inferred', 
    label_mode='int', 
    color_mode='rgb', 
    batch_size=batch_size, 
    image_size=(img_width, img_height), 
    shuffle=True, 
    seed=123, 
    validation_split=0.2, 
    subset="validation"
)

# 加载视图2数据集
data_train_2 = tf.keras.preprocessing.image_dataset_from_directory(
    '_view_2', 
    labels='inferred', 
    label_mode='int', 
    color_mode='rgb', 
    batch_size=batch_size, 
    image_size=(img_width, img_height), 
    shuffle=True, 
    seed=123, 
    validation_split=0.2, 
    subset="training"
)
data_validation_2 = tf.keras.preprocessing.image_dataset_from_directory(
    '_view_2', 
    labels='inferred', 
    label_mode='int', 
    color_mode='rgb', 
    batch_size=batch_size, 
    image_size=(img_width, img_height), 
    shuffle=True, 
    seed=123, 
    validation_split=0.2, 
    subset="validation"
)

# 获取分类数量(从任意一个数据集提取)
class_names = data_train_1.class_names
num_classes = len(class_names)

# 定义共享CNN特征提取器
shared_cnn = keras.Sequential([
    layers.Rescaling(1./255),
    layers.Conv2D(16, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(32, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Conv2D(64, 3, activation='relu'),
    layers.MaxPooling2D(),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
])

# 定义双视图输入
view1_input = keras.Input(shape=(img_height, img_width, 3))
view2_input = keras.Input(shape=(img_height, img_width, 3))

# 提取双视图特征
view1_features = shared_cnn(view1_input)
view2_features = shared_cnn(view2_input)

# 融合特征
merged_features = layers.concatenate([view1_features, view2_features], axis=1)

# 分类输出层(多分类用softmax)
predictions = layers.Dense(num_classes, activation='softmax')(merged_features)

# 创建模型
model = keras.Model(inputs=[view1_input, view2_input], outputs=predictions)

# 编译模型:分类任务用稀疏交叉熵损失
model.compile(
    optimizer=keras.optimizers.Adam(),
    loss=keras.losses.SparseCategoricalCrossentropy(),
    metrics=['accuracy']
)

# 合并双视图训练数据集(确保样本对应)
train_dataset = tf.data.Dataset.zip((data_train_1, data_train_2)).map(
    lambda x, y: ((x[0], y[0]), x[1])  # 提取两个视图的图像,取第一个视图的标签(双视图标签一致)
)
val_dataset = tf.data.Dataset.zip((data_validation_1, data_validation_2)).map(
    lambda x, y: ((x[0], y[0]), x[1])
)

# 训练模型(直接用fit更简洁,无需手动梯度带)
epochs = 10
model.fit(
    train_dataset,
    validation_data=val_dataset,
    epochs=epochs
)

额外说明

  • 如果确实需要使用对比损失(比如双视图相似性匹配任务),需调整标签为二元相似/不相似标签,并将输出层改为单神经元sigmoid激活。
  • 使用model.fit()代替手动梯度带循环,代码更简洁且自动处理批次、验证等逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:39:56