Home CS231N chapter 13 - Generative Models
Post
Cancel

CS231N chapter 13 - Generative Models

12강 리뷰

1) Dimensionality Reduction

2) Occlusion Experiment

3) Gradient Ascent

4) Texture Synthesis

5) Style Transfer



지금까지는 지도학습(supervised learning)에 대해 배웠다. 지도 학습에는 데이터 x, 레이블 y가 있다. 지도학습의 목적은 데이터 x를 레이블 y에 매핑시키는 것이다. 레이블은 다양한 형태를 띈다.

예를 들어 분류(classification) 문제의 예를 들어보자면 이미지가 입력이고, 출력은 클래스 레이블 y이다.

image

object detection 문제에서의 출력은 각 객체들의 bounding box를, segmentation은 모든 픽셀마다 각 픽셀이 속하는 카테고리를, image captioning은 한 문장일 것이다.

Unsupervised learning

비지도 학습에서는 레이블이 없는 학습 데이터만 가지고 데이터에 숨어있는 기본적인 구조를 학습시켜야 한다. 비지도 학습의 예로는 군집화(clustering)이 있다. 군집화의 목표는 일정 metric을 가지고 유사한 데이터들끼리 묶어주는 것이다.


가령 k-means clustering이 있다. 또는 차원 축소(dimensionality reduction)이 있다. 차원 축소를 통해 학습 데이터가 가장 많이 퍼져있는 축을 찾아낸다. 이 방법은 데이터의 차원을 감소시키는데 사용한다. 가령 위와 같이 3차원 데이터가 있을 때 이 데이터의 두 개의 축을 찾아낸다. 2차원으로 축소시키기 위해서다.


비지도 학습의 또 다른 예는 데이터의 feature representation을 학습하는 것이다.

앞서 분류 문제와 같은 supervised loss를 이용한 feature representation을 배웠다. 여기서는 분류를 위한 레이블이 있고 softmax loss를 사용한다. 그렇게 네트워크를 학습시켜 FC layer의 특징을 데이터의 feature representation으로 사용할 수 있다.

비지도 학습의 경우 feature representation을 활용한 AE(Autoencoders)가 있다. AE의 loss는 입력 데이터를 얼마나 잘 재구성했느냐인데, 이를 이용해서 특징들을 학습시킬 수 있다. AE를 사용하면 추가적인 레이블 없이도 feature representation을 학습시킬 수 있다.


비지도 학습의 예에는 분포 추정(density estimation)이 있다. 이는 데이터가 가진 기본적인 분포를 추정하는 방법이다.

예를 들어 오른쪽 맨 위의 1차원 점들이 있다. 이 점들의 분포를 가우시안으로 추정한다. 또 하단의 예제는 2차원 데이터의 분포를 추정한 것이다. 점들이 더 많이 밀집되어 있는 곳의 분포가 더 크도록 이들의 분포를 적절히 모델링할 수 있다.


지도/비지도 학습의 차이점을 요약해보면. 지도학습의 경우 레이블을 통해 x에서 y로의 매핑을 학습한다. 비지도학습의 경우 레이블이 없는 대신 데이터의 숨겨진 구조를 학습한다. 예를 들어 군집화, 변화의 중심 축, 데이터의 밀도추정 등이 있다.

비지도 학습의 장점은 레이블이 필요하지 않기 때문에 데이터를 아주 많이 모을 수 있다. 데이터에 대한 비용이 적어지는 것이다.


Generative models

비지도학습(unsupervised learning)의 일종인 생성 모델(generative model)을 다루고자 한다.

생성모델은 크게 pixelRNN and PixelCNN, Variational Autoencoders(VAE), Generative Adversarial Networks(GAN) 이 있다.


생성 모델의 목적은 동일한 분포에서 새로운 샘플들을 생성해내는 것이다. 분포 P_data로부터 나온 학습 데이터들이 있다. 우리가 하고자 하는 것은 P_model을 학습시키는 것이다. p_model이 p_data와 같은 데이터를 생성하도록 만든다. 이를 위해서는 p_model과 p_data가 유사해야 할 것이다.

생성 모델에서는 분포 추정을 다뤄야 한다.

앞서 말했듯이 학습 데이터의 근본이 되는 분포를 추정해야 한다. 이는 비교사 학습의 핵심 문제이기도 하다. 분포 추정에는 여러 가지 전략이 있다. 하나는 생성 모델 p_model의 분포가 어떨지를 명시적으로 정의해주는 경우다.

또는 간접적인 방법도 있다. 모델이 p_model에서 샘플을 만들어내도록 학습시키는 것은 동일하지만, 이번에는 p_model의 분포를 정의하지 않는다.


생성 모델이 중요한 이유는 생성 모델을 통해 많은 것들을 할 수 있기 때문이다. 데이터 분포로부터 사실적인 샘플들을 생성해낼 수만 있으면 이를 이용해 아주 많은 것들을 할 수 있다.

위의 사진은 생성 모델을 통해 생성된 샘플들이다. 생성 모델을 이미지에 적용하면 초해상도(super resolution) 이나 색입힘(colorization)과 같은 테스크를 적용할 수 있다.

colorization의 에를 보면 지갑의 밑그림만 그려놓으면 생성 모델이 색을 채워줘서 지갑이 실제로 어떻게 생겼을지 알 수 있다.

생성 모델은 강화 학습을 이용한 시뮬레이션이나 플래닝(planning)을 위한 시계열 데이터 생성에도 이용할 수 있다.

생성 모델을 학습하면 latent representation을 추정해볼 수 있다. 데이터의 잠재적인 특징(latent features)을 잘 학습시켜 놓으면 추후 다른 테스크에도 아주 유용하게 쓸 수 있다.


생성 모델의 종류로는 다음과 같은 taxonomy로 분류해볼 수 있다. 앞서 설명한 명시적/간접적 분포 모델에서 서브 카테고리로 더 쪼갤 수 있다.

여기서 세가지 모델만 배울 것이다. PixelRNN/CNN과 VAE(variational autoencoders) 이 두가지 모델은 명시적 분포 모델에 속한다. pixelRNN/CNN은 계산 가능한 확률 모델 사용(tractable density)에 속하고, VAE는 근사적 밀도추정(Approximate density)에 속한다. 마지막으로 generative adversarial networks(GAN)에 대해 배울 것이다. GAN의 경우 간접적인 분포 추정(implicit density)에 속한다.

PixelRNN/CNN

pixelRNN/CNN은 fully visible brief networks의 일종이다. 밀도를 명시적으로 정의하는 모델이다.

이미지 데이터 x가 있고, 이 x에 대한 likelihood인 p(x)를 모델링한 것이다. 이 모델의 경우 chain rule로 likelihood인 p(x)를 1차원 분포들간의 곱의 형태로 분해한다. 이렇게 분해하면 픽셀 x_i에 대해 각각 p(x_i|conditions)를 정의할 수 있다. conditions는 이전의 모든 픽셀 x1부터 x_(i-1)이다. 따라서 이미지 내 모든 픽셀에 대한 likelihood는 모든 픽셀의 likelihood의 곱의 형태와 같다.

이제는 모델을 학습시키기 위해 학습 데이터의 likelihood를 최대화시킨다. 픽셀 값에 대한 분포를 보면 p(x_i|이전의 모든 픽셀)이다.

복잡한 변환(transformation)을 수행할 때는 neural network를 사용해왔기에 이런 복잡한 분포를 표현하기 위해서 신경망을 사용한다. 여기서 문제는 픽셀들의 순서는 어떻게 할지를 생각해봐야 한다. 분포 p(현재 픽셀|모든 이전 픽셀)에서 모든 이전 픽셀이 의미하는 바는 앞으로 살펴볼 것이다.


pixelRNN은 기본적으로 이 문제를 풀기 위해 고안된 방법이다. 우선 좌상단 코너에 있는 픽셀부터 생성한다. 위의 사진에 보이는 그리드가 이미지의 픽셀로 볼 수 있고, 화살표 방향으로의 연결성을 기반으로 순차적으로 픽셀을 생성한다. 이런 방향성을 기반으로 픽셀들간의 종속성을 RNN 중 LSTM을 사용한다.

이 방법은 잘 동작하지만 순차적 생성 방식때문에 아주 느리다는 단점이 있다. 예를 들어 새로운 이미지를 생성한다고 하면 여러번의 feed forward를 거쳐야 한다. 모든 픽셀이 생성될 때까지 반복적으로 네트워크를 수행해야 하는 것이다.


pixelRNN 후 pixelCNN이라는 또 다른 모델이 있다. pixelCNN는 pixelRNN과 거의 동일하다. 왼쪽 코너부터 새로운 이미지를 생성한다. 차이점은 모든 종속성을 고려하여 모델링하는 RNN과 달리 CNN으로 모델링한다. 이전의 모든 픽셀을 고려하는 대신 픽셀을 생성할 때 특정 픽셀만을 고려하는 것이다.

또한, CNN은 출력 값을 softmax loss를 계산한다. 예기에서는 레이블이 0-255가 될 것이다. 우리는 학습 데이터로 likelihood가 최대화하도록 학습시킬 수 있다.

이렇게 픽셀을 생성하는 과정에서 각 픽셀 값은 정답(Ground Truth)를 가지고 있을 것이다. 이 정답값은 0-255사이의 분류 문제를 풀기 위한 레이블이라고 볼 수 있다. 따라서 softmax loss로 학습시킬 수 있는 것이다. 이런 학습 과정은 동일하게 likelihood를 최대화한다.

위의 분류 레이블은 loss를 계산할 때 쓴다.

pixelCNN이 pixelRNN보다 훨씬 빠르다. 왜냐하면 Train time에서는 모든 데이터에 대해 학습 데이터의 likelihood를 최대화하는 것이기 때문이다. 학습 데이터는 이미 우리가 알고 있는 값이므로 학습 과정을 병렬화할 수 있다. 그러나 새로운 이미지를 생성해야 하는 test time에서는 여전히 코너에서부터 시작해야 하고 생성 방법에 대한 새로운 제안이 없기에 이전 픽셀부터 시작해야 하지만, 모든 픽셀을 고려하는 것이 아니기 때문에 빠를 것이다.

첫 픽셀의 분포에 따라 민감할 수 있다. 처음 픽셀이 모든 분포에 영향을 미치기 때문이다. 초기 픽셀의 분포를 선택하는 방법은 training time에서 학습 데이터의 픽셀 값을 가져온다. test time에서 uniform distribution을 사용할 수 있고, 첫 픽셀만 가져올 수도 있다. 초기 값만 설정하면 나머지는 네트워크가 알아서 한다.

Q. 한번에 모든 픽셀을 예측하는 대신 chain rule 방식으로 이를 정의하는 방법은 있는가?

=> chain rule은 계산 가능한 확률모델을 기반으로 likelihood를 직접 최적화시킬 수 있도록 도와준다.


이는 pixelRNN/CNN으로 생성한 이미지들이다.

요약하자면, pixelRNN/CNN은 likelihood p(x)를 명시적으로 계산하는 방법이다. 우리가 최적화시킬 수 있는 분포(밀도)를 명시적으로 정의한다.

이렇게 분포를 명시적으로 정의하는 경우의 추가적인 장점은 측정 공식(evaluation metric)이 존재한다는 것이다. 우리가 데이터를 통해 계산할 수 있는 likelihood를 이용하면 생성된 샘플이 얼마나 잘 만들어졌는지를 평가할 수 있다.

pixelRNN/CNN의 가장 큰 단점은 생성 과정이 순차적이기 때문에 상당히 느리다는 것이다.

하지만, pixelRNN/CNN은 음성생성(audio generation)에도 사용될 수 있다. 음성생성의 경우에도 느리다는 단점은 여전히 존재한다.


Variational AutoEncoders(VAE)

지금까지 살펴본 pixelCNN은 여기 있는 정의처럼 계산이 가능한 확률모델을 기반으로 한다. 이를 기반으로 학습 데이터의 likelihood를 직접 최적화한다.

하지만 VAE의 경우 직접 계산이 불가능한 확률 모델을 정의한다.


이제 추가적인 잠재 변수(latent variable) z를 모델링한다.

VAE에서는 data likelihood p(x)가 적줍 형태를 띄고 있다. 가능한 모든 z값에 대한 기댓값을 구하는 방식이다. 문제는 이 식을 직접 최적화할 수 없다. 대신 이 likelihood p(x)의 lower bound를 구해서 최적화시켜야 한다.


VAE의 배경을 살펴보기 위해 AE를 먼저 살펴봐야 한다.

  • AutoEncoders

autoencoders(AE)라는 비지도 학습 모델과 관련이 있다. 우선 autoencoders는 데이터 생성이 목적이 아니다. AE는 레이블되지 않은 학습 데이터로부터 저차원의 feature representation을 학습하기 위한 비지도 학습 방법이다. 위의 사진을 보면 입력 데이터 x가 있다고 하고, 어떤 특징 z를 학습하길 원한다. encoder는 입력 데이터 x를 특징 z로 변환하는 매핑 함수의 역할을 한다. encoder는 다양한 방법으로 설계할 수 있다. 일반적으로는 neural network를 사용한다.

autoencoder는 예전부터 linear + nonlinearity를 이용한 모델을 사용했고, 이후 FC-Layer를 사용한 더 깊은 네트워크와 CNN을 사용하게 되었다.

일반적으로 z는 x보다 작다. 이로 인해 기본적으로 AE를 통해 차원 축소의 효과를 기대할 수 있다. 차원 축소를 하는 이유는 z가 데이터 x의 중요한 요소들이 담겨 있는 특징들을 학습하길 원하기 때문이다.


그렇다면 어떻게 feature representation을 학습할 수 있는가?

AE는 원본을 다시 복원하는데 사용될 수 있는 특징들을 학습하는 방식을 취한다. AE의 과정을 보면 입력 데이터 x가 있고, encoder는 x를 더 낮은 차원의 z로 매핑시킨다. z는 encoder의 출력이다.


z는 두번째 네트워크인 decoder의 입력으로 사용된다. decoder의 출력은 입력 x와 동일한 차원이고 x와 유사해야 한다. 즉 원본 데이터를 복원하는 것이다.

decoder와 encoder는 동일한 구조를 지니며 대칭적이어야 한다. 대게는 CNN으로 구성한다.


전체 과정을 보면 입력 데이터 x를 encoder에 통과시킨다. encoder는 4 layer CNN이 될 수 있을 것이다. encoder를 거쳐 특징 z를 얻으면 z를 decoder에 통과시킨다. decoder는 upconv 일 수 있다.

CNN모델로 AE를 설계했을 때 encoder는 conv net, decoder는 upconv net인 이유는 encoder는 고차원 입력 x를 받아 저차원 특징 z로 변환하는 반면 decoder는 저차원 특징 z를 고차원으로 복원해야 하기 때문이다.

loss로는 L2 loss function을 사용하는데, 복원된 이미지의 픽셀 값과 입력 이미지의 픽셀 값이 서로 같은지를 비교하는 것이다.

중요한 것은 AE에서는 학습과정에서 추가적인 레이블을 필요로 하지 않는다는 것이다. 우리가 가진 데이터가 레이블이 없는 데이터여도 가능하다는 것이고, 그것으로 loss를 구할 수 있다.


사실 decoder는 training time에서 입력을 복원해서 loss 함수를 계산하는 용도로만 사용된다. 따라서 특징 z가 나오면 추가적인 분류기를 붙힌다.


레이블이 필요하지 않은 AE는 데이터가 부족한 지도 학습 모델의 초기 가중치로 이용할 수 있는 것이다. 소량의 데이터로 학습할 경우 과적합(overfitting)과 같은 다양한 문제가 발생한다.


AE를 통해 학습 데이터의 변형(variation)을 잘 포착해낼 수 있다. 즉 잠재 변수인 벡터 z가 학습 데이터의 variation을 잘 가지고 있다. VAE는 AE와는 관점이 조금 다르다. VAE는 새로운 데이터를 생성할 것이고, 이를 위해 모델로부터 데이터를 샘플링할 것이다.

VAE에서는 학습 데이터 xi가 있다. i는 1 ~ N이다. 이 학습 데이터는 잠재 변수 z에 의해 생성된다고 가정해보자. z는 어떤 벡터고, z의 각 요소들은 데이터의 변동 요소들을 잘 포착해내고 있을 것이다.

즉, 벡터 z가 다양한 종류의 속성들을 담고 있다. 예를 들어 얼굴을 생성한다고 하면, z는 생성된 얼굴이 웃고있는지, 눈썹의 위치, 머리의 방향 등이 있을 것이다. 이런 것들이 학습될 수 있는 잠재된 요소다.

생성 과정에서는 z에 대한 사전정보로부터 샘플링이 진행된다. 속성을 담기 위해서는 속성들이 어떤 분포를 가지는지에 대한 사전정보를 정의해야 한다. 가령 z에 대한 사전정보로 가우시안 분포를 선택할 수 있다. distribution, p로부터 샘플링하여 데이터 x를 생성해낸다.

파라미터에는 사진에 보이는 distribution, theta* 과 prior 등이 있다. 생성모델이 새로운 데이터를 잘 생성하게 하려면 true parameter, theta* 을 잘 추정해야 한다.


그렇다면 모델을 어떻게 설계할까?

prior인 p(z)는 단순한 가우시안으로 정한다. 하지만 conditional distribution, p(x|z)는 다르다. 우리는 p(x|z)를 가지고 이미지를 생성해야 한다. 대체로 p(x|z)는 neural network로 모델링한다.

이렇게 설계된 네트워크를 decoder network라고 한다. decoder는 잠재 변수z를 받아서 이미지로 디코딩하는 역할을 한다.


모델들의 파라미터를 추정하기 위해서는 모델을 학습시켜야 할 것이다. 위의 pixelRNN/CNN의 전략을 떠올려보자면 모델 파라미터가 학습 데이터의 likelihood를 최대화하도록 학습시키는 것이다. VAE의 경우 잠재 변수 z가 있다. p(x)는 모든 z에 대한 기댓값(likelihood)이다. p(x)를 최대화시키려고 할 때, pixelRNN처럼 gradient를 계산하며 최대화하지 못한다.


더 자세하게 들어가서 likelihood, p(x)의 첫번째 항은 prior, p(z)다. p(z)는 가우시안일 것이고, 이는 계산이 가능하다. p(x|z)는 우리가 정의한 decoder neural network의 출력이다. 따라서 z가 주어지기만 하면 p(x|z)는 계산이 가능하다. 그렇다면 문제는 모든 z에 대해 p(x|z)를 계산하고 싶지만 계산할 수 없다는 것이다.


해결책으로는 decoder network가 p(x|z)와 추가적으로 encoder network를 정의하는 것이다. encoder는 q(z|x)이고, encoder를 이용해서 입력 x를 z로 인코딩할 것이다. 이 encoder를 통해 p(z|x)를 근사시킨다.

이와 같이 p(x|z) 대신 p(z|x)를 정의하면 계산이 가능해진다. p(z|x)를 근사시키면 data likelihood의 최솟값(lower bound)를 구할 수 있고, 이를 통해 최적화가 가능해진다.


더 구체적으로 살펴보자. VAE에서 우리가 하고싶은 것은 데이터의 확률론적 생성(probabilistic generation)모델을 만드는 것이다. autoencoder에서는 encoder에서 입력 x를 받아 z를 만들고 decoder에서 z를 받아 다시 이미지를 생성했다. VAE도 기본적으로 encoder-decoder 구조다. 추가적으로 확률론적 의미를 가미한다.

우선 파라미터 ∅를 가진 encoder network q(z|x)를 살펴보자. encoder의 출력은 평균과 공분산으로, μ(z|x)∑(z|x)이다. 이 두개를 평균하여 z를 구한다.

decoder의 입력으로 z일 것이고, 출력으로는 다시 μ(x|z)∑(x|z)가 된다. 이를 평균내어 출력한다. p(x|z)에서 x의 차원은 입력 x와 동일하다.

z|xx|z를 얻으려면 이들의 분포로부터 샘플링해야 한다. 따라서 encoder/decoder network는 각각 z와 x에 대한 분포를 생성해야 한다.


data likelihood를 보게 되면 likelihood, p(x)에 log가 취해져 있는 것을 볼 수 있다. 거기에 z에 대한 기댓값(expectation)을 취한다. expectation을 취할 수 있는 이유는 p(x)가 z에 독립적이기 때문이다.


이 식을 확장해서 베이즈 룰(Bayes’ Rule)를 적용해보자. 그 다음 분모분자에 각각 상수인 q(z|x)를 곱해준다. 그리고 이 식을 3개 항으로 나눈다. 첫번째 항은 E(logp(x|z))이고, 나머지 두 개는 KL 항이다. 간단하게 설명하자면 KL divergence(차이)는 분포간의 거리를 측정하는 척도로, 두 분포가 얼마나 가까운지를 알려준다. 첫번째 KL는 q(z|x)와 p(z)가 얼마나 가까운지를 나타내는 것이다.


p(x|z)는 decoder network다. 이 첫 번째 항은 샘플링을 통해서 계산할 수 있다. 이런 샘플링 과정에서 미분이 가능하도록 하는 “re-parametrization trick”이라는 기법이 있다.

두 번째 항을 보게 되면 두 가우시안 분포 간의 KL divergence다. 우선 q(z|x)는 encoder에서 발생하는 분포로 평균/공분산을 가지는 가우시간 분포다. 그리고 prior, p(z)도 가우시안이다. 참고로 KL divergence에서 두 개의 분포가 모두 가우시안이면 closed form solution으로 풀 수 있다.

마지막으로 세 번째 항은 q(z|x)p(z|x)간의 KL이다. 앞서 p(z|x)는 계산할 수 없는 항이었다. p(z|x)를 계산하지 못하여 q로 근사시킨 것이다. 하지만 여기서 KL이란 두 분포간의 거리다. 즉 항상 0보다 크다는 것이다.

따라서 앞의 두 항만 가지고 gradient를 이용해 최적화시키면 된다.


VAE를 학습시키는 것은 최솟값을 최대화시키도록 최적화하는 것이다. 다시 말해 data likelihood의 최솟값을 최적화시키는 것이다. 최솟값을 최대화시키기 위해서는 파라미터 θ와 ∅를 구해야 한다.

최솟값 항을 보면 첫번째 항은 모든 샘플 z에 대한 기댓값(expectation)이다. z는 encoder의 출력이다. encoder로 z를 샘플링한 후, 모든 z에 대해 p(x|z)의 기댓값을 구한다. 즉 복원(reconstruction)을 의미한다. 첫번째 항이 크다는 것은 likelihood p(x|z)가 크다는 것이고, 이것은 데이터가 잘 복원되고 있다는 것을 의미한다.

두번째 항을 보면 KL divergence가 작아야 한다는 것이다. 우리가 근사시킨 분포(q)와 prior의 분포(p)가 최대한 가까워야 한다. 즉, 잠재 변수 z의 분포가 prior 분포(가우시안)와 유사해야 한다.


이렇게 구한 최솟값을 통해 VAE를 학습시키는 과정을 살펴보자. 우리는 이 lower bound를 최대화하길 원한다.

우선 forward pass에서 입력 데이터 x가 minibatch 크기로 있을 것이고, encoder를 통과하면 q(z|x)를 얻을 수 있다. q(z|x)는 KL divergence를 계산할 때 이용할 수 있다. q(z|x) 분포로부터 잠재변수 z를 샘플링한다. 샘플링한 z를 decoder에 통과시킨다. decoder network의 출력은 p(x|z)에 대한 평균과 분산이다. 이 분포를 바탕으로 샘플링하여 x^를 구한다.

training time에서는 log(p(x|z))가 최대가 되도록 학습시킨다.

이렇게 모든 항은 미분이 가능하기 때문에 backpropagation을 할 수 있다. gradient를 계산하여 encoder/decoder의 파라미터 θ와 ∅를 최대화한다.


VAE를 학습시키고 나면 데이터 생성시에는 decoder network만 필요하다. 앞서 training time에서는 z를 p(z|x)에 대해 샘플링했다. 하지만 생성과정에서는 prior(가우시안)에서 샘플링한다. 이를 바탕으로 데이터 x^을 샘플링한다.


VAE를 MNIST로 학습시키고 샘플들을 생성시킨 결과다. 변수 z가 데이터의 잠재적인 속성들을 나타낸다. 오른쪽이 2차원 z분포에서 vary z1 / vary z2 의 조합으로 생성된 이미지다. z1과 z2의 값이 변함에 따라 이미지도 아주 부드럽게 변하고 잇는 것을 볼 수 있다. z는 독립적이고 이로 인해 각 차원마다 독립적인 해석이 가능한 요소들이 있다.


얼굴 이미지의 예로 vary z1은 위 아래로 웃음의 정도를 나타낸다. vary z2는 머리의 위치가 바뀌는 것을 나타낸다. 이를 통해 VAE를 학습시킨 결과 z라는 변수가 해석 가능하고 아주 다양한 의미를 가지는 요소들이 인코딩될 수 있다는 것을 알 수 있다.

앞서 학습시킨 encoder network에 새로운 입력 x를 넣어 z 공간으로 매핑시키면, 이 특징벡터를 classification이나 다른 테스크에 사용할 수 있다.


VAE는 이미지들을 잘 생성해내지만, 단점으로는 원본에 비해 흐리다는 점이다. 특히 얼굴 이미지는 더더욱 그렇다.

VAE는 autoencoders의 확률론적 변형 버전이다. AE는 x를 받아 z를 만들고 다시 x를 복원하지만, VAE는 데이터를 생성해내기 위해 분포와 샘플링 개념이 추가되었다. 또, 계산할 수 없는 분포를 다루기 위해 최솟값을 계산했다. Variational은 계산할 수 없는 형태를 계산할 수 있도록 근사시키는 방법을 의미한다. 따라서 VAE가 된다.

VAE의 장점은 생성 모델에 대한 원칙적 접근 방법이라는 점과 모델에서 q(z|x)를 추론한다는 점이다. q(z|x)는 다른 테스크에서도 유용한 방법이 될 수 있다. 단점으로는 likelihood의 최솟값을 계산하는 것이다. 이렇게 되면 섬세하지 못할 수 있다.



Generative Adversarial Networks(GAN)

앞서 살펴본 pixelRNN/CNN은 계산 가능한 확률분포를 가정했다. 이를 이용해서 학습 데이터의 likelihood를 최적화시켰다.

반면 VAE는 잠재 변수 z를 두고 생성 과정을 정의했다. 잠재 변수 z는 많은 이점이 있지만, VAE는 계산할 수 없는 확률분포를 가정하기 때문에 likelihood를 직접 최적화시키지 못하고 최솟값을 구해 그것을 최적화시켰다.

하지만, “확률분포를 직접 모델링하지 않아도 되지 않을까”에 대한 의문으로 시작되어 GAN에서는 확률분포를 모델링하지 않는다. GAN에서는 2 player game 이라는 방식으로 학습 분포를 학습한다. GAN에서는 복잡한 고차원 학습 분포로부터 샘플링하는 것이다.

하지만, 우리가 가진 분포가 매우 복잡(neural network)하기 때문에 분포에서 직접 샘플을 만들어내는 과정이 없다. 따라서 우선 gaussian random noise같은 더 단순한 분포를 활용할 것이다. 단순한 분포에서 우리가 원하는 학습 분포로 변환하는 함수를 배워야 한다.


GAN에서는 입력으로 random noise 벡터(z)를 받는다. 벡터의 차원 수를 직접 명시해준다. 그리고 입력 z가 생성 네트워크를 통과하면 학습 분포로부터 직접 샘플링된 값을 출력한다. 따라서 모든 random noise 입력이 학습 분포의 샘플에 매핑되길 원한다.


two player game을 살펴보자. 하나는 generator이고, 다른 하나는 discriminator(식별자)이다. generator는 사실적인 이미지를 생성하여 discriminator를 속이는 것이 목표이다. 식별자는 입력 이미지가 실제인지 거짓인지 구별하는 것이 목표이다.

식별자는 이미지가 generator가 만든 가짜 이미지는인지 아닌지를 가능한 잘 구분해 내야 한다.


random noise가 generator의 입력으로 들어가고, generator는 가짜 이미지를 생성한다. 식별자는 실제/가짜 이미지를 구별할 줄 알아야 한다. 그래서 식별자의 출력은 이미지가 진짜/가짜인지 이다.

즉, 아주 좋은 generative model을 만들기 위해서는 discriminator가 아주 잘 학습되어 진짜인지 가짜인지 잘 구별해야 하고, 그러려면 generator가 더 실제같은 가짜 이미지를 만들 수 있어야 한다.


minmax objective function는 generator network의 파라미터인 G를 최소화시킨다. 또, discriminator network의 파라미터인 D는 최대화시킨다. 이 함수에서 말하는 것은 데이터에 대한 Expectation(logD(x))이다. log D(x)는 실제 데이터(x)가 데이터 분포 p_data에 속할 확률(likelihood)이다.

두번째 항을 보면 p(z)를 따르는 z에 대한 기댓값에서 z ~p(z)의 의미는 generator에서 샘플링한다는 의미다. 그리고 D(G(z))는 생성된 가짜 이미지(G(z))에 대한 식별자의 출력이다. D(x)는 실제 데이터이므로 값이1 이면 좋다. 반면 D(F(x))는 가짜 데이터에 대한 것이므로 0일수록 좋다.

그리고 식별자의입장에서 objective function을 최대화시킨다는 것은 진짜인지 가짜인지를 더 잘 구별해낸다는 의미다. 반면 generator는 objective function이 작을수록 좋으므로 D(G(z))가 1에 가까울수록 좋다.

D(G(z))가 1에 가까우면 1-D(G(z))는 값이 작아진다. 작아진다는 것은 가짜 이미지를 진짜라고 잘못 분류한다는 의미다. 다시 말해 generator가 진짜 같은 이미지를 잘 만들고 있다는 것이다.


GAN은 기본적으로 비지도 학습에 해당한다. 즉, 레이블이 필요하지 않다. generator에서 생성된 데이터의 레이블은 가짜 이미지라는 의미에서 0이다. 그렇다면 실제 이미지의 경우 1에 해당한다. 이 레이블은 식별자의 loss함수에서 사용된다.


학습을 시킬 때는 generator를 학습시키는 경우에는 식별자를 고정시키고 backprop를 진행하고, 식별자를 학습시키는 경우에는 generator를 고정시킨 후 backprop를 진행한다.

GAN을 학습시키려면 generator와 discriminator를 번갈아가면서 학습시킨다. 식별자의 경우 objective function이 최대가 되는 theta를 학습시키기 위해 gradient ascent를 이용하고, generator는 반대로 gradient descent를 이용한다. descent를 통해 파라미터 theta_G를 학습시켜서 objective function이 최소가 되도록 한다.


따라서 GAN은 two player, minmax 를 이용해서 discriminator/generator를 번갈아가면서 학습시킨다.

여기서 중요한 것은 실제로는 generator의 objective function이 학습이 잘 안된다. 그 이유는 loss 곡선을 보면 알 수 있는데, 오른쪽 아래의 그래프가 D(G(x))의 loss 곡선이다. generator의 경우 1-D(G(x))의 값이 높을수록 좋다. loss가 최소가 되길 원하는데, loss의 길울기는 오른쪽으로 갈수록 점점 커진다. 즉, D(G(x))가 1에 가까울수록 기울기도 커진다는 것이다.

이는 generator가 식별자를 잘 속이고 있으면 gradient도 점점 더 커진다. 반대로 generator가 아직 잘 학습되지 않는 경우라면 식별자가 쉽게 구분할 수 있는 상태로 x축 상의 0에 가까울 것이다. 이 지점은 gradient가 상대적으로 평평하다.

이는, gradient가 generator가 생성을 이미 잘 하고 있는 지역에 몰려있다는 것이다. 우리가 원하는 것은 샘플이 좋지 않을수록 gradient가 높아야 한다. 따라서 generator가 학습이 어렵다.


그렇기에 gradient 개선을 위해 objective function을 조금 변경해야 한다. generator에서도 gradient ascent를 사용해준다. 앞의 수식에서는 식별자가 정답을 잘 맞출 확률(likelihood)를 최소화시키는 방법이었다면, 이제는 반대로 식별자가 틀릴 확률을 최대화시키는 것이다. 이를 통해 objective function을 log(D(G(x)))를 최대화시키는 것으로 구현할 수 있다. 오른쪽 밑 그래프의 초록색 그래프에서 음수만 붙여주면 된다.


요약하면, 학습은 반복으로 진행될 것이고, 학습 순서는 우선 식별자를 먼저 조금 학습시킨 후 generator를 학습시키는 방식이다.

k번만큼 식별자를 학습시키고, noise prior z, p(z)에서 미니배치만큼 샘플링한다. 그리고 학습 데이터 x에서 실제 샘플을 미니배치만큼 샘플링한다. 샘플링한 노이즈를 generator에 통과시키면 가짜 이미지가 생성될 것이다. 그러면 미니배치만큼의 가짜 이미지와 미니배치만큼의 진짜 이미지가 존재하게 된다.

식별자의 gradient를 계산할 때 이렇게 준비한 진짜/가짜 이미지를 사용한다. 그 후 식별자의 파라미터를 업데이트한다.

이 작업이 끝나면 generator를 학습시킨다. 또 다시 noise prior, p(z)에서 노이즈를 샘플링한다. 그 노이즈를 generator에 통과시키고 generator를 최적화시킨다.

이런식으로 반복적으로 번갈아 학습한다.


GAN의 안정적인 학습을 위한 방법 중 대표적인 예로 “Wasserstein GAN”이 있다.

원래의 GAN은 fully connected network를 사용한다. 그러나 기술이 발전함에 따라 FC layer 대신 CNN을 적용시켰다. 그 모델 이름이 DCGAN이다.

전체적인 내용을 보면 입력 노이즈 벡터 z가 있고, z를 위와 같은 과정을 통해 변환 출력한다.


그 결과 위와 같이 다양한 가구들이 잘 생성된 것을 볼 수 있다.


여기에서는 2개의 랜덤 노이즈 벡터z 2개를 잡고, 그 사이를 보간한 것을 볼 수 있다. 위의 사진은 두 개의 랜덤 노이즈 z를 보간해서 이미지를 생성한 결과다. 양 끝단이 z이고, 이를 보간하며 자연스럽게 연결시킨다.


다른 방식으로 접근해보자. 벡터 z를 가지고 벡터 연산을 한다. 이 실험에서는 웃고 있는 여성의 이미지와 웃고 있지 않은 여성/남성의 사진도 뽑는다. 그리고 뽑은 벡터 z 들에 각 평균을 취한다.

그 후 3개를 벡터 연산하면 웃는 남성이 만들 수 있다.


Reference

http://cs231n.stanford.edu/slides/2017/cs231n_2017_lecture13.pdf

This post is licensed under CC BY 4.0 by the author.