[Deep Learning] Autoencoders

2023. 5. 23. 19:17
🧑🏻‍💻용어 정리
Neural Networks
Encoder
Decoder
Autoencoders
feature
dropout
novelty
CNN
stacked
denoising
DAE
CAE
VAE

 

 

 

input이 들어오는 것은 neural network 뿐 아니라 다른 Model도 마찬가지로,

 

어떻게든 connection을 엮어서, 이 connection은 벡터 연산으로 matmul이죠.

 

이것들을 여러 Layer로 엮어서 우리가 원하는 output을 뽑아내는 것이 우리의 목적입니다.

 

Autoencoders

 

Autoencoders는 똑같이 이런 concept을 이용하면서,

 

목적에 맞게 모델의 design을 살짝 바꾸며 다른 task에 대한 접근이 가능하게 합니다.

 

Autoencoders는 아래와 같이 생겼습니다.

 

아래 input을 x_1 ~ x_3 을 받으면 3-dimensional input을 받겠다는 것입니다.

 

그리고 output을 봅시다.

 

일반적인 형태의 NN이면 input이 x가 들어가면 output은 y가 들어와야합니다.

 

그런데 autoencoder는 output에서도 x'_1이 들어왔습니다.

 

이게 과연 어떤 의미일까요?

 

 

이제 가운데 부분을 봅시다.

 

우리가 지금까지 hidden이라고 불러온 이 부분은 autoencoder에서는 code라고 표현합니다. 혹은 code vector라고 합니다.

 

위 사진을 보면 code 부분에서 차원이 더 줄어든 것을 볼 수 있습니다.

 

그리고 output은 다시 input이 그대로 들어오니 다시 3차원으로 늘어납니다.

 

위와 같은 구조를 Undercomplete Autoencoder라고 합니다.

 

이렇게 차원이 줄어들면서 필연적으로 정보 손실이 발생하겠죠.

 

그리고 다시 Output에 input이 나오도록 맞춰보라고 하는 작업을 합니다.

 

 

아래와 같은 model이 있다고 해봅시다.

이러한 구조에서는 당연히 완벽하게 output을 input으로 맞출 수 있습니다.

 

위와 같이 3차원에서, 3차원, 3차원 구조이므로 우리 정보를 손실 없이 transfor하기 때문에 위와 같이 x = x'을 정확히 맞출 수 있습니다.

 

이러한 구조를 우리가 complete라고 하며,

 

3차원보다 늘어나면 over complete라고 하기도 합니다.

 

 

여러분들이 아시는 jpg도 정보 손실 압축으로 이루어져있죠. 그리고 다시 원래 bit map으로 만듭니다.

 

그것과 같이 위 autoencoder 구조는 정보 손실이 일어납니다. 그리고 다시 원래 input의 차원으로 풀죠.

 

이러한 상황에서 우리의 loss를 아래와 같은 식으로 잡습니다.

앞에 있는 x 값은 model의 output 값, 뒤에 있는 값은 model의 input 값이 됩니다.

 

이런 undercomplete 구조에서의 autoencoder는 당연히 정보 손실이 오기 때문에 x' 과 x는 당연히 같지 않을 것입니다.

 

그런데 우리가 위와 같이 loss function을 잡고 x'과 x의 차이를 최소화 시키라고 하겠죠.

 

 

그래서 우리의 목적은 x'을 최대한 x에 비슷하게 만드는 게 목표입니다.

 

정보를 잃어버렸음에도 불구하고 복원했을 때, 최대한 비슷하게 복원시키는 것이 목적이죠.

 

 

이 정보를 축약하는 과정을 encoder, 정보를 다시 펼쳐서 복원하는 과정을 decoder라고 합니다. 이 decoder는 reconstruction이라고 하기도 합니다.

 

이러한 개념이 autoencoder라고 볼 수 있겠습니다.

 

 

feature extraction

 

우선, 우리가 autoencoder로 가장 먼저 하고싶어 하는 일은,

 

 

feature extraction입니다.

 

우선, 차원 축소에 대해 알아보겠습니다.

 

차원 축소에는 feature selection이 있습니다. 이것은 여러 변수가 있을 때, 중요한 변수만 뽑아내는 것을 의미합니다.

 

이를테면, x1 ~ x100 중에 x2, x29, x57과 같이 뽑아냅니다.

 

이러한 과정을 통해 이렇게만 써도 충분하다 혹은 결과가 더 좋아지는 것을 생각해볼 수 있습니다.

 

위와 같이 변수를 x1 ~ x100을 사용하여 모아둔 상태에서 모델링을 하면 의미 없는 변수가 들어갈 수 있습니다.

 

이 의미 없는 변수로 인해 overfit이 발생할 수도 있습니다.

 

이를테면, 오늘 새차를 하면 내일 비가온다. 와 같이 무의미한 변수가 들어가 있을 때,

 

우연히 training data 상에서 이 x와 y 사이의 관계가 발견된다면, 이 이상한 rule을 모델들이 만들어줄 수도 있습니다.

 

이것은 그 변수에 overfit을 한 경우가 되죠.

 

그래서 차원을 축소하는 것이 굉장히 중요합니다.

 

이와 같이 original 변수만 쓰지 않고 중요한 변수만 쓰는 것이 굉장히 중요하죠.

 

 

 

그리고 feature extraction이 있습니다.

 

이것은 새로운 변수를 사용합니다.

 

z1, z2, z3 를 만들고 이 각각은 original 변수에 대한 조합으로 이루어집니다.

 

즉, projection을 하는 것입니다.

 

원래 100개의 변수가 있었는데 projection만 잘 시키면 이 3개의 변수만 가지고도 모델링을 할 수 있다는 것입니다.

 

이렇게 의미없는 변수는 이 projection 과정에서 다 역할을 상실하게 되죠.

 

아런 식의 접근이 feature extraction입니다.

 

PCA라는 모델이 바로 이러한 역할을 하는 것이죠.

 

 

사전에 feature extraction을 통해서 우리 데이터를 조금 더 함축적으로 중요한 것만 뽑아놓은 다음에 그것으로 모델링을 하자는 것입니다.

 

이것이 feature extraction이고 PCA의 역할입니다.

 

 

사실 Deep Learning에서는 이 feature selection이나 feature extraction의 역할이 조금 무의미해졌습니다.

 

CNN만 보더라도 9단계로 있다면, 앞에 7개는 다 representation Learning 단계입니다.

 

그리고 나머지 2개는 classification이든 regression이든 prediction 단계입니다.

 

그래서 앞 7개는 conv layer, 뒤 2개는 dense layer를 써서 작업을 해줬습니다.

 

 

 

그럼에도 불구하고 feature extraction이 필요한 분야는 아직 있습니다.

 

 

우리가 해야할 일은 위에서 4D -> 3D -> 2D -> 3D -> 4D의 차원으로 구성되어 있는 것에서,

 

이것들에 대해 x와 x'의 차이를 MSE를 최소화하며, x'을 최대한 x와 비슷하게 만드는 것입니다.

 

그런데 undercomplete를 통해 가혹환 환경을 부여했습니다. 즉, 정보 손실이 있는 환경이죠.

 

위 error을 reconstruction error라고도 합니다.

 

복원이 original과 얼마나 비슷한지를 따지는 것이죠.

 

 

만약, 100만개 정도를 학습했는데 이 error 가 0.01정도가 나오면 이 model이 복원을 굉장히 잘 하는 model인 것입니다.

 

이 model이 복원을 잘 한다는 의미는, 위 compressed data를 보면, encoder 부분에서 차원을 줄이고 다시 decoder 부분에서 차원을 늘려서 충분히 복원을 잘 해냈다는 의미입니다.

 

그 의미는, 결국 이 data는 4차원의 정보가 필요하지 않고, 2차원만 가지고도 충분히 모든 대부분의 변화량을 설명할 수 있다는 것입니다.

 

즉, 2차원의 변수만으로도 충분하게 이 데이터들의 특성들을 설명할 수 있는 것이죠.

 

그래서 original 변수에서 '새차하면 다음 날 비온다'와 같은 정보들을 빼버린 것입니다.

 

 

 

이렇게 autoencoder가 잘 학습되었다는 가정 하에,

 

그러니까 reconstruction error가 우리가 생각하는 threshold보다 낮다면,

 

잘 학습되었다는 것이고,

 

그 얘기는 데이터를 잘 복원한다는 이야기이고,

 

위 compressed Data 혹은 code vector만 가지고도 충분히 전체 변수에 대한 변화량을 잘 표현할 수 있다는 것입니다.

 

즉, 전체 변수를 잘 설명할 수 있다는 내용입니다.

 

 

 

그래서 input이 만약에 x1, x2, x3, x4라고 한다면, 가운데 2D는 c1, c2라고 했을 때, 다음에 prediction 모델을 만들 때에는,

 

c1, c2로 모델을 만드는 것입니다.

 

 

code vector로 충분히 표현이 가능하니 original vector를 쓰지 않고 code vector만 사용하도록 합니다.

 

이렇게 code data만 가지고 모델을 만들어 prediction하자.는 것입니다.

 

그러면 변수가 줄어드니 계산량이 줄어들어 효율성도 좋아지고, overfit 위험도 벗어납니다.

 

 

이 autoencoder는 특정한 제약조건을 가질 때 PCA와 똑같이 행동한다고 알려져 있습니다.

 

그러니 어떤 측면에서 PCA는 굉장히 specialized된 Neural Network다 라고 볼 수 있죠.

 

이 Neural Network의 성질들이 정말 모든 것을 설명하는 것이죠.

 

 

Novelty Detection

 

그 다음으로 살펴볼 것은 Novelty Detection입니다.

 

번역하면 '이상치 탐지'입니다.

 

보통 기본적인 2-class 분류기는 위와 같이 2-class 로 Linear separabilty로 나눕니다.

 

그런데, novelty detection은 위와 같이 class를 분류합니다.

 

데이터가 정상치가 아니면 모두 비정상으로 따지는 것입니다.

 

체온, 혈압, 맥박, 심전도 등 정상 범위가 있을 것입니다.

 

정상 범위를 벗어나면 이상입니다.

 

이런 경우 2-class 분류기를 쓰기 애매하죠.

 

그래서 정상 데이터만 가지고 영역을 규명하고 벗어나면 무조건 다 이상으로 판단합니다.

 

정상만 가지고 정상의 범위를 잘 만들어놓는 Novelty detection 혹은 one-class 분류라고 합니다.

 

 

 

 

 

만약 이 잘 학습된 autoencoder가 새로운 Input을 다음과 같이 입력받았다고 합시다.

 

그리고 reconstruction error가 다음과 같다고 합시다.

 

 

input 1

-> reconstruction error = 0.01

input 2

-> reconstruction error = 0.02

input 3

-> reconstruction error = 0.35

 

 

reconstruction error가 0.01 근처에서 움직인다면, 이건 학습 때 봤던 데이터라고 볼 수 있겠죠.

 

이 reconstruction error의 범주, 분포를 벗어난 reconstruction error가 나왔을 경우, 이 것은 학습할 때 보지 못했던 data임을 의미합니다.

 

즉 이는 이상치 혹은 그림과 같이 슈퍼마리오가 됩니다.

 

 

 

그래서 이 autoencoder가 할 수 있는 역할이 novelty detection입니다.

 

학습 데이터로 autoencoder를 잘 학습시켜 둔 다음, reconstruction error를 잘 비교하여서,

 

우리가 학습 시 봤던 데이터인지 안 봤던 데이터인지를 구분하는 것입니다.

 

threshold도 설정해야합니다.

 

이는 얼마나 민감한 모델을 만드느냐에 따라 다르겠죠.

 

 

 

우리가 지금까지 사용하는 autoencoder를 가지고 Input과 Output을 살짝 변경하였더니,

 

우리가 일반적으로 생각하는 classification, regression과는 혹은 object detection과는 또 다른 완전히 새로운 task를 수행할 수 있는 그런 autoencoder, NN이 만들어졌습니다.

 

이 autoencoder는 architecture를 잘 만들고, 그 task에 잘 맞는 loss를 설계하면 그 후에는 Backpropagation이 알아서 최적화를 잘 해줍니다.

 

 

Stacked (deep) autoencoder

당연히 차원을 축소하는 데 있어,

 

한꺼번에 너무 많은 차원을 축소해버리면 많은 정보가 손실됩니다.

 

그래서 순차적으로 차원을 떨어뜨리고 순차적으로 차원을 올려줘야합니다.

 

그래서 큰차원에서 작은 차원으로 줄이고 싶을 때는,

 

위와 같이 deep한 구조의 Stacked autoencoder를 사용합니다.

 

 

이것은 DNN과 같은 이점을 가집니다. 그리고 gradient 전파에 대한 똑같은 한계점도 있을 것입니다.

 

보통 위와 같은 대칭구조로 사용합니다. 완벽한 대칭을 만들 때는 weight를 묶어버리기도 합니다.

 

그렇게 parameter sharing 효과도 가져옵니다.

 

 

 

그리고 아래와 같은 sequential learning의 효과도 있습니다.

 



 

Denoising autoencoders

그리고, Denoising autoencoders (DAE)를 봅시다.

 

이것은 우리가 Regularization에서의 noise robustness의 개념을 생각하시면 됩니다.

 

우리가 네모를 입력으로 주고 다시 축소시킨 다음 네모를 복원해보라고 하면 이 task는 너무 쉽습니다.

 

이것은 overfit이 발생할 수 있죠.

 

그래서 이 네모에 noise를 줍니다. 일반적으로 Gaussian noise를 사용합니다.

 

그리고 출력으로 클린한 네모를 맞추라고 하는 것입니다.

 

noise를 조금 추가했음에도 불구하고, 원본의 네모를 맞추며 학습하기에, 이것은 조금 더 generalized된 모델이라고 할 수 있겠죠.

 

 

그래서 나중에 test data에서 조금 더 안 좋은 이미지가 들어와도 잘 복원할 수 있을 것입니다.

 

모델이 마음대로 학습되지 않도록 방해공작을 하는 일명 regularization으로 볼 수 있습니다.

 

그래서 Model을 이렇게 가혹한 환경에서 혹독하게 training을 시키는 것입니다.

 

 

 

그래서 위 수식에서, x~이 입력, f(x~)이 encoder, g(f(x~))는 decoder이니, 이 최종값이 출력이라고 볼 수 있죠.

 

입력 x~는 x 틸다, 즉, x에 noise를 더한 값을 넣어주고, 출력에는 reconstruction error를 계산하기 위한 깨끗한 이미지를 넣어줍니다.

 

이번에는 x~ 를 넣고 x를 맞추라고 하는 것입니다.

 

 

그래서 다음 그림을 한 번 살펴봅시다.

위 과정을 그림으로 썼습니다.

 

original data에 Noise를 더하고 그것을 encoder, code, decoder에 차례로 들어간 다음 output을 잘 복원해냈습니다.

 

위와 같이 original image가 x이고 noisy input이 x~겠죠.

 

그래서 위와 같이 output을 내니까 x와 비슷하게, robust해지게 할 수 있습니다.

 

그래서 나중에 test data가 들어왔을 때 더 잘하고, 이는 generalization 되었다고 볼 수 있고,

 

즉, Regularization 효과가 있다고 볼 수 있습니다.

 

 

 

그래서 아래와 같은 DAE의 결과를 볼 수 있습니다.

 

복원이 잘 됐다는 걸 볼 수 있습니다.

 

 

 

Convolutional Autoencoders(CAE)

 

여기까지 보시면 autoencoder는 MLP 구조로 만들어졌다는 것을 알 수 있습니다.

 

dense layer 구조로 만들어졌죠.

 

 

그런데 우리가 결국 대상이 이미지라면, 아예 Dense layer 말고 conv layer와 pooling layer를 쓰면 되지 않을까 라고 생각이 듭니다.

 

그것이 바로 convolutional autoencoders입니다.

 

입력 넣고 출력으로 같게 맞춰보아라. 그리고 undercomplete으로 정보를 줄여보겠다의 task입니다.

 

정보를 줄이는 것은 dense layer가 아닌 conv layer와 pooling layer로 줄이겠다는 것이죠.

 

 

결국 CNN을 이용한 autoencoder를 만들겠다는 것입니다.

 

 

자, convolutional autoencoder에서 encoding은 CNN과 유사합니다.

 

원하는 구조로 정보를 줄이기만 하면 됩니다.

 

그리고 flatten을 통해서 code vector를 우리가 원하는 Size로 맞춰주기도 합니다. 해당 부분은 dense layer가 들어간 거죠.

 

이렇게 해도 되고, conv layer로 쫙 뽑아서 마지막이 global average pooling 을 통해서 늘려줘도 상관 없습니다.

 

이렇게 flatten을 쓰는 게 기본인데, 안 써도 상관은 없습니다.

 

encoding은 우리가 알고 있는 CNN과 같습니다.

우리가 encoder에서 conv layer와 pooling layer를 통해 정보를 줄인 것은,

 

정보를 단순히 matmul을 통해 줄인 것만이 아니라, 이미지 size를 계속 줄여나갔습니다.

 

그것을 다시 공간적인 특성에 맞춰서 키워주어야합니다.

 

그래서 공간적인 특성을 보존하면서 어떻게 이미지를 키워줄 것인가, 그것을 생각해보아야합니다.

 

 

그래서 Pooling은 굉장히 쉽습니다.

 

encoder에서 size를 줄이는 pooling은 우리가 아는 방식과 같이 index를 기억했다가 적용해주기만 하면 됩니다.

 

runnable parameter가 있는 것은 아닙니다.

 

 

이제 decoder 단계에서 unpooling을 할 때에,

 

그 index에 그 값을 넣으면 됩니다. 그리고 나머지는 0으로 둡니다.

 

그런데 이 conv layer에서 줄어들었던 image의 크기를 키우는 것은 조금 다른 문제입니다.

 

그래서 이 technique을 transpose conv라고 합니다.

 

보통 과정을 Deconvolutional 라고 부르지 않습니다.

 

이 deconvolution은 f *(conv) g = h일 때, f, h를 이용해 g를 구하는 방식을 뜻합니다.

 

그래서 우리는 transpose convolution이라고 불러야합니다.

 

결국 transpose convolution은 convolution을 역으로 해서 복원하는 것을 뜻합니다.

 

 



 

stride가 없는 경우 위 사진에서 가운데 그림처럼 가운데에 값을 놓고 해주면 되고,

 

stride가 있는 상황이면 오른쪽 그림처럼 값을 떨어뜨려놓고 해주시면 됩니다.

 

그러면 더 많이 축약된 image도 늘릴 수 있게 됩니다.

 

그리고 zero-padding도 넣어줍니다.

 

 

이것이 가장 기본적인 upscaling을 하기 위한 transpose convolution입니다.

 

 

 

이번엔 또 다른 방법의 transpose convolution입니다.

 

이전에 배운 방법이 더 많이 사용되긴 하지만, 이렇게 사용하기도 합니다.

주어진 input에 대해서 zero-padding을 수행하고, 그리고 kernel을 돌리며 convolution을 합니다.

 

위 과정은 input이 0 ,1, 2, 3 있는데, 여기서 0 x kernel, 1 x kernel, 2 x kernel, 3 x kernel을 해준 것입니다.

 

이러한 방법도 있다고 하고 넘어갑니다.

 

 

아래는 Deconvolution에 대한 내용입니다.

위 b 과정을 보면,

 

Activation 된 왼쪽 matrix에 output을 ReLU를 이용하여 넘겨주는 것이 위 forward pass입니다.

 

여기서, 위 forward pass에서 ReLU로 activation된 index 부분만 값을 넘겨주는 것이 일반적인 Backpropagation에서의 gradient 전파 방법입니다.

 

Activation 되지 않은 것들은 넘겨줄 필요가 없죠.

 

 

같은 index로 activation 되었으면 Backpropagation도 같은 Index로 gradient가 전파되는 것입니다.

 

그런데 이렇게하다보니 무시되는 gradient가 존재하게 됩니다.

 

그러면 gradient가 큰 게 전파되어야 할 거 같은데, 작은 gradient가 전파되는 것이 보입니다.

 

 

deconvnet은 3번째 Deconvent에서는 큰 gradient Signal을 가지고 있는 것이 gradient가 전파되도록 하는 것입니다.

 

forward propagation 단계에서 activation 된 것들 위주로 backpropagation 하는 게 아니라,

 

backpropagation 때는 그것은 잊고 gradient가 큰 애만 넘겨주도록 합니다.

 

이것이 바로 Deconvnet입니다.

 

그래서 transpose convolution과 deconvnet을 구분하여 용어를 사용하여야합니다.

 

그리고 4번째 guided backpropagation은 2,3번째 줄의 교집합으로 보시면 됩니다.

 

 

그리고 conv, backpropagation 의 Index 연산 자체도 목적에 따라 개선하려는 연구가 진행되고 있습니다.

 

 

 

 

그리고 autoencoder의 또 다른 그림을 살펴봅시다.

위 그림에 따라 input이 줄어들었다가 다시 늘어나며 output을 만들어냅니다.

 

이러한 일반적인 autoencoder 구조에서 stacked encoder라는 것을 알 수 있습니다.

 

hidden 을 여러 개 썼기 때문이죠.

 

그리고 가운데 가장 함축된 이 정보를 code vector라고 합니다.

 

code vector가 reconstruction이 잘 되는 모델이면 굉장히 훌륭한 feature로 사용될 수 있습니다.

 

 

 

 

이번에는 대칭에 parameter sharing도 합니다.

 

 

위와 구조는 같지만 위 weight들이 transpose 형태로 parameter를 묶어버렸습니다.

 

이것은 당연히 Regularization을 위해서 합니다.

 

이렇게 간단한 autoencoder 구조에서도 regularization을 신경써주는 모습을 보일 정도로 regularization은 중요합니다.

 

이렇게 서로 완벽하게 같은 weight 값을 가지게 됩니다.

 

 

 

 

위 stacked autoencoder에서 Layer가 너무 많이 쌓이다 보면,

 

최적화를 한꺼번에 하는 것이 힘들어집니다.

그럴 때는 pre-train을 합니다.

 

원래 전체를 학습해야하지만, 전체 weight를 학습시키기는 너무 어렵습니다.

 

그래서 왼쪽부터 짧은 구조의 autoencoder를 한 번 학습시킵니다.

 

그리고, 그 사이에 있는 것만 또 따로 학습을 시킵니다. 이것은 hidden 1의 값이 Input이 됩니다.

 

그래서 마지막에 이것들을 한 번 붙여서 fine-tunning을 해줍니다.

 

 

 

이렇게 pre-training 을 해서 sequential 하게 학습하는 autoencoder도 있습니다.

 

 

 

그리고 autoencoder를 완전히 supervised model의 pre-trainer로 쓰는 경우도 있습니다.

 

왼쪽에서 encoder 부분은 represention learning에 해당하는 부분이죠.

 

hidden 2가 우리가 가진 가장 함축적인 표현이니 그렇습니다.

 

이것을 그대로 가져와서 dense layer로 붙여서 classification이나 regression 등의 prediction을 합니다.

 

즉 이것을 pre-trainer로 사용하는 것이죠.

 

 

위 예시보다 더 많은 stack을 쌓은 autoencoder에서는 이것이 큰 의미를 발휘할 것입니다.

 

 

이렇게 fine-tunning을 하지 않고 위만 학습하는 경우도 있습니다.

 

그렇다면 Hidden 2의 내용을 그대로 Input으로 사용하는 것이니, 이것은 feature extraction이 됩니다.

 

 

위 상태에서 전체 weight를 다 Fine-tunning하면 dense layer는 위에서 겨우 tunning이 시작되는 것이고,

 

밑에까지 같이 fine-tunning을 해버리면 low layers들의 pre-trainer로서의 역할을 하게 됩니다.

 

밑에를 freeze 시켜 학습을 안 하겠다고 하면, 위에만 학습이 되므로 code vector 자체를 feature, 또 다른 입력으로 사용하여 prediction을 하는 것입니다.

 

이것은 feature extractor 역할을 하는 게 되겠죠.

 

 

이것은 denoising autoencoder입니다.

 

이것은 다 같지만, gaussian noise를 추가하여 x~를 만들어냅니다.

 

그리고 drop out도 noise roubustness입니다.

 

drop out을 한다는 것 자체가 masking vector를 곱하는 것이기 때문에 이것은 어떠한 Multiply noise가 추가되는 개념입니다.

 

drop out 도 noise를 추가하는 어떤 변수를 쓰지 말라는 weight를 곱하여 추가하는 느낌입니다.

 

이것도 denoising autoencoder 역할을 합니다.

 

 

Variational autoencoder 로 VAE라고 합니다.

 

이것은 generative model로 다룰 수 있습니다.

 

 

BELATED ARTICLES

more