1. AutoEncoder 란?

  • 자기 자신을 학습하는 Unsupervised Learning

    • 입력과 출력층의 뉴런 수가 동일
    • encoder 부분만 분리하면 Clustering model이 됨
    • decoder 부분만 만들면 Generation model이 됨
    • AutoEncoding 과정에 de-noising 처리됨(인코딩 과정에서 입력된 데이터의 핵심 Feature 정보만 Hidden Layer에서 학습하고, 나머지 정보는 손실시킴. 디코딩 과정에서 Hidden Layer의 출력값을 뽑았을 때 완벽한 값 복사가 아닌 입력값의 근사치가 됨)

    AutoEncoder

  • AutoEncoder 종류 : https://iq.opengenus.org/types-of-autoencoder

2. Encoder/Decoder란?

  • Encoder란?
    • 일반적 의미 : 물리 환경으로부터 피드백을 제공하는 센서 장치
    • 데이터 과학에서의 의미 : 분석을 위해 데이터를 부호화
    • set() Operation을 통해 속성을 추출하고, 순번을 매핑한 결과가 Encoder임
  • Decoder란?
    • Encoding된 데이터를 원래의 형태로 복원함
    • Encoder의 Key:Value를 뒤집은 결과가 Decoder임(Key가 Value가 되고, Value가 Key가 됨)
  • Encoder는 set() 함수로 Key를 추출한 후 dict() 객체를 직접 만들어서 구현할 수도 있고, Scikit-Learn의 preprocessing.LabelEncoder()를 사용하여 fit()으로 생성할 수도 있음

2.1 Encoder/Decoder 직접 만들기

  # Encoder 만들기
  data = ["ACCOUNTING","RESEARCH", "SALES", "RESEARCH", "RESEARCH"]
  enc = { k:v for v,k in enumerate( set(data))}
  print(enc['SALES'])    # 0

  # Decoder 만들기
  dec = { v:k for v,k in enumerate(set(data)) }
  print(dec[0])     # 'SALES'

2.2 Encoder/Decoder 사용하기

  enc_data = [ enc[i] for i in data]
  print(enc_data)     # [2, 1, 0, 1, 1]
  
  dec_data = [ dec[i] for i in enc_data ]
  print(dec_data)     # ['ACCOUNTING', 'RESEARCH', 'SALES', 'RESEARCH', 'RESEARCH']

2.3 Scikit-Learn 기반 Encoding/Decoding

  # Encoder/Decoder 생성
  from sklearn import preprocessing
  le = preprocessing.LabelEncoder()
  data = ["ACCOUNTING","RESEARCH", "SALES", "RESEARCH", "RESEARCH"]
  le.fit(data)   # Encoder/Decoder가 학습됨
  # Record 확인
  le.classes_     # array(['ACCOUNTING', 'RESEARCH', 'SALES'], dtype='<U10')
  # Encoding
  le.transform(data)    # array([0, 1, 2, 1, 1])
  # Decoding
  le.inverse_transform([0, 0, 1, 2])    # array(['ACCOUNTING', 'ACCOUNTING', 'RESEARCH', 'SALES'], dtype='<U10')

3. Keras AutoEncoder on Iris Dataset

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

# Importing Data
data = pd.read_csv("iris.csv")
display(data.head())

x_train, x_test, y_train, y_test = train_test_split(data[['Sepal.Length', 'Sepal.Width',
                                  'Petal.Length', 'Petal.Width']],
                                  data['Species'],test_size=0.1, random_state=1)
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.callbacks import TensorBoard
from tensorflow.keras.optimizers import RMSprop

# this is the size of our encoded representations
encoding_dim1 = 6
encoding_dim2 = 4
encoding_dim3 = 2
input_dim = 4

# this is our input placeholder
input_img = Input(shape=(input_dim,))

# "encoded" is the encoded representation of the input
encoded = Dense(encoding_dim1)(input_img)
encoded = Dense(encoding_dim2)(encoded)
encoded = Dense(encoding_dim3)(encoded)

# "decoded" is the lossy reconstruction of the input
decoded = Dense(encoding_dim2)(encoded)
decoded = Dense(encoding_dim1)(decoded)
decoded = Dense(input_dim)(decoded)
# AutoEncoder 모델 생성(this model maps an input to its reconstruction)
autoencoder = Model(input_img, decoded)
# Encoder 모델 생성(this model maps an input to its encoded representation)
encoder = Model(input_img, encoded)
# Decoder 모델 생성
# create a placeholder for an encoded (2-dimensional) input
encoded_input = Input(shape=(encoding_dim3,))

# retrieve the last layer of the autoencoder model
decoder_layer = autoencoder.layers[-3](encoded_input)
decoder_layer = autoencoder.layers[-2](decoder_layer)
decoder_layer = autoencoder.layers[-1](decoder_layer)

# create the decoder model
decoder = Model(encoded_input, decoder_layer)
# compile
opt=RMSprop(lr=0.001)
autoencoder.compile(loss='mean_squared_error', optimizer=opt)
autoencoder.summary()
# training
autoencoder.fit(x_train, x_train,
              epochs=333,
              batch_size=123,
              shuffle=True,
              validation_data=(x_test, x_test),
              callbacks=[])

# encode and decode some data points
# note that we take them from the *test* set
encoded_datapoints = encoder.predict(x_test)
decoded_datapoints = decoder.predict(encoded_datapoints)

# print('Original Datapoints :')
# print(x_test)
# print('Reconstructed Datapoints :')
# print(decoded_datapoints)
# Plotting Encoded Features
encoded_dataset = encoder.predict(x_test[['Sepal.Length', 'Sepal.Width',
                                  'Petal.Length', 'Petal.Width']])
# Encode Dataset
plt.scatter(encoded_dataset[:,0], encoded_dataset[:,1], c=y_test.astype('category').cat.codes)
plt.show()
# Decoded Dataset(reconstruncted)
decoded_dataset=decoder.predict(encoded_dataset)
plt.scatter(decoded_dataset[:,2], decoded_dataset[:,3], c=y_test.astype('category').cat.codes)
plt.show()
# Orignal Data
plt.scatter(x_test['Petal.Length'], x_test['Petal.Width'],c=y_test.astype('category').cat.codes)
plt.show()

4. AutoEncoder 응용사례

4.1 Anomaly Detection

  • 정상 데이터에 비해 비정상 데이터 수가 너무 적으면(1만배 이상 차이가 나면) 지도학습으로 학습이 잘 안됨
  • AutoEncoder 모델로 정상을 학습 -> 구현시 재구성 Error가 크면 비정상 이라고 간주함

4.2 Denoising Autoencoder

  • 오토인코더가 의미있는 특성(feature)을 학습하도록 제약을 주기 위해 입력에 노이즈(noise, 잡음)를 추가
  • 노이즈가 없는 원본 입력을 재구성하도록 학습시키는 것
  • 노이즈 발생 방법
    • 입력에 가우시안(Gaussian) 노이즈를 추가
    • 드롭아웃(dropout)처럼 랜덤하게 입력 유닛(노드)를 끔