我怎样才能让这个模型生成 512x512 像素或更大的图像?现在它生成 64x64px 图像。我尝试更改模型中的一些值,但没有成功。这些卷积层(尤其是 Conv2D 和 Conv2DTranspose)如何工作?我不明白如何在这些层中调整图像的大小。
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tqdm import tqdm
import numpy as np
import matplotlib.pyplot as plt
cd /content/drive/MyDrive
dataset = keras.preprocessing.image_dataset_from_directory(
directory = 'Humans', label_mode = None, image_size = (64,64), batch_size = 32,
shuffle = True
).map(lambda x: x/255.0)
discriminator = keras.models.Sequential(
[
keras.Input(shape = (64,64,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(128, kernel_size = 4, strides = 2, padding = 'same'),
layers.LeakyReLU(0.2),
layers.Flatten(),
layers.Dropout(0.2),
layers.Dense(1,activation = 'sigmoid')
]
)
latent_dim = 128
generator = keras.models.Sequential(
[
layers.Input(shape = (latent_dim,)),
layers.Dense(8*8*128),
layers.Reshape((8,8,128)),
layers.Conv2DTranspose(128, kernel_size = 4, strides = 2, padding = 'same'),
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(256, kernel_size = 4, strides = 2, padding = 'same'),
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(512, kernel_size = 4, strides = 2, padding = 'same'),
layers.LeakyReLU(0.2),
layers.Conv2D(3, kernel_size = 5,padding = 'same',activation = 'sigmoid')
]
)
opt_gen = keras.optimizers.Adam(1e-4)
opt_disc = keras.optimizers.Adam(1e-4)
loss_fn = keras.losses.BinaryCrossentropy()
for epoch in range(500):
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 % 50 == 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)
)
我尝试更改图像大小和转换层中的一些值,但它不起作用。
你几乎成功了!图像大小的增加方式是正确的,但你漏掉了一个生成器模型中的一个小细节。
你在生成器中使用
strides=2
的
Conv2DTranspose
层,这会导致图像大小在每一层翻倍。从一个
8x8x128
的张量开始,你得到 16x16、32x32,最后是 64x64。你需要再添加一个
Conv2DTranspose
层来达到 128x128,然后是 256x256,最后是 512x512。
下面是修改后的生成器模型:
latent_dim = 128
generator = keras.models.Sequential(
[
layers.Input(shape = (latent_dim,)),
layers.Dense(8*8*128),
layers.Reshape((8,8,128)),
layers.Conv2DTranspose(128, kernel_size=4, strides=2, padding='same'),
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(256, kernel_size=4, strides=2, padding='same'),
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding='same'),
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding='same'), # 添加新层
layers.LeakyReLU(0.2),
layers.Conv2DTranspose(512, kernel_size=4, strides=2, padding='same'), # 添加新层
layers.LeakyReLU(0.2),
layers.Conv2D(3, kernel_size=5, padding='same', activation='sigmoid')
]
)
在这个修改后的模型中,我们添加了两个
Conv2DTranspose
层,每个层的
strides=2
。这样,图像大小会从 8x8 逐渐增加到 512x512。
以下是关于
Conv2D
和
Conv2DTranspose
层如何工作以及它们如何影响图像大小的简要说明:
-
Conv2D
: 此层执行卷积运算,通常会降低图像大小。strides
参数决定了卷积核在图像上移动的步长。strides=2
会将图像大小减半。 -
Conv2DTranspose
: 此层执行转置卷积,通常用于增加图像大小。它通过在输入数据中添加零值(也称为上采样)来实现这一点,然后执行卷积。strides
参数控制上采样的程度。strides=2
会将图像大小翻倍。
在你的代码中,你使用
Conv2D
层作为鉴别器的一部分,并使用
Conv2DTranspose
层作为生成器的一部分。鉴别器会降低图像大小以提取特征,而生成器会增加图像大小以生成更大的图像。
通过向生成器添加额外的
Conv2DTranspose
层,你就可以生成 512x512 像素的图像。请记住,生成更高分辨率的图像可能需要更多的计算资源和训练时间。