为什么我是用GAN进行图片生成,完全没有生成效果?
import cv2
import numpy as np
import os
import tensorflow.keras as keras
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, Dense, MaxPooling2D, Conv2DTranspose, BatchNormalization, LeakyReLU, Reshape, Flatten
from tensorflow.keras.losses import BinaryCrossentropy, MeanSquaredError
import tensorflow as tf
import tqdm
class GAN:
def __init__(self, lr, noiseDim, batchSize, epoch, mean=0, var=1):
# 初始化参数
self.lr = lr
self.noiseDim = noiseDim
self.epoch = epoch
self.mean = mean
self.var = var
self.batchSize = batchSize
# 损失函数
self.lossFunc = BinaryCrossentropy(from_logits=False)
# 优化器
self.generator_opt = keras.optimizers.Adam(self.lr)
self.discriminator_opt = keras.optimizers.Adam(self.lr)
# 初始化网络
self.model_d = self.discriminator_model()
self.model_g = self.generator_model()
def generator_model(self):
"""生成器"""
model1 = Sequential()
# 全连接层
model1.add(Dense(256, use_bias=True, activation="selu"))
model1.add(Dense(64, use_bias=True, activation="selu"))
model1.add(Dense(256, use_bias=True, activation="selu"))
model1.add(Dense(12 * 12 * 64, use_bias=True, activation="selu"))
# 变换数据形状
model1.add(Reshape((12, 12, 64)))
# 卷积层
model1.add(Conv2DTranspose(32, kernel_size=1, strides=(1, 1), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
model1.add(Conv2DTranspose(16, kernel_size=3, strides=(2, 2), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
model1.add(Conv2DTranspose(8, kernel_size=3, strides=(2, 2), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
model1.add(Conv2DTranspose(3, kernel_size=3, strides=(2, 2), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
return model1
def discriminator_model(self):
"""判别器"""
model2 = Sequential()
# 卷积层
model2.add(Conv2D(8, kernel_size=1, strides=(1, 1), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
# 池化层
model2.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding="same", data_format="channels_last")) # 48*48*8
# 卷积层
model2.add(Conv2D(16, kernel_size=3, strides=(2, 2), use_bias=True, padding="same", activation="selu", data_format="channels_last"))
# 池化层
model2.add(MaxPooling2D(pool_size=(2, 2), strides=2, padding="same", data_format="channels_last")) # 12*12*16
# 改变形状
model2.add(Flatten())
# 全连接层
model2.add(Dense(128, activation="selu"))
model2.add(Dense(64, activation="selu"))
model2.add(Dense(1, activation="sigmoid"))
return model2
def generator_loss(self, fake_out):
loss = self.lossFunc(tf.ones_like(fake_out), fake_out)
return loss
def discriminator_loss(self, fake_out, real_out):
loss = self.lossFunc(tf.ones_like(real_out), real_out) + self.lossFunc(tf.zeros_like(fake_out), fake_out)
return loss
def train_step(self, X):
# 生成噪声
noise = tf.random.normal([self.batchSize, self.noiseDim], self.mean, self.var)
# 训练
with tf.GradientTape() as gen_tape:
self.gen_data = self.model_g(noise, training=True)
self.fake_out = self.model_d(self.gen_data, training=True)
self.gen_loss = self.generator_loss(self.fake_out)
self.gradient_gen = gen_tape.gradient(self.gen_loss, self.model_g.trainable_variables)
self.generator_opt.apply_gradients(zip(self.gradient_gen, self.model_g.trainable_variables))
with tf.GradientTape() as disc_tape:
self.real_out = self.model_d(X, training=True)
self.disc_loss = self.discriminator_loss(self.fake_out, self.real_out)
self.gradient_disc = disc_tape.gradient(self.disc_loss, self.model_d.trainable_variables)
self.discriminator_opt.apply_gradients(zip(self.gradient_disc, self.model_d.trainable_variables))
def fit(self, X):
for loop in range(self.epoch):
for batch in range(len(X)//self.batchSize):
subData = X[batch*self.batchSize:(batch+1)*self.batchSize]
self.train_step(subData)
print(f"epoch={loop+1}/{self.epoch}, gen_loss={self.gen_loss.numpy()}, disc_loss={self.disc_loss.numpy()}, "
f"fake_out={np.mean(self.fake_out)}, real_out={np.mean(self.real_out)}")
keras.Model.save(self.model_g, "./GAN_TF2_CNN/generator/")
keras.Model.save(self.model_d, "./GAN_TF2_CNN/discriminator/")
def predict(self, length):
model_g = keras.models.load_model("./GAN_TF2_CNN/generator/")
# 生成噪声
noise = tf.random.normal([length, self.noiseDim], self.mean, self.var)
# 生成数据
gen_data = model_g(noise, training=False)
return gen_data.numpy()
def loadData():
dir = "D:\\BaiduNetdiskDownload\\faces\\faces\\"
fileName = os.listdir(dir)
data = []
for name in tqdm.tqdm(fileName, desc="load images", unit="img", ncols=100, colour="green"):
img = cv2.imread(dir + name)
img = (img / 255) * 2 - 1
data.append(img)
cv2.destroyAllWindows()
return np.array(data)
def convertImages(data):
data = ((data + 1)/2)*255
for i in range(data.shape[0]):
cv2.imwrite(f"./GeneatorImages/{i}.jpg", data[i])
cv2.destroyAllWindows()
if __name__ == "__main__":
data = loadData()
gan = GAN(lr=0.001, noiseDim=100, batchSize=200, epoch=10, mean=0, var=1)
gan.fit(data)
result = gan.predict(10)
convertImages(result)
这是部分训练图片
这是数据集链接:
链接:https://pan.baidu.com/s/1qDXTSarO_Y7BGgHnWBP34w?pwd=1234
提取码:1234
这是训练过程:(其中gen_loss是生成器损失,disc_loss是判别器损失,fake_out是噪声通过判别器的输出,real_out是真实训练样本通过判别器的输出)
这是生成的图片(完全是噪声,感觉一点都没有学习到东西):
求帮忙看一下..