Windows10 GPU 머신으로 GAN을 시험해 2/2(2.실행편)

Windows10 GPU 머신으로 GAN을 시험해 2.실행편(본 투고)에서는, 코드예와 함께, GAN의 실행 플로우를 기재합니다.
1. 설치편에서는 GAN을 실행하는 데 필요한 다양한 소프트웨어 설치 절차를 설명합니다.

전체 개요



다음 절차에 따라 실행 중입니다.


1. 사전 준비



1-1. 패키지 가져오기


%matplotlib inline

import pickle as pkl
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

1-2. 데이터 다운로드



이번에는 MNIST (필기 문자) 데이터를 사용합니다.
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data')

2. 정의



2-1. 입력 데이터 정의



자리 표시자를 만드는 함수를 정의합니다.
def model_inputs(real_dim, z_dim):
    inputs_real = tf.placeholder(tf.float32, (None, real_dim), name='input_real')
    inputs_z = tf.placeholder(tf.float32, (None, z_dim), name='input_z')

    return inputs_real, inputs_z

2-2. 제너레이터 디스크리미네이터 정의



발전기 정의
Leaky RELU를 max 함수로 표현하고 있습니다.
def generator(z,out_dim,n_units=128,reuse=False,alpha=0.01):
    with tf.variable_scope('generator',reuse=reuse):
        h1 = tf.layers.dense(z, n_units, activation=None)#全結合層
        h1 = tf.maximum(alpha * h1, h1) #Leaky RERU

        logits = tf.layers.dense(h1,out_dim,activation=None)#全結合層
        out = tf.tanh(logits)#画像なので-1~1の数字

        return out

디스크리미네이터 정의
def discriminator(x, n_units=128,reuse=False,alpha=0.01):
    with tf.variable_scope('discriminator',reuse=reuse):
        h1 = tf.layers.dense(x, n_units, activation=None)#全結合層
        h1 = tf.maximum(alpha * h1, h1) #Leaky RERU

        logits = tf.layers.dense(h1,1,activation=None)#全結合層
        out = tf.sigmoid(logits)#確率なので0~1の数字

        return out,logits

하이퍼파라미터 정의
input_size = 784 #28*28
z_size = 100 #Generatorに与えるランダムベクトルサイズ
g_hidden_size = 128#Generatorの隠れ層のノード数
d_hidden_size = 128#Discriminatorの隠れ層のノード数
alpha = 0.01 #Leaky RELUの傾き
smooth = 0.1 #Discriminatorの学習を円滑にする調整(確率が1に近づきすぎると学習が進まなくなることがあるため、0.9程度に抑えるための変数)

모델 정의
tf.reset_default_graph()
input_real, input_z = model_inputs(input_size, z_size)

g_model = generator(input_z, input_size, n_units=g_hidden_size, alpha=alpha)

d_model_real, d_logits_real = discriminator(input_real, n_units=d_hidden_size, alpha=alpha)
d_model_fake, d_logits_fake = discriminator(g_model, reuse=True, n_units=d_hidden_size, alpha=alpha)

2-3. 손실 함수 정의


d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_real,
                                            labels=tf.ones_like(d_logits_real)*(1 - smooth)))
d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,
                                            labels = tf.zeros_like(d_logits_real)))
d_loss = d_loss_real + d_loss_fake#本物をTrue, 偽物をFalseと判定する精度

#Generator #偽データが本物として分類されると成功
g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=d_logits_fake,
                                                               labels=tf.ones_like(d_logits_fake)))

2-4. 최적화 기법 정의


learning_rate = 0.002

t_vars = tf.trainable_variables()
g_vars = [var for var in t_vars if var.name.startswith('generator')]
d_vars = [var for var in t_vars if var.name.startswith('discriminator')]

d_train_optimize = tf.train.AdamOptimizer(learning_rate).minimize(d_loss, var_list=d_vars)
g_train_optimize = tf.train.AdamOptimizer(learning_rate).minimize(g_loss, var_list=g_vars)

3. 훈련



3-1. 훈련


epochs = 100
samples = []
losses = []
saver = tf.train.Saver(var_list=g_vars)#tensorflowの途中経過をファイルに保存する関数。generatorのパラメータ群を保存している。generatorのモデルで画像を生成することが可能になる。
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())#reset
    for e in range(epochs):
        for i in range(mnist.train.num_examples//batch_size):#各エポックのループ内でミニバッチ学習を行う回数 = サンプル総数/バッチサイズ
            batch = mnist.train.next_batch(batch_size)#ミニバッチ

            batch_images =  batch[0].reshape((batch_size, 784))  #batch_size(100行)*(784列)のデータセット
            batch_images = batch_images * 2 -1 #0~1の濃淡データを-1~1の値に変換。generatorから来るデータとrangeを揃える

            #Generator
            batch_z = np.random.uniform(-1,1,size=(batch_size, z_size))#一様分布

            #トレーニングを実行
            _ = sess.run(d_train_optimize, feed_dict={input_real:batch_images,input_z:batch_z})#最適化計算・パラメータ更新を行う
            _ = sess.run(g_train_optimize, feed_dict={input_z:batch_z})#最適化計算・パラメータ更新を行う
            # _=は、実行はするけど、値を保持しないときに使う

        train_loss_d = sess.run(d_loss,{input_z:batch_z, input_real:batch_images})#トレーニングのロスを計算
        train_loss_g = g_loss.eval({input_z: batch_z})

        print("エポック {}/{} ".format(e+1,epochs),
            "D ロス: {:.4f}".format(train_loss_d),
            "G ロス: {:.4f}".format(train_loss_g))

        losses.append((train_loss_d,train_loss_g))

        sample_z = np.random.uniform(-1,1,size=(16,z_size))
        gen_samples = sess.run(generator(input_z, input_size, n_units=g_hidden_size, reuse=True, alpha=alpha)
                              ,feed_dict={input_z:sample_z})#画像ファイルの生成
        samples.append(gen_samples)
        saver.save(sess,'./checkpoints/generator,ckpt')#途中経過を保存

with open('training_samples.pkl','wb') as f:
    pkl.dump(samples,f)


4. 평가



4-1. 손실 평가



수집 프로세스를 시각화합니다.
fig, ax = plt.subplots()
losses = np.array(losses)
plt.plot(losses.T[0], label='D')#Dロスのみを取得
plt.plot(losses.T[1], label='G')#Gロスのみを取得
plt.title('Train Loss')
plt.legend()

↓이런 느낌으로 손실 함수의 추이를 가시화할 수 있습니다.

※상기 그래프에 대해서
G는 손실이 떨어지고 정확도가 향상되었습니다.
D는 가짜를 가짜로 보는 정밀도가 올라 있기 때문에 좀처럼 개선되지 않는다.

4-2. 데이터 확인



생성기가 생성한 이미지를 시각화할 수 있습니다.
#イメージに変換して表示
def view_samples(epoch, samples):
    fig, axes = plt.subplots(figsize=(7,7),nrows=4, ncols=4, sharey=True, sharex=True)
    for ax,img in zip(axes.flatten(),samples[epoch]):
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)
        im = ax.imshow(img.reshape((28,28)),cmap='Greys_r')
    return fig, axes
with open('training_samples.pkl','rb')as f:
    samples = pkl.load(f)
_ = view_samples(-1, samples)
#samples[-1]なので、最終エポックのデータ

↓이런 느낌입니다.


또한 최종 에포크뿐만 아니라 학습중인 이미지 데이터의 추이를 시각화합니다.
#10エポックおきに、6個のデータを表示させる
rows,cols = 10, 6
#fig:グラフ全体、axes:個別指定表示要素
fig, axes = plt.subplots(figsize=(7,12), nrows=rows, ncols=cols,sharex=True, sharey=True)

for sample, ax_row in zip(samples[::int(len(samples)/rows)], axes): #サンプル数/10おき
    #100/6 = 15こおきに取り出す
    for img, ax in zip(sample[::int(len(samples)/cols)],ax_row):#::x x分だけインクリメント 指定幅でデータをsamplesから取り出す
        #数字の列を濃淡差として扱い、画像として表示する
        #784個の1次元ベクトルを28*28の2次元行列に変換
        ax.imshow(img.reshape((28,28)),cmap='Greys_r')
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)


10 에포크마다 이미지를 시각화하고 있습니다.


처음에는 거의 랜덤 노이즈입니다만, 학습해 가는 것으로, 점점 인간이 판별할 수 있는 화상이 되고 있습니다.

좋은 웹페이지 즐겨찾기