GAN出一个女朋友

文章目录

  • GAN(生成对抗网络)
    • 1. 生成对抗网络简述
    • 2.具体内容
      • 2.1 网络如何训练
      • 2.2 网络训练时会遇到的问题
    • 3.GAN的发展
    • 4.GAN的代码实践
      • 4.1 基于GAN的mnist数据生成
      • 4.2 放大招—生成美女图片
        • 4.2.1 爬取美女图片
        • 4.2.2 提取人脸
        • 4.2.3 开始训练

GAN(生成对抗网络)

没有女朋友也没关系,现在我们就试试自己GAN出一个。

1. 生成对抗网络简述

首先要提的肯定是2014年Ian J. Goodfellow大佬的关于GAN的论文,应该也算是GAN的开山之作。Generative Adversarial Network 论文链接

生成对抗网络顾名思义包含了生成对抗的思想,按照原始的GAN网络结构中主要包含了两部分,分别是生成模型 G判别模型 D,通常这两部分都是神经网络,其中G负责通过我们输入的数据生成一些新的数据(生成的数据要尽可能接近我们的数据集中的数据);而D则负责作判别,判断输入的数据是来自真实数据集的 “真数据” 还是由G生成的 ”假数据“ ,所以D是一个用来分辨真伪的二分类模型,网络最后一层往往也使用sigmoid激活函数。

举个简单的例子:

G就像现实中制作假币的机器,而D就是验钞机。一开始G和D的技术都不太好,往往G产生的假币假到人肉眼就看出来是假的,而D判断的技术也很差,往往人肉眼都觉得的是假币而它判断确实真币;经过一段时间的改进优化,D可以比人眼更好的分辨真假币,而G制作出来的假币也能骗过人的眼睛;到了最后,G生成的假币已经可以完美的媲美真币,而D这个时候已经无法区分到底是真币还是G生成的假币(准确率50%),这个时候就是最完美的时候,我们的目的也就达到了。

GAN整体示意图如下:

img

从图来看,G网络所需要的输入只有一个随机噪音,通过随机噪音来生成数据,而D网络的输入就是我们真实的样本数据以及G所生成的数据,并对它们作真假判断。

结合上面的简述,我们可以体会到生成以及对抗的含义,这个想法非常好两者在对抗竞争中互相提高,但是实际上往往会出现一些意外情况,导致模型无法达到预期效果。

  • 当我们的验钞机非常厉害,而假币制造技术还很差的时候。不管怎么努力做出的假币还是会被分辨出来,这个时候就没有人会去想着制造假币(无利可图),还不如老老实实工作。

  • 当验钞机判别能力相当弱的时候,不管假币制造的多么假,它还是会觉得是真币,尽管这个时候人眼就能看出这是假币;那这个时候假币制造机已经觉得满足了,也不会去进一步增强自己的造假能力。现实中的情况往往是只会生成假的1元,而5元、10元、20元等都不会生成。

上面两种情况其实就是我们训练GAN时通常会遇到的两种情况,都会导致我们的生成器无法达到我们预期想要的结果。此外,对于这样的一种网络概念,怎么对它进行优化训练也是我们需要考虑的,这些就留到下面继续说。

2.具体内容

由上面的简述,我们有了一种新的网络设计思想,通过两种网络的竞争从而得到性能优异的生成模型,并且同时我们还得到了一个能力不错的判定模型。但是当我们把想法实践的时候也遇到了不少问题,上面的D性能太好和太坏都会导致G的训练失败,而且如何训练这两个模型也是我们需要思考的问题,在这里我就展开详细的说说。

2.1 网络如何训练

有了上面零和博弈的思想,我们就会开始设计网络,通常我们的生成器和判定器都是深层神经网络,简单的全连接到复杂点的卷积……;设计好网络后,我们就需要对网络进行训练,也就是更新网络参数,这个时候就需要设置网络的目标函数。

image-20210630093847824

从论文上看,所给出的目标函数

min ⁡ G max ⁡ D V ( D , G ) = E x ∼ p d a t a ( x ) [ log ⁡ D ( x ) ] + E z ∼ p z ( z ) [ log ⁡ ( 1 − D ( G ( z ) ) ) ] \min\limits_{G}\max\limits_{D}V(D,G)=E_{x \sim p_{data}(x)}[\log{D(x)}]+E_{z \sim p_{z}(z)}[\log{(1-D(G(z)))}] GminDmaxV(D,G)=Expdata(x)[logD(x)]+Ezpz(z)[log(1D(G(z)))]

实际训练过程中,我们的损失函数分别为:

  • 对于G

    最小化 log ⁡ ( 1 − D ( G ( z ) ) ) \log{(1-D(G(z)))} log(1D(G(z)))但是在早期可能无法提供足够的梯度来训练G,所以有了替代为最大化 log ⁡ D ( G ( z ) ) \log{D(G(z))} logD(G(z))

  • 对于D

    − ( log ⁡ D ( x ) + log ⁡ ( 1 − D ( G ( x ) ) ) ) -(\log{D(x)}+\log{(1-D(G(x)))}) (logD(x)+log(1D(G(x))))

img

有了上面的损失函数,我们就可以对网络权重进行更新,从而训练网络。不过GAN训练起来可并不容易,往往理想很丰满,现实很骨感。

2.2 网络训练时会遇到的问题

再解释我上面提到的两种情况

  1. Vanishing Gradient 梯度消失

    梯度消失是指D判别器训练的判别效果远比G的生成效果好,导致无论G生成什么数据,它都觉得与真实数据分布不一致,这个时候就会导致G的训练一直停滞。

    image-20210630102342591

    从论文上看,我们最终可以得到一个最优解 D ∗ ( x ) = p d a t a ( x ) p d a t a ( x ) + p g ( x ) D^*(x)=\frac{p_{data}(x)}{p_{data}(x)+p_{g}(x)} D(x)=pdata(x)+pg(x)pdata(x),带入目标函数,得到简化后的函数 min ⁡ G ( 2 ∗ J S ( P d a t a ∣ ∣ P G ) − l o g 4 ) \min\limits_{G}(2*JS(P_{data}||P_G)-log4) Gmin(2JS(PdataPG)log4)

    当我们生成的数据与实际数据集数据分布相差过大,几乎没有重叠部分的时候,散度就成了一个常数,这个时候函数的梯度就是0,也就出现了梯度消失的现象。

  2. Mode Collapse 模式坍塌

    模式坍塌则是我们GAN训练过程中会出现的另一种问题,当D的判别性能跟不上G的生成效果时,G生成的图片都会被判定为真实的,这个时候 D ( G ( x ) ) = 1 D(G(x))=1 D(G(x))=1,G也就失去了训练的方向。往往这种情况下就会导致只能很好的生成某一类数据,或者生成的数据重复率过高。具体如下图

    img

    生成的图像中出现了多个相似图片,失去了生成模型的多样性。

3.GAN的发展

基于零和博弈策略的GAN作为生成模型,相比之前的生成模型不再需要知道数据的分布,而是先生成数据然后往我们所给出的数据分布上去靠拢。GAN往往用于图像、视频的生成,也有用于文字的生成。从它的原理我们可以看出,它对于不同的输入noise,就会生成不同的数据;另外,它生成的数据往往是整体的,而不能依赖于某一个数据去控制另一个数据。

对于图像的生成,将全连接神经网络改为了卷积神经网络,并且优化激活函数等,比如DCGAN;对于风格迁移的CycleGAN;为了使GAN训练更稳定提出的WGAN和WGAN-GP以及Conditional GAN;最后是复杂的StyleGAN,也是我目前需要研究学习的,下一篇应该就是关于StyleGANStyleGAN2的博客

4.GAN的代码实践

4.1 基于GAN的mnist数据生成

来源:pytorch-exercise/pt01_generative_adversarial_network.py at main · Baileyswu/pytorch-exercise

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from torch.utils.data import DataLoaderfrom bokeh.io import show, output_notebook
from bokeh.plotting import figure, gridplot
from bokeh.models import LinearAxis, Range1d
output_notebook()train_dataset = dsets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True)
test_dataset = dsets.MNIST(root='./data', train=False, transform=transforms.ToTensor())batch_size = 50
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=1, shuffle=True)# 定义模型
class GAN(nn.Module):def __init__(self):super().__init__()# 生成器self.G = nn.Sequential(nn.Linear(64, 256),nn.LeakyReLU(0.2),nn.Linear(256, 256),nn.LeakyReLU(0.2),nn.Linear(256, 784),nn.Tanh())# 判定器self.D = nn.Sequential(nn.Linear(784, 256),nn.LeakyReLU(0.2),nn.Linear(256, 256),nn.LeakyReLU(0.2),nn.Linear(256, 1),nn.Sigmoid())def forward(self, z):return self.G(z)# 将输入噪音z传入G,然后G生成的数据给D进行判断def score(self, z):fake_imgs = self.G(z)fake_score = self.D(fake_imgs)return fake_scorelrate = 0.0001
epochs = 300# 模型实例化
model = GAN().cuda()
# 损失函数
criterion = nn.BCELoss()
# 优化器
optim_G = torch.optim.Adam(model.G.parameters(), lr = lrate)
optim_D = torch.optim.Adam(model.D.parameters(), lr = lrate)# 模型可视化
model# 绘制图片
def list_img(i, img, title):img = img.reshape(28, 28)plt.subplot(2, 5, i+1)plt.imshow(img)plt.title('%s' % (title))# 可视化生成的数据
def generate_test(inputs, title=''):plt.figure(figsize=(15, 6))imgs = model(inputs)imgs = (imgs + 1) / 2imgs.clamp(0, 1)for i in range(len(inputs)):list_img(i, imgs[i].cpu().detach().numpy(), title)plt.show()result_d = []
result_g = []
test_inputs = torch.randn(5, 64).cuda()# 开始训练
for e in range(epochs):for i, (inputs, _) in enumerate(train_loader):inputs = inputs.view(-1, 28*28).cuda()real_labels = torch.ones(batch_size, 1).cuda()fake_labels = torch.zeros(batch_size, 1).cuda()# 对D进行训练real_score = model.D(inputs)loss_d_real = criterion(real_score, real_labels)fake_score = model.score(torch.randn(batch_size, 64).cuda())loss_d_fake = criterion(fake_score, fake_labels)optim_D.zero_grad() loss_d = loss_d_real + loss_d_fakeloss_d.backward()optim_D.step()fake_score = model.score(torch.randn(batch_size, 64).cuda())loss_g = criterion(fake_score, real_labels)optim_G.zero_grad()loss_g.backward()optim_G.step()if i % 100 == 0:result_d.append(float(loss_d))result_g.append(float(loss_g))if e % 30 == 0:generate_test(test_inputs, str(e))
fig = figure()
fig.line(range(len(result_d)), result_d, legend_label='D loss', line_width=1.5)
fig.line(range(len(result_g)), result_g, legend_label='G loss', line_color="green")
show(fig)# 测试生成器效果
new_data=model.G(torch.randn(1,64).cuda())
img=new_data.cpu().detach().numpy().reshape(28,28)
plt.imshow(img)
plt.show()

训练图片过程

image-20210630125138751

image-20210630125150450

损失曲线

image-20210630125240056

测试生成图片

image-20210630125310068

4.2 放大招—生成美女图片

4.2.1 爬取美女图片

这里我爬取的是百度图片,爬虫代码链接爬取百度图片——详细思路_小白一直白-CSDN博客_爬取百度图片

# 爬取数据
import requests
import os
import urllibclass Spider_baidu_image():def __init__(self):self.url = 'http://image.baidu.com/search/acjson?'self.headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\3497.81 Safari/537.36'}self.headers_image = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.\3497.81 Safari/537.36','Referer':'http://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1557124645631_R&pv=&ic=&nc=1&z=&hd=1&latest=0&copyright=0&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&sid=&word=%E8%83%A1%E6%AD%8C'}# self.keyword = '刘亦菲壁纸'self.keyword = input("请输入搜索图片关键字:")self.paginator = int(input("请输入搜索页数,每页30张图片:"))# self.paginator = 50# print(type(self.keyword),self.paginator)# exit()def get_param(self):"""获取url请求的参数,存入列表并返回:return: """keyword = urllib.parse.quote(self.keyword)params = []for i in range(1,self.paginator+1):params.append('tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord={}&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=&hd=1&latest=0&copyright=0&word={}&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&expermode=&force=&cg=star&pn={}&rn=30&gsm=78&1557125391211='.format(keyword,keyword,30*i))return paramsdef get_urls(self,params):"""由url参数返回各个url拼接后的响应,存入列表并返回:return:"""urls = []for i in params:urls.append(self.url+i)return urlsdef get_image_url(self,urls):image_url = []for url in urls:json_data = requests.get(url,headers = self.headers).json()json_data = json_data.get('data')for i in json_data:if i:image_url.append(i.get('thumbURL'))return image_urldef get_image(self,image_url):"""根据图片url,在本地目录下新建一个以搜索关键字命名的文件夹,然后将每一个图片存入。:param image_url: :return: """cwd = os.getcwd()file_name = os.path.join(cwd,self.keyword)if not os.path.exists(self.keyword):os.mkdir(file_name)for index,url in enumerate(image_url,start=1):with open(file_name+'\\{}.jpg'.format(index),'wb') as f:f.write(requests.get(url,headers = self.headers_image).content)if index != 0 and index % 30 == 0:print('{}第{}页下载完成'.format(self.keyword,index/30))def __call__(self, *args, **kwargs):params = self.get_param()urls = self.get_urls(params)image_url = self.get_image_url(urls)self.get_image(image_url)if __name__ == '__main__':spider = Spider_baidu_image()spider()

4.2.2 提取人脸

  1. 首先去https://github.com/nagadomi/lbpcascade_animeface 下载xml文件

  2. 将文件夹重命名英文(我这里改为girls),为了解决opencv读取图片不能有中文的问题

最后将文件夹中的图片全部变为128*128

 # 提取美女的面部图片import cv2import sysimport numpy as npimport os.pathfrom glob import globdef detect(filename, cascade_file="lbpcascade_animeface.xml"):if not os.path.isfile(cascade_file):raise RuntimeError("%s: not found" % cascade_file)cascade = cv2.CascadeClassifier(cascade_file)image = cv2.imread(filename)#image = cv2.imdecode(np.fromfile(filename, dtype=np.uint8),0)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)gray = cv2.equalizeHist(gray)faces = cascade.detectMultiScale(gray,# detector optionsscaleFactor=1.1,minNeighbors=5,minSize=(48, 48))for i, (x, y, w, h) in enumerate(faces):face = image[y: y + h, x:x + w, :]face = cv2.resize(face, (128,128))save_filename = '%s-%d.jpg' % (os.path.basename(filename).split('.')[0], i)cv2.imwrite("faces/" + save_filename, face)if __name__ == '__main__':if os.path.exists('faces') is False:os.makedirs('faces')file_list = glob('girls/*.jpg')for filename in file_list:detect(filename)

4.2.3 开始训练

这里是基于tensorflow 1.X写的DCGAN,当然如果你现在环境是2.X也无所谓,使用

import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()

屏蔽掉2.X的代码部分就好

# 开始训练生成美女图片
import os
import time
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()import numpy as np
from glob import glob
import datetime
import random
from PIL import Image
import matplotlib.pyplot as plt
%matplotlib inline# 生成器
def generator(z, output_channel_dim, training):with tf.variable_scope("generator", reuse= not training):# 8x8x1024fully_connected = tf.layers.dense(z, 8*8*1024)fully_connected = tf.reshape(fully_connected, (-1, 8, 8, 1024))fully_connected = tf.nn.leaky_relu(fully_connected)# 8x8x1024 -> 16x16x512trans_conv1 = tf.layers.conv2d_transpose(inputs=fully_connected,filters=512,kernel_size=[5,5],strides=[2,2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name="trans_conv1")batch_trans_conv1 = tf.layers.batch_normalization(inputs = trans_conv1,training=training,epsilon=EPSILON,name="batch_trans_conv1")trans_conv1_out = tf.nn.leaky_relu(batch_trans_conv1,name="trans_conv1_out")# 16x16x512 -> 32x32x256trans_conv2 = tf.layers.conv2d_transpose(inputs=trans_conv1_out,filters=256,kernel_size=[5,5],strides=[2,2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name="trans_conv2")batch_trans_conv2 = tf.layers.batch_normalization(inputs = trans_conv2,training=training,epsilon=EPSILON,name="batch_trans_conv2")trans_conv2_out = tf.nn.leaky_relu(batch_trans_conv2,name="trans_conv2_out")# 32x32x256 -> 64x64x128trans_conv3 = tf.layers.conv2d_transpose(inputs=trans_conv2_out,filters=128,kernel_size=[5,5],strides=[2,2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name="trans_conv3")batch_trans_conv3 = tf.layers.batch_normalization(inputs = trans_conv3,training=training,epsilon=EPSILON,name="batch_trans_conv3")trans_conv3_out = tf.nn.leaky_relu(batch_trans_conv3,name="trans_conv3_out")# 64x64x128 -> 128x128x64trans_conv4 = tf.layers.conv2d_transpose(inputs=trans_conv3_out,filters=64,kernel_size=[5,5],strides=[2,2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name="trans_conv4")batch_trans_conv4 = tf.layers.batch_normalization(inputs = trans_conv4,training=training,epsilon=EPSILON,name="batch_trans_conv4")trans_conv4_out = tf.nn.leaky_relu(batch_trans_conv4,name="trans_conv4_out")# 128x128x64 -> 128x128x3logits = tf.layers.conv2d_transpose(inputs=trans_conv4_out,filters=3,kernel_size=[5,5],strides=[1,1],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name="logits")out = tf.tanh(logits, name="out")return out# 判定器
def discriminator(x, reuse):with tf.variable_scope("discriminator", reuse=reuse): # 128*128*3 -> 64x64x64 conv1 = tf.layers.conv2d(inputs=x,filters=64,kernel_size=[5,5],strides=[2,2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name='conv1')batch_norm1 = tf.layers.batch_normalization(conv1,training=True,epsilon=EPSILON,name='batch_norm1')conv1_out = tf.nn.leaky_relu(batch_norm1,name="conv1_out")# 64x64x64-> 32x32x128 conv2 = tf.layers.conv2d(inputs=conv1_out,filters=128,kernel_size=[5, 5],strides=[2, 2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name='conv2')batch_norm2 = tf.layers.batch_normalization(conv2,training=True,epsilon=EPSILON,name='batch_norm2')conv2_out = tf.nn.leaky_relu(batch_norm2,name="conv2_out")# 32x32x128 -> 16x16x256  conv3 = tf.layers.conv2d(inputs=conv2_out,filters=256,kernel_size=[5, 5],strides=[2, 2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name='conv3')batch_norm3 = tf.layers.batch_normalization(conv3,training=True,epsilon=EPSILON,name='batch_norm3')conv3_out = tf.nn.leaky_relu(batch_norm3,name="conv3_out")# 16x16x256 -> 16x16x512conv4 = tf.layers.conv2d(inputs=conv3_out,filters=512,kernel_size=[5, 5],strides=[1, 1],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name='conv4')batch_norm4 = tf.layers.batch_normalization(conv4,training=True,epsilon=EPSILON,name='batch_norm4')conv4_out = tf.nn.leaky_relu(batch_norm4,name="conv4_out")# 16x16x512 -> 8x8x1024conv5 = tf.layers.conv2d(inputs=conv4_out,filters=1024,kernel_size=[5, 5],strides=[2, 2],padding="SAME",kernel_initializer=tf.truncated_normal_initializer(stddev=WEIGHT_INIT_STDDEV),name='conv5')batch_norm5 = tf.layers.batch_normalization(conv5,training=True,epsilon=EPSILON,name='batch_norm5')conv5_out = tf.nn.leaky_relu(batch_norm5,name="conv5_out")flatten = tf.reshape(conv5_out, (-1, 8*8*1024))logits = tf.layers.dense(inputs=flatten,units=1,activation=None)out = tf.sigmoid(logits)return out, logits    #  模型损失
def model_loss(input_real, input_z, output_channel_dim):g_model = generator(input_z, output_channel_dim, True)noisy_input_real = input_real + tf.random_normal(shape=tf.shape(input_real),mean=0.0,stddev=random.uniform(0.0, 0.1),dtype=tf.float32)d_model_real, d_logits_real = discriminator(noisy_input_real, reuse=False)d_model_fake, d_logits_fake = discriminator(g_model, reuse=True)d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real,labels=tf.ones_like(d_model_real)*random.uniform(0.9, 1.0)))d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,labels=tf.zeros_like(d_model_fake)))d_loss = tf.reduce_mean(0.5 * (d_loss_real + d_loss_fake))g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,labels=tf.ones_like(d_model_fake)))return d_loss, g_loss# 模型优化
def model_optimizers(d_loss, g_loss):t_vars = tf.trainable_variables()g_vars = [var for var in t_vars if var.name.startswith("generator")]d_vars = [var for var in t_vars if var.name.startswith("discriminator")]update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS)gen_updates = [op for op in update_ops if op.name.startswith('generator')]with tf.control_dependencies(gen_updates):d_train_opt = tf.train.AdamOptimizer(learning_rate=LR_D, beta1=BETA1).minimize(d_loss, var_list=d_vars)g_train_opt = tf.train.AdamOptimizer(learning_rate=LR_G, beta1=BETA1).minimize(g_loss, var_list=g_vars)  return d_train_opt, g_train_opt# 模型输入
def model_inputs(real_dim, z_dim):inputs_real = tf.placeholder(tf.float32, (None, *real_dim), name='inputs_real')inputs_z = tf.placeholder(tf.float32, (None, z_dim), name="input_z")learning_rate_G = tf.placeholder(tf.float32, name="lr_g")learning_rate_D = tf.placeholder(tf.float32, name="lr_d")return inputs_real, inputs_z, learning_rate_G, learning_rate_D# 展示样例
def show_samples(sample_images, name, epoch):figure, axes = plt.subplots(1, len(sample_images), figsize = (IMAGE_SIZE, IMAGE_SIZE))for index, axis in enumerate(axes):axis.axis('off')image_array = sample_images[index]axis.imshow(image_array)image = Image.fromarray(image_array)image.save(name+"_"+str(epoch)+"_"+str(index)+".png") plt.savefig(name+"_"+str(epoch)+".png", bbox_inches='tight', pad_inches=0)plt.show()plt.close()# 测试 
def test(sess, input_z, out_channel_dim, epoch):example_z = np.random.uniform(-1, 1, size=[SAMPLES_TO_SHOW, input_z.get_shape().as_list()[-1]])samples = sess.run(generator(input_z, out_channel_dim, False), feed_dict={input_z: example_z})sample_images = [((sample + 1.0) * 127.5).astype(np.uint8) for sample in samples]show_samples(sample_images, OUTPUT_DIR + "samples", epoch)# 每个epoch的训练情况总结
def summarize_epoch(epoch, duration, sess, d_losses, g_losses, input_z, data_shape):minibatch_size = int(data_shape[0]//BATCH_SIZE)print("Epoch {}/{}".format(epoch, EPOCHS),"\nDuration: {:.5f}".format(duration),"\nD Loss: {:.5f}".format(np.mean(d_losses[-minibatch_size:])),"\nG Loss: {:.5f}".format(np.mean(g_losses[-minibatch_size:])))fig, ax = plt.subplots()plt.plot(d_losses, label='Discriminator', alpha=0.6)plt.plot(g_losses, label='Generator', alpha=0.6)plt.title("Losses")plt.legend()plt.savefig(OUTPUT_DIR + "losses_" + str(epoch) + ".png")plt.show()plt.close()test(sess, input_z, data_shape[3], epoch)# 获得批次    
def get_batches(data):batches = []for i in range(int(data.shape[0]//BATCH_SIZE)):batch = data[i * BATCH_SIZE:(i + 1) * BATCH_SIZE]augmented_images = []for img in batch:image = Image.fromarray(img)if random.choice([True, False]):image = image.transpose(Image.FLIP_LEFT_RIGHT)augmented_images.append(np.asarray(image))batch = np.asarray(augmented_images)normalized_batch = (batch / 127.5) - 1.0batches.append(normalized_batch)return batches# 训练
def train(get_batches, data_shape, checkpoint_to_load=None):input_images, input_z, lr_G, lr_D = model_inputs(data_shape[1:], NOISE_SIZE)d_loss, g_loss = model_loss(input_images, input_z, data_shape[3])d_opt, g_opt = model_optimizers(d_loss, g_loss)with tf.Session() as sess:sess.run(tf.global_variables_initializer())d_losses = []g_losses = []for epoch in range(EPOCHS):        start_time = time.time()for batch_images in get_batches:batch_z = np.random.uniform(-1, 1, size=(BATCH_SIZE, NOISE_SIZE))_ = sess.run(d_opt, feed_dict={input_images: batch_images, input_z: batch_z, lr_D: LR_D})_ = sess.run(g_opt, feed_dict={input_images: batch_images, input_z: batch_z, lr_G: LR_G})d_losses.append(d_loss.eval({input_z: batch_z, input_images: batch_images}))g_losses.append(g_loss.eval({input_z: batch_z}))if epoch%30==0:summarize_epoch(epoch, time.time()-start_time, sess, d_losses, g_losses, input_z, data_shape)# 参数设置
INPUT_DATA_DIR = "./faces" 
OUTPUT_DIR = './newpics/'
if not os.path.exists(OUTPUT_DIR):os.makedirs(OUTPUT_DIR)IMAGE_SIZE = 128
NOISE_SIZE = 100
LR_D = 0.00003
LR_G = 0.0003
BATCH_SIZE = 64
EPOCHS = 300
BETA1 = 0.5
WEIGHT_INIT_STDDEV = 0.02
EPSILON = 0.00005
SAMPLES_TO_SHOW = 5# 正式训练
input_images = np.asarray([np.asarray(Image.open(file).resize((IMAGE_SIZE, IMAGE_SIZE))) for file in glob(INPUT_DATA_DIR + '/*.jpg')])
print ("Input: " + str(input_images.shape))np.random.shuffle(input_images)sample_images = random.sample(list(input_images), SAMPLES_TO_SHOW)
show_samples(sample_images, OUTPUT_DIR + "inputs", 0)with tf.Graph().as_default():train(get_batches(input_images), input_images.shape)

随机输出五张输入的图片

image-20210630173737436

开始的loss

image-20210630173800378

第15个epoch的loss以及生成的图片

image-20210630180421206

这个时候女朋友已经初具雏形,继续训练,第30个epoch

image-20210630180515265

轮廓更明显,但是整体还是很模糊。
在这里插入图片描述
生成的图片这哪里是女朋友,明明是阿姨,还带点异国风情的那种。。。
失败原因可能在于:

  • 爬取的百度图片里面不全是美女,有卡通图片以及一些一场图片干扰,我没有对图片进行清理,下次可以用一下百度的api,颜值没有60分的pass掉。
  • 网络训练提前结束,笔记本训练属实不给力,慢而且烫,明天用工作站试试。
  • DCGAN中生成器网络设计还可以优化。

这一次制作女朋友应该算是以失败告终,下次用其它网络再试试!毕竟这可比现实中找女朋友容易多了,呜呜呜

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38270.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

chatgpt赋能python:Python更换桌面背景指南:教你如何用Python快速实现桌面背景更换

Python更换桌面背景指南:教你如何用Python快速实现桌面背景更换 如果你已经厌倦了一成不变的桌面背景,那么Python可以帮助你快速实现更换功能。本指南将教您如何用Python编写简单的代码来更改桌面背景。 如何用Python更换桌面背景 Python中有几个库可…

chatgpt赋能python:Python自定义背景:让你的编程世界更加缤纷多彩

Python 自定义背景:让你的编程世界更加缤纷多彩 随着科技的迅速发展,人们的日常生活和工作中越来越多地依赖于电脑和各种数字设备。而对于程序员来说,他们的编程世界更是离不开电脑和代码编辑器。因此,如何让这个世界变得更加优美…

chatgpt赋能python:如何使用Python将背景色更改为黑色

如何使用Python将背景色更改为黑色 在网页设计中,背景色是非常重要的元素之一。有时候,为了让网页看起来更加时尚和艺术,设计师可能会使用黑色背景来营造一种神秘和高质感的感觉。在本篇文章中,我们将介绍如何使用Python将背景色…

chatgpt赋能python:Python图片查看器:优化你的图片浏览体验

Python图片查看器:优化你的图片浏览体验 如果你常常处理图片,那么一个高效的图片浏览器会节约你大量的时间。本文将介绍一款使用Python编写的开源图片查看器,它可以帮助你快速预览和编辑图片。此外,我们还会分享如何使用关键字优…

C/C++编程:继承构造函数

引入 在传统C中,如果派生类要使用使用基类的构造函数,通常需要在构造函数中显式声明: struct A{ public:A(int i) {} };struct B : A{B (int i) : A(i){} };B派生自A,B又在构造函数中调用A的构造函数,从而完成构造函…

C++11之继承构造函数(using 声明)

系列文章 C11之正则表达式(regex_match、regex_search、regex_replace) C11之线程库(Thread、Mutex、atomic、lock_guard、同步) C11之智能指针(unique_ptr、shared_ptr、weak_ptr、auto_ptr)浅谈内存管…

继承与派生(Part Ⅱ)——派生类的构造函数/析构函数

派生类的构造函数和析构函数 构造函数的主要作用是对数据成员初始化。基类的构造函数是不能继承的,在声明派生类时,派生类并没有把基类的构造函数继承过来,因此,对继承过来的基类成员初始化的工作也要由派生类的构造函数承担。所…

6.12C++:继承基类的构造函数、单继承的构造函数、多继承的构造函数、派生类复制构造函数、派生类的析构函数

1 继承基类的构造函数 class A{ public:A(){}; // A的构造函数 }; class B : public A{ public:using A:A; }2 单继承的构造函数 class A{ public:A(int i){}; }; class B : public A{ public:B(int i, int j): A(i), bb(j); /i传递给A的构造函数,j初始…

JavaScript构造函数继承

首先介绍对象的call()函数和apply()函数,这两个函数的作用相同、用法不同。它们的作用均是指定当前调用函数的this对象是谁。 call()函数:在第一个传递的参数为一个对象,该对象为该函数的this对象,后面依次传递函数的实参。 apply…

c++继承构造函数

【1】为什么需要继承构造函数? 首先,看看如下代码片段: 1 struct A2 { 3 A(int i)4 {} 5 }; 6 7 struct B : A8 { 9 B(int i) : A(i) 10 {} 11 }; 在C中非常常见:B派生于A,B在构造函数中调用A的构造函…

openAI注册/登录 报错汇总

目录 报错类型问题原因及解决**access denied**<br />**提示An error occurred**<br />**Not available**<br />**同一IP地址频繁注册**<br />**cloudflare死循环验证**<br /> 最后 报错类型 access denied You do not have access to chat.op…

【Java面试题】真实的二面面试题(参考答案为纯个人理解)

1. 你掌握前端的哪些知识&#xff1f; vue2element-ui了解一些css,js 2. 那你说一下vue中的路由吧&#xff1f; vue中的路由是用来设定访问路径的,将路径映射到组件页面上 3. 说一下前端vue页面之间传参的方式&#xff1f; 路由查询字符串(我用的) // 路由定义 { path: /a…

yolo

目标检测 导言&#xff1a;目标检测的任务表述 如何从图像中解析出可供计算机理解的信息&#xff0c;是机器视觉的中心问题。深度学习模型由于其强大的表示能力&#xff0c;加之数据量的积累和计算力的进步&#xff0c;成为机器视觉的热点研究方向。 那么&#xff0c;如何理解…

神经网络与深度学习-学习笔记(5)

1.目标检测与YOLO 目标检测问题 目标检测是在给定的图片中精确找到物体所在位置&#xff0c;并标注出物体的类别。物体的尺寸变化范围很大&#xff0c;摆放物体的角度&#xff0c;姿态不定&#xff0c;而且可以出现在图片的任何地方&#xff0c;并且物体还可以是多个类别。 目…

可见光遥感目标检测(一)任务概要介绍

前言 本篇开始对遥感图像的目标检测进行介绍&#xff0c;介绍了其目标前景、数据集以及评价指标。 本教程禁止转载。同时&#xff0c;本教程来自知识星球【CV技术指南】更多技术教程&#xff0c;可加入星球学习。 Transformer、目标检测、语义分割交流群 欢迎关注公众号CV技…

YOLOv5全面解析教程①:网络结构逐行代码解读

撰文 | Fengwen, BBuf 本教程涉及的代码在&#xff1a; https://github.com/Oneflow-Inc/one-yolov5 教程也同样适用于 Ultralytics/YOLOv5&#xff0c;因为 One-YOLOv5 仅仅是换了一个运行时后端而已&#xff0c;计算逻辑和代码相比 Ultralytics/YOLOv5 没有做任何改变&#x…

可见光遥感图像目标检测(三)文字场景检测之Arbitrary

前言 前面介绍了关于可见光遥感图像目标检测任务主要面临的问题&#xff0c;现在对旋转目标的问题进行优化&#xff0c;为了便于大家理解与之前通用目标检测区别&#xff0c;采用Faster-Rcnn网络模型的架构对旋转目标的检测进行改进。 本教程禁止转载。同时&#xff0c;本教程来…

yolov5的简单使用

yolov5是什么 来自chatGPT的描述如下 YOLOv5是一种目标检测算法&#xff0c;它是YOLO系列算法的最新版本&#xff0c;由Joseph Redmon和Alexey Bochkovskiy等人开发。与之前的版本相比&#xff0c;YOLOv5在准确性和速度方面都有所提高。YOLOv5使用一种名为“Bag of Freebies”…

yolov3_spp项目中的各种配置文件读取

目录 1. open 函数 2. cfg文件夹下文档解析 2.1 hyp.yaml 2.2 my_yolov_3.cfg 3. data文件夹下文档解析 3.1 my_data.data 3.2 其它 后缀名 .ymal .txt .json .cfg .data .names .shapes 可以自定义后缀名&#xff1f;&#xff1f; pyhon文件操作大…

目标检测算法——YOLOv5/YOLOv7改进之结合CBAM注意力机制

&#x1f496;&#x1f496;>>>加勒比海带&#xff0c;QQ2479200884<<<&#x1f496;&#x1f496; &#x1f340;&#x1f340;>>>【YOLO魔法搭配&论文投稿咨询】<<<&#x1f340;&#x1f340; ✨✨>>>学习交流 | 温澜潮…