通过DCGAN进行生成花朵

环境是你要安装Keras和Tensorflow

先来个network.py,里面定义了生成器网络和鉴别器网络:

 1 # -*- coding: UTF-8 -*-
 2 
 3 """
 4 DCGAN 深层卷积的生成对抗网络
 5 """
 6 
 7 import tensorflow as tf
 8 
 9 # Hyper parameter(超参数)
10 EPOCHS = 100
11 BATCH_SIZE = 128
12 LEARNING_RATE = 0.0002
13 BETA_1 = 0.5
14 
15 
16 # 定义判别器模型
17 def discriminator_model():
18     model = tf.keras.models.Sequential()
19 
20     model.add(tf.keras.layers.Conv2D(
21         64,  # 64 个过滤器,输出的深度(depth)是 64
22         (5, 5),  # 过滤器在二维的大小是(5 * 5)
23         padding='same',  # same 表示输出的大小不变,因此需要在外围补零2圈
24         input_shape=(64, 64, 3)  # 输入形状 [64, 64, 3]。3 表示 RGB 三原色
25     ))
26     model.add(tf.keras.layers.Activation("tanh"))  # 添加 Tanh 激活层
27     model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))  # 池化层
28     model.add(tf.keras.layers.Conv2D(128, (5, 5)))
29     model.add(tf.keras.layers.Activation("tanh"))
30     model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))
31     model.add(tf.keras.layers.Conv2D(128, (5, 5)))
32     model.add(tf.keras.layers.Activation("tanh"))
33     model.add(tf.keras.layers.MaxPool2D(pool_size=(2, 2)))
34     model.add(tf.keras.layers.Flatten())  # 扁平化
35     model.add(tf.keras.layers.Dense(1024))  # 1024 个神经元的全连接层
36     model.add(tf.keras.layers.Activation("tanh"))
37     model.add(tf.keras.layers.Dense(1))  # 1 个神经元的全连接层
38     model.add(tf.keras.layers.Activation("sigmoid"))  # 添加 Sigmoid 激活层
39 
40     return model
41 
42 
43 # 定义生成器模型
44 # 从随机数来生成图片
45 def generator_model():
46     model = tf.keras.models.Sequential()
47     # 输入的维度是 100, 输出维度(神经元个数)是1024 的全连接层
48     model.add(tf.keras.layers.Dense(input_dim=100, units=1024))
49     model.add(tf.keras.layers.Activation("tanh"))
50     model.add(tf.keras.layers.Dense(128 * 8 * 8))  # 8192 个神经元的全连接层
51     model.add(tf.keras.layers.BatchNormalization())  # 批标准化
52     model.add(tf.keras.layers.Activation("tanh"))
53     model.add(tf.keras.layers.Reshape((8, 8, 128), input_shape=(128 * 8 * 8, )))  # 8 x 8 像素
54     model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 16 x 16像素
55     model.add(tf.keras.layers.Conv2D(128, (5, 5), padding="same"))
56     model.add(tf.keras.layers.Activation("tanh"))
57     model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 32 x 32像素
58     model.add(tf.keras.layers.Conv2D(128, (5, 5), padding="same"))
59     model.add(tf.keras.layers.Activation("tanh"))
60     model.add(tf.keras.layers.UpSampling2D(size=(2, 2)))  # 64 x 64像素
61     model.add(tf.keras.layers.Conv2D(3, (5, 5), padding="same"))
62     model.add(tf.keras.layers.Activation("tanh"))
63 
64     return model
65 
66 
67 # 构造一个 Sequential 对象,包含一个 生成器 和一个 判别器
68 # 输入 -> 生成器 -> 判别器 -> 输出
69 def generator_containing_discriminator(generator, discriminator):
70     model = tf.keras.models.Sequential()
71     model.add(generator)
72     discriminator.trainable = False  # 初始时 判别器 不可被训练
73     model.add(discriminator)
74     return model

接着我们写个训练模型的文件,train..py

 1 # -*- coding: UTF-8 -*-
 2 
 3 """
 4 训练 DCGAN
 5 """
 6 
 7 import os
 8 import glob
 9 import numpy as np
10 from scipy import misc
11 import tensorflow as tf
12 
13 from network import *
14 
15 
16 def train():
17     # 确保包含所有图片的 images 文件夹在所有 Python 文件的同级目录下
18     # 当然了,你也可以自定义文件夹名和路径
19     if not os.path.exists("images"):
20         raise Exception("包含所有图片的 images 文件夹不在此目录下,请添加")
21 
22     # 获取训练数据
23     data = []
24     for image in glob.glob("images/*"):
25         image_data = misc.imread(image)  # imread 利用 PIL 来读取图片数据
26         data.append(image_data)
27     input_data = np.array(data)
28 
29     # 将数据标准化成 [-1, 1] 的取值, 这也是 Tanh 激活函数的输出范围
30     input_data = (input_data.astype(np.float32) - 127.5) / 127.5
31 
32     # 构造 生成器 和 判别器
33     g = generator_model()
34     d = discriminator_model()
35 
36     # 构建 生成器 和 判别器 组成的网络模型
37     d_on_g = generator_containing_discriminator(g, d)
38 
39     # 优化器用 Adam Optimizer
40     g_optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1)
41     d_optimizer = tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1)
42 
43     # 配置 生成器 和 判别器
44     g.compile(loss="binary_crossentropy", optimizer=g_optimizer)
45     d_on_g.compile(loss="binary_crossentropy", optimizer=g_optimizer)
46     d.trainable = True
47     d.compile(loss="binary_crossentropy", optimizer=d_optimizer)
48 
49     # 开始训练
50     for epoch in range(EPOCHS):
51         for index in range(int(input_data.shape[0] / BATCH_SIZE)):
52             input_batch = input_data[index * BATCH_SIZE : (index + 1) * BATCH_SIZE]
53 
54             # 连续型均匀分布的随机数据(噪声)
55             random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
56             # 生成器 生成的图片数据
57             generated_images = g.predict(random_data, verbose=0)
58 
59             input_batch = np.concatenate((input_batch, generated_images))
60             output_batch = [1] * BATCH_SIZE + [0] * BATCH_SIZE
61 
62             # 训练 判别器,让它具备识别不合格生成图片的能力
63             d_loss = d.train_on_batch(input_batch, output_batch)
64 
65             # 当训练 生成器 时,让 判别器 不可被训练
66             d.trainable = False
67 
68             # 重新生成随机数据。很关键
69             random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
70 
71             # 训练 生成器,并通过不可被训练的 判别器 去判别
72             g_loss = d_on_g.train_on_batch(random_data, [1] * BATCH_SIZE)
73 
74             # 恢复 判别器 可被训练
75             d.trainable = True
76 
77             # 打印损失
78             print("Epoch {}, 第 {} 步, 生成器的损失: {:.3f}, 判别器的损失: {:.3f}".format(epoch, index, g_loss, d_loss))
79 
80         # 保存 生成器 和 判别器 的参数
81         # 大家也可以设置保存时名称不同(比如后接 epoch 的数字),参数文件就不会被覆盖了
82         if epoch % 1 == 0:
83             g.save_weights("./generator_weight.h5", True)
84             d.save_weights("./discriminator_weight", True)
85 
86 
87 if __name__ == "__main__":
88     train()

运行这个文件,就可以产生生成器网络的权重文件  generator_weight.h5, 这里我选择每个训练epoch都保存一次权重文件。你可以按你的喜好来。

  训练好了之后,那么我们就可以用generate.py文件,从随机数据生成好看的花朵了。

 1 # -*- coding: UTF-8 -*-
 2 
 3 """
 4 用 DCGAN 的生成器模型 和 训练得到的生成器参数文件 来生成图片
 5 """
 6 
 7 import numpy as np
 8 from PIL import Image
 9 import tensorflow as tf
10 
11 from network import *
12 
13 
14 def generate():
15     # 构造生成器
16     g = generator_model()
17 
18     # 配置 生成器
19     g.compile(loss="binary_crossentropy", optimizer=tf.keras.optimizers.Adam(lr=LEARNING_RATE, beta_1=BETA_1))
20 
21     # 加载训练好的 生成器 参数
22     g.load_weights("generator_weight.h5")
23 
24     # 连续型均匀分布的随机数据(噪声)
25     random_data = np.random.uniform(-1, 1, size=(BATCH_SIZE, 100))
26 
27     # 用随机数据作为输入,生成器 生成图片数据
28     images = g.predict(random_data, verbose=1)
29 
30     # 用生成的图片数据生成 PNG 图片
31     for i in range(BATCH_SIZE):
32         image = images[i] * 127.5 + 127.5
33         Image.fromarray(image.astype(np.uint8)).save("./generated_image/image-%s.png" % i)
34 
35 
36 if __name__ == "__main__":
37     generate()

附注1: 一些训练过程

C:\ProgramData\Anaconda3\python.exe D:/threeTFproject/Case2_AI_Photoshop/train.py
C:\ProgramData\Anaconda3\lib\site-packages\h5py\__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.
  from ._conv import register_converters as _register_converters
2018-11-01 09:29:35.205667: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2
Epoch 0, 第 0 步, 生成器的损失: 0.169, 判别器的损失: 0.732
Epoch 0, 第 1 步, 生成器的损失: 0.258, 判别器的损失: 0.577
Epoch 0, 第 2 步, 生成器的损失: 0.680, 判别器的损失: 0.534
Epoch 0, 第 3 步, 生成器的损失: 1.493, 判别器的损失: 0.451
Epoch 0, 第 4 步, 生成器的损失: 1.484, 判别器的损失: 0.513
Epoch 0, 第 5 步, 生成器的损失: 2.465, 判别器的损失: 0.350
Epoch 0, 第 6 步, 生成器的损失: 4.008, 判别器的损失: 0.313
Epoch 0, 第 7 步, 生成器的损失: 2.139, 判别器的损失: 0.494
Epoch 0, 第 8 步, 生成器的损失: 2.939, 判别器的损失: 0.501
Epoch 0, 第 9 步, 生成器的损失: 3.805, 判别器的损失: 0.415
Epoch 0, 第 10 步, 生成器的损失: 3.413, 判别器的损失: 0.590
Epoch 0, 第 11 步, 生成器的损失: 2.520, 判别器的损失: 0.486
Epoch 0, 第 12 步, 生成器的损失: 2.286, 判别器的损失: 0.471
Epoch 0, 第 13 步, 生成器的损失: 1.228, 判别器的损失: 0.670
Epoch 0, 第 14 步, 生成器的损失: 0.561, 判别器的损失: 0.655
Epoch 0, 第 15 步, 生成器的损失: 0.560, 判别器的损失: 0.517
Epoch 0, 第 16 步, 生成器的损失: 0.643, 判别器的损失: 0.490
Epoch 0, 第 17 步, 生成器的损失: 0.727, 判别器的损失: 0.488
Epoch 0, 第 18 步, 生成器的损失: 1.003, 判别器的损失: 0.734
Epoch 0, 第 19 步, 生成器的损失: 1.235, 判别器的损失: 0.379
Epoch 0, 第 20 步, 生成器的损失: 1.869, 判别器的损失: 0.377
Epoch 0, 第 21 步, 生成器的损失: 2.073, 判别器的损失: 0.384
Epoch 0, 第 22 步, 生成器的损失: 1.185, 判别器的损失: 0.613
WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.Adam object at 0x0000019D240A8BA8>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
Epoch 1, 第 0 步, 生成器的损失: 2.079, 判别器的损失: 0.590
Epoch 1, 第 1 步, 生成器的损失: 1.161, 判别器的损失: 0.506
Epoch 1, 第 2 步, 生成器的损失: 1.137, 判别器的损失: 0.451
Epoch 1, 第 3 步, 生成器的损失: 1.538, 判别器的损失: 0.346
Epoch 1, 第 4 步, 生成器的损失: 1.733, 判别器的损失: 0.362
Epoch 1, 第 5 步, 生成器的损失: 2.059, 判别器的损失: 0.275
Epoch 1, 第 6 步, 生成器的损失: 2.376, 判别器的损失: 0.243
Epoch 1, 第 7 步, 生成器的损失: 2.260, 判别器的损失: 0.300
Epoch 1, 第 8 步, 生成器的损失: 3.750, 判别器的损失: 0.240
Epoch 1, 第 9 步, 生成器的损失: 3.422, 判别器的损失: 0.222
Epoch 1, 第 10 步, 生成器的损失: 4.694, 判别器的损失: 0.275
Epoch 1, 第 11 步, 生成器的损失: 2.299, 判别器的损失: 0.411
Epoch 1, 第 12 步, 生成器的损失: 4.065, 判别器的损失: 0.547
Epoch 1, 第 13 步, 生成器的损失: 1.834, 判别器的损失: 0.470
Epoch 1, 第 14 步, 生成器的损失: 0.398, 判别器的损失: 1.344
Epoch 1, 第 15 步, 生成器的损失: 1.134, 判别器的损失: 0.973
Epoch 1, 第 16 步, 生成器的损失: 2.866, 判别器的损失: 0.374
Epoch 1, 第 17 步, 生成器的损失: 1.056, 判别器的损失: 0.767
Epoch 1, 第 18 步, 生成器的损失: 0.916, 判别器的损失: 0.603
Epoch 1, 第 19 步, 生成器的损失: 1.151, 判别器的损失: 0.645
Epoch 1, 第 20 步, 生成器的损失: 1.947, 判别器的损失: 0.411
Epoch 1, 第 21 步, 生成器的损失: 3.122, 判别器的损失: 0.314
Epoch 1, 第 22 步, 生成器的损失: 1.805, 判别器的损失: 0.642
WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.Adam object at 0x0000019D240A8BA8>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
Epoch 2, 第 0 步, 生成器的损失: 1.240, 判别器的损失: 0.569
Epoch 2, 第 1 步, 生成器的损失: 1.151, 判别器的损失: 0.449
Epoch 2, 第 2 步, 生成器的损失: 1.395, 判别器的损失: 0.332
Epoch 2, 第 3 步, 生成器的损失: 1.649, 判别器的损失: 0.258
Epoch 2, 第 4 步, 生成器的损失: 1.777, 判别器的损失: 0.277
Epoch 2, 第 5 步, 生成器的损失: 1.562, 判别器的损失: 0.268
Epoch 2, 第 6 步, 生成器的损失: 2.229, 判别器的损失: 0.224
Epoch 2, 第 7 步, 生成器的损失: 2.432, 判别器的损失: 0.272
Epoch 2, 第 8 步, 生成器的损失: 4.502, 判别器的损失: 0.229
Epoch 2, 第 9 步, 生成器的损失: 4.549, 判别器的损失: 0.211
Epoch 2, 第 10 步, 生成器的损失: 4.481, 判别器的损失: 0.263
Epoch 2, 第 11 步, 生成器的损失: 3.766, 判别器的损失: 0.423
Epoch 2, 第 12 步, 生成器的损失: 2.195, 判别器的损失: 0.562
Epoch 2, 第 13 步, 生成器的损失: 1.682, 判别器的损失: 2.144
Epoch 2, 第 14 步, 生成器的损失: 0.911, 判别器的损失: 0.543
Epoch 2, 第 15 步, 生成器的损失: 0.301, 判别器的损失: 0.342
Epoch 2, 第 16 步, 生成器的损失: 0.159, 判别器的损失: 0.429
Epoch 2, 第 17 步, 生成器的损失: 0.208, 判别器的损失: 0.392
Epoch 2, 第 18 步, 生成器的损失: 0.241, 判别器的损失: 0.390
Epoch 2, 第 19 步, 生成器的损失: 0.826, 判别器的损失: 0.224
Epoch 2, 第 20 步, 生成器的损失: 1.065, 判别器的损失: 0.204
Epoch 2, 第 21 步, 生成器的损失: 0.824, 判别器的损失: 0.226
Epoch 2, 第 22 步, 生成器的损失: 4.178, 判别器的损失: 0.579
WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.Adam object at 0x0000019D240A8BA8>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
Epoch 3, 第 0 步, 生成器的损失: 0.122, 判别器的损失: 0.613
Epoch 3, 第 1 步, 生成器的损失: 1.310, 判别器的损失: 0.799
Epoch 3, 第 2 步, 生成器的损失: 1.949, 判别器的损失: 0.168
Epoch 3, 第 3 步, 生成器的损失: 1.606, 判别器的损失: 0.167
Epoch 3, 第 4 步, 生成器的损失: 1.433, 判别器的损失: 0.281
Epoch 3, 第 5 步, 生成器的损失: 1.427, 判别器的损失: 0.323
Epoch 3, 第 6 步, 生成器的损失: 2.604, 判别器的损失: 0.292
Epoch 3, 第 7 步, 生成器的损失: 2.925, 判别器的损失: 0.377
Epoch 3, 第 8 步, 生成器的损失: 4.519, 判别器的损失: 0.292
Epoch 3, 第 9 步, 生成器的损失: 4.978, 判别器的损失: 0.415
Epoch 3, 第 10 步, 生成器的损失: 5.062, 判别器的损失: 0.506
Epoch 3, 第 11 步, 生成器的损失: 2.873, 判别器的损失: 0.648
Epoch 3, 第 12 步, 生成器的损失: 3.078, 判别器的损失: 0.610
Epoch 3, 第 13 步, 生成器的损失: 2.059, 判别器的损失: 0.783
Epoch 3, 第 14 步, 生成器的损失: 0.750, 判别器的损失: 1.088
Epoch 3, 第 15 步, 生成器的损失: 1.064, 判别器的损失: 0.898
Epoch 3, 第 16 步, 生成器的损失: 0.329, 判别器的损失: 0.714
Epoch 3, 第 17 步, 生成器的损失: 0.133, 判别器的损失: 0.446
Epoch 3, 第 18 步, 生成器的损失: 0.401, 判别器的损失: 0.476
Epoch 3, 第 19 步, 生成器的损失: 0.419, 判别器的损失: 0.374
Epoch 3, 第 20 步, 生成器的损失: 0.960, 判别器的损失: 0.225
Epoch 3, 第 21 步, 生成器的损失: 1.431, 判别器的损失: 0.203
Epoch 3, 第 22 步, 生成器的损失: 1.061, 判别器的损失: 0.717
WARNING:tensorflow:This model was compiled with a Keras optimizer (<tensorflow.python.keras.optimizers.Adam object at 0x0000019D240A8BA8>) but is being saved in TensorFlow format with `save_weights`. The model's weights will be saved, but unlike with TensorFlow optimizers in the TensorFlow format the optimizer's state will not be saved.

Consider using a TensorFlow optimizer from `tf.train`.
Epoch 4, 第 0 步, 生成器的损失: 2.778, 判别器的损失: 0.743
Epoch 4, 第 1 步, 生成器的损失: 0.179, 判别器的损失: 0.724
Epoch 4, 第 2 步, 生成器的损失: 2.880, 判别器的损失: 0.836
Epoch 4, 第 3 步, 生成器的损失: 2.585, 判别器的损失: 0.290
Epoch 4, 第 4 步, 生成器的损失: 2.781, 判别器的损失: 0.339
Epoch 4, 第 5 步, 生成器的损失: 2.925, 判别器的损失: 0.517
Epoch 4, 第 6 步, 生成器的损失: 5.254, 判别器的损失: 0.537

 

 

 

 附注2:这是train了一个epoch的generate_weight.ht拿来给generate.py生成花朵用的,效果如下:

用34 epoch的generate_weight.ht试试,效果如下:

如果你epoch到200以上,那么就可以看到如下的效果:

 

posted @ 2018-11-01 15:25  彩印网  阅读(421)  评论(0编辑  收藏  举报