GAN模型训练误差图解

之前在课程中讲解GAN模型,自己略懂,但是却无法向同学形象地讲解GAN模型中辨别模型和生成模型究竟是如何训练的。以及为啥两个模型都进行训练了,而辨别模型的表现却越来越差,而生成模型就越来越好(最起码从训练误差来看)。同时网上对GAN模型讲解也不是很形象,略抽象,因此希望能帮助更多同学理解GAN模型的原理

两个模型是如何训练

每一个iteration内(即一个batch内):
	魔高一尺,生成假数据
	道高一丈,辨别真假数据(假数据来自刚刚生成的假数据)
	中场阶段,两者通过自定义的损失函数,进行反向传播学习,提升自己的能力
循环上述阶段直至进行完所有iteration,

魔高一尺,道高一丈
道高一丈,魔高一尺
最后两败俱伤,也就是双发都无法继续分出胜负。但是这时候双方都已经提高了自己的能力

GAN模型训练详解

  1. 假设辨别器刚开始还未训练时的损失
    在这里插入图片描述
    从图解可以看到,
    图形横轴 表示模型接受的是真实数据还是虚假数据
    图形纵轴 表示辨别模型对数据是真实数据还是虚假数据给出的概率
    红色区域 表示辨别模型的训练误差(是两个红色面积之和)
    绿色区域 表示生成模型的训练误差(只有右边绿色面积)
    中红左绿 中间红色区域之外的白色区域从两个模型的损失函数的定义来开,是等于右边绿色区域的。

即在还没开始反向传播的时候,辨别器不能正确分别真实数据和虚假数据,生成模型也不能生成高仿真数据

  1. 辨别器和生成模型经过反向传播,学习了对方的招式
    在这里插入图片描述
    从图解可以看到,对于辨别器来说,在训练初期虚假数据和真实数据是简单易分辨的。而对于生成模型来说,由于不能直接对图片数据进行学习,所以生成模型最开始的训练误差巨高

  2. 多轮迭代训练之后,生成模型的图片生成技术大大提升
    在这里插入图片描述
    从图解可以看到,生成模型的训练误差(绿色区域)正在降低,而辨别模型的训练误差(红色区域)开始不断增高

  3. 训练结束,辨别模型的辨别能力失效
    在这里插入图片描述
    从图解可以看到,生成模型给出真实数据和虚假数据的概率均为0.5,辨别模型不能够通过误差反向传播来优化自己,因为生成模型生成的数据,从理论上来说与真实数据并不存在特征差异。而生成模型也因为无法在辨别模型中学习生成能力,因为造出来的数据无法比真数据还真。

具体实现代码

代码实现借鉴网络

import os
import warnings
warnings.filterwarnings('ignore')
import tensorflow as tf 
import pandas as pd
import glob
from tensorflow import keras
import matplotlib as mpl
import matplotlib.pyplot as plt
from tf.keras.layers import *

batch_size = 64
buffer_size = 60000

datasets = tf.data.Dataset.from_tensor_slices(train_image)
datasets = datasets.shuffle(buffer_size).batch(batch_size)

# 生成器构建,采用反卷积的操作
def generator_model():
	model = tf.keras.Sequential()
	# input_shape 是自由定义的
	model.add(Dense(512*3*3, input_shape=(256,),use_bias = False))
	model.add(Reshape((3,3,512)))
	model.add(LeakyRelu())
	model.add(Conv2DTranspose(256,kernel_size=3,strides=3,'valid'))
	model.add(BatchNormalization())
	model.add(LeakyReLu())
	model.add(Conv2DTranspose(128,kernel_size=5,strides=2,'valid'))
	model.add(BatchNormalization())
	model.add(Conv2DTranspose(32,kernel_size=4,strides=1,'valid'))
	model.add(BatchNormalization())
	model.add(LeakyReLu())
	model.add(Conv2DTranspose(1,kernal_size=5,strides=1,'valid)

	model.summary()
	return model
	
# 判别器的构建,采取卷积的操作,采用序贯模型的方式
def discriminator_model():
	discriminator = keras.Sequential(
	[
		tf.keras.layers.Conv2D(32,(3,3),input_shape=(28,28,1))
		tf.keras.layers.BatchNormalization()
		tf.keras.layers.LeakyRelu()
		# 下面代码等价于 tf.keras.Conv2D(64,kernel_size= 3)
		tf.keras.layers.Conv2D(64,(3,3)
		tf.keras.layers.BatchNormalization()
		tf.keras.layers.LeakRelu()
		# 将二维图片转换为一维数据结构
		tf.keras.layers.Flatten()
		tf.keras.layers.Dense(128,activation='relu')
		tf.keras.layers.Dense(1,activation='sigmoid')
		return discriminator

# 损失函数的构建
#其中,from_logits参数表示是否从Logits(即模型输出层之前的激活函数输出)计算损失,
#如果为True,表示输入是原始的Logits,即没有经过激活函数的输出;
#如果为False,表示输入是经过激活函数后的概率值
cross_entropy = keras.losses.BinaryCrosssentropy(from_logits=False))

def discriminator_loss(real_out, fake_out):
	real_loss = cross_entropy(tf.ones_like(real_out),real_out)
	fake_loss = cross_entropy(tf.zeros_like(fake_out),fake_out)
	return real_loss + fake_loss

def generator_loss(fake_out):
	return cross_entropy(tf.ones_like(fake_out),fake_out)
	
# 优化器的构造
generator_optimizer = tf.keras.optimizers.Adam(1e-4)
discriminator_optimizer = tf.keras.optimizers.Adam(1e-4)
	
epochs = 100
noise_dim = 256
num = 16
# 初始化一维向量作为生成器的输入
seed = tf.random.normal([num,noise_dim])

discriminator = discriminator_model()
generator = generator_model()

# 自定义训练过程
def train_step(images);
	noise = tf.random.normal([batch_size,noise_dim])
	with tf.GradientTape() as G_tape, tf.GradientTape() as D_tape:
		real_out = discriminator(images, training=True)
		gen_image = generator(noise, training=True)
		fake_out = discriminator(gen_image, training=True)
		gen_loss = generator_loss(fake_out)
		discr_loss = discriminator_loss(real_out,fake_out)

	gradient_gen = G_tape.gradient(gen_loss,generator.trainabel_variables)
	gradient_discr = D_tape.gradient(gen_loss,discriminator.trainable_variables)

	generator_optimizer.apply_gradients(zip(gradient_gen, generator.trainable_variables)
	discriminator_optimizer.apply_gradients(zip(gradient_discr,discriminator.trainable_variables)
	return gen_loss, discr_loss

def plot_gen_image(gen_model, test_noise):
	pre_image = gen_model(test_noise, training=False)
	fig = plt.figure(figsize=(4,4))
	# 是batch数据,所以有多个样本,需要用for循环进行一个个遍历
	for i in range(pre_image.shape[0]):
		plt.subplot(4,4,i+1)
		plt.imshow((pre_image[i,:,:,0]),camp='gray')
		plt.axis('off')
	plt.show()

def train(dataset,epochs);
	for epoch in range(epochs):
		print("第%d次迭代"%(epoch+1))
		for image_batch in dataset:
			gen_loss, discr_loss = train_step(image_batch)
			print('#', end = '')
		print("损失函数为", gen_loss, discr_loss)
		plot_gen_image(generator,seed)
		
train(datasets, epochs)

	
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值