<jupyter_start><jupyter_text>训练目标 $$\min _{G} \max _{D} V(D, G)=\mathbb{E}_{\boldsymbol{x} \sim p_{\text { data }}(\boldsymbol{x})}[\log D(\boldsymbol{x})]+\mathbb{E}_{\boldsymbol{z} \sim p_{\boldsymbol{z}}(\boldsymbol{z})}[\log (1-D(G(\boldsymbol{z})))]$$ > ◆D(x)输出是否是真实图像, Prob  > ◆训练判别器,就是使V(D,G)变大，**真图判对，假图判错的Prob**  > ◆训练生成器,就是使V(D,G)变小，**假图判错的Prob**  反卷积![image.png](attachment:image.png)b = (w) * [a]T ![image.png](attachment:image.png)a = (w)T * b  Code 1. Data provider:      a. Imgae data      b. random vector(generate a random image)  2. Build computer graph:      a. generator      b. discriminator      c. DCGAN          connect g and d        define loss        define train_op3. trianing process<jupyter_code>import os
import sys
import tensorflow as tf
from tensorflow import logging
from tensorflow import gfile
import pprint
import numpy as np
import random
import math
from PIL import Image
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets('./rnn_DCGAN/MNIST_data/', one_hot=True)

output_dir = './rnn_DCGAN/local_run'
if not gfile.Exists(output_dir):
    gfile.MakeDirs(output_dir)


def get_default_params():
    return tf.contrib.training.HParams(
        z_dim=100,  # random vector size
        init_conv_size=4,  # 反卷积初始特征图大小
        g_channels=[128, 64, 32, 1],   
        d_channels=[32, 64, 128, 256],  
        batch_size=128,
        learning_rate=0.002,
        beta1=0.5,  # Adam
        img_size=32, # 生成图片大小
    )


hps = get_default_params()<jupyter_output>D:\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<jupyter_text>图片数据处理<jupyter_code>class MnistData(object):
    def __init__(self, mnist_train, z_dim, img_size):
        self._data = mnist_train
        self._example_num = len(self._data)
        self._z_data = np.random.standard_normal((self._example_num, z_dim))
        self._indicator = 0
        self._resize_mnist_img(img_size)
        self._random_shuffle()
    
    def _random_shuffle(self):
        p = np.random.permutation(self._example_num)
        self._z_data = self._z_data[p]
        self._data = self._data[p]
    
    def _resize_mnist_img(self, img_size):
        """Resize mnist image to img_size"""
        data = np.asarray(self._data * 255, np.uint8)
        data = data.reshape((self._example_num, 1, 28, 28))
        data = data.transpose((0, 2, 3, 1))
        new_data = []
        for i in range(self._example_num):
            img = data[i].reshape((28, 28))
            img = Image.fromarray(img)
            img = img.resize((img_size, img_size))
            img = np.asarray(img)
            img = img.reshape((img_size, img_size, 1))
            new_data.append(img)
        new_data = np.asarray(new_data, dtype=np.float32)
        new_data = new_data / 127.5 - 1
        self._data = new_data
        
    def next_batch(self, batch_size):
        end_indicator = self._indicator + batch_size
        if end_indicator > self._example_num:
            self._random_shuffle()
            # 重置
            self._indicator = 0
            end_indicator = self._indicator + batch_size
        assert end_indicator < self._example_num
        
        batch_data = self._data[self._indicator: end_indicator]
        batch_z = self._z_data[self._indicator: end_indicator]
        self._indicator = end_indicator
        return batch_data, batch_z

mnist_data = MnistData(mnist.train.images, hps.z_dim, hps.img_size)
batch_data, batch_z = mnist_data.next_batch(5)
print(batch_data.shape)
print(batch_z.shape)<jupyter_output>(5, 32, 32, 1)
(5, 100)<jupyter_text>定义G and D<jupyter_code>def conv2d_transpose(inputs, out_channel, name, training, with_bn_relu=True):
    """反卷积。注意最后一层需要激活层和BN，只需要tanh转换到（-1，1）"""
    with tf.variable_scope(name):
        conv2d_trans = tf.layers.conv2d_transpose(
            inputs, out_channel, [5, 5], strides=(2, 2), padding='SAME')
        if with_bn_relu:
            bn = tf.layers.batch_normalization(conv2d_trans, training=training)
            relu = tf.nn.relu(bn)
            return relu
        else:
            return conv2d_trans


def conv2d(inputs, out_channel, name, training):
    """判别器卷积"""
    def leaky_relu(x, leak=0.2, name=''):
        return tf.maximum(x, x * leak, name=name)

    with tf.variable_scope(name):
        conv2d_output = tf.layers.conv2d(
            inputs, out_channel, [5, 5], strides=(2, 2), padding='SAME')
        bn = tf.layers.batch_normalization(conv2d_output, training=training)
        return leaky_relu(bn, name='outputs')


class Generator(object):
    """Generator of GAN"""
    def __init__(self, channels, init_conv_size):
        assert len(channels) > 1
        self._channels = channels
        self._init_conv_size = init_conv_size
        self._reuse = False   # 训练时，需要重用，改为True

    def __call__(self, inputs, training):
        inputs = tf.convert_to_tensor(inputs)
        with tf.variable_scope('generator', reuse=self._reuse):
            """
            random vector > fc > channel * init_conv_size**2 > reshape > 
            [init_conv_size, init_conv_size, channel]
            """
            with tf.variable_scope('inputs'):
                fc = tf.layers.dense(
                    inputs, self._channels[0] * self._init_conv_size *
                    self._init_conv_size)
                conv0 = tf.reshape(fc, [
                    -1, self._init_conv_size, self._init_conv_size,
                    self._channels[0]
                ])
                bn0 = tf.layers.batch_normalization(conv0, training=training)
                relu0 = tf.nn.relu(bn0)

            deconv_inputs = relu0
            # deconvolutions * 4
            for i in range(1, len(self._channels)):
                # 最后一层不需要bn relu
                with_bn_relu = (i != len(self._channels) - 1)
                deconv_inputs = conv2d_transpose(
                    deconv_inputs, self._channels[i], 'deconv-%d' % i,
                    training, with_bn_relu)
            # generator输出
            img_inputs = deconv_inputs
            with tf.variable_scope('generate_imgs'):
                # imgs value scope: [-1, 1]
                imgs = tf.tanh(img_inputs, name='imgaes')
        self._reuse = True
        
        # 保存生成器的所有参数（生成器和判别器是分开训练的，变量分开存储）
        # tf.get_collection获得某个scope下的所有参数
        self.variables = tf.get_collection(
            tf.GraphKeys.TRAINABLE_VARIABLES, scope='generator')
        return imgs


class Discriminator(object):
    """Discriminator of GAN"""
    def __init__(self, channels):
        self._channels = channels
        self._reuse = False

    def __call__(self, inputs, training):
        inputs = tf.convert_to_tensor(inputs, dtype=tf.float32)

        conv_inputs = inputs
        with tf.variable_scope('discriminator', reuse=self._reuse):
            for i in range(len(self._channels)):
                conv_inputs = conv2d(conv_inputs, self._channels[i],
                                     'deconv-%d' % i, training)
            fc_inputs = conv_inputs
            with tf.variable_scope('fc'):
                flatten = tf.contrib.layers.flatten(fc_inputs)
                logits = tf.layers.dense(flatten, 2, name="logits")
        self._reuse = True
        self.variables = tf.get_collection(
            tf.GraphKeys.TRAINABLE_VARIABLES, scope='discriminator')
        return logits<jupyter_output><empty_output><jupyter_text>DCGAN<jupyter_code>class DCGAN(object):
    """DCGAN implementation."""
    def __init__(self, hps):
        g_channels = hps.g_channels
        d_channels = hps.d_channels
        
        self._batch_size = hps.batch_size
        self._init_conv_size = hps.init_conv_size
        self._batch_size = hps.batch_size
        self._z_dim = hps.z_dim
        self._img_size = hps.img_size

        self._generator = Generator(g_channels, self._init_conv_size)
        self._discriminator = Discriminator(d_channels)

    def build(self):
        """Build compute graph."""
        # 初始随机变量placeholder
        self._z_placholder = tf.placeholder(tf.float32,
                                            (self._batch_size, self._z_dim))
        # 真实图像
        self._img_placeholder = tf.placeholder(
            tf.float32, (self._batch_size, self._img_size, self._img_size, 1))

        generated_imgs = self._generator(
            self._z_placholder, training=True)
        fake_img_logits = self._discriminator(
            generated_imgs, training=True)
        real_img_logits = self._discriminator(
            self._img_placeholder, training=True)

        loss_on_fake_to_real = tf.reduce_mean(
            tf.nn.sparse_softmax_cross_entropy_with_logits(
                labels=tf.ones([self._batch_size], dtype=tf.int64),
                logits=fake_img_logits))    # 1，训练G
        loss_on_fake_to_fake = tf.reduce_mean(
            tf.nn.sparse_softmax_cross_entropy_with_logits(
                labels=tf.zeros([self._batch_size], dtype=tf.int64),
                logits=fake_img_logits))    # 0， 训练D
        loss_on_real_to_real = tf.reduce_mean(
            tf.nn.sparse_softmax_cross_entropy_with_logits(
                labels=tf.ones([self._batch_size], dtype=tf.int64),
                logits=real_img_logits))    # 1， 训练D

        # 相当于字典
        tf.add_to_collection('g_losses', loss_on_fake_to_real)
        tf.add_to_collection('d_losses', loss_on_fake_to_fake)
        tf.add_to_collection('d_losses', loss_on_real_to_real)

        loss = {
            'g': tf.add_n(tf.get_collection('g_losses'), name='total_g_loss'),
            'd': tf.add_n(tf.get_collection('d_losses'), name='total_d_loss')
        }

        return (self._z_placholder, self._img_placeholder, generated_imgs,
                loss)

    def build_train(self, losses, learning_rate, beta1):
        """Build train op."""
        g_opt = tf.train.AdamOptimizer(
            learning_rate=learning_rate, beta1=beta1)
        d_opt = tf.train.AdamOptimizer(
            learning_rate=learning_rate, beta1=beta1)
        
        g_opt_op = g_opt.minimize(
            losses['g'], var_list=self._generator.variables)
        d_opt_op = d_opt.minimize(
            losses['d'], var_list=self._discriminator.variables)
        with tf.control_dependencies(control_inputs=[g_opt_op, d_opt_op]):
            # control_inputs: A list of `Operation` or `Tensor` objects which
            # must be executed or computed before running the operations
            # defined in the context.
            # 执行顺序：g_opt_op > d_opt_op > g_opt_op ...
            return tf.no_op(name='train')


dcgan = DCGAN(hps)
z_placeholder, img_placeholder, generated_imgs, losses = dcgan.build()
train_op = dcgan.build_train(losses, hps.learning_rate, hps.beta1)<jupyter_output><empty_output><jupyter_text>Training<jupyter_code>def combine_and_show_imgs(batch_imgs, img_size, rows=8, cols=16):
    """Combine small images in a batch into a big pic."""
    # batch_imgs: [batch_size, img_size, img_size, 1]
    result_big_img = []
    for i in range(rows):
        row_imgs = []
        for j in range(cols):
            img = batch_imgs[cols * i + j]
            img = img.reshape((img_size, img_size))
            img = (img + 1) * 127.5
            row_imgs.append(img)    # 注意不要append自身。。
        row_imgs = np.hstack(row_imgs)
        result_big_img.append(row_imgs)
    result_big_img = np.vstack(result_big_img)
    result_big_img = np.asarray(result_big_img, np.uint8)
    result_big_img = Image.fromarray(result_big_img)
    return result_big_img
init_op = tf.global_variables_initializer()
train_steps = 10000

with tf.Session() as sess:
    sess.run(init_op)
    for step in range(train_steps):
        batch_img, batch_z = mnist_data.next_batch(hps.batch_size)

        fetches = [train_op, losses['g'], losses['d']]
        should_sample = (step + 1) % 50 == 0
        
        if should_sample:
            fetches += [generated_imgs]
        
        out_values = sess.run(
            fetches,
            feed_dict={
                z_placeholder: batch_z,
                img_placeholder: batch_img
            })
        _, g_loss_val, d_loss_val = out_values[0:3]
        logging.info('step: %d, g_loss: %4.3f, d_loss: %4.3f' %
                     (step, g_loss_val, d_loss_val))
        if should_sample:
            gen_imgs_val = out_values[3]
            
            # generated image
            gen_img_path = os.path.join(output_dir,
                                        '%05d-gen.jpg' % (step + 1))
            # groud truth
            gt_img_path = os.path.join(output_dir, '%05d-gt.jpg' % (step + 1))

            gen_img = combine_and_show_imgs(gen_imgs_val, hps.img_size)
            gt_img = combine_and_show_imgs(batch_img, hps.img_size)

            gen_img.save(gen_img_path)
            gt_img.save(gt_img_path)<jupyter_output>INFO:tensorflow:step: 0, g_loss: 0.484, d_loss: 1.984
INFO:tensorflow:step: 1, g_loss: 17.201, d_loss: 0.004
INFO:tensorflow:step: 2, g_loss: 0.001, d_loss: 10.027
INFO:tensorflow:step: 3, g_loss: 26.140, d_loss: 10.231
INFO:tensorflow:step: 4, g_loss: 23.698, d_loss: 0.002
INFO:tensorflow:step: 5, g_loss: 20.158, d_loss: 0.002
INFO:tensorflow:step: 6, g_loss: 3.154, d_loss: 0.258
INFO:tensorflow:step: 7, g_loss: 0.000, d_loss: 14.111
INFO:tensorflow:step: 8, g_loss: 7.200, d_loss: 0.062
INFO:tensorflow:step: 9, g_loss: 2.901, d_loss: 0.302
INFO:tensorflow:step: 10, g_loss: 0.932, d_loss: 1.004
INFO:tensorflow:step: 11, g_loss: 4.873, d_loss: 1.323
INFO:tensorflow:step: 12, g_loss: 0.069, d_loss: 2.826
INFO:tensorflow:step: 13, g_loss: 7.676, d_loss: 0.895
INFO:tensorflow:step: 14, g_loss: 6.785, d_loss: 0.201
INFO:tensorflow:step: 15, g_loss: 3.703, d_loss: 0.064
INFO:tensorflow:step: 16, g_loss: 0.143, d_loss: 2.075
INFO:tensorflow:step: 17, g_loss: 8.911, d_loss: 1.115
INFO:tensorfl[...]
{'fraction_non_alphanumeric': 0.11344597472667897, 'fraction_numerical': 0.02506034360357802, 'mean_word_length': 2.528807615230461, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '5', 'dir': 'jupyter-structured-clean-dedup', 'id': '196778', 'license': 'Apache-2.0', 'n_tokens_mistral': 5210, 'n_tokens_neox': 4942, 'n_words': 891, 'path': 'DCGAN/DCGAN.ipynb', 'repo_name': 'RacleRay/-Have_Fun_Doing', 'size': '14086'}