如何解决DCGAN生成T恤设计时的模式崩溃与损失收敛问题?
T恤设计生成DCGAN的模式崩溃与收敛问题
我在完成MNIST数据集的DCGAN实验后,尝试将其应用到T恤设计生成这一更复杂的场景中。搭建模型时严格遵循DCGAN论文的架构准则:
- 用步幅卷积(判别器)和分数步幅卷积(生成器)替代池化层
- 生成器和判别器中均使用BatchNorm
- 移除深层架构的全连接隐藏层
- 生成器除输出层用Tanh外,其余层用ReLU
- 判别器全层使用LeakyReLU
但目前生成的输出完全一致,疑似出现模式崩溃,同时无法确定是否存在梯度消失或收敛失败问题。我已尝试调整学习率、修改架构、标签平滑、分开训练真假样本等方法,且多次在损失为0或波动剧烈时提前终止训练,但问题仍未解决。
数据集与实验结果
- 真实训练样本:

- 生成样本:

- 损失曲线:

模型代码
import matplotlib.pyplot as plt import numpy as np import os from tensorflow.keras.layers import Conv2D, Conv2DTranspose, Dense, Dropout, Flatten, BatchNormalization, Input, Reshape, LeakyReLU, ReLU from tensorflow.keras.models import Sequential from tensorflow.keras.optimizers import Adam from tensorflow.keras.utils import img_to_array, load_img def discriminator(input_shape=(128, 128, 3)): model = Sequential([ Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=input_shape, kernel_initializer='glorot_uniform'), # kernel initializer was removed LeakyReLU(alpha=0.2), Conv2D(128, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), LeakyReLU(alpha=0.2), Conv2D(256, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), LeakyReLU(alpha=0.2), Conv2D(512, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), LeakyReLU(alpha=0.2), # Output => 8 * 8 * 512 Flatten(), Dense(1, activation='sigmoid') ]) opt = Adam(learning_rate=0.0002, beta_1=0.5) model.compile(loss='binary_crossentropy', optimizer=opt, metrics=None) return model def generator(): model = Sequential([ Dense(8*8*512, input_shape=(100,), kernel_initializer='glorot_uniform'), Reshape((8, 8, 512)), BatchNormalization(momentum=0.5), ReLU(), Conv2DTranspose(256, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), ReLU(), Conv2DTranspose(128, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), ReLU(), Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', kernel_initializer='glorot_uniform'), BatchNormalization(momentum=0.5), ReLU(), Conv2DTranspose(3, (5, 5), strides=(2, 2), padding='same', activation='tanh', kernel_initializer='glorot_uniform'), ]) return model def gan(gen_model, disc_model): disc_model.trainable = False model = Sequential([ gen_model, disc_model ]) opt = Adam(learning_rate=0.0002, beta_1=0.5) model.compile(loss='binary_crossentropy', optimizer=opt) return model def load_dataset(directory="/content/tshirt-resized", target_size=(128, 128)): images = [] for filename in os.listdir(directory): img = load_img(os.path.join(directory, filename), target_size=target_size) images.append(img_to_array(img)) dataset = np.array(images) dataset = dataset.astype('float32') dataset /= 255.0 return dataset def generate_real_samples(dataset, num_samples): ix = np.random.randint(0, dataset.shape[0], num_samples) X = dataset[ix] y = np.ones((num_samples, 1)) - 0.1 # Label smoothing return X, y def generate_latent_points(num_samples): # gen model input x_input = np.random.randn(100 * num_samples) x_input = x_input.reshape(num_samples, 100) return x_input def generate_fake_samples(gen_model, num_samples): # gen model output x_input = generate_latent_points(num_samples) X = gen_model.predict(x_input) y = np.zeros((num_samples, 1)) + 0.1 # Label smoothing return X, y def train(gen_model, disc_model, gan_model, dataset, epochs=200, batch_size=128): num_batches_per_epoch = int(dataset.shape[0] / batch_size) d1_loss_hist = [] d2_loss_hist = [] gan_loss_hist = [] for i in range(epochs): for j in range(num_batches_per_epoch): X_real, y_real = generate_real_samples(dataset, batch_size // 2) d1_loss = disc_model.train_on_batch(X_real, y_real) X_fake, y_fake = generate_fake_samples(gen_model, batch_size // 2) d2_loss = disc_model.train_on_batch(X_fake, y_fake) X_gan = generate_latent_points(batch_size) y_gan = np.ones((batch_size, 1)) gan_loss = gan_model.train_on_batch(X_gan, y_gan) print('>%d, %d/%d, d1=%.3f, d2=%.3f, g=%.3f' % (i+1, j+1, num_batches_per_epoch, d1_loss, d2_loss, gan_loss)) d1_loss_hist.append(d1_loss) d2_loss_hist.append(d2_loss) gan_loss_hist.append(gan_loss) if (i+1) % 50 == 0: filename = 'generator_model_%03d.keras' % (i + 1) gen_model.save(filename) plt.plot(d1_loss_hist, label='d-real') plt.plot(d2_loss_hist, label='d-fake') plt.plot(gan_loss_hist, label='gan') plt.legend() plt.savefig("Loss Plot.png") disc_model = discriminator() gen_model = generator() gan_model = gan(gen_model, disc_model) dataset = load_dataset() train(gen_model, disc_model, gan_model, dataset)
内容的提问来源于stack exchange,提问作者Adit Desai
相关产品推荐
相关产品推荐

