GAN(Generative Adversarial Networks) 모델, VAE

BodeulMaNN·2023년 4월 5일
0

VAE $ GAN

VAE 변이형 오토 인코더

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

VAE 수식

K = tf.keras.backend
class Sampling(tf.keras.layers.Layer):
def call(self, input):
mean, log_var = input
return K.random_normal(tf.shape(log_var)) * K.exp(log_var/2) + mean

VAE : 변이형 오토 인코더

coding_size = 10
input_layer = tf.keras.layers.Input(shape=[28, 28])

2차원 데이터 이기 때문에 펴줘야 함.

outputs = tf.keras.layers.Flatten()(input_layer)
outputs = tf.keras.layers.Dense(150, activation='selu')(outputs)
outputs = tf.keras.layers.Dense(100, activation='selu')(outputs)

평균을 구해줘야함. VAE에서 평균을 구해서 이미지를 복구하기 때문

codings_mean = tf.keras.layers.Dense(coding_size)(outputs)

VAE가 수학적 모델이기 때문에 시그마를 표현하기 위해 log 사용.

codings_log_var = tf.keras.layers.Dense(coding_size)(outputs)
codings = Sampling()([codings_mean, codings_log_var])

VAE 생성

#인코더
va_encoder = tf.keras.models.Model( inputs=[input_layer],
outputs=[codings_mean, codings_log_var, codings])

디코더

decoder_inputs = tf.keras.layers.Input(shape=[coding_size])
outputs = tf.keras.layers.Dense(100, activation='selu')(decoder_inputs)
outputs = tf.keras.layers.Dense(150, activation='selu')(outputs)
outputs = tf.keras.layers.Dense(28*28, activation='sigmoid')(outputs)
outputs = tf.keras.layers.Reshape([28,28])(outputs)
va_decoder = tf.keras.models.Model(inputs=[decoder_inputs],
outputs=[outputs])

VAE 변분 오토 인코더

dum, dum, codings = va_encoder(input_layer)
reconstuructions = va_decoder(codings)
vae = tf.keras.models.Model(inputs=[input_layer],
outputs=[reconstuructions])

VAE 수식

latent_loss = -0.5*K.sum(
1+ codings_log_var - K.exp(codings_log_var) - K.square(codings_mean), axis=1
)
vae.add_loss(K.mean(latent_loss)/784.0)

accuracy 메트릭스 함수 생성.

def my_accuracy(y_true, y_pred):
return tf.keras.metrics.binary_accuracy(tf.round(y_true), tf.round(y_pred))

컴파일

vae.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=[my_accuracy])

history = vae.fit(X_train_sc, X_train_sc, epochs = 25, batch_size = 64,
validation_data=(X_train_sc, X_train_sc))

#VAE shape 확인하기
res = vae.predict(X_test_sc[:5])
res.shape

#VAE 정확도 시각화 하기
plt.plot(history.history['my_accuracy'])
plt.plot(history.history['val_my_accuracy'])

#원본과 VAE 결과 비교
#평균치라서 결과가 흐릿 함. / coding_size(신경망 갯수) = 10 일때.
i = 0
plt.subplot(141)
plt.imshow(X_test_sc[i], 'gray')
plt.subplot(142)
plt.imshow(res[i], 'gray')
plt.subplot(143)
plt.imshow(X_test_sc[i+1], 'gray')
plt.subplot(144)
plt.imshow(res[i+1], 'gray')

=========================================== GAN알고리즘 ====================================
'''
갠 알고리즘은 원본 데이터를 토대로 공간백터에서 디코딩(생성자)을 통해 새로운 가상이미지를 생성(generative) 하고
원본과 라이벌 관계를 형성해서 판별기에게 원본과 가상이미지를 대조한 다음 무엇이 실제 이미지인지 예측시키고 둘중에
판별기가 옳다고 한 결과에 대해서 결과를 출력한다. (이 과정에서 생성자는 실물에 가깝도록 반복해서 훈련시키고 판별기에게
지속적으로 검사를 맡는다.)

역전파 : 판별기가 생성기에게 답에 가깝게 생성할 수 있도록 피드백을 계속 해줌.

'''

codings_size = 30

생성자 모델

generator = tf.keras.models.Sequential([

# 랜덤값 30을 인풋shape로 넣어줌.
tf.keras.layers.Dense(100, activation='selu', input_shape=[codings_size]),
tf.keras.layers.Dense(150, activation='selu'),
# 마지막은 판별기에게 진짜 사진처럼 보여줘야하기 때문에 sigmoid로 합쳐줌.
tf.keras.layers.Dense(28*28, activation='sigmoid'),
# 위와 마찬가지로 판별기에게 판별 맡기기 위해 원래 값으로 돌려줌.
tf.keras.layers.Reshape([28, 28])

])

판별기 모델

discriminator = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=[28,28]),
tf.keras.layers.Dense(150, activation='selu'),
tf.keras.layers.Dense(100, activation='selu'),
tf.keras.layers.Dense(1, activation='sigmoid')
])
gan = tf.keras.models.Sequential([ generator, discriminator ])

discriminator.compile(loss='binary_crossentropy', optimizer='rmsprop')
#판별기는 학습 시키지 않음. GAN알고리즘에서 생성기가 학습할 동안에 판별기에 영향을 끼치면 안되기 때문.

GAN알고리즘에 생성기와 판별기 둘다 묶여있기 때문에 이렇게 해주는 것임.

discriminator.trainable = False
gan.compile(loss='binary_crossentropy', optimizer='rmsprop')

batch는 묶어주는거임. 32개씩 묶어달라는 소리

batch_size = 32
dataset = tf.data.Dataset.from_tensor_slices(X_train_sc).shuffle(1000)
dataset = dataset.batch(batch_size, drop_remainder=True).prefetch(1)

#model.fit 처럼 학습 시킬건데 일반 모델 돌리듯이 학습 X (구조가 너무 복잡함)
def train_gan(gan, dataset, batch_size, codings_size, n_epochs):
generator, discriminator= gan.layers #생성자와 판별자를 겐 신경망에서 받아옴
for epoch in range(n_epochs):
print(f'Epoch {epoch+1} of {n_epochs}')
for X_batch in dataset:
print('=', end='', )

        # step 1 : discriminator 학습 수행 (라이벌 관계라서 여기에선 학습 시켜줘야 함.)
        noise = tf.random.normal(shape=[batch_size, codings_size])
        generated_img = generator(noise)
        # 진짜 그림과 가상이미지를 합쳐줌. 판별자에게 맡겨야 하기 때문
        X_mixed = tf.concat([generated_img, X_batch], axis=0)
        y1 = tf.constant([[0.]] * batch_size + [[1.]] * batch_size)
        #여기서 판별기의 학습능력을 잠시 on
        discriminator.trainable = True
        discriminator.train_on_batch(X_mixed, y1)
        # step 2 : generator 학습 수행 (gan학습: 판별자의 감시 하에 전체 학습)
        # 비교를 위해 다시 판별기의 학습능력 off
        discriminator.trainable = False
        noise = tf.random.normal(shape=[batch_size, codings_size])
        y2 = tf.constant([[1.]] * batch_size)
        gan.train_on_batch(noise, y2)
    # 시각화
    for index in range(32):
        row = index//8 +1
        col = index%8 +1
        plt.subplot(4, 8, index+1)
        plt.imshow(generated_img[index], 'gray')
    print('>', end="\n")

#gan 학습
train_gan(gan, dataset, batch_size, codings_size, 3)

profile
반갑습니다

0개의 댓글