[TensorFlow_Python] GAN 알고리즘을 이용한 MNIST 이미지 생성
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
# 데이터셑 다운로드
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
# 실제 이미지는 28 * 28 = 784개의 특징을 가집니다.
X = tf.placeholder(tf.float32, [None, 784])
# 가짜 이미지를 위해 필요한 노이즈의 크기는 128로 설정합니다.
Z = tf.placeholder(tf.float32, [None, 128])
# 생성자: 128(노이즈) → 256(은닉층) → 784(입력층)
G_W1 = tf.Variable(tf.random_normal([128, 256], stddev=0.01))
G_b1 = tf.Variable(tf.zeros([256]))
G_W2 = tf.Variable(tf.random_normal([256, 784], stddev=0.01))
G_b2 = tf.Variable(tf.zeros([784]))
# 구분자: 784(입력층) → 256(은닉층) → 0 ~ 1(일치도)
D_W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01))
D_b1 = tf.Variable(tf.zeros([256]))
D_W2 = tf.Variable(tf.random_normal([256, 1], stddev=0.01))
D_b2 = tf.Variable(tf.random_normal([1]))
# 생성자 객체를 생성하는 함수입니다.
def generator(noise):
hidden = tf.nn.relu(tf.matmul(noise, G_W1) + G_b1)
output = tf.nn.sigmoid(tf.matmul(hidden, G_W2) + G_b2)
return output
# 구분자 객체를 생성하는 함수입니다.
def discriminator(inputs):
hidden = tf.nn.relu(tf.matmul(inputs, D_W1) + D_b1)
output = tf.nn.sigmoid(tf.matmul(hidden, D_W2) + D_b2)
return output
# 무작위 노이즈를 생성합니다.
def get_noise(batch_size, noise):
return np.random.normal(size=(batch_size, noise))
# 가짜 이미지 생성자는 128 크기의 노이즈에서 불러옵니다.
G = generator(Z)
# 가짜 이미지 구분자는 128 크기의 노이즈가 생성한 784 크기의 이미지에서 불러옵니다.
D_gene = discriminator(G)
# 실제 이미지 구분자는 784 크기의 이미지에서 불러옵니다.
D_real = discriminator(X)
# 구분자의 손실 함수는 진짜 이미지가 1에 가깝고, 가짜 이미지가 0에 가깝도록 설정합니다.
loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1 - D_gene))
# 생성자의 손실 함수는 가짜 이미지가 1에 가깝도록 설정합니다.
loss_G = tf.reduce_mean(tf.log(D_gene))
# 구분자는 구분자 가중치 및 바이어스만을 사용합니다.
D_var_list = [D_W1, D_b1, D_W2, D_b2]
# 생성자는 생성자 가중치 및 바이어스만을 사용합니다.
G_var_list = [G_W1, G_b1, G_W2, G_b2]
# 구분자 최적화를 진행합니다.
train_D = tf.train.AdamOptimizer(0.001).minimize(-loss_D, var_list=D_var_list)
# 생성자 최적화를 진행합니다.
train_G = tf.train.AdamOptimizer(0.001).minimize(-loss_G, var_list=G_var_list)
# 세션을 생성해 그래프를 동작시킵니다.
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# 구분자와 생성자의 비용 변수를 생성합니다.
loss_val_D, loss_val_G = 0, 0
# 배치 크기를 100으로 설정합니다.
batch_size = 100
total_batch = int(mnist.train.num_examples / batch_size)
for epoch in range(100):
# 전체 배치 크기만큼 반복합니다.
for i in range(total_batch):
batch_x, batch_y = mnist.train.next_batch(batch_size)
noise = get_noise(batch_size, 128)
# 구분자는 실제 이미지 및 노이즈를 이용해 학습을 진행합니다.
_, loss_val_D = sess.run([train_D, loss_D], feed_dict={X: batch_x, Z: noise})
# 생성자는 노이즈만을 이용해 학습을 진행합니다.
_, loss_val_G = sess.run([train_G, loss_G], feed_dict={Z: noise})
# 1번 돌 때마다 학습 상황을 출력합니다.
print('학습:', '%04d' % epoch,
'구분자 오차: {:.4}'.format(loss_val_D),
'생성자 오차: {:.4}'.format(loss_val_G))
# 10번 돌 때마다 결과를 그림으로 확인합니다.
if epoch == 0 or (epoch + 1) % 10 == 0:
# 샘플 이미지의 크기는 10입니다.
size = 10
noise = get_noise(size, 128)
# 생성자가 임의의 샘플 이미지를 생성하도록 합니다.
samples = sess.run(G, feed_dict={Z: noise})
# 만든 그림을 폴더에 출력할 수 있도록 합니다.
fig, ax = plt.subplots(1, size, figsize=(size, 1))
for i in range(size):
ax[i].set_axis_off()
# 28 * 28 크기의 이미지를 생성합니다.
ax[i].imshow(np.reshape(samples[i], (28, 28)))
plt.savefig('samples/{}.png'.format(str(epoch).zfill(4)), bbox_inches='tight')
plt.close(fig)
아래는 출력된 이미지