import os
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import glob
from PIL import Image
image_size = 64
SHUFFLE_SIZE = 1000
batch_size = 64
z_dim = 100 # 隐藏向量z的长度
img_shape = (image_size, image_size, 3)
PATH = '.\faces/'
X_train = tf.data.Dataset.list_files(PATH+'*.jpg')
img_path = glob.glob(r'.faces*.jpg')
print('images num:', len(img_path))
images num: 51223
def load(image_file):image = ad_file(image_file)image = tf.image.decode_jpeg(image)image = tf.cast(image, tf.float32)image = size(image, [image_size, image_size])image = (image - 127.5) / 127.5return image
dataset = X_train.map(load, num_parallel_calls=perimental.AUTOTUNE).cache().shuffle(SHUFFLE_SIZE).batch(batch_size).repeat(100)
class Generator(tf.keras.Model):def __init__(self):super(Generator, self).__init__()filter = 64# 转置卷积层1,输出channel为filter*8,核大小4,步长1,不使用padding,不使用偏置v1 = layers.Conv2DTranspose(filter*8, 4,1, 'valid', use_bias=False)self.bn1 = layers.BatchNormalization()# 转置卷积层v2 = layers.Conv2DTranspose(filter*4, 4,2, 'same', use_bias=False)self.bn2 = layers.BatchNormalization()# 转置卷积层v3 = layers.Conv2DTranspose(filter*2, 4,2, 'same', use_bias=False)self.bn3 = layers.BatchNormalization()# 转置卷积层v4 = layers.Conv2DTranspose(filter*1, 4,2, 'same', use_bias=False)self.bn4 = layers.BatchNormalization()# 转置卷积层v5 = layers.Conv2DTranspose(3, 4,2, '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 = lu(x) # 激活函数# 转置卷积-BN-激活函数:(b, 4, 4, 512)x = lu(self.v1(x), training=training))# 转置卷积-BN-激活函数:(b, 8, 8, 256)x = lu(self.v2(x), training=training))# 转置卷积-BN-激活函数:(b, 16, 16, 128)x = lu(self.v3(x), training=training))# 转置卷积-BN-激活函数:(b, 32, 32, 64)x = lu(self.v4(x), training=training))# 转置卷积-激活函数:(b, 64, 64, 3)x = v5(x)x = tf.tanh(x) # 输出x范围0~1,与预处理一致return x
class Discriminator(tf.keras.Model):# 判别器def __init__(self):super(Discriminator, self).__init__()filter = 64# 卷积层v1 = layers.Conv2D(filter, 4, 2, 'valid', use_bias=False)self.bn1 = layers.BatchNormalization()# 卷积层v2 = layers.Conv2D(filter*2, 4, 2, 'valid', use_bias=False)self.bn2 = layers.BatchNormalization()# 卷积层v3 = layers.Conv2D(filter*4, 4, 2, 'valid', use_bias=False)self.bn3 = layers.BatchNormalization()# 卷积层v4 = layers.Conv2D(filter*8, 3, 1, 'valid', use_bias=False)self.bn4 = layers.BatchNormalization()# 卷积层v5 = layers.Conv2D(filter*16, 3, 1, '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.v1(inputs), training=training))# 卷积-BN-激活函数:(4, 14, 14, 128)x = tf.nn.leaky_relu(self.v2(x), training=training))# 卷积-BN-激活函数:(4, 6, 6, 256)x = tf.nn.leaky_relu(self.v3(x), training=training))# 卷积-BN-激活函数:(4, 4, 4, 512)x = tf.nn.leaky_relu(self.v4(x), training=training))# 卷积-BN-激活函数:(4, 2, 2, 1024)x = tf.nn.leaky_relu(self.v5(x), training=training))# 卷积-BN-激活函数:(4, 1024)x = self.pool(x)# 打平x = self.flatten(x)# 输出,[b, 1024] => [b, 1]logits = self.fc(x)return logits
generator = Generator() # 创建生成器
generator.build(input_shape = (4, z_dim))
discriminator = Discriminator() # 创建判别器
discriminator.build(input_shape=(4, 64, 64, 3))
其中input_shape 的第一个维度其实随便设一个数就可以,但是用None 会报错,不知道为什么……
loss_object = tf.keras.losses.BinaryCrossentropy(from_logits=True)
def g_loss_fn(d_fake_logits):# 计算生成图片与1之间的误差loss = tf.reduce_mean(loss_s_like(d_fake_logits), d_fake_logits))return loss
def d_loss_fn(d_real_logits, d_fake_logits):# 真实图片与1之间的误差d_loss_real = tf.reduce_mean(loss_s_like(d_real_logits), d_real_logits))# 生成图片与0之间的误差d_loss_fake = tf.reduce_mean(loss_s_like(d_fake_logits), d_fake_logits))# 合并误差loss = d_loss_fake + d_loss_realreturn loss
# 分别为生成器和判别器创建优化器
learning_rate = 0.0002
g_optimizer = keras.optimizers.Adam(learning_rate=learning_rate, beta_1=0.5)
d_optimizer = keras.optimizers.Adam(learning_rate=learning_rate, beta_1=0.5)
def train_step(batch_x):# 采样隐藏向量batch_z = al([batch_size, z_dim])with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:# 采样生成图片fake_image = generator(batch_z, training=True)# 判定生成图片d_fake_logits = discriminator(fake_image, training=True)# 判定真实图片d_real_logits = discriminator(batch_x, training=True)d_loss = d_loss_fn(d_real_logits, d_fake_logits)g_loss = g_loss_fn(d_fake_logits)grads_d = adient(d_loss, ainable_variables)grads_g = adient(g_loss, ainable_variables)d_optimizer.apply_gradients(zip(grads_d, ainable_variables))g_optimizer.apply_gradients(zip(grads_g, ainable_variables))return d_loss, g_loss
注意,要将所有关于生成器、判别器的操作都放在梯度带中。
def save_result(val_out, val_block_size, image_path, color_mode):preprocesed = ((val_out + 1.0) * 127.5).astype(np.uint8)final_image = np.array([])single_row = np.array([])for b in range(val_out.shape[0]):# concat image into a rowif single_row.size == 0:single_row = preprocesed[b, :, :, :]else:single_row = np.concatenate((single_row, preprocesed[b, :, :, :]), axis=1)# concat image row to final_imageif (b+1) % val_block_size == 0:if final_image.size == 0:final_image = single_rowelse:final_image = np.concatenate((final_image, single_row), axis=0)# reset single rowsingle_row = np.array([])Image.fromarray(final_image).save(image_path)
for n, data umerate():d_loss, g_loss = train_step(data)print('.', end='')if n % 100 == 0:print()print(n.numpy(), 'd-loss:',float(d_loss), 'g-loss:', float(g_loss))# 可视化z = al([100, z_dim])fake_image = generator(z, training=False)img_path = os.path.join('gan_images', 'gan-%d.png'%n)save_result(fake_image.numpy(), 10, img_path, color_mode='P')
本文发布于:2024-02-04 19:53:40,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170715231859046.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |