딥러닝/cs231n

[CS231n] Generative Models (1) - AutoEncoder, Variational AutoEncoder(VAE)

모끼주인 2019. 4. 15. 14:57

* 이 글은 Stanford 대학의 CS231n 강의를 듣고 요약한 글입니다.

 

1. AutoEncoder(AE)

AutoEncoder는 데이터 생성 모델이 아닌, 학습 데이터에 대해 보다 낮은 차원의 feature representation을 학습하는 것이 목적이다. 구조는 아래 그림과 같다.

[그림] AutoEncoder의 구조

즉, input data x 그 자체를 label로 삼아 저차원의 feature z를 학습하겠다는 것이다. 학습에 쓰이는 Encoder와 Decoder로는 Linear + nonlinearlity(sigmoid), fully connected, ReLU CNN 등이 사용된다. 입력 데이터를 있는 그대로 복원해야 하기 때문에 L2 loss function(x와 reconstructed x의 차의 제곱)을 통하여 최적화 할 수 있다.

 

학습이 완료된 AutoEncoder는 z만 떼어내어 classification에 활용할 수 있다. 데이터의 수가 매우 적어 학습이 어려운 경우 이 방법을 사용한다.

 

2. Variational AutoEncoder(VAE)

- VAE의 개념 및 intractable objective function

AutoEncoder를 Generative Model로 사용하기 위해, Sampling과 확률적 개념을 집어넣은 것이다.

 

생성 모델을 만든다는 것은, training data set x의 분포로부터 임의로 샘플링한 이미지를 생성하는 모델을 만든다는 것이다. 따라서, 주어진 데이터 x의 분포 P(x)를 구해야 한다.

 

P(x)를 구하기 위해 가장 쉬운 방법은 P(x)의 수식을 직접 정의하는 것이다. PixelRNN이나 PixelCNN과 같은 연구에서는, 이미지에서 한 픽셀의 주변 픽셀을 이용하여 해당 픽셀이 0~255 사이의 어떤 값을 가질 것인가에 대한 확률 모델을 정의한다. 수식은 아래와 같다.

Pixel RNN/CNN에서 P(x)의 정의

그러나 이 방법은 매우 느려서 사용하기 어렵다는 단점이 있다. 때문에 사람들은 P(x)의 수식 자체를 직접 정의하기 보다는, 어떤 latent variable z의 기댓값으로 x를 표현하는 방법에 대해 생각하게 된다.

이게 뭔 소리인지..? 라고 생각할 것이다. latent variable z란 앞서 언급한 AutoEncoder에서의 저차원의 벡터 z로, x의 핵심 요소들을 요약하여 가지고 있는 벡터이다. AutoEncoder를 통해서, 이미지의 요약본 z를 통해 이미지 x를 복원할 수 있다는 사실을 알게 되었다. 따라서 training data x의 분포 P(x) 또한 x와 z의 joint distribution P(x, z)가 있을 때, 이를 z에 대하여 적분한 "x의 marginal distribution"으로 표현할 수 있을 것이다. (그냥 P(x)를 어떤 변수 z의 기댓값으로 나타냈다는 뜻이다. joint distribution, marginal distribution에 대해서는 확률과 통계 참고)

latent variable z 를 사용한 새로운 p(x)의 정의

그런데 이 수식의 문제점은... 계산이 안된다는 것이다.

먼저 P(z)의 경우, latent variable의 prior distribution이다. 여기서 일반적으로 prior distribution을 gaussian distribution으로 가정한다. 생각해 보면, 사람 얼굴 이미지를 생성할 때 z에는 웃음의 정도, 눈썹 위치 등이 있을 수 있다. 일반적으로 이러한 특징들은 정규분포를 따르므로 합리적인 생각이다. (추후에 GAN에서는 prior distribution을 직접 input으로 학습시킨다. VAE의 단점이 이러한 가정에서 나온다고 할 수 있음)

그럼 계산이 안되는 이유는?? P(x|z) 때문인데,  모든 z에 대해서 P(x|z)를 계산할 수 없기 때문이다. Bayes 정리를 이용하여 P(z|x)로 순서를 변환해도 계산이 불가능 한 것은 마찬가지인데, 아래 수식에서와 같이 P(x)를 구할 수 없기 때문이다. (구하고자 하는 것이 P(x)이므로)

Posterior density also intractable!!!!

- VAE의 최종 구조 및 Lower Bound를 통한 intractableness 해소

그럼 어떡하지??? 라고 생각하던 과학자들은 P(z|x)를 neural network encoder를 통해 직접 근사하기로 한다. 그 방법은 아래와 같다.

즉, 그림은 먼저 x를 input으로 Encoder network를 학습하여 P(z|x)의 분포를 찾아낸 후, 거기서 z를 몇 개 sampling하여 decoder network에 대입하고, 이로부터 P(x|z)를 찾아내겠다는 뜻이다. 앞에서 P(z)의 분포를 gaussian이라고 가정하였으므로, P(z|x)나 P(x|z)를 찾아낼 때는 평균과 공분산 행렬을 알면 그 분포를 구할 수 있다.

 

그럼 어쨌든 구조를 정의했으니 이걸 학습을 시켜야 하는데, 궁극적으로 VAE를 학습하는 방향은 P(x)를 최대화(maximize)하는 방향이다. P(x)보다는 logP(x)가 최적화 하기 쉬우므로 log를 씌워 주고, 이를 앞서 정의한 대로 z에 대한 기댓값으로 표현해 보면 아래와 같다.

z~q(z|x)는 Encoder에서 학습시킨 결과인 q(z|x)로부터 샘플링한 z라는 뜻이다. phi(Φ)는 무엇인가 불편한 마음이 들 텐데, Encoder neural network의 가중치 행렬, 즉 parameter를 의미하는 것이다. 즉 Encoder network에서 update시켜야 할 대상은 Φ가 되겠다.

 

이 수식을 계산하기 위해 아래와 같이 풀어쓰면...

맨 아랫줄과 같이 된다. ㅎㅎ

여기서 VAE의 한계점이 또 하나 드러나는데, 바로 맨 아래 수식 또한 정확하게 계산할 수 없다는 것이다. 때문에 Lower Bound를 구하고, 이를 최대화 함으로써 목적식을 최대화 하는 것에 가까워지고자 한다. 왜 계산이 불가능 한지 이유를 살펴보자.

 

첫 번째 항은 decoder network의 출력인 P(x|z)이므로, 얼마나 input data가 잘 reconstruct 되었는지를 의미한다. 이것은 계산할 수 있다. (encoder와 decoder의 중간에 z를 샘플링 하는데, re-parametrization trick을 통해 샘플링도 미분이 가능하다고 한다. 따라서 back-propagation 가능하므로 학습 가능)

 

두 번째 항은 KL divergence term으로, q(z|x)와 p(z)사이의 유사도를 의미한다. q(z|x)는 공분산 행렬을 가정한 gaussian, p(z)역시 gaussian이므로 이 값을 구할 수 있다.

 

마지막 항이 바로계산 불가능한 항이다. 맨 처음 정의한 적분 식에서와 같이 p(z|x)는 여전히 구할 수 없다.(이거 안구할려고 encoder network를 통해서 q(z|x)로 근사한 것) 하지만 희소식은 이 항 또한 KL term이기 때문에 항상 0보다 크거나 같다는 것이다. 따라서 우리는 첫 번째, 두 번째 항만 이용해 Lower Bound를 구할 수 있고 이를 최적화 하면 된다!

 

VAE의 Lower Bound

Lower Bound를 잘 생각해 보면,

첫 번째 항은 P(x|z)이므로 input data가 잘 복원될수록 그 값이 커진다.

두 번째 항은 q(z|x)와 p(z)의 KL term이므로, 0에 가까울수록 두 분포가 가까워지게 된다.

 

따라서 Lower bound를 maximize하면 z로부터 x를 잘 생성해 낼 수 있게 되고(decoder 학습), q(z|x)가 p(z)에 근사하게 된다.(encoder 학습)

 

- VAE 학습 과정 및 학습 결과

 

아래는 최종적으로 정리된 VAE의 전체적인 구조이다.

 

학습 과정은

<forward>

1. x가 encoder 통과하여 q(z|x)분포 구해짐

2. q(z|x)로부터 z 샘플링, decoder에 대입하여 p(x|z)얻음

<backward>

3. objective function값을 구하고, 이를 기반으로 back-propagation:

encoder : Φ를 update

decoder : θ를 update

(둘 다 각각 encoder와 decoder의 neural net 가중치를 표현한 것)

 

 

학습을 다 시킨 VAE는 Decoder만 따로 떼어 사용한다.

이 때, z는 training time에서와 같이 q(z|x)에서 샘플링하지 않고 p(z)에서 직접 샘플링하여 사용한다.

test time에서의 VAE

 

아래는 VAE로 이미지를 생성한 결과이다.

즉, 최종적으로 학습시킨 decoder의 P(x|z)분포에서 샘플링한 이미지가 되겠다.

임의로 특징 z1과 z2를 정하고, 두 가지를 축으로 값을 조금씩 변화하며 이미지를 샘플링 한 결과이다.

이미지가 자연스럽게 연속적으로 변화하는 것을 볼 수 있다.

 

애초에 수식을 계산할 때 p(z)를 gaussian으로 가정하였으므로, diagonal covariance를 가정한 것이다.

따라서 z의 각 차원이 독립이고, 결과적으로 각 차원마다 독립적으로 해석 가능한 요소들이 인코딩 되었다고 볼 수 있다.

 

그러나 꼭 모든 요소들이 독립이라고 단정지을 수는 없으므로 다양한 차원을 나타내기 위한 여러가지 연구들이 진행 중이라고 한다. (수학적인 연구 대단....)

 

 

'딥러닝 > cs231n' 카테고리의 다른 글

[CS231n] Generative Models (2) - GAN  (0) 2019.04.15