ResNet34作为Unet骨干训练时维度不匹配错误求助
解决ResNet34 + Unet训练时的尺寸不匹配错误
你的错误核心是输入图像尺寸无法被ResNet34编码器的下采样倍数整除,导致解码器上采样后的特征图(14x14)和编码器对应的特征图(13x13)尺寸不一致,无法完成拼接操作。另外需要确认你到底是做图像分类还是分割任务,因为当前模型和标签的匹配存在疑问:
核心问题拆解
- 尺寸不匹配根源:ResNet34编码器会进行4次2倍下采样(总下采样倍数为32),输入图像的高度/宽度必须是32的倍数,否则经过多次下采样后会出现非整数尺寸,导致解码器上采样后的特征图无法和编码器特征图对齐。200不是32的倍数(32×6=192,32×7=224),因此会出现13和14的尺寸差异。
- 任务与模型不匹配(可选):如果你的任务是图像分类(每张图对应一个类别标签),使用Unet是不合适的——Unet是为分割任务设计的,输出是和输入同尺寸的像素级标签;此时应该用ResNet34的分类模型。
解决方案分两种情况:
情况1:你要做图像分类任务
- 更换为分类模型结构
from tensorflow.keras.applications import ResNet34 from tensorflow.keras.layers import Dense, GlobalAveragePooling2D from tensorflow.keras.models import Model from tensorflow.keras.losses import SparseCategoricalCrossentropy # 调整输入尺寸为32的倍数,比如192x192 INPUT_SHAPE = (192, 192, 1) # 单通道灰度图 base_model = ResNet34(weights=None, input_shape=INPUT_SHAPE, include_top=False) # 添加分类头 x = base_model.output x = GlobalAveragePooling2D()(x) predictions = Dense(7, activation='softmax')(x) model = Model(inputs=base_model.input, outputs=predictions) # 编译模型:因为y是整数标签,用SparseCategoricalCrossentropy model.compile(optimizer='Adam', loss=SparseCategoricalCrossentropy(), metrics=['accuracy'])
- 调整图像预处理与尺寸
# 去掉手动除以255的步骤,用ResNet的标准预处理 BACKBONE = 'resnet34' preprocess_input = get_preprocessing(BACKBONE) x_train = preprocess_input(X_train) x_val = preprocess_input(X_test) # 重塑为192x192(32的倍数) x_train = np.array([i.reshape(192,192,1) for i in x_train]) x_val = np.array([i.reshape(192,192,1) for i in x_val])
- 训练模型
model.fit( x=x_train, y=np.array(y_train), batch_size=16, epochs=100, validation_data=(x_val, np.array(y_test)), )
情况2:你要做图像分割任务
- 调整输入尺寸为32的倍数
将图像重塑为192x192或224x224:
x_train2=[] for i in x_train: x_train2.append(i.reshape(192,192,N)) # 替换200为192 x_val2=[] for i in x_val: x_val2.append(i.reshape(192,192,N)) x_train=np.array(x_train2) x_val=np.array(x_val2)
- 修正标签格式
分割任务的标签必须是和输入同尺寸的掩码(每个像素对应类别),而不是单整数标签。假设你的标签掩码存储在某个列中,需要将其调整为(num_samples, 192, 192, 1)或one-hot编码为(num_samples, 192, 192,7):
# 示例:如果y_train是掩码列表,转成数组并调整尺寸 y_train = np.array([mask.reshape(192,192,1) for mask in y_train]) y_test = np.array([mask.reshape(192,192,1) for mask in y_test]) # 如果需要one-hot编码(配合softmax) from tensorflow.keras.utils import to_categorical y_train = to_categorical(y_train, num_classes=7) y_test = to_categorical(y_test, num_classes=7)
- 保持Unet模型训练
此时模型的输入尺寸匹配,标签格式正确,即可正常训练。
额外注意事项
- 灰度图处理:ResNet34原生设计是3通道输入,如果你坚持用单通道,确保模型初始化时input_shape正确;也可以将单通道复制为3通道,避免潜在兼容问题:
# 加载图片时将灰度图转3通道 img = cv2.imread(file) img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img = np.stack([img]*3, axis=-1) # 变成(height, width, 3)
- 预处理顺序:不要同时手动做
/255和get_preprocessing,后者已经包含了ResNet所需的标准化操作,保留其中一个即可。
内容的提问来源于stack exchange,提问作者VICTOR JESUS GARCIA HERNANDEZ
相关产品推荐
相关产品推荐

