甘损微小,鉴别损失巨大?

时间:2019-08-24 15:01:49

标签: deep-learning loss gan

我在代码中找不到问题-我正在训练GAN,而gan损失和鉴别损失非常低,为0.04,看来收敛得很好,但是-图片看起来不是很好但是实际的问题是,b-当我执行gan.predict(noise)时,它非常接近1,但是当我执行discriminator.predict(gan(noise))时,尽管它应该是相同的,但它非常接近0。 。这是我的代码:

生成器代码:

subscription = Subscription.first
order = subscription.orders.first

# Pass the Order object that needs to be removed from association table
subscription.orders.delete(order)

区分代码:


def create_generator():
    generator=tf.keras.Sequential()
    #generator.add(layers.Dense(units=50176,input_dim=25))
    generator.add(layers.Dense(units=12544,input_dim=100))
    #generator.add(layers.Dropout(0.2))
    generator.add(layers.Reshape([112,112,1])) #112,112
    generator.add(layers.Conv2D(32, kernel_size=3,padding='same',activation='relu'))
    generator.add(layers.UpSampling2D()) #224,224
    generator.add(layers.Conv2D(1, kernel_size=4,padding='same',activation='tanh'))   

    generator.compile(loss='binary_crossentropy', optimizer=adam_optimizer())
    return generator
g=create_generator()
g.summary()

邮政编码:

#IMAGE DISCRIMINATOR
def create_discriminator():
  discriminator=tf.keras.Sequential()
  discriminator.add(layers.Conv2D(64, kernel_size=2,padding='same',activation='relu',input_shape=[224,224,1]))
  discriminator.add(layers.Dropout(0.5))
  discriminator.add(layers.Conv2D(32,kernel_size=2,padding='same',activation='relu'))
  discriminator.add(layers.Dropout(0.5))
  discriminator.add(layers.Conv2D(16,kernel_size=2,padding='same',activation='relu'))
  discriminator.add(layers.Dropout(0.5))
  discriminator.add(layers.Conv2D(8,kernel_size=2,padding='same',activation='relu'))
  discriminator.add(layers.Dropout(0.5))
  discriminator.add(layers.Conv2D(1,kernel_size=2,padding='same',activation='relu'))
  discriminator.add(layers.Dropout(0.5))
  discriminator.add(layers.Flatten())

  discriminator.add(layers.Dense(units=1, activation='sigmoid'))

  discriminator.compile(loss='binary_crossentropy', optimizer=tf.optimizers.Adam(lr=0.0002))
  return discriminator
d =create_discriminator()
d.summary()

训练代码(我故意不使用gan来进行train_on_batch,因为我想看看梯度是否为零。)

def create_gan(discriminator, generator):
    discriminator.trainable=False
    gan_input = tf.keras.Input(shape=(100,))
    x = generator(gan_input)
    gan_output= discriminator(x)
    gan= tf.keras.Model(inputs=gan_input, outputs=gan_output)
    #gan.compile(loss='binary_crossentropy', optimizer='adam')
    gan.compile(loss='binary_crossentropy', optimizer=adam_optimizer())
    return gan
gan = create_gan(d,g)
gan.summary()

现在,在大约2000个时代之后,发电机的最终损失为0.039,鉴别器的最终损失为0.034。问题是,当我执行以下操作时,请看得到的内容

#@tf.function
def training(epochs=1, batch_size=128, rounds=50):
    batch_count = X_bad.shape[0] / batch_size

    # Creating GAN
    generator = create_generator()
    discriminator = create_discriminator()
    ###########if you want to continue training an already trained gan
    #discriminator.set_weights(weights)
    gan = create_gan(discriminator, generator)
    start = time.time()

    for e in range(1,epochs+1 ):
        #print("Epoch %d" %e)
        #for _ in tqdm(range(batch_size)):
        #generate  random noise as an input  to  initialize the  generator
        noise= np.random.normal(0,1, [batch_size, 100])

            # Generate fake MNIST images from noised input
        generated_images = generator.predict(noise)
            #print('gen im shape: ',np.shape(generated_images))

            # Get a random set of  real images
        image_batch = X_bad[np.random.randint(low=0,high=X_bad.shape[0],size=batch_size)]
            #print('im batch shape: ',image_batch.shape)

            #Construct different batches of  real and fake data 
        X= np.concatenate([image_batch, generated_images])

            # Labels for generated and real data
        y_dis=np.zeros(2*batch_size)
        y_dis[:batch_size]=0.99

            #Pre train discriminator on  fake and real data  before starting the gan. 
        discriminator.trainable=True
        discriminator.train_on_batch(X, y_dis)

            #Tricking the noised input of the Generator as real data
        noise= np.random.normal(0,1, [batch_size, 100])
        y_gen = np.ones(batch_size)

            # During the training of gan, 
            # the weights of discriminator should be fixed. 
            #We can enforce that by setting the trainable flag
        discriminator.trainable=False

            #training  the GAN by alternating the training of the Discriminator 
            #and training the chained GAN model with Discriminator’s weights freezed.

        #gan.train_on_batch(noise, y_gen)
        with tf.GradientTape() as tape:
          pred=gan(noise)
          loss_val=tf.keras.losses.mean_squared_error(y_gen,pred)
    #     loss_val=gan.test_on_batch(noise,y_gen)
    #     loss_val=tf.cast(loss_val,dtype=tf.float32)
        grads=tape.gradient(loss_val,gan.trainable_variables)
        optimizer.apply_gradients(zip(grads, gan.trainable_variables))

        if e == 1 or e % rounds == 0:
          end = time.time()

          loss_value=discriminator.test_on_batch(X, y_dis)
          print("Epoch {:03d}: Loss: {:.3f}".format(e,loss_value))
          gen_loss=gan.test_on_batch(noise,y_gen)
          print('gan loss: ',gen_loss)
          #print('Epoch: ',e,' Loss: ',)
          print('Time for ',rounds,' epochs: ',end-start,' seconds')
          local_time = time.ctime(end)
          print('Printing time: ',local_time)
          plot_generated_images(e, generator,examples=5)
          start = time.time()
    return discriminator,generator,grads

有人可以找到问题吗?

谢谢!

1 个答案:

答案 0 :(得分:-1)

如果有人偶然发现了这个,那么我就算了(尽管我还没有解决)。这里发生的是,我的Gan对象仅训练发电机的重量。鉴别器是一个本身正在训练的对象,但是当我训练gan时,我不更新gan中的鉴别器权重,而是只更新了发生器权重,因此当我将噪声作为gan的输入时,输出是我想要的,接近一个,但是当我将生成的图像作为鉴别器的输入时,由于鉴别器是与生成器分开训练的(鉴别器的权重在gan内部根本没有改变),因此结果接近于零。更好的方法是将GAN作为一个类来创建,并且能够接近gan中的鉴别器和gan中的生成器,以更新其在gan中的权重。