基于gan网络的手写数字图像生成
【摘要】 基于gan网络的手写数字图像生成,使用kreas框架
直接贴代码
import os
import cv2
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential,Model,load_model
from keras.layers import Dropout, Conv2D, Dense, LeakyReLU, Input,Reshape, Flatten, Conv2DTranspose
from keras.optimizers import adam_v2
import struct
os.environ["CUDA_VISIBLE_DEVICES"]="0"
def loadData_MNIST(path, kind='train'):
labels_path = os.path.join(path,'%s-labels.idx1-ubyte'% kind)
images_path = os.path.join(path,'%s-images.idx3-ubyte'% kind)
with open(labels_path, 'rb') as lbpath:
magic, n = struct.unpack('>II',lbpath.read(8))
labels = np.fromfile(lbpath,dtype=np.uint8)
with open(images_path, 'rb') as imgpath:
magic, num, rows, cols = struct.unpack('>IIII',imgpath.read(16))
images = np.fromfile(imgpath,dtype=np.uint8).reshape(len(labels),28,28,1)
#由于源数据有些数据过大,会导致激活函数计算溢出,所以对数据集集体缩小,
#由于图片数据每一位的值均为0-255之间,但统一除以255后发现当神经元个数达到一定数目或层数增加时还是会计算溢出,于是决定统一除以2550
return (images-127.5)/127.5
#img_dataset为一个3维矩阵,数量*(64,64)的矩阵
# img_dataset=load_data()
def show_images(images,index = -1):
"""
展示并保存图片
:param images: 需要show的图片
:param index: 保存图片名
:return:
"""
#定义一个图片
plt.figure()
for i, image in enumerate(images):
#设置为5行5列显示
ax = plt.subplot(5, 5, i+1)
#关闭坐标轴
plt.axis('off')
plt.imshow(image)
plt.savefig("data_%d.png"%index)
plt.show()
# show_images(img_dataset[0:25],0)
# show_images(img_dataset[0: 25])
images=loadData_MNIST("data2")
show_images(images[0: 25])
#____________________________________________________
# noise的维度
noise_dim = 100
# 图片的shape
image_shape = (28,28,1)
Adam=adam_v2.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
def build_G():
"""
构建生成器
:return:
"""
#model为生成模型
model = Sequential()
model.add(Input(shape=noise_dim))
#(100)
model.add(Dense(14*14*16))
# Conv2D(1,3,padding='same')
#(131072)
model.add(LeakyReLU(0.2))
model.add(Reshape((14,14,16)))
#(32,32,128)
#空间维数256,SAME是在进行卷积前,在图像的周围补一圈0
model.add(Conv2D(32,5,padding='same'))
model.add(LeakyReLU(0.2))
#(32,32,256)
#出256,核4*4,stride就是在相邻元素之间添加stride-1个0元素
#反卷积中如果padding为same的话则output_shape = input_shape * stride
model.add(Conv2DTranspose(32,4,strides=2,padding='same'))
model.add(LeakyReLU(0.2))
#(64,64,256)
model.add(Conv2D(32,5,padding='same'))
model.add(LeakyReLU(0.2))
#(64,64,256)
model.add(Conv2D(32,5,padding='same'))
model.add(LeakyReLU(0.2))
#(64,64,256)
model.add(Conv2D(1,7,activation='tanh',padding='same'))
#(64,64,3)
return model
G = build_G()
def build_D():
"""
构建判别器
:return:
"""
model = Sequential()
# 卷积层
model.add(Conv2D(16,3,input_shape = image_shape))
model.add(LeakyReLU(0.2))
#[62,62,128]
model.add(Conv2D(16,4, strides=2))
model.add(LeakyReLU(0.2))
#[30,30,128]
# model.add(Conv2D(128,4, strides=2))
# model.add(LeakyReLU(0.2))
#[14,14,128]
model.add(Conv2D(16,4, strides=2))
model.add(LeakyReLU(0.2))
#[6,6,128]
model.add(Flatten())
#[4608]
model.add(Dropout(0.4))
model.add(Dense(1,activation='sigmoid'))
#损失选择交叉熵损失,是鼻主。
model.compile(loss='binary_crossentropy',
optimizer=adam_v2.Adam(learning_rate=0.0002, beta_1=0.5))
return model
D = build_D()
def build_gan():
"""
构建GAN网络
:return:
"""
# 冷冻判别器,也就是在训练的时候只优化G的网络权重,而对D保持不变
D.trainable = False
# GAN网络的输入
gan_input = Input(shape=(noise_dim,))
# GAN网络的输出
gan_out = D(G(gan_input))
# 构建网络
gan = Model(gan_input,gan_out)
# 编译GAN网络,使用Adam优化器,以及加上交叉熵损失函数(一般用于二分类)
gan.compile(loss='binary_crossentropy',optimizer=adam_v2.Adam(learning_rate=0.0002, beta_1=0.5))
return gan
GAN = build_gan()
#————————————————————————————————————————————————————————
def sample_noise(batch_size):
"""
随机产生正态分布(0,1)的noise
:param batch_size:
:return: 返回的shape为(batch_size,noise)
"""
return np.random.normal(size=(batch_size, noise_dim))
def smooth_pos_labels(y):
"""
使得true label的值的范围为[0.8,1]
:param y:
:return:
"""
return y - (np.random.random(y.shape) * 0.2)
def smooth_neg_labels(y):
"""
使得fake label的值的范围为[0.0,0.3]
:param y:
:return:
"""
return y + np.random.random(y.shape) * 0.3
def load_batch(data, batch_size,index):
"""
按批次加载图片
:param data: 图片数据集
:param batch_size: 批次大小
:param index: 批次序号
:return:
"""
return data[index*batch_size: (index+1)*batch_size]
#————————————————————————————————————————————————————————
def train(img_dataset,epochs=100, batch_size=64):
"""
训练函数
:param epochs: 训练的次数
:param batch_size: 批尺寸
:return:
"""
# 判别器损失
discriminator_loss = 0
# 生成器损失
generator_loss = 0
# img_dataset.shape[0] / batch_size 代表这个数据可以分为几个批次进行训练
n_batches = int(img_dataset.shape[0] / batch_size)
for i in range(epochs):
print("第{}轮训练开始".format(i))
for index in range(n_batches):
print(index)
# 按批次加载数据
x = load_batch(img_dataset, batch_size,index)
# 产生noise
noise = sample_noise(batch_size)
# G网络产生图片
generated_images = G.predict(noise)
# 产生为1的标签
y_real = np.ones(batch_size)
# 将1标签的范围变成[0.8 , 1.0]
y_real = smooth_pos_labels(y_real)
# 产生为0的标签
y_fake = np.zeros(batch_size)
# 将0标签的范围变成[0.0 , 0.3]
y_fake = smooth_neg_labels(y_fake)
# 训练真图片loss
d_loss_real = D.train_on_batch(x, y_real)
# 训练假图片loss
d_loss_fake = D.train_on_batch(generated_images, y_fake)
discriminator_loss = d_loss_real + d_loss_fake
# 产生为1的标签
y_real = np.ones(batch_size)
# 训练GAN网络,input = fake_img ,label = 1
generator_loss = GAN.train_on_batch(noise, y_real)
print('[Epoch {0}]. Discriminator loss : {1}. Generator_loss: {2}.'.format(i, discriminator_loss, generator_loss))
# 每个epoch保存一次。
if i%1 == 0:
# 随机产生(25,100)的noise
test_noise = sample_noise(25)
# 使用G网络生成25张图偏
test_images = G.predict(test_noise)
# show 预测 img
show_images(test_images,i)
# GAN.save("/mymodle")
# %%
# print(int(img_dataset.shape[0] / 256))
# %%
train(images[:10000],epochs=100, batch_size=256)
# GAN=load_model("C:\\Users\\23502\\Documents\\codeProjects\\code_Py_learn\\上课\\大作业\\dcgan_anime_avatars-master\\文件\\my_model_gan")
# test_noise = sample_noise(25)
# # 使用G网络生成25张图偏
# test_images = G.predict(test_noise)
# # show 预测 img
# show_images(test_images,10)
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)