인공지능02

서유리·2022년 3월 31일
1

AI_Study

목록 보기
2/25
post-thumbnail

02-텐서플로를 이용한 GAN 구현하기

2-1. 텐서플로를 이용한 GAN을 구현하는 방법

  • 가중치 초기화하기
  • GAN 구축
  • GAN 학습

2-2. GAN : 오토인코더와 마찬가지로 대표적인 자율 학습 모델의 하나임

  • 위폐범과 경찰이 연관된 위조화폐 제작과 감별을 GAN으로 구현
  • 조건은 다음과 같음 :
  • 위폐범은 위조화폐를 정교하게 만들고자 최선을 다함. 즉, 경찰이 위조화폐를 감별하지 못할 확률을 높이려고 노력함
  • 경찰은 위폐를 감별하는데 최선을 다함. 즉, 자신이 실수할 확률을 낮추려고 노력함
  • 위폐범(G)의 네트워크를 생성 네트워크(Generative Network)라고 함
  • 경찰(D)의 네트워크를 식별 네트워크(Discriminator Network)라고 함
  • G는 D가 실수할 확률을 높이려고 노력(maximize)하고, D는 자신의 실수 확률을 낮추려고 노력(minimize)하므로, 이는 미니맥스 문제(minimax problem)임
  • GAN에서는 어려운 확률분포를 다루지 않고 확률을 통해 생성한 샘플을 다룸
  • G는 Z를 입력받으므로 G(Z)라고 함. 이때 Z는 확률분포와 맵핑하는 prior라는 개념임. 무작위 노이즈(Random noise)가 됨
  • G(Z)의 결과는 위폐화폐임
  • D는 이미지 X를 입력받으므로 D(X)라고 함. D(X)의 결과물은 0~1 사이의 확률임
  • 양자의 균형을 맞추는 평행 상태에 이르면 G는 진짜 화폐와 100% 같은 위조화폐를 만들어 D가 이를 감별할 확률은 0.5임

🟡 필요한 모듈 불러오기

# 필요한 모듈을 불러오기 MNIST 데이터를 저장함
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
import os

mnist = tf.keras.datasets.mnist.load_data(
    path='mnist.npz')

🟡 가중치 초기화

# 가중치의 초기화에 좋은 성능을 보이는 세이비어 초기화(xavier initialization)를 함수로 만들어서 이용함
def xavier_init(size):
    in_dim = size[0]
    xavier_stddev = 1. / tf.sqrt(in_dim / 2.)
    return tf.random_normal(shape = size, stddev = xavier_stddev)

# compatibility mode를 적용해 1.x 버전의 기능을 그대로 사용할 수 있음 
# 위와 같이 tf.disable_v2_behavior()를 실행해서 tf.placeholder를 그대로 사용할 수 있음
import tensorflow.compat.v1 as tf 
tf.disable_v2_behavior()

# 확률을 출력하는 식별 네트워크에서 사용할 가중치를 설정함
# 노드 수는 784 -> 128 -> 1의 순서로 줄임

# 식별 네트워크
X = tf.placeholder(tf.float32, shape = [None, 784], name = 'X')

W1_dis = tf.Variable(xavier_init([784, 128]), name = 'W1_dis')
b1_dis = tf.Variable(tf.zeros(shape=[128]), name = 'b1_dis')

W2_dis = tf.Variable(xavier_init([128, 1]), name = 'W2_dis')
b2_dis = tf.Variable(tf.zeros(shape=[1]), name = 'b2_dis')

theta_dis = [W1_dis, W2_dis, b1_dis, b2_dis]
  • 이미지를 출력하는 생성 네트워크에서 사용할 가중치를 설정함
  • 노드 수는 100 -> 128 -> 784의 순서로 줄임
# 생성 네트워크
Z = tf.placeholder(tf.float32, shape = [None, 100], name = 'Z')

W1_gen = tf.Variable(xavier_init([100, 128]), name = 'W1_gen')
b1_gen = tf.Variable(tf.zeros(shape=[128]), name = 'b1_gen')

W2_gen = tf.Variable(xavier_init([128, 784]), name = 'W2_gen')
b2_gen = tf.Variable(tf.zeros(shape=[784]), name = 'b2_gen')

theta_gen = [W1_gen, W2_gen, b1_gen, b2_gen]
  • 생성 네트워크에서 Z를 무작위로 생성하는 함수를 정의함
  • 그래프 구축을 완료한 이후 실행할 때, 사용하려고 미리 정의해둔 것임
def random_Z(z1, z2):
    return np.random.uniform(-1., 1., size = [z1, z2])

🟡 생성 네트워크 구축

# 생성 네트워크를 구축함
# 이미지 출력
def gen(z):
    h1_gen = tf.nn.relu(tf.matmul(z, W1_gen) + b1_gen)
    log_prob_gen = tf.matmul(h1_gen, W2_gen) + b2_gen
    prob_gen = tf.nn.sigmoid(log_prob_gen)
    
    return prob_gen

🟡 식별 네트워크 구축

# 식별 네트워크를 구축함 
# 확률을 출력하게 하는 것임
def dis(x):
    h1_dis = tf.nn.relu(tf.matmul(x, W1_dis) + b1_dis)
    logit_dis = tf.matmul(h1_dis, W2_dis) + b2_dis
    prob_dis = tf.nn.sigmoid(logit_dis)
    
    return prob_dis, logit_dis
    
# plot 함수는 16개의 이미지를 4x4 형태로 보여줌
# 그래프 구축을 완료한 이후 실행할 때, 사용하려고 미리 정의해둔 것임
def plot(samples): 
    fig = plt.figure(figsize = (4, 4))
    grid = gridspec.GridSpec(4, 4)
    grid.update(wspace = 0.1, hspace = 0.1)
    
    for i, sample in enumerate(samples):
        ax = plt.subplot(grid[i])
        plt.axis('off')
        ax.set_xticklabels([])
        ax.set_yticklabels([])
        ax.set_aspect('equal')
        plt.imshow(sample.reshape(28, 28), cmap = 'gray')
        
    return fig

🟡 GAN 학습하기

# GAN을 학습시키기 위한 Adversarial 과정을 선언함
sample_gen = gen(Z)
real_dis, logit_real_dis = dis(X)
fake_dis, logit_fake_dis = dis(sample_gen)

loss_real_dis = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
    logits = logit_real_dis, labels = tf.ones_like(logit_real_dis)))
loss_fake_dis = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
    logits = logit_fake_dis, labels = tf.zeros_like(logit_fake_dis)))
loss_dis = loss_real_dis + loss_fake_dis
loss_gen = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(
    logits = logit_fake_dis, labels = tf.ones_like(logit_fake_dis)))

solver_dis = tf.train.AdamOptimizer().minimize(loss_dis, var_list=theta_dis)
solver_gen = tf.train.AdamOptimizer().minimize(loss_gen, var_list=theta_gen)

# 그래프 실행
batch_size = 128
dim_Z = 100

sess = tf.Session()
sess.run(tf.global_variables_initializer())

i = 0

for j in range(100000):
    if j % 2000 == 0:
        samples = sess.run(sample_gen, feed_dict={Z: random_Z(16, dim_Z)})
        fig = plot(samples)
        plt.show()
        i += 1
        plt.close(fig)
        
        
    X_batch, _ = mnist.train.next_batch(batch_size)
    
    _, loss_curr_dis = sess.run([solver_dis, loss_dis],
                                feed_dict={X: X_batch, Z: random_Z(batch_size, dim_Z)})
    _, loss_curr_gen = sess.run([solver_gen, loss_gen],
                               feed_dict={Z: random_Z(bath_size, dim_Z)})
    if j % 2000 == 0:
        print('Iteration: {}'.format(j))
        print('Discriminator loss: {:.3}'. format(loss_curr_dis))
        print('Generator loss: {:.3}'. format(loss_curr_gen))
        print()

profile
best of best

0개의 댓글