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

TensorFlow代码运行报错:conv2d_transpose形状不兼容求助

解决TensorFlow中conv2d_transpose的形状不兼容错误

我帮你排查了代码里的几个问题,这个Shapes (64, 48, 48, 128) and (64, 24, 24, 128) are not compatible错误主要是反卷积层的输出形状硬编码错误,还有几个其他潜在问题共同导致的,下面是具体的解决思路和修正后的代码:

核心问题分析

错误出在梯度计算阶段,根源是反卷积层的输出形状手动固定,没有和输入张量的实际形状动态对齐,再加上网络通道数不匹配,导致正向传播的张量形状和反向传播时的梯度形状无法兼容。

具体修正点

  1. 修复字符串格式化错误
    原代码中"conv_d_w" % (i + 1)的写法不符合Python语法,需要用f-string或者str.format()生成带编号的变量名,否则会触发TypeError。

  2. 修正残差拼接后的通道数
    在18层循环里,每次将卷积结果和初始的low_tensor(64通道)拼接后,通道数变为128,但后续卷积层的输入通道参数还是64,这会导致卷积操作形状不兼容,需要把后续卷积权重的输入通道改为128。

  3. 动态设置反卷积的输出形状
    原代码硬编码了反卷积的output_shape为[64,48*(j+1),48*(j+1),128],应该基于输入张量的形状动态计算,比如用tf.shape(tensor)[0]获取当前batch_size,用输入尺寸乘以stride得到输出尺寸,避免硬编码带来的形状不匹配。

  4. 移除重复的权重列表拼接
    原代码最后weights = weights + biases是多余的,因为前面已经将biases添加到weights列表中了,这会导致变量重复,干扰梯度计算。

修正后的完整代码

import tensorflow as tf
import numpy as np

def model(input_tensor):
    with tf.device("/gpu:0"):
        weights = []
        biases = []
        tensor = None
        # 初始卷积层
        conv_00_w = tf.get_variable("conv_00_w", [3, 3, 1, 64], initializer=tf.random_normal_initializer(stddev=np.sqrt(2.0 / 9)))
        conv_00_b = tf.get_variable("conv_00_b", [64], initializer=tf.constant_initializer(0))
        weights.append(conv_00_w)
        biases.append(conv_00_b)
        low_tensor = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(input_tensor, conv_00_w, strides=[1, 1, 1, 1], padding='SAME'), conv_00_b))
        
        # 18层残差卷积(修正通道数)
        tensor = low_tensor
        for i in range(18):
            # 修正变量名格式化,同时根据循环次数调整输入通道数
            in_channels = 128 if i > 0 else 64
            conv_w = tf.get_variable(f"conv_d_w{i+1}", [3, 3, in_channels, 64], 
                                    initializer=tf.random_normal_initializer(stddev=np.sqrt(2.0 / 9 / in_channels)))
            conv_b = tf.get_variable(f"conv_d_b{i+1}", [64], initializer=tf.constant_initializer(0))
            weights.append(conv_w)
            biases.append(conv_b)
            # 卷积操作
            conv_out = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d(tensor, conv_w, strides=[1, 1, 1, 1], padding='SAME'), conv_b))
            # 拼接残差,第一次后通道变为128
            tensor = tf.concat([conv_out, low_tensor], axis=3)
        
        # 反卷积上采样层(修正输出形状)
        for j in range(2):
            # 获取当前输入的动态形状
            batch_size = tf.shape(tensor)[0]
            curr_height = tf.shape(tensor)[1]
            curr_width = tf.shape(tensor)[2]
            # 反卷积权重:[kernel_h, kernel_w, output_channels, input_channels]
            deconv_w = tf.get_variable(f"deconv_d_w{j+1}", [2, 2, 128, 128],
                                      initializer=tf.random_normal_initializer(stddev=np.sqrt(2.0 / 4 / 128)))
            deconv_b = tf.get_variable(f"deconv_d_b{j+1}", [128], initializer=tf.constant_initializer(0))
            weights.append(deconv_w)
            biases.append(deconv_b)
            # 动态计算输出形状:上采样2倍
            output_shape = tf.stack([batch_size, curr_height * 2, curr_width * 2, 128])
            deconv_tensor = tf.nn.relu(tf.nn.bias_add(tf.nn.conv2d_transpose(tensor, deconv_w, output_shape, strides=[1, 2, 2, 1], padding='SAME'), deconv_b))
            
            # 输出卷积层:为每次反卷积后的结果生成1通道特征
            conv_w = tf.get_variable(f"conv_20_w{j+1}", [3, 3, 128, 1], initializer=tf.random_normal_initializer(stddev=np.sqrt(2.0 / 9 / 128)))
            conv_b = tf.get_variable(f"conv_20_b{j+1}", [1], initializer=tf.constant_initializer(0))
            weights.append(conv_w)
            biases.append(conv_b)
            tensor = tf.nn.bias_add(tf.nn.conv2d(deconv_tensor, conv_w, strides=[1, 1, 1, 1], padding='SAME'), conv_b)
        
        # 移除重复的权重拼接
        return tensor, weights

if __name__ == '__main__':
    INPUT_SIZE = (24, 24)
    OUTPUT_SIZE = (96, 96)
    BATCH_SIZE = 64
    train_input = tf.placeholder(tf.float32, shape=(BATCH_SIZE, INPUT_SIZE[0], INPUT_SIZE[1], 1))
    train_gt = tf.placeholder(tf.float32, shape=(BATCH_SIZE, OUTPUT_SIZE[0], OUTPUT_SIZE[1], 1))
    shared_model = tf.make_template('shared_model', model)
    train_output, weights = shared_model(train_input)
    loss = tf.reduce_sum(tf.nn.l2_loss(tf.subtract(train_output,train_gt)))
    learning_rate = 0.001
    params = tf.trainable_variables()
    grads = tf.gradients(loss, weights)
    print("finished")

额外说明

  • 原代码中在两次反卷积后都接了一个1通道的卷积,最终输出的train_output形状会是(64,96,96,1),和train_gt的形状完美匹配,这个逻辑我保留了,如果你的需求是两次上采样后再统一生成最终输出,可以调整这部分逻辑。
  • 动态计算output_shape可以避免因为输入尺寸变化导致的形状不兼容问题,比硬编码更灵活。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:24:12