NeuroWhAI의 잡블로그

[TensorFlow] GAN으로 MNIST 이미지 생성하기 본문

개발 및 공부/라이브러리&프레임워크

[TensorFlow] GAN으로 MNIST 이미지 생성하기

NeuroWhAI 2018. 1. 23. 21:23


※ 이 글은 '골빈해커의 3분 딥러닝 텐서플로맛'이라는 책을 보고 실습한걸 기록한 글입니다.


GAN(Generative Adversarial Networks)라는 신경망 구조를 이용해서
생성기와 판별기의 경쟁으로 생성기가 사실적인 이미지를 생성하도록 학습시킬 수 있습니다.
이 예제에서는 생성기가 노이즈 입력을 받아 MNIST 이미지와 비슷한 이미지를 생성하도록 하는게 목표입니다.

코드:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#-*- coding: utf-8 -*-
 
import tensorflow as tf
import numpy as np

import matplotlib.pyplot as plt
 
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
 
learning_rate = 0.0002
total_epoch = 100
batch_size = 100
n_hidden = 256
n_input = 28*28
n_noise = 128
 
= tf.placeholder(tf.float32, [None, n_input])
= tf.placeholder(tf.float32, [None, n_noise])
 
G_W1 = tf.Variable(tf.random_normal([n_noise, n_hidden], stddev=0.01))
G_b1 = tf.Variable(tf.zeros([n_hidden]))
G_W2 = tf.Variable(tf.random_normal([n_hidden, n_input], stddev=0.01))
G_b2 = tf.Variable(tf.zeros([n_input]))
 
D_W1 = tf.Variable(tf.random_normal([n_input, n_hidden], stddev=0.01))
D_b1 = tf.Variable(tf.zeros([n_hidden]))
D_W2 = tf.Variable(tf.random_normal([n_hidden, 1], stddev=0.01))
D_b2 = tf.Variable(tf.zeros([1]))
 
def generator(noise_z):
    hidden = tf.nn.relu(tf.matmul(noise_z, 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, n_noise):
    return np.random.normal(size=(batch_size, n_noise))
 
= generator(Z)
D_gene = discriminator(G)
D_real = discriminator(X)
 
loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1 - D_gene))
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(learning_rate).minimize(-loss_D,
    var_list=D_var_list)
train_G = tf.train.AdamOptimizer(learning_rate).minimize(-loss_G,
    var_list=G_var_list)
 
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
 
    total_batch = int(mnist.train.num_examples / batch_size)
 
    for epoch in range(total_epoch):
        loss_val_D, loss_val_G = 00
 
        for i in range(total_batch):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            noise = get_noise(batch_size, n_noise)
 
            _, loss_val_D = sess.run([train_D, loss_D],
                feed_dict={X: batch_xs, Z: noise})
            _, loss_val_G = sess.run([train_G, loss_G],
                feed_dict={Z: noise})
 
        print('Epoch:''%04d' % epoch,
            'D loss: {:.4}'.format(loss_val_D),
            'G loss: {:.4}'.format(loss_val_G))
 
        if epoch == 0 or (epoch + 1) % 10 == 0:
            sample_size = 10
            noise = get_noise(sample_size, n_noise)
            samples = sess.run(G, feed_dict={Z: noise})
 
            fig, ax = plt.subplots(1, sample_size, figsize=(sample_size, 1))
 
            for i in range(sample_size):
                ax[i].set_axis_off()
                ax[i].imshow(np.reshape(samples[i], (2828)))
 
            plt.savefig('{}.png'.format(str(epoch).zfill(3)),
                bbox_inches='tight')
            
            plt.close(fig)
 
    
 
cs

결과:
Epoch: 0000 D loss: -0.4134 G loss: -2.316
Epoch: 0001 D loss: -0.1492 G loss: -2.991
Epoch: 0002 D loss: -0.1701 G loss: -2.897
Epoch: 0003 D loss: -0.5953 G loss: -1.569
Epoch: 0004 D loss: -0.491 G loss: -1.694
Epoch: 0005 D loss: -0.461 G loss: -2.115
Epoch: 0006 D loss: -0.3064 G loss: -2.728
Epoch: 0007 D loss: -0.1951 G loss: -3.024
Epoch: 0008 D loss: -0.4306 G loss: -2.372
Epoch: 0009 D loss: -0.3764 G loss: -2.236
(중략)
Epoch: 0090 D loss: -0.6892 G loss: -1.972
Epoch: 0091 D loss: -0.6233 G loss: -1.893
Epoch: 0092 D loss: -0.8435 G loss: -1.886
Epoch: 0093 D loss: -0.6601 G loss: -1.996
Epoch: 0094 D loss: -0.631 G loss: -1.981
Epoch: 0095 D loss: -0.7304 G loss: -2.278
Epoch: 0096 D loss: -0.7336 G loss: -2.331
Epoch: 0097 D loss: -0.7128 G loss: -2.14
Epoch: 0098 D loss: -0.5892 G loss: -2.148
Epoch: 0099 D loss: -0.6145 G loss: -1.939

(한줄이 한 epoch이고 아래로 갈수록 학습이 더 진행된 결과입니다.)










손실 그래프: (이건 위 코드에 없습니다.)

각 신경망 입장에서 loss가 커야 더 잘 학습된 상태를 나타냅니다.
때문에 Optimizer의 minimize(최소화) 함수에 전달할때 마이너스 부호를 붙혔습니다.
보시면 서로 경쟁하는 관계이기 때문에 각 loss가 많이 떨립니다.
다만 전체적으로 보면 G_loss(생성기)는 점점 오차가 줄어드는데
D_loss(판별기)는 오차가 점점 커집니다.
즉, 판별기가 실제 이미지를 가짜라고 혹은 가짜 이미지를 진짜라고 잘못된 출력을 냈다는 뜻이며
후자의 경우 생성기가 잘 학습되고 있다는 뜻이기도 합니다.

Optimizer를 생성할때 var_list라는 파라미터를 넣어주던데
생성기를 학습할때는 생성기를 구성하는 파라미터만,
판별기를 학습할때는 판별기를 구성하는 파라미터만 조정하도록 하는거라고 합니다.

책의 다음 장에서는 원하는 숫자에 해당하는 이미지를 생성하도록 할거라네요.
기대가 됩니다. ㅎㅎ





Comments