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

GAN生成48×48人脸图异常:滤波器尺寸影响及选型咨询

GAN生成48×48人脸图像的架构问题

我正在开发一个用于生成48×48人脸图像的GAN,但无论训练多久,生成器始终生成怪异图像,且判别器始终判定其为伪造图像,我认为这是架构问题。

生成图像示例

  • 未训练输出:未训练
  • 训练25轮后:25轮训练后
  • 使用5×5核尺寸时的生成图像:5×5核生成图像

生成图像呈现方块图案,而非未训练GAN应有的随机像素。该问题似乎与生成器反卷积层的滤波器尺寸有关,但我不确定具体关联机制。

我的问题:

  1. 为什么会出现这种情况?滤波器尺寸对图像产生了何种影响,从而导致此类图案?
  2. 如何根据图像尺寸或其他参数确定应使用的滤波器尺寸?

模型代码

generator = keras.Sequential([
    keras.layers.Dense(4*4*32, input_shape=(100,), use_bias=False),
    keras.layers.LeakyReLU(),
    
    keras.layers.Reshape((4, 4, 32)),
    
    SpectralNormalization(keras.layers.Conv2DTranspose(64, (2, 2), strides=(2, 2), padding="same", use_bias=False)),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2DTranspose(32, (2, 2), strides=(2, 2), padding="same", use_bias=False)),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2DTranspose(3, (2, 2), strides=(3, 3), padding="same", use_bias=False)),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2DTranspose(3, (2, 2), strides=(2, 2), padding="same", use_bias=False)),
])


discriminator = keras.Sequential([
    keras.layers.Conv2D(128, (2, 2), strides=(2, 2), input_shape=(96, 96, 3), padding="same"),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2D(64, (2, 2), strides=(2, 2), padding="same")),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2D(32, (2, 2), strides=(2, 2), padding="same")),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2D(16, (2, 2), strides=(2, 2), padding="same")),
    keras.layers.LeakyReLU(),
    
    SpectralNormalization(keras.layers.Conv2D(8, (2, 2), strides=(2, 2), padding="same")),
    keras.layers.LeakyReLU(),
    
    keras.layers.Flatten(),
    keras.layers.Dense(1, activation="sigmoid")
])

训练循环

cross_entropy = tf.keras.losses.BinaryCrossentropy()

def discriminator_loss(real_output, fake_output):
    real_loss = cross_entropy(tf.ones_like(real_output), real_output)
    fake_loss = cross_entropy(tf.zeros_like(fake_output), fake_output)
    total_loss = real_loss + fake_loss
    return total_loss

def generator_loss(fake_output):
    return cross_entropy(tf.ones_like(fake_output), fake_output)

generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)

@tf.function
def train_step(images):
    noise = tf.random.normal([32, 100])

    with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
        generated_images = generator(noise, training=True)

        real_output = discriminator(images, training=True)
        fake_output = discriminator(generated_images, training=True)

        gen_loss = generator_loss(fake_output)
        disc_loss = discriminator_loss(real_output, fake_output)

    gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
    gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)

    generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
    discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))

问题解答

1. 方块图案的成因与滤波器尺寸的影响

你看到的方块图案是转置卷积的棋盘格伪影,和2×2小核+同padding+大步长的组合直接相关:

  • 当strides > 1且kernel_size无法被strides整除时,转置卷积会让相邻输出像素由输入的独立区域生成,导致像素间出现不连续的方块边界。
  • 2×2核的感受野极小,生成器无法学习全局人脸特征,只能生成局部重复的方块结构;再加上某一层用了strides=(3,3)这种非2倍数的步长,进一步加剧了像素对齐混乱,伪影更明显。
  • 换成5×5核后,更大的感受野能捕捉更连贯的特征,同时5无法被2整除,反而缓解了棋盘格的对齐问题,图像因此更平滑。

2. 滤波器尺寸的选择原则

确定滤波器尺寸需要结合图像尺寸、步长和特征连贯性,核心原则如下:

  • 避免棋盘格伪影:使用转置卷积且strides = s时,优先选kernel_size = 2s或kernel_size > s的尺寸,让输出像素的生成区域有重叠。比如strides=(2,2)时,选4×4或5×5核,不要用2×2核。
  • 匹配图像缩放倍数:你的目标是生成48×48图像,但当前生成器最终输出是96×96,和训练数据尺寸错配,先修正生成器的输出维度,确保和判别器输入、训练数据一致。
  • 感受野与特征层级:浅层(靠近噪声输入)用3×3、4×4小核捕捉局部细节,深层(靠近输出图像)用5×5稍大核整合全局特征;优先用奇数核,方便padding后特征对齐。
  • 参考成熟架构:标准DCGAN的转置卷积层通常用4×4核、2×2步长、same padding,这种组合能有效避免伪影,稳定生成图像。

额外架构修正建议

除滤波器尺寸外,你的模型还有几个关键问题:

  • 生成器输出尺寸错误:目标是48×48,但当前生成器最后一层输出96×96,和训练数据尺寸不匹配,导致训练失效。
  • 通道数设计不合理:从噪声到图像的过程中,通道数应先增后减,你中间有通道数下降后又上升的情况,不利于特征传递。
  • 生成器缺少最终激活:人脸图像像素值通常在[-1,1]或[0,1]之间,最后一层需加tanh()或sigmoid()激活,否则输出值范围不受控,判别器极易识别。

修正后的生成器示例(目标48×48):

generator = keras.Sequential([
    keras.layers.Dense(6*6*128, input_shape=(100,), use_bias=False),
    keras.layers.BatchNormalization(),
    keras.layers.LeakyReLU(),
    
    keras.layers.Reshape((6, 6, 128)),
    
    # 6×6 → 12×12
    SpectralNormalization(keras.layers.Conv2DTranspose(64, (4, 4), strides=(2, 2), padding="same", use_bias=False)),
    keras.layers.BatchNormalization(),
    keras.layers.LeakyReLU(),
    
    # 12×12 → 24×24
    SpectralNormalization(keras.layers.Conv2DTranspose(32, (4, 4), strides=(2, 2), padding="same", use_bias=False)),
    keras.layers.BatchNormalization(),
    keras.layers.LeakyReLU(),
    
    # 24×24 → 48×48
    SpectralNormalization(keras.layers.Conv2DTranspose(3, (4, 4), strides=(2, 2), padding="same", use_bias=False)),
    keras.layers.Activation('tanh')  # 添加最终激活函数
])

内容的提问来源于stack exchange,提问作者A random coder

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 00:35:25