import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
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
coding_size = 10
input_layer = tf.keras.layers.Input(shape=[28, 28])
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)
codings_mean = tf.keras.layers.Dense(coding_size)(outputs)
codings_log_var = tf.keras.layers.Dense(coding_size)(outputs)
codings = Sampling()([codings_mean, codings_log_var])
#인코더
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])
dum, dum, codings = va_encoder(input_layer)
reconstuructions = va_decoder(codings)
vae = tf.keras.models.Model(inputs=[input_layer],
outputs=[reconstuructions])
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)
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알고리즘에서 생성기가 학습할 동안에 판별기에 영향을 끼치면 안되기 때문.
discriminator.trainable = False
gan.compile(loss='binary_crossentropy', optimizer='rmsprop')
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)