๋์๋ฆฌ,ํํ/GDGoC
[AI ์คํฐ๋] Section 10 : Autoencoder
egahyun
2024. 12. 27. 02:55
์ฐจ์์ ๊ฐ์
: most relevant feature ์ถ์ถ
- PCA : linear transformation → ์ ํ๋์ ์ฌ์ฉ
- Autoencoder : non-linear transformation → ๋น์ ํ activation ํจ์๊ฐ ๋ด๋ฐ์ ๋ค์ด๊ฐ ์๊ธฐ๋๋ฌธ์
์ ์ฉ ๋ถ์ผ
⇒ structed data, unstructed data ๋ญ๋ ์๊ด์์
- ์ ๋ณด์ ์์ถ
- ๋ ธ์ด์ฆ ์ ๊ฑฐ : ๋ถํ์ํ ์ ๋ณด๋ฅผ ์์ค์ํค๋๋ก
- ์ ์ฌํ ์ด๋ฏธ์ง ๊ฒ์
- ์ด๋ฏธ์ง ๋ณํ์ ์ํ ์๋ก์ด ์ด๋ฏธ์ง ์์ฑ
- pre-training : ๋ ธ์ด์ฆ ์ ๊ฑฐ๋ก ๋ถํ์ํ๊ฑฐ ์ง์ฐ๊ณ ์์ํ๋ค.
์์ ) ์ด๋ฏธ์ง autoencoder

- input ์ด๋ฏธ์ง๋ฅผ ๋ฐ์์ ์ฐจ์์ถ์๋ฅผ ์งํ
⇒ ์ค์ด๋๋ ํํ๋ก ๋ด๋ด ๋คํธ์ํฌ ๊ตฌํ - reconstructed ์ด๋ฏธ์ง(์๋์ ์ด๋ฏธ์ง)๋ก ์ฌ๊ตฌ์ฑ (=๋ณต์)
⇒ ์ ํํ ์๋ ์ด๋ฏธ์ง๋ก ๋์ค์ง ์์ (์ฝ๊ฐ ๋ธ๋ฌ๋ ํํ)
⇒ ์ด๋ฏธ์ง์ ๊ผญ ํ์ํ ์ ๋ณด๋ค์ ๋ค ๋จ์ (์ด์ : ์๋ณธ ์ด๋ฏธ์ง์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ๋์ค๋๋ก ์ค๊ฐ์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ ๋ฐ์ดํธ ํ๊ธฐ ๋๋ฌธ )
์ ์ฌํํ (latent representation)
: ์ฌ๋์ด ์ ์ ์๋ ์จ๊ฒจ์ง ๋ฐ์ดํฐ ํจํด
⇒ ๋จธ์ ๋ฌ๋์ด ์ด๋ฅผ ์ ์ก์๋ธ๋ค. (⇒ ๋ฅ๋ด๋ด ๋คํธ์ํฌ์ ์๊ณ ๋ฆฌ์ฆ)
๊ธฐ๋ณธ ๊ตฌ์กฐ


- ์์ถ
- ๋ฐฉ๋ฒ : ์ด๋ฏธ์ง์ ๊ฐ์ ๊ณ ์ฐจ์ ๋ฐ์ดํฐ๋ฅผ ์ธ์ฝ๋ฉ์ ํตํด ์ ์ฐจ์์ hidden ๊ณต๊ฐ์ผ๋ก ํํ
⇒ Bottleneck (= latent space, ์ ์ฌ๊ณต๊ฐ, ํผ์ฒ, ์ฝ๋) ์ด ์ด๋ฃจ์ด์ง - ํ๋ ํจํด : ์ ์ฌ ํํ์ ํ์ตํ๋ ์จ๊ฒจ์ง ํจํด
- ์ธ์ฝ๋ : ํ๋ ํจํด์ ํ์ตํ๋ ๋ด๋ด ๋คํธ์ํฌ ๋ถ๋ถ
- ๋ฐฉ๋ฒ : ์ด๋ฏธ์ง์ ๊ฐ์ ๊ณ ์ฐจ์ ๋ฐ์ดํฐ๋ฅผ ์ธ์ฝ๋ฉ์ ํตํด ์ ์ฐจ์์ hidden ๊ณต๊ฐ์ผ๋ก ํํ
- ๋ณต์
- ๋ฐฉ๋ฒ : Latent Variable ์ ์ ๋ณด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์๋์ ์ด๋ฏธ์ง๋ฅผ ๋ณต์ํ๋ ๊ณผ์ ์ํ
- ๋์ฝ๋ : ์์ถ๋ ๋ฐ์ดํฐ๋ฅผ ์๋๋ก ๋ณต์์ํค๋ ๋ด๋ด ๋คํธ์ํฌ ๋ถ๋ถ
- ์๋ ๋ฐฉ์
: ๋น์ง๋ํ์ต ๋ฌธ์ ๋ฅผ ์ง๋ํ์ต ๋ฌธ์ ๋ก ๋ฐ๊พธ์ด ํด๊ฒฐ ⇒ y๊ฐ ์์ผ๋ฏ๋ก ์์ ์ ๋ ์ด๋ธ๋ก ์ฌ์ฉ
์ธ์ฝ๋ : \( G_\theta \) / ๋์ฝ๋ : \( F_\phi \) ⇒ ์ธํ์ ํ์ด๋ก ํ ์ด์ : ํ๋ผ๋ฏธํฐ๋ฅผ ๊ตฌ๋ถํ๊ธฐ ์ํด
- ์คํ ์ธ์ฝ๋ ํ์ต ๋ฐฉ๋ฒ : backpropagation(์ค์ฐจ์ญ์ ํ) + gradient descent(๊ฒฝ์ฌํ๊ฐ๋ฒ)
⇒ ์ ๋ต ๋ ์ด๋ธ : ์๊ธฐ ์์
⇒ ๊ฒฝ์ฌํ๊ฐ๋ฒ ํ์ต : ๋ชจ๋ธ์ด ์์ธกํ ๊ฐ, ์๊ณ ์๋ ์ ๋ต ๊ฐ๊ณผ ๋น๊ตํ ์ค์ฐจ๋ฅผ ์ค์ด๋ ๋ฐฉํฅ์ผ๋ก ์งํ - ์์คํจ์
$$L(x, y) = \|X - \hat{X}\|^2$$
: ์๋ณธ๊ฐ - ์์ธกํ๊ฐ์ ํ๊ท ์ ๊ณฑ ์ค์ฐจ (MSE)
: MSE (์ ๋ ฅ์ด ์ ๊ท๋ถํฌ ์ผ๋) & cross-entropy (์ ๋ ฅ์ด ๋ฒ ๋ฅด๋์ด ๋ถํฌ ์ผ๋)) - \( z = G(X) \) : ๋ ์ดํดํธ ๋ฒกํฐ
- \( \hat{X} = F(z) = F(G(X)) \)
- ์คํ ์ธ์ฝ๋ ํ์ต ๋ฐฉ๋ฒ : backpropagation(์ค์ฐจ์ญ์ ํ) + gradient descent(๊ฒฝ์ฌํ๊ฐ๋ฒ)
์ค์ต : Autoencoder ์๊ฐํ

3์ฐจ์ ๋ฐ์ดํฐ ์์ฑ
import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
tf.random.set_seed(42)
m = 100
angles = np.random.rand(m) * 3 * np.pi / 2 - 0.5
data = np.empty((m, 3)) # (100, 3)
data[:,0] = np.cos(angles) + np.sin(angles)/2 + 0.1 * np.random.randn(m)/2
data[:,1] = np.sin(angles) * 0.7 + 0.1 * np.random.randn(m) / 2
data[:,2] = data[:, 0] * 0.1 + data[:, 1] * 0.3 + 0.1 * np.random.randn(m)
# 3์ฐจ์ data ์๊ฐํ
X_train = data #- data.mean(axis=0, keepdims=0)
ax = plt.axes(projection='3d') # 3์ฐจ์์ผ๋ก ํฌ์ํ๊ฒ
ax.scatter3D(X_train[:, 0], X_train[:, 1],
X_train[:, 2], c=X_train[:, 0], cmap='Reds');

Autoencoder model ์์ฑ
→ ์ธ์ฝ๋๊ฐ ์ค์ !!
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
# 3 ์ฐจ์ => 2 ์ฐจ์
# ๋ฐฉ๋ฒ 1
model = Sequential([
Dense(2, input_shape=(3,)), # ์ฌ๋ฌ ์ฐจ์์ด ๋ค์ด์ฌ ์ ์๊ธฐ ๋๋ฌธ์ ํํ
Dense(3)
])
# ๋ฐฉ๋ฒ 2 : ๋์ค์ ์ธ์ฝ๋๋ง ๋ฝ์์ ์ธ ์ ์๊ธฐ ๋๋ฌธ์ ์ธ์ฝ๋์ ๋์ฝ๋๋ก ๋๋ ์ ์งํํ ๊ฒ
# ๊ฐ๊ฐ sequential๋ก ํ์ฌ ๋๊ฐ์ ๋ชจ๋ธ์ ์์ฑํ๋ค.
encoder = **Sequential**([Dense(2, input_shape=(3,))])
decoder = **Sequential**([Dense(3, input_shape=(2,))])
autoencoder = Sequential([encoder, decoder])
autoencoder.summary()
# ์ปดํ์ผ
autoencoder.compile(loss="mse", optimizer=keras.optimizers.SGD(learning_rate=0.1))
history = autoencoder.fit(X_train, X_train, epochs=200)

encoder output
# ํ์ต์ํจ encoder ๋ฅผ ์ด์ฉํ์ฌ data๋ฅผ ์ฐจ์ ์ถ์
encodings = encoder.predict(X_train)
encodings.shape
# encoder output์ ์๊ฐํ
fig = plt.figure(figsize=(4,3))
plt.plot(encodings[:,0], encodings[:, 1], "b.")
plt.xlabel("$z_1$", fontsize=18)
plt.ylabel("$z_2$", fontsize=18, rotation=0)
plt.grid(True)
plt.show()

Decoder ๋ฅผ ์ด์ฉํ data ๋ณต์
# ํ์ต๋ decoder๋ฅผ ์ด์ฉํ์ฌ data ๋ณต์
decodings = decoder.predict(encodings)
decodings.shape # (100, 3)
# ๋ณต์๋ data ์๊ฐํ
ax = plt.axes(projection='3d')
ax.scatter3D(decodings[:, 0], decodings[:, 1],
decodings[:, 2], c=decodings[:, 0], cmap='Reds');

์ค์ต : Simple stacked autoencoder -MNIST
Deep Auto-Encoders

- fashion_mnist dataset ์ ์ด์ฉํ deep autoencoder ์์ฑ
- Mnist dataset ์ ์๊ธ์จ์ฒด๋ฅผ encoding ํ decoding ํ์ฌ ๋ณต์
plot model ์ฌ์ฉ์ ์ํ graphviz ์ pydot
# anaconda prompt๋ฅผ ์คํํด ์
๋ ฅ
# ๋ค ์ค์นํ, ์ปค๋ restart ํ์
conda install pydot
conda install graphviz
๋ฐ์ดํฐ ๋ถ๋ฌ์ค๊ธฐ ๋ฐ ์ํ ์๊ฐํ
import numpy as np
import tensorflow as tf
from tensorflow.keras.datasets import fashion_mnist
from tensorflow.keras import regularizers
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Input, Dense
from tensorflow.keras.utils import plot_model
import matplotlib.pyplot as plt
(X_train, _), (X_test, _) = fashion_mnist.load_data()
# sample image ์๊ฐํ
fig, ax = plt.subplots(1, 10, figsize=(20, 4))
for i in range(10):
ax[i].imshow(X_test[i], cmap='gray')
ax[i].set_xticks([])
ax[i].set_yticks([])
# data normalization : 0~ 1 ์ฌ์ด์ ๊ฐ์ผ๋ก ๋ฐ๋
X_train = X_train / 255.
X_test = X_test / 255.
# 2์ฐจ์ ์ด๋ฏธ์ง๋ฅผ 1์ฐจ์์ผ๋ก ๋ณ๊ฒฝ
X_train = X_train.reshape(-1, 784)
X_test = X_test.reshape(-1, 784)
X_train.shape, X_test.shape # ((60000, 784), (10000, 784))

stacked autoencoder ์์ฑ
input = Input(shape=(784,))
# stacked autoencoder : functional API ์ฌ์ฉ (ํจ์ํ์ผ๋ก)
x = Dense(units=128, activation='relu')(input) # units : ๋ด๋ฐ์ ๊ฐ์ => ์๋ต ๊ฐ๋ฅ
x = Dense(units=64, activation='relu')(x)
encoder = Dense(units=32, activation='relu')(x) # 2๊ฐ๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ dense ํ์
x = Dense(units=64, activation='relu')(encoder) # ์ธ์ฝ๋์ ์ถ๋ ฅ์ ๋์ฝ๋์ ์
๋ ฅ์ผ๋ก ๋ฃ์
x = Dense(units=128, activation='relu')(x)
decoder = Dense(units=784, activation='sigmoid')(x) # 784๊ฐ์ ํฝ์
๋ก ๋ณต์ ํ์ (0~1 ์ฌ์ด์ ๊ฐ์ผ๋ก normalizeํ์ผ๋ฏ๋ก sigmoid ์ฌ์ฉํ์)
# autoencoder model
encoder_model = Model(inputs=input, outputs=encoder)
autoencoder = Model(inputs=input, outputs=decoder)
autoencoder.compile(loss='binary_crossentropy', optimizer='adam')
autoencoder.summary() # ์ผ์ชฝ ๊ฒฐ๊ณผ
plot_model(autoencoder, show_shapes=True) # ์ค๋ฅธ์ชฝ ๋ชจ๋ธ ์๊ฐํ


์คํ ์ธ์ฝ๋ ํ๋ จ + ๊ฒฐ๊ณผ ์๊ฐํ
history = autoencoder.fit(X_train, X_train, epochs=50, shuffle=True, # shuffle์ ํตํด ์ํญ์ด ๋ฐ๋๋๋ง๋ค ๋ฐ์ดํฐ๋ฅผ ์์
batch_size=256, validation_data=(X_test, X_test))
# ์์ค ์๊ฐํ
plt.plot(history.history['loss'], label='train loss')
plt.plot(history.history['val_loss'], label='validation_loss')
plt.legend()
# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง ์๊ฐํ
fig, ax = plt.subplots(3, 10, figsize=(20, 8))
for i in range(10):
ax[0, i].imshow(X_test[i].reshape(28, 28), cmap='gray') #784 ํฝ์
์ ๋ค์ 28x28์ ์๋๋ก ๋๋๋ ค์ผํจ
img = np.expand_dims(X_test[i], axis=0)
ax[1, i].imshow(encoder_model.predict(img, verbose=0).reshape(8, 4), cmap='gray')
ax[2, i].imshow(autoencoder.predict(img, verbose=0).reshape(28, 28), cmap='gray')
ax[0, i].axis('off')
ax[1, i].axis('off')
ax[2, i].axis('off')

