如何在GAN中生成非正方形N×M尺寸图像?TensorFlow实现求助
嗨,我来帮你搞定这个非正方形GAN图像生成的问题!你遇到的核心问题是原来的生成器结构是对称设计的,所以每次转置卷积都会保持正方形比例,要生成128×48的图像,关键是打破这种对称性,下面是具体的修改步骤和代码示例:
1. 打破生成器初始特征图的对称性
原来的生成器可能把潜在向量(latent vector)reshape成了正方形的特征图(比如4×4),这直接导致后续所有转置卷积都会保持正方形比例。你需要先把初始特征图的比例调整成和目标图像一致的非正方形:
目标图像比例是128:48 = 8:3,所以初始特征图可以设为8×3、16×6这类符合8:3比例的尺寸。注意:不能直接把潜在向量reshape成非对称尺寸,需要先通过全连接层把潜在向量映射到对应维度,比如:
# 假设潜在向量z是100维 z = tf.placeholder(tf.float32, [None, 100]) # 把z映射到8×3×128的特征图维度(8*3*128=3072) g_fc = tf.contrib.layers.fully_connected(z, 8*3*128, activation_fn=tf.nn.relu) # reshape成非对称特征图 g_initial = tf.reshape(g_fc, [-1, 8, 3, 128])
2. 调整转置卷积层的步长与层数
接下来的转置卷积层,只要保持步长在height和width方向的放大倍数一致,就能维持8:3的比例。比如目标是128×48,8×3的初始特征图需要总共放大16倍(128/8=16,48/3=16),用4次步长为(2,2)的转置卷积就能实现(2^4=16):
# 第一层转置卷积:8×3 → 16×6 deconv1 = tf.contrib.layers.conv2d_transpose(g_initial, 64, [5,5], strides=(2,2), padding='SAME') # 第二层:16×6 → 32×12 deconv2 = tf.contrib.layers.conv2d_transpose(deconv1, 32, [5,5], strides=(2,2), padding='SAME') # 第三层:32×12 → 64×24 deconv3 = tf.contrib.layers.conv2d_transpose(deconv2, 16, [5,5], strides=(2,2), padding='SAME') # 第四层:64×24 → 128×48,输出3通道RGB图像 deconv4 = tf.contrib.layers.conv2d_transpose(deconv3, 3, [5,5], strides=(2,2), padding='SAME', activation_fn=tf.tanh)
这里用padding='SAME'是因为它的输出尺寸计算更直观:输出尺寸 = 输入尺寸 × 步长,能严格保持比例。如果用VALID,需要手动计算输出尺寸(公式:(输入尺寸-1)*步长 + 卷积核大小),容易出错,所以优先用SAME。
3. 同步修改判别器结构
生成器输出改成128×48后,判别器的输入也必须对应调整,否则会出现维度不匹配的错误。你需要把判别器的卷积层步长和结构调整为能处理非正方形图像的版本,比如:
def discriminator(x): # x是128×48×3的输入图像 conv1 = tf.contrib.layers.conv2d(x, 16, [5,5], strides=(2,2), padding='SAME', activation_fn=tf.nn.leaky_relu) # 128×48 → 64×24 conv2 = tf.contrib.layers.conv2d(conv1, 32, [5,5], strides=(2,2), padding='SAME', activation_fn=tf.nn.leaky_relu) # 64×24 →32×12 conv3 = tf.contrib.layers.conv2d(conv2, 64, [5,5], strides=(2,2), padding='SAME', activation_fn=tf.nn.leaky_relu) #32×12 →16×6 conv4 = tf.contrib.layers.conv2d(conv3, 128, [5,5], strides=(2,2), padding='SAME', activation_fn=tf.nn.leaky_relu) #16×6 →8×3 # flatten后接全连接层 flat = tf.contrib.layers.flatten(conv4) logits = tf.contrib.layers.fully_connected(flat, 1, activation_fn=None) return logits
判别器的卷积步长同样用(2,2),保持和生成器的放大/缩小比例一致,这样每一步的空间尺寸都会按8:3的比例缩小,最终能顺利flatten到全连接层。
关键注意事项
- 所有转置卷积/卷积层的步长,在height和width方向的比例要和目标图像比例一致,避免中途破坏比例
- 初始特征图的比例必须严格匹配目标图像的比例(128:48=8:3),这是生成非正方形图像的核心
- 如果一定要用对称的初始特征图(比如4×4),可以用非对称步长(比如(2,1)或(1,2)),但要确保每一步的输出尺寸是整数,否则会报错
内容的提问来源于stack exchange,提问作者ajp55

