【问题标题】:How can I reduce the loss rate of G and D in GAN?如何降低 GAN 中 G 和 D 的损失率?
【发布时间】:2020-01-31 09:37:42
【问题描述】:

我正在使用 Tensorflow 构建一个 GAN。

起初,我创建了一个生成 32x32 图像的 GAN。

修改模型以添加图层以创建 128x128 图像。

顺便说一句,32x32 GAN G,D的损失值还可以,但是随着层大小和图像大小的增加,损失值非常高。

我修改了图层并修改了其他超参数以降低损失,但仍然很高。

我想知道如何减少G和D的损失。

import os.path
import numpy as np
from keras.models import *
from keras.layers import *
from keras.optimizers import *
from keras.layers.convolutional import Conv2DTranspose, MaxPooling2D, UpSampling2D, Conv2D
from keras.layers.core import Reshape, Dense, Dropout, Flatten
from keras.layers.advanced_activations import LeakyReLU, ReLU
from keras.layers.normalization import BatchNormalization
import keras.backend as K
import matplotlib.pyplot as plt
from PIL import Image
from keras.models import load_model
K.set_image_data_format('channels_last')

class Gan:
    def __init__(self,img_data):
        img_size = img_data.shape[1]
        channel = img_data.shape[3] if len(img_data.shape) >= 4 else 1

        self.img_data = img_data
        self.input_shape = (img_size,img_size,channel)

        self.img_rows = img_size
        self.img_cols = img_size
        self.channel = channel
        self.noise_size = 128

        self.create_d()
        self.create_g()

        optimizer = Adam(lr=0.0008)
        self.D.compile(loss='binary_crossentropy', optimizer=optimizer)

        optimizer = Adam(lr=0.0004)
        self.D.trainable = False
        self.AM = Sequential()
        self.AM.add(self.G)
        self.AM.add(self.D)
        self.AM.compile(loss='binary_crossentropy',optimizer=optimizer)

    def create_g(self):
        self.G = Sequential()
        dropout = 0.4

        self.G.add(Dense(8 * 8 * 1024, input_dim=self.noise_size))
        self.D.add(Dropout(dropout))
        self.G.add(Activation('relu'))
        self.G.add(Reshape((8, 8, 1024)))
        self.G.add(Dropout(dropout))
        self.G.add(Conv2DTranspose(512, 5, strides=2, padding ='same'))
        self.D.add(Dropout(dropout))
        self.G.add(Activation('relu'))
        self.G.add(Conv2DTranspose(256, 5, strides=2, padding ='same'))
        self.D.add(Dropout(dropout))
        self.G.add(Activation('relu'))
        self.G.add(Conv2DTranspose(128, 5, strides=2, padding ='same'))
        self.D.add(Dropout(dropout))
        self.G.add(Activation('relu'))
        self.G.add(Conv2DTranspose(64, 5, strides=2, padding='same'))
        self.D.add(Dropout(dropout))
        self.G.add(Activation('relu'))
        self.G.add(Conv2DTranspose(self.channel, 5, strides =1,padding='same'))
        self.G.add(Activation('sigmoid'))
        self.G.summary()
        return self.G

    def create_d(self):
        self.D = Sequential()
        dropout = 0.4
        self.D.add(Conv2D(64, 5, strides=2, input_shape=self.input_shape, padding='same'))
        self.D.add(LeakyReLU(alpha=0.2))
        self.D.add(Dropout(dropout))
        self.D.add(BatchNormalization(momentum=0.9))
        self.D.add(Conv2D(128, 5, strides=2, input_shape=self.input_shape, padding='same'))
        self.D.add(LeakyReLU(alpha=0.2))
        self.D.add(Dropout(dropout))
        self.D.add(Conv2D(256, 5, strides=2, input_shape=self.input_shape, padding='same'))
        self.D.add(LeakyReLU(alpha=0.2))
        self.D.add(Dropout(dropout))
        self.D.add(Conv2D(512, 5, strides=1, input_shape=self.input_shape, padding='same'))
        self.D.add(LeakyReLU(alpha=0.2))
        self.D.add(Dropout(dropout))
        self.D.add(Conv2D(1024, 5, strides=2, input_shape=self.input_shape, padding='same'))
        self.D.add(LeakyReLU(alpha=0.2))
        self.D.add(Dropout(dropout))
        self.D.add(Flatten())
        self.D.add(Dense(1))
        self.D.add(Activation('sigmoid'))
        self.D.summary()
        return self.D


    def train(self, sess, batch_size=100):

        images_train = self.img_data[np.random.randint(0, self.img_data.shape[0], size=batch_size), :, :, :] #shape[0] -> image data의 숫자
        noise = np.random.uniform(-1.0,1.0, size=[batch_size,self.noise_size])
        images_fake = self.G.predict(noise)

        x = np.concatenate((images_train, images_fake))
        y = np.ones([2*batch_size,1])
        y[batch_size:,:] = 0
        self.D.trainable = True
        d_loss = self.D.train_on_batch(x,y)

        y = np.ones([batch_size,1])
        noise = np.random.uniform(-1.0,1.0,size=[batch_size,self.noise_size])
        self.D.trainable = False
        a_loss = self.AM.train_on_batch(noise,y)

        return d_loss, a_loss, images_fake

    def save_weigths(self):

        self.G.save_weights('gan_g_weights')
        self.D.save_weights('gan_d_weights')


    def load(self):
        if os.path.isfile('gan_g_weights'):
            self.G.load_weights('gan_g_weights')
            print("Load G from file")
        if os.path.isfile('gan_d_weights'):
            self.D.load_weights('gan_d_weights')
            print("Load D from file")

class faceData():
    def __init__(self):
        img_data_list = []
        images = os.listdir("data_rgb1")

        for path in images:
            img = Image.open("data_rgb1/" + path)
            img_data_list.append([np.array(img).astype('float32')])

        self.x_train = np.vstack(img_data_list) / 255.0
        print(self.x_train.shape)

dataset = faceData()
x_train =dataset.x_train

gan = Gan(x_train)
gan.load()

sess = tf.Session()
saver = tf.train.Saver()
sess.run(tf.global_variables_initializer())

epochs = 1000
sample_size = 10
batch_size = 50
train_per_epoch = x_train.shape[0] // batch_size



for epoch in range(0,epochs):
    total_d_loss = 0.0
    total_a_loss = 0.0
    imgs = None

    for batch in range(0, train_per_epoch):
        d_loss, a_loss, t_imgs = gan.train(batch_size)
        total_d_loss += d_loss
        total_a_loss += a_loss
        if imgs is None:
            imgs = t_imgs


    total_d_loss /= train_per_epoch
    total_a_loss /= train_per_epoch
    print("Epoch: {}, D Loss: {}, AM loss: {} " .format(epoch, total_d_loss, total_a_loss))
    fig, ax = plt.subplots(1, sample_size, figsize = (sample_size, 1))
    if epoch == 999:
        for i in range(0, sample_size):
            ax[i].set_axis_off()
            ax[i].imshow(imgs[i].reshape((gan.img_rows, gan.img_cols, gan.channel)), interpolation='nearest');
            plt.savefig('result%d.png' % epoch)
        saver.save(sess, os.path.join('save', 'model_{}'.format(epoch)))


    plt.close('all')
    gan.save_weigths()



结果:

Epoch:0,D 损失:8.065221479096389,AM 损失:14.922738138189171

Epoch:1,D 损失:8.052544213793604,AM 损失:14.836829509831928

Epoch:2,D 损失:8.02602034776949,AM 损失:14.889192866794954

Epoch:3,D 损失:8.05762272074743,AM 损失:14.88101108667209

Epoch:4,D 损失:8.045719083795692,AM 损失:14.863829361000642

Epoch:5,D 损失:8.052135099614333,AM 损失:14.872829325913173

Epoch:6,D 损失:8.026918762226396,AM 损失:14.900647337666623

Epoch:7,D 损失:8.091860083759133,AM 损失:14.836829485626994

Epoch:8,D 损失:8.05686701130746,AM 损失:14.935828973799188

Epoch:9,D 损失:8.038368832641448,AM 损失:14.832738677862332

Epoch:10,D 损失:8.06173144016169,AM 损失:14.904738174477204

Epoch:11,D 损失:8.032495556749064,AM 损失:14.926010857983893 . . .

【问题讨论】:

    标签: tensorflow keras generative-adversarial-network


    【解决方案1】:

    欢迎来到训练 GAN 的美好世界。这不是一件容易的事,但也不是不可能。我无法仅通过查看前 10 个时期的损失来判断问题所在。

    高度建议你看看这个article。您可能遇到了麻烦,因为当您添加更多层时,平衡肯定已经被打破。

    文章中推荐的一些技巧是:

    1. 查看渐变。
    2. 执行预训练。
    3. 不要使用硬标签。

    一些个人提示是:在生成器中添加批量标准化。不要在生成器中使用密集层。

    祝你好运,玩得开心!发布一些你正在生成的图像我很好奇!

    【讨论】:

    • 非常感谢您的回复。现在我改变了时代,但损失几乎相同。我读了文章,我有一些猜测。什么是硬标签?
    • 这意味着,在判别器的训练中,我们不是将假/真图像标记为 1 或 0,而是放置软标签,数字介于 1 和 0.9 之间或 0 和 0.1 之间图片。
    • 我还有一件事要问。这是关于生成器和判别器的损失。在我的修改模型中,生成器的损失在增加,判别器的损失值为 0.11 ~ 0.15。它是否正确?我想知道生成器的损失和判别器的损失是否应该是好的模型。示例:当 G loss 高 D loss 低时,一个好的模型?
    • 嗯。 GAN 的收敛是很难实现的。在你的情况下。看起来判别器太“聪明”或生成器太“笨”。您应该检查生成的图像在各个时期内的变化情况,并在两种损失都相当低且生成的图像质量良好且对您的目的有意义时尽早停止!通过快速搜索,我发现了这个:towardsdatascience.com/…。可能会有帮助!
    猜你喜欢
    • 2021-07-17
    • 2019-12-22
    • 1970-01-01
    • 2018-10-03
    • 2021-11-19
    • 2019-09-06
    • 2020-10-14
    • 2018-03-28
    • 1970-01-01
    相关资源
    最近更新 更多