UNet训练报错:张量尺寸不匹配与Concatenate层形状冲突求助
UNet训练中的尺寸不匹配问题解决方案
问题1:数据集图像尺寸不一致导致Batch失败
错误原因
扩充数据集后混入了尺寸为[761,720,3]的图像,但代码中强制设置输入形状为[256,256,3],TensorFlow在批量加载时发现张量形状不匹配,抛出错误。
解决方案
在读取图像和掩码时,强制将所有数据resize到统一的目标尺寸,不管原始图像大小。修改read_image和read_mask函数:
def read_image(path): path = path.decode() x = cv2.imread(path, cv2.IMREAD_COLOR) x = cv2.resize(x, (width, height)) # 新增:统一尺寸 x = x/255.0 return x def read_mask(path): path = path.decode() x = cv2.imread(path, cv2.IMREAD_GRAYSCALE) x = cv2.resize(x, (width, height)) # 新增:统一尺寸 x = x/255.0 x = np.expand_dims(x, axis = -1) return x
问题2:UNet编码器与解码器特征图尺寸不匹配导致拼接失败
错误原因
UNet的核心是编码器下采样后的特征图与解码器上采样后的特征图拼接。你的UNet包含4次下采样(每次用MaxPool2D(2,2)将尺寸减半),若输入尺寸无法被2^4=16整除,下采样/上采样后的尺寸会出现奇数,导致编码器输出的特征图与解码器上采样后的特征图尺寸不一致(比如输入761x720时,编码器的s4尺寸是95x90,解码器上采样后是94x90,无法拼接)。
解决方案
有两种可行方案:
方案1:选择能被16整除的输入尺寸
将输入的高和宽设置为16的倍数(比如把height=768,width=720,768和720都能被16整除),这样每次下采样/上采样的尺寸都能完美匹配,无需修改网络结构。
修改参数:
height = 768 # 768 = 16*48 width = 720 # 720 = 16*45
方案2:修改解码器,强制对齐特征图尺寸
如果必须使用非16倍数的尺寸,修改decoder_block函数,在拼接前将上采样后的特征图尺寸调整为与编码器特征图一致:
def decoder_block(inputs, skip, num_filters): x = Conv2DTranspose(num_filters, (2,2), strides=2, padding='same')(inputs) # 新增:调整x的尺寸与skip一致 x = tf.keras.layers.Resizing(height=skip.shape[1], width=skip.shape[2])(x) x = Concatenate()([x, skip]) x = conv_block(x, num_filters) return x
完整修改后的训练流程要点
- 确保所有训练/验证集的图像和掩码都被resize到统一尺寸。
- 优先选择能被
2^N整除的尺寸(N为下采样次数,这里N=4),避免额外的尺寸调整操作。 - 重新运行训练代码,即可解决两个尺寸不匹配的错误。
内容的提问来源于stack exchange,提问作者Dennis
相关产品推荐
相关产品推荐

