Notice
Recent Posts
Recent Comments
NeuroWhAI의 잡블로그
[TensorFlow] DCGAN으로 MNIST 이미지 생성하기 (최종) 본문
지식 부족으로 계속 실패했었는데 그럭저럭 완성됬습니다.
인터넷 블로그의 글들과 GitHub의 소스코드들을 참고해서 만들었습니다.
코드:
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | #-*- 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) total_epoch = 100 batch_size = 100 n_noise = 100 D_global_step = tf.Variable(0, trainable=False, name='D_global_step') G_global_step = tf.Variable(0, trainable=False, name='G_global_step') X = tf.placeholder(tf.float32, [None, 28, 28, 1]) Z = tf.placeholder(tf.float32, [None, n_noise]) is_training = tf.placeholder(tf.bool) def leaky_relu(x, leak=0.2): return tf.maximum(x, x * leak) def generator(noise): with tf.variable_scope('generator'): output = tf.layers.dense(noise, 128*7*7) output = tf.reshape(output, [-1, 7, 7, 128]) output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training)) output = tf.layers.conv2d_transpose(output, 64, [5, 5], strides=(2, 2), padding='SAME') output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training)) output = tf.layers.conv2d_transpose(output, 32, [5, 5], strides=(2, 2), padding='SAME') output = tf.nn.relu(tf.layers.batch_normalization(output, training=is_training)) output = tf.layers.conv2d_transpose(output, 1, [5, 5], strides=(1, 1), padding='SAME') output = tf.tanh(output) return output def discriminator(inputs, reuse=None): with tf.variable_scope('discriminator') as scope: if reuse: scope.reuse_variables() output = tf.layers.conv2d(inputs, 32, [5, 5], strides=(2, 2), padding='SAME') output = leaky_relu(output) output = tf.layers.conv2d(output, 64, [5, 5], strides=(2, 2), padding='SAME') output = leaky_relu(tf.layers.batch_normalization(output, training=is_training)) output = tf.layers.conv2d(output, 128, [5, 5], strides=(2, 2), padding='SAME') output = leaky_relu(tf.layers.batch_normalization(output, training=is_training)) flat = tf.contrib.layers.flatten(output) output = tf.layers.dense(flat, 1, activation=None) return output def get_noise(batch_size, n_noise): return np.random.uniform(-1.0, 1.0, size=[batch_size, n_noise]) def get_moving_noise(batch_size, n_noise): assert batch_size > 0 noise_list = [] base_noise = np.random.uniform(-1.0, 1.0, size=[n_noise]) end_noise = np.random.uniform(-1.0, 1.0, size=[n_noise]) step = (end_noise - base_noise) / batch_size noise = np.copy(base_noise) for _ in range(batch_size - 1): noise_list.append(noise) noise = noise + step noise_list.append(end_noise) return noise_list G = generator(Z) D_real = discriminator(X) D_gene = discriminator(G, True) loss_D_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_real, labels=tf.ones_like(D_real) )) loss_D_gene = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_gene, labels=tf.zeros_like(D_gene) )) loss_D = loss_D_real + loss_D_gene loss_G = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( logits=D_gene, labels=tf.ones_like(D_gene) )) vars_D = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='discriminator') vars_G = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, scope='generator') update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS) with tf.control_dependencies(update_ops): train_D = tf.train.AdamOptimizer().minimize(loss_D, var_list=vars_D, global_step=D_global_step) train_G = tf.train.AdamOptimizer().minimize(loss_G, var_list=vars_G, global_step=G_global_step) tf.summary.scalar('loss_D', loss_D) tf.summary.scalar('loss_G', loss_G) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) merged = tf.summary.merge_all() writer = tf.summary.FileWriter('./logs', sess.graph) total_batch = int(mnist.train.num_examples / batch_size) for epoch in range(total_epoch): loss_val_D, loss_val_G = 0, 0 batch_xs, batch_ys = None, None noise = None for i in range(total_batch): batch_xs, batch_ys = mnist.train.next_batch(batch_size) batch_xs = batch_xs.reshape(-1, 28, 28, 1) noise = get_noise(batch_size, n_noise) _, loss_val_D = sess.run([train_D, loss_D], feed_dict={X: batch_xs, Z: noise, is_training: True}) _, loss_val_G = sess.run([train_G, loss_G], feed_dict={X: batch_xs, Z: noise, is_training: True}) summary = sess.run(merged, feed_dict={X: batch_xs, Z: noise, is_training: True}) writer.add_summary(summary, global_step=sess.run(G_global_step)) print('Epoch:', '%04d' % epoch, 'D loss: {:.4}'.format(loss_val_D), 'G loss: {:.4}'.format(loss_val_G)) if epoch == 0 or (epoch + 1) % 5 == 0: sample_size = 10 noise = get_noise(sample_size, n_noise) samples = sess.run(G, feed_dict={Z: noise, is_training: False}) test_noise = get_moving_noise(sample_size, n_noise) test_samples = sess.run(G, feed_dict={Z: test_noise, is_training: False}) fig, ax = plt.subplots(2, sample_size, figsize=(sample_size, 2)) for i in range(sample_size): ax[0][i].set_axis_off() ax[1][i].set_axis_off() ax[0][i].imshow(np.reshape(samples[i], (28, 28))) ax[1][i].imshow(np.reshape(test_samples[i], (28, 28))) plt.savefig('{}.png'.format(str(epoch).zfill(3)), bbox_inches='tight') plt.close(fig) | cs |
결과:
아래는 생성한 결과 이미지 입니다.
첫째줄은 단순하게 랜덤 노이즈로 생성한 결과물이고
둘째줄은 노이즈를 두개(a, b) 만들고 자연스럽게 a에서 b로 노이즈 값을 변화시키면서 만든 결과물 입니다.
DCGAN의 장점 중 하나가 입력에 대해 오버피팅되지 않는다는 거라서
학습이 잘 되었다면 노이즈를 변화시키면 결과물도 자연스럽게 바뀐다고 하니 그걸 보려고 두번째 줄을 만들었습니다.
학습 초기의 결과는 뺐습니다.
GPU는 GTX 960M을 사용했는데 100 epochs에 4시간 걸렸네요. ㅠㅠ
왜 고성능 GPU가 딸린 ML 전용 클라우드 서비스를 쓰는지 알 것 같습니다....
아무튼 만족스러운 결과입니다!
딥러닝을 배우고는 있지만 정작 실용적인 무언가를 아직 못만들어봐서 이렇게라도 만족하고 있습니다.
언젠가 노하우가 늘고 창의적인 아이디어가 떠오른다면 열정을 불태워서 진행해보고 싶습니다.
'개발 및 공부 > 라이브러리&프레임워크' 카테고리의 다른 글
[Keras] GAN으로 입력 데이터의 확률분포 변환하기 (0) | 2018.03.24 |
---|---|
[Keras] Autoencoder로 MNIST 학습하기 (0) | 2018.03.20 |
[Keras] LSTM으로 영화 리뷰의 평점 예측하기 - imdb (2) | 2018.03.09 |
[Machine Learning] sklearn.metrics.confusion_matrix (0) | 2018.03.08 |
[Keras] CNN으로 MNIST 이미지 분류하기 (0) | 2018.03.04 |
Comments