#차원을 축소했다가 증폭했다는 개념
#pca - 1. 차원축소, 2. 특성추출 - 즉, 중요한 부분빼고는 지워진다
#즉 오토인코더를 사용하면 차원축소, 특성추출이 가능하다
#cifar10 으로 만들기
import numpy as np
from tensorflow.keras.datasets import mnist, cifar10

# (x_train, y_train), (x_test, y_test) = mnist.load_data()
(x_train, _ ), (x_test, _ ) = cifar10.load_data()

print(x_train.shape) #(50000, 32, 32, 3)
print(x_test.shape) #(10000, 32, 32, 3)

x_train = x_train.reshape(50000,3072).astype('float32')/255.
x_test = x_test.reshape(10000,3072)/255.

x_train_noised = x_train + np.random.normal(0, 0.1, size=x_train.shape)
x_test_noised = x_test + np.random.normal(0, 0.1, size=x_test.shape)

x_train_noised = np.clip(x_train_noised, a_min=0, a_max=1)
x_test_noised = np.clip(x_test_noised, a_min=0, a_max=1)


from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Input

def autoencoder(hidden_layer_size):
    model = Sequential()
    model.add(Dense(units=hidden_layer_size, input_shape=(3072,), activation='relu'))
    model.add(Dense(32))
    model.add(Dense(64))
    model.add(Dense(128))
    model.add(Dense(256))
    model.add(Dense(units=3072, activation='sigmoid'))
    return model

model = autoencoder(hidden_layer_size=3072)

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])

model.fit(x_train_noised, x_train, epochs=10)

output = model.predict(x_test_noised)

from matplotlib import pyplot as plt
import random

fig, ((ax1, ax2, ax3, ax4, ax5), (ax6, ax7, ax8, ax9, ax10), (ax11, ax12, ax13, ax14, ax15)) = plt.subplots(3, 5, figsize=(20,7))


#이미지 5개를 무작위로 고른다
random_images = random.sample(range(output.shape[0]), 5)

#원본(입력) 이미지를 맨 위에 그린다datetime A combination of a date and a time. Attributes: ()
for i, ax in enumerate([ax1, ax2, ax3, ax4, ax5]):
    ax.imshow(x_test[random_images[i]].reshape(32,32,3), cmap='gray')
    if i == 0:
        ax.set_ylabel("INPUT", size=20)
    ax.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])

#잡음을 넣은 이미지
for i, ax in enumerate([ax6, ax7, ax8, ax9, ax10]):
    ax.imshow(x_test_noised[random_images[i]].reshape(32,32,3), cmap='gray')
    if i == 0:
        ax.set_ylabel("NOISE", size=20)

    ax.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])

#오토 인코더가 출력한 이미지를 아래에 그린다

for i, ax in enumerate([ax11, ax12, ax13, ax14, ax15]):
    ax.imshow(output[random_images[i]].reshape(32,32,3), cmap='gray')
    if i == 0:
        ax.set_ylabel("OUTPUT", size=20)

    ax.grid(False)
    ax.set_xticks([])
    ax.set_yticks([])

plt.tight_layout()
plt.show()
