GAN¶
GANGenerative Adversarial Network
- 서로 대립adversarial하는 두 신경망을 경쟁시켜가며 결과물 생성 방법을 학습
GAN을 제안한 Ian Goodfellow가 논문에서 제시한 비유를 사용
- 위조지폐범(생성자)과 경찰(구분자)로 나눈 후
- 위조지폐범은 경찰을 취대한 속이려 하고, 경찰을 위조지폐를 최대한 감별하려 노력
이처럼 위조지폐범을 만들고 감별하려는 경쟁을 통해 서로의 능력이 바전하게 되고, 결국 위조지폐범은 진짜와 거의 구분할 수 없을 정도로
진짜 같은 위조지폐를 만듬
In [1]:
import tensorflow as tf
import numpy as np
In [3]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
setting hyper-parameter¶
In [4]:
total_epoch = 100
batch_size = 100
learning_rate = 0.0001
n_hidden = 256
n_input = 28*28
n_noise = 128
- GAN도 비지도 학습이므로 Y를 사용하지 않음
- 구분자에 넣을 이미지가 실제 이미지와 생성한 가짜 이미지 두 개이고
- 가짜 이미지는 노이즈에서 생성할 것이므로 노이즈를 입력할 placeholder Z를 추가
In [5]:
X = tf.placeholder(tf.float32, [None, n_input])
Z = tf.placeholder(tf.float32, [None, n_noise])
setting Generator¶
- 첫 번째 가중치와 bias는 hidden layer로 출력하기 위한 변수
- 두 번째 가중치와 bias는 export layer로 사용할 변수들
- 두 번째 가중치의 변수 크기는 실제 이미지 크기와 같아야 함
In [6]:
with tf.name_scope("Generator_W1"):
G_W1 = tf.Variable(tf.random_normal([n_noise, n_hidden], stddev=0.01))
with tf.name_scope("Generator_b1"):
G_b1 = tf.Variable(tf.zeros([n_hidden]))
with tf.name_scope("Generator_W2"):
G_W2 = tf.Variable(tf.random_normal([n_hidden, n_input], stddev=0.01))
with tf.name_scope("Generator_b2"):
G_b2 = tf.Variable(tf.zeros([n_input]))
setting discriminator¶
- hidden layer는 Generrator와 동일하게 구성
- discriminator는 진짜와 얼마나 가까운지를 판단하는 값으로 0~1사이의 값을 구성
출력값은 하나의 scalar
- 실제 이미지를 판별하는 구분자 신경망과 생성한 이미지를 판별하는 구분자 신경망은 같은 변수를 사용해야함
- 같은 신경망으로 구분을 시켜와 진짜 이미지와 가짜 이미지를 구변하는 특징들을 잡아낼 수 있기 때문
In [7]:
with tf.name_scope("discriminator_W1"):
D_W1 = tf.Variable(tf.random_normal([n_input, n_hidden], stddev=0.01))
with tf.name_scope("discriminator_b1"):
D_b1 = tf.Variable(tf.zeros([n_hidden]))
with tf.name_scope("discriminator_W2"):
D_W2 = tf.Variable(tf.random_normal([n_hidden, 1], stddev=0.01))
with tf.name_scope("discriminator_b2"):
D_b2 = tf.Variable(tf.zeros([1]))
setting neural network¶
In [8]:
def generator(noise_z):
hidden = tf.nn.relu(tf.add(tf.matmul(noise_z, G_W1), G_b1))
output = tf.nn.sigmoid(tf.add(tf.matmul(hidden, G_W2), G_b2))
return output
def discriminator(inputs):
hidden = tf.nn.relu(tf.add(tf.matmul(inputs, D_W1), D_b1))
output = tf.nn.sigmoid(tf.add(tf.matmul(hidden, D_W2), D_b2))
return output
def get_noise(batch_size, n_noise):
output = np.random.normal(size=(batch_size, n_noise))
return output
noiseZ를 이용해 가짜 이미지를 만들 생성자 G를 만들고 이 G가 만든 가짜 이미지와 진짜 이미지 X를 각각 구분자에 넣어 입력한 이미지가 진짜인지를 판별
In [9]:
G = generator(Z)
D_gene = discriminator(G)
D_real = discriminator(X)
cost¶
- cost는 2개가 필요
- 생성자가 만든 이미지를 구분자가 가짜라고 판단하도록 하는 손실값(경찰 학습용)
- 진짜라고 판단하도록 하는 손실값(위조지폐범 학습용)
- 경찰을 학습시키려면 진짜 이미지 판별값 D_real은 1에 가까워야 하고(진짜라고 판별)
- 가짜 이미지 판별값 D_gene는 0에 가까워야함(가짜라고 판별)
In [10]:
with tf.name_scope("cost"):
loss_D = tf.reduce_mean(tf.log(D_real) + tf.log(1-D_gene)) # 경찰, 높아야함
loss_G = tf.reduce_mean(tf.log(D_gene)) # 위조지폐범, 높아야함
tf.summary.scalar("loss_D", loss_D)
tf.summary.scalar("loss_G", loss_G)
training¶
- loss_D를 구할 때는 구분자 신경망에 사용되는 변수들만 사용
- loss_G를 구할 때는 생성자 신경망에 사용되는 변수들만 사용
- loss_D를 학습할 때는 생성자가 변하지 않고, loss_G를 학습할때는 구분자가 변하지 않기 때문
In [11]:
D_var_list = [D_W1, D_b1, D_W2, D_b2]
G_var_list = [G_W1, G_b1, G_W2, G_b2]
논문에 의하면 loss를 최대화 해야하지만, minize에 -를 붙여 최대화
In [12]:
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)
In [13]:
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
merge = tf.summary.merge_all()
writer = tf.summary.FileWriter("./logs/mnist_gan", sess.graph)
total_batch = int(mnist.train.num_examples / batch_size)
loss_val_D, loss_val_G = 0, 0
tot_loss_val_D, tot_loss_val_G = 0, 0
- session 설정과 minibatch를 위한 코드를 만들고 loss_D와 loss_G의 결과값을 받을 변수를 지정
- 구분자는 X값을, 생성자는 노이즈인 Z값을 받으므로 노이즈를 생성해주는 get_noise 함수를 통해 배치 크기만큼 노이즈를 만들고 이를 입력
- 그리고 구분자와 생성자 신경망을 학습
In [14]:
import matplotlib.pyplot as plt
plt.rcParams["axes.unicode_minus"] = False
loss_val_D_list = []
loss_val_G_list = []
In [15]:
for epoch in range(total_epoch):
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})
tot_loss_val_D += -loss_val_D
tot_loss_val_G += -loss_val_G
loss_val_D_list.append(tot_loss_val_D)
loss_val_G_list.append(tot_loss_val_G)
if epoch == 0 or epoch % 20 == 19:
print("Epoch: {}\tlossD: {:0.4f}\tlossG: {:0.4f}".format(epoch+1,
loss_val_D,
loss_val_G))
if epoch ==0 or (epoch+1) % 20 == 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], (28, 28)))
plt.show()
# plt.show()
print("\n optimization complete!")
In [16]:
_, axe = plt.subplots(1, 2, figsize=(15, 5))
axe[0].set_title("loss_D")
axe[1].set_title("loss_G")
axe[0].plot(loss_val_D_list)
axe[1].plot(loss_val_G_list)
Out[16]:
In [17]:
import jptensor as jp
tf_graph = tf.get_default_graph().as_graph_def()
jp.show_graph(tf_graph)
In [18]:
from IPython.core.display import HTML, display
display(HTML("<style> .container{width:100% !important;}</style>"))
'Deep_Learning' 카테고리의 다른 글
16.RNN_word_autoComplete (0) | 2018.12.18 |
---|---|
15.RNN_mnist (1) | 2018.12.18 |
13.auto-encoder (0) | 2018.12.15 |
12.mnist_cnn (0) | 2018.12.12 |
11.mnist_matplotlib_dropout_tensorgraph (0) | 2018.12.10 |