如何让GAN模型生成512×512及更大尺寸图像?卷积层原理答疑
GAN生成大尺寸图像问题解决及卷积层尺寸原理
一、Conv2D与Conv2DTranspose的尺寸调整逻辑
Conv2D(下采样,缩小图像)
输入经过Conv2D后,输出尺寸由公式计算:输出尺寸 = floor((输入尺寸 - 核尺寸 + 2×填充)/步长) + 1
- 当padding设为
same时,填充值为(核尺寸-1)//2,保证输入输出尺寸比例为1/步长(步长为2时,尺寸减半)。
比如原网络中,64×64输入经过Conv2D(64,4,2,'same'),计算过程:(64-4+2×1)/2 +1 = 32,输出32×32,三次下采样后得到8×8特征图。
Conv2DTranspose(上采样,放大图像)
输入经过Conv2DTranspose后,输出尺寸公式:输出尺寸 = (输入尺寸 -1)×步长 + 核尺寸 - 2×填充
- 同样当padding为
same时,填充值为(核尺寸-1)//2,输入输出尺寸比例为步长×1(步长为2时,尺寸翻倍)。
原网络中8×8输入经过Conv2DTranspose(128,4,2,'same'),计算:(8-1)×2 +4 -2×1=16,输出16×16,三次上采样后得到64×64图像。
二、修改为生成512×512图像的具体方案
1. 数据集适配
修改image_dataset_from_directory的image_size参数为(512,512),同时调小batch_size避免显存溢出:
dataset = keras.preprocessing.image_dataset_from_directory( directory = 'Humans', label_mode = None, image_size = (512,512), batch_size = 8, shuffle = True ).map(lambda x: x/255.0)
2. 生成器重构
从4×4的初始特征图开始,通过6次上采样将尺寸翻倍至512×512,同时增加批量归一化稳定训练:
latent_dim = 128 generator = keras.models.Sequential( [ layers.Input(shape = (latent_dim,)), layers.Dense(4*4*256), layers.Reshape((4,4,256)), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(128, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(128, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(64, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(64, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(32, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2DTranspose(32, kernel_size = 4, strides = 2, padding = 'same'), layers.BatchNormalization(), layers.LeakyReLU(0.2), layers.Conv2D(3, kernel_size = 5,padding = 'same',activation = 'sigmoid') ] )
3. 判别器重构
对应处理512×512输入,增加6次下采样层,逐步提升通道数捕捉细节:
discriminator = keras.models.Sequential( [ keras.Input(shape = (512,512,3)), layers.Conv2D(64, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Conv2D(128, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Conv2D(256, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Conv2D(512, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Conv2D(512, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Conv2D(512, kernel_size = 4, strides = 2, padding = 'same'), layers.LeakyReLU(0.2), layers.Flatten(), layers.Dropout(0.3), layers.Dense(1,activation = 'sigmoid') ] )
4. 训练参数优化
调低学习率避免大模型训练震荡,增加训练轮数保证收敛:
opt_gen = keras.optimizers.Adam(5e-5) opt_disc = keras.optimizers.Adam(5e-5) loss_fn = keras.losses.BinaryCrossentropy() for epoch in range(1000): for idx, real in enumerate(tqdm(dataset)): batch_size = real.shape[0] random_latent_vectors = tf.random.normal(shape = (batch_size,latent_dim)) fake = generator(random_latent_vectors) if idx % 20 == 0: img = keras.preprocessing.image.array_to_img(fake[0]) img.save(f'gen_images/generated_img{epoch}_{idx}_.png') with tf.GradientTape() as disc_tape: loss_disc_real = loss_fn(tf.ones((batch_size,1)), discriminator(real)) loss_disc_fake = loss_fn(tf.zeros((batch_size,1)), discriminator(fake)) loss_disc = (loss_disc_real+loss_disc_fake)/2 grads = disc_tape.gradient(loss_disc, discriminator.trainable_weights) opt_disc.apply_gradients(zip(grads, discriminator.trainable_weights)) with tf.GradientTape() as gen_tape: fake = generator(random_latent_vectors) output = discriminator(fake) loss_gen = loss_fn(tf.ones((batch_size,1)),output) grads = gen_tape.gradient(loss_gen, generator.trainable_weights) opt_gen.apply_gradients(zip(grads, generator.trainable_weights))
注意事项
- 若出现显存溢出,可进一步调小batch_size至4,或开启混合精度训练;
- 大尺寸GAN训练初期图像会模糊,需训练500轮以上才能看到清晰效果;
- 数据集图像质量直接影响生成效果,建议提前预处理高清图像。
内容的提问来源于stack exchange,提问作者Andrei Arseni
相关产品推荐
相关产品推荐

