采用tensorflow2.0反卷积神经网络构建对抗生成网络,作为入门学习使用
import tensorflow as tf
from tensorflow import keras
from keras import layers
class Generator(keras.Model):
# 生成器网络
def __init__(self):
super(Generator, self).__init__()
filter = 64
# 转置卷积层1,输出channel为filter*8,核大小4,步长1,不使用padding,不使用偏置
self.conv1 = layers.Conv2DTranspose(filters=filter*8, kernel_size=4,strides=1, padding='valid', use_bias=False)
self.bn1 = layers.BatchNormalization()
# 转置卷积层2
self.conv2 = layers.Conv2DTranspose(filters=filter*4, kernel_size=4,strides=2, padding='same', use_bias=False)
self.bn2 = layers.BatchNormalization()
# 转置卷积层3
self.conv3 = layers.Conv2DTranspose(filters=filter*2, kernel_size=4,strides=2, padding='same', use_bias=False)
self.bn3 = layers.BatchNormalization()
# 转置卷积层4
self.conv4 = layers.Conv2DTranspose(filters=filter*1, kernel_size=4,strides=2, padding='same', use_bias=False)
self.bn4 = layers.BatchNormalization()
# 转置卷积层5
self.conv5 = layers.Conv2DTranspose(filters=3, kernel_size=4,strides=2, padding='same', use_bias=False)
def call(self, inputs, training=None):
x = inputs # [z, 100]
# Reshape乘4D张量,方便后续转置卷积运算:(b, 1, 1, 100)
x = tf.reshape(x, (x.shape[0], 1, 1, x.shape[1]))
x = tf.nn.relu(x) # 激活函数
# 转置卷积-BN-激活函数:(b, 4, 4, 512)
x = tf.nn.relu(self.bn1(self.conv1(x), training=training))
# 转置卷积-BN-激活函数:(b, 8, 8, 256)
x = tf.nn.relu(self.bn2(self.conv2(x), training=training))
# 转置卷积-BN-激活函数:(b, 16, 16, 128)
x = tf.nn.relu(self.bn3(self.conv3(x), training=training))
# 转置卷积-BN-激活函数:(b, 32, 32, 64)
x = tf.nn.relu(self.bn4(self.conv4(x), training=training))
# 转置卷积-激活函数:(b, 64, 64, 3)
x = self.conv5(x)
x = tf.tanh(x) # 输出x范围-1~1,与预处理一致
return x
class Discriminator(keras.Model):
# 判别器
def __init__(self):
super(Discriminator, self).__init__()
filter = 64
# 卷积层
self.conv1 = layers.Conv2D(filters=filter, kernel_size=4, strides=2, padding='valid', use_bias=False)
self.bn1 = layers.BatchNormalization()
# 卷积层
self.conv2 = layers.Conv2D(filters=filter*2, kernel_size=4, strides=2, padding='valid', use_bias=False)
self.bn2 = layers.BatchNormalization()
# 卷积层
self.conv3 = layers.Conv2D(filters=filter*4, kernel_size=4, strides=2, padding='valid', use_bias=False)
self.bn3 = layers.BatchNormalization()
# 卷积层
self.conv4 = layers.Conv2D(filters=filter*8, kernel_size=3, strides=1, padding='valid', use_bias=False)
self.bn4 = layers.BatchNormalization()
# 卷积层
self.conv5 = layers.Conv2D(filters=filter*16, kernel_size=3, strides=1, padding='valid', use_bias=False)
self.bn5 = layers.BatchNormalization()
# 全局池化层
self.pool = layers.GlobalAveragePooling2D()
# 特征打平
#self.flatten = layers.Flatten()
# 2分类全连接层
self.fc = layers.Dense(1)
def call(self, inputs, training=None):
# 卷积-BN-激活函数:(4, 31, 31, 64)
x = tf.nn.leaky_relu(self.bn1(self.conv1(inputs), training=training))
# 卷积-BN-激活函数:(4, 14, 14, 128)
x = tf.nn.leaky_relu(self.bn2(self.conv2(x), training=training))
# 卷积-BN-激活函数:(4, 6, 6, 256)
x = tf.nn.leaky_relu(self.bn3(self.conv3(x), training=training))
# 卷积-BN-激活函数:(4, 4, 4, 512)
x = tf.nn.leaky_relu(self.bn4(self.conv4(x), training=training))
# 卷积-BN-激活函数:(4, 2, 2, 1024)
x = tf.nn.leaky_relu(self.bn5(self.conv5(x), training=training))
# 卷积-BN-激活函数:(4, 1024)
#print(x.shape)
x = self.pool(x)
#print(x.shape)
# 打平
#x = self.flatten(x)
# 输出,[b, 1024] => [b, 1]
x = tf.reshape(x,[-1,1024])
logits = self.fc(x)
return logits
d =Discriminator()
x = tf.random.normal([2, 64, 64, 3])
d(x)
'''def celoss_ones(logits):
# 计算属于与标签为1的交叉熵
y = tf.ones_like(logits)
loss = keras.losses.binary_crossentropy(y, logits, from_logits=True)
return tf.reduce_mean(loss)
def celoss_zeros(logits):
# 计算属于与便签为0的交叉熵
y = tf.zeros_like(logits)
loss = keras.losses.binary_crossentropy(y, logits, from_logits=True)
return tf.reduce_mean(loss)
def d_loss_fn(generator, discriminator, batch_z, batch_x, is_training):
# 计算判别器的误差函数
# 采样生成图片
fake_image = generator(batch_z, is_training)
# 判定生成图片
d_fake_logits = discriminator(fake_image, is_training)
# 判定真实图片
d_real_logits = discriminator(batch_x, is_training)
# 真实图片与1之间的误差
d_loss_real = celoss_ones(d_real_logits)
# 生成图片与0之间的误差
d_loss_fake = celoss_zeros(d_fake_logits)
# 合并误差
loss = d_loss_fake + d_loss_real
return loss
def g_loss_fn(generator, discriminator, batch_z, is_training):
# 采样生成图片
fake_image = generator(batch_z, is_training)
# 在训练生成网络时,需要迫使生成图片判定为真
d_fake_logits = discriminator(fake_image, is_training)
# 计算生成图片与1之间的误差
loss = celoss_ones(d_fake_logits)
return loss
import numpy as np
generator = Generator()
x = tf.random.normal([2, 64, 64, 3])
z = tf.random.normal([2, 100])
d = generator(z,True)
h = d[0]
print(lambda h:h[:,:,:,:])
#x_hat = x_hat.astype(np.uint8)
import cv2
cv2.imwrite('F:\\GAN\\DCGAN\\images\\1.png',h)'''
#discriminator = Discriminator()
'''z = discriminator(x)
#g_loss_fn(generator,discriminator,z,True)
fake_image = generator(z, True)
# 在训练生成网络时,需要迫使生成图片判定为真
d_fake_logits = discriminator(fake_image, True)
y = tf.ones_like(d_fake_logits)
loss = keras.losses.binary_crossentropy(d_fake_logits, y, from_logits=True)
print(tf.reduce_mean(loss))
'''
'''def main():
generator = Generator() # 创建生成器
generator.build(input_shape=(2, 100))
discriminator = Discriminator() # 创建判别器
discriminator.build(input_shape=(4, 64, 64, 3))
d = Discriminator()
g = Generator()
x = tf.random.normal([2, 64, 64, 3])
z = tf.random.normal([2, 100])
prob = d(x)
print(prob)
x_hat = g(z)
print(x_hat.shape)
if __name__ == '__main__':
main()'''