AutoEncoder

68747470733a2f2f692e696d6775722e636f6d2f396a625442324f2e706e67 (1).png

AutoEncoder 의 활용

Example 1: 축소 후 복원

print(x_train.shape)  
# flatten으로 펴주면 (28*28) = 784 차원이 된다. 잠재벡터는 이것보다 작으면 되고 정하는 사람 마음 
print(x_test.shape)

(60000, 28, 28)
(10000, 28, 28)
# 잠재 벡터(Latent vector)의 차원 수를 정해줍니다.
LATENT_DIM = 64 

class Autoencoder(Model):
    def __init__(self, latent_dim):
        super(Autoencoder, self).__init__()
        self.latent_dim = latent_dim   
        self.encoder = tf.keras.Sequential([ # 줄여주는 역할 
            layers.Flatten(), #인코더 부분에서 벡터로 
            layers.Dense(latent_dim, activation='relu'), 
            #덴스층 레이턴트 디멘젼, 벡터의 차원대로 줄여줌 
        ])
        self.decoder = tf.keras.Sequential([   # 늘려주는 역할 
            layers.Dense(784, activation='sigmoid'), # 784 차원으로 늘림 
            layers.Reshape((28, 28)) # 28, 28 으로 리쉐이프 
        ])

    def call(self, x): #디코딩 된 결과를 돌려줌
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

model = Autoencoder(LATENT_DIM)
model.fit(x_train, x_train,
          epochs=10,
          shuffle=True,
          validation_data=(x_test, x_test))

# 5. **학습된 모델을 사용하여 시험(`test`) 이미지를 인코딩 후 디코딩하여줍니다.**
# 이후 특정 10개의 이미지를 시각화하여 잘 복원되었는지 확인해봅니다.

encoded_imgs = model.encoder(x_test).numpy()   #테스트 이미지 인코딩 후 디코딩 
decoded_imgs = model.decoder(encoded_imgs).numpy()

n = 10

plt.figure(figsize=(20, 4))

for i in range(n):
    # 원본 이미지를 출력합니다.
    ax = plt.subplot(2, n, i + 1)
    plt.imshow(x_test[i])
    plt.title("Original")
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # AutoEncoder에 의해서 복원된 이미지를 출력합니다.
    # 원본보다는 해상도가 뜰어짐. 압축 후 다시 늘려놓은 거. 
    # 어느 정도의 형태를 보존이 된다. 
    
    ax = plt.subplot(2, n, i + 1 + n)
    plt.imshow(decoded_imgs[i])
    plt.title("Reconstructed")
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

plt.show()

스크린샷 2022-04-02 오후 2.13.51.png

Example 2 - Denoising AutoEncoder

# 원본에 있는 노이즈를 제거하는 것 
# 완전 연결이 아닌 컨볼루션.. 
# 임의의 채널을 추가해서 차원을 맞춘다. 

(x_train, _), (x_test, _) = fashion_mnist.load_data()
x_train = x_train.astype('float32') / 255. # 정규화 
x_test = x_test.astype('float32') / 255.

x_train = x_train[..., tf.newaxis]  #새로운 차원을 추가. 왜?? 
x_test = x_test[..., tf.newaxis]

print(x_train.shape) #1이 추가 됨..
(60000, 28, 28, 1)

noise_factor = 0.2
x_train_noisy = x_train + noise_factor * tf.random.normal(shape=x_train.shape) 
x_test_noisy = x_test + noise_factor * tf.random.normal(shape=x_test.shape) 

x_train_noisy = tf.clip_by_value(x_train_noisy, clip_value_min=0., clip_value_max=1.)
x_test_noisy = tf.clip_by_value(x_test_noisy, clip_value_min=0., clip_value_max=1.)

n = 10
plt.figure(figsize=(20, 2))
for i in range(n):
    ax = plt.subplot(1, n, i + 1)
    plt.title("Original + Noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
plt.show()

# 원본 이미지에 꽤나 노이즈가 추가됨.

스크린샷 2022-04-02 오후 2.25.14.png

# Denoising AuotoEncoder 모델을 구축 

class Denoise(Model):
    def __init__(self):
        super(Denoise, self).__init__()
        self.encoder = tf.keras.Sequential([
            layers.Input(shape=(28, 28, 1)), 
            layers.Conv2D(16, (3,3), activation='relu', padding='same', strides=2),  #다운 샘플링 
            layers.Conv2D(8, (3,3), activation='relu', padding='same', strides=2)])
        
        self.decoder = tf.keras.Sequential([
            layers.Conv2DTranspose(8, kernel_size=3, strides=2, activation='relu', padding='same'), #conv2dtrans를 통해서 원래 이미지 크기로 리턴 
            layers.Conv2DTranspose(16, kernel_size=3, strides=2, activation='relu', padding='same'),
            layers.Conv2D(1, kernel_size=(3,3), activation='sigmoid', padding='same')])
        
    def call(self, x):
        encoded = self.encoder(x)
        decoded = self.decoder(encoded)
        return decoded

model = Denoise() # 구성한 클래스를 객체로 받기

model.compile(optimizer='adam', loss='mse')
model.fit(x_train_noisy, x_train,  # 좌 노이즈, 우 원본...  타겟은 원본 있는 데이터로부터 없는 데이터를 학습? 
          epochs=10,
          shuffle=True,
          validation_data=(x_test_noisy, x_test))

encoded_imgs = model.encoder(x_test).numpy()
decoded_imgs = model.decoder(encoded_imgs).numpy()

n = 10
plt.figure(figsize=(20, 4))
for i in range(n):

    # Noise가 추가된 원본 이미지를 출력합니다.
    ax = plt.subplot(2, n, i + 1)
    plt.title("Original + Noise")
    plt.imshow(tf.squeeze(x_test_noisy[i]))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)

    # AutoEncoder에 의해서 복원된 이미지를 출력합니다.
    bx = plt.subplot(2, n, i + n + 1)
    plt.title("Reconstructed")
    plt.imshow(tf.squeeze(decoded_imgs[i]))
    plt.gray()
    bx.get_xaxis().set_visible(False)
    bx.get_yaxis().set_visible(False)
plt.show()