Skip to content

Instantly share code, notes, and snippets.

@solaris33
Last active March 24, 2018 17:10
Show Gist options
  • Save solaris33/a9c5cdbd2b6e9be20b30ffd47863dd3e to your computer and use it in GitHub Desktop.
Save solaris33/a9c5cdbd2b6e9be20b30ffd47863dd3e to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
"""
GAN(Generative Adversarial Networks)을 이용한 MNIST 데이터 생성
Reference : https://github.com/TengdaHan/GAN-TensorFlow
Author : solaris33
Project URL : http://solarisailab.com/archives/2482
"""
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os
# MNIST 데이터를 불러옵니다.
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
# 생성된 MNIST 이미지를 8x8 Grid로 보여주는 plot 함수를 정의합니다.
def plot(samples):
fig = plt.figure(figsize=(8, 8))
gs = gridspec.GridSpec(8, 8)
gs.update(wspace=0.05, hspace=0.05)
for i, sample in enumerate(samples):
ax = plt.subplot(gs[i])
plt.axis('off')
plt.imshow(sample.reshape(28, 28))
return fig
# 설정값들을 선언합니다.
num_epoch = 100000
batch_size = 64
num_input = 28 * 28
num_latent_variable = 100
num_hidden = 128
learning_rate = 0.001
# 플레이스 홀더를 선언합니다.
X = tf.placeholder(tf.float32, [None, num_input]) # 인풋 이미지
z = tf.placeholder(tf.float32, [None, num_latent_variable]) # 인풋 Latent Variable
# Generator 변수들 설정
# 100 -> 128 -> 784
with tf.variable_scope('generator'):
# 히든 레이어 파라미터
G_W1 = tf.Variable(tf.random_normal(shape=[num_latent_variable, num_hidden], stddev=5e-2))
G_b1 = tf.Variable(tf.constant(0.1, shape=[num_hidden]))
# 아웃풋 레이어 파라미터
G_W2 = tf.Variable(tf.random_normal(shape=[num_hidden, num_input], stddev=5e-2))
G_b2 = tf.Variable(tf.constant(0.1, shape=[num_input]))
# Discriminator 변수들 설정
# 784 -> 128 -> 1
with tf.variable_scope('discriminator'):
# 히든 레이어 파라미터
D_W1 = tf.Variable(tf.random_normal(shape=[num_input, num_hidden], stddev=5e-2))
D_b1 = tf.Variable(tf.constant(0.1, shape=[num_hidden]))
# 아웃풋 레이어 파라미터
D_W2 = tf.Variable(tf.random_normal(shape=[num_hidden, 1], stddev=5e-2))
D_b2 = tf.Variable(tf.constant(0.1, shape=[1]))
# Generator를 생성하는 함수를 정의합니다.
# Inputs:
# X : 인풋 Latent Variable
# Output:
# generated_mnist_image : 생성된 MNIST 이미지
def build_generator(X):
hidden_layer = tf.nn.relu((tf.matmul(X, G_W1) + G_b1))
output_layer = tf.matmul(hidden_layer, G_W2) + G_b2
generated_mnist_image = tf.nn.sigmoid(output_layer)
return generated_mnist_image
# Discriminator를 생성하는 함수를 정의합니다.
# Inputs:
# X : 인풋 이미지
# Output:
# predicted_value : Discriminator가 판단한 True(1) or Fake(0)
# logits : sigmoid를 씌우기전의 출력값
def build_discriminator(X):
hidden_layer = tf.nn.relu((tf.matmul(X, D_W1) + D_b1))
logits = tf.matmul(hidden_layer, D_W2) + D_b2
predicted_value = tf.nn.sigmoid(logits)
return predicted_value, logits
# 생성자(Generator)를 선언합니다.
G = build_generator(z)
# 구분자(Discriminator)를 선언합니다.
D_real, D_real_logits = build_discriminator(X) # D(x)
D_fake, D_fake_logits = build_discriminator(G) # D(G(z))
# Discriminator의 손실 함수를 정의합니다.
d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_real_logits, labels=tf.ones_like(D_real_logits))) # log(D(x))
d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_fake_logits, labels=tf.zeros_like(D_fake_logits))) # log(1-D(G(z)))
d_loss = d_loss_real + d_loss_fake # log(D(x)) + log(1-D(G(z)))
# Generator의 손실 함수를 정의합니다.
g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=D_fake_logits, labels=tf.ones_like(D_fake_logits))) # log(D(G(z))
# 전체 파라미터를 Discriminator와 관련된 파라미터와 Generator와 관련된 파라미터로 나눕니다.
tvar = tf.trainable_variables()
dvar = [var for var in tvar if 'discriminator' in var.name]
gvar = [var for var in tvar if 'generator' in var.name]
# Discriminator와 Generator의 Optimizer를 정의합니다.
d_train_step = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=dvar)
g_train_step = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=gvar)
# 생성된 이미지들을 저장할 generated_outputs 폴더를 생성합니다.
num_img = 0
if not os.path.exists('generated_output/'):
os.makedirs('generated_output/')
with tf.Session() as sess:
# 변수들에 초기값을 할당합니다.
sess.run(tf.global_variables_initializer())
# num_epoch 횟수만큼 최적화를 수행합니다.
for i in range(num_epoch):
# MNIST 이미지를 batch_size만큼 불러옵니다.
batch_X, _ = mnist.train.next_batch(batch_size)
# Latent Variable의 인풋으로 사용할 noise를 Uniform Distribution에서 batch_size만큼 샘플링합니다.
batch_noise = np.random.uniform(-1., 1., [batch_size, 100])
# 500번 반복할때마다 생성된 이미지를 저장합니다.
if i % 500 == 0:
samples = sess.run(G, feed_dict={z: np.random.uniform(-1., 1., [64, 100])})
fig = plot(samples)
plt.savefig('generated_output/%s.png' % str(num_img).zfill(3), bbox_inches='tight')
num_img += 1
plt.close(fig)
# Discriminator 최적화를 수행하고 Discriminator의 손실함수를 return합니다.
_, d_loss_print = sess.run([d_train_step, d_loss], feed_dict={X: batch_X, z: batch_noise})
# Generator 최적화를 수행하고 Generator 손실함수를 return합니다.
_, g_loss_print = sess.run([g_train_step, g_loss], feed_dict={z: batch_noise})
# 100번 반복할때마다 Discriminator의 손실함수와 Generator 손실함수를 출력합니다.
if i % 100 == 0:
print('반복(Epoch): %d, Generator 손실함수(g_loss): %f, Discriminator 손실함수(d_loss): %f' % (i, g_loss_print, d_loss_print))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment