본문 바로가기

Programming Project/CS294-158

[한글-1] CS294-158 Deep Unsupervised Learning Spring 2019


투명한 기부를 하고싶다면 이 링크로 와보세요! 🥰 (클릭!)

바이낸스(₿) 수수료 평생 20% 할인받는 링크로 가입하기! 🔥 (클릭!)


* 이 글을 쓰는데 3주가량 걸렸다;; 생각보다 강의가 너무 길고 내용이 많고 이해하기라 힘들고 조금 지루하다. 동영상 강의도 온전하지 않지만 그렇기에 이 글도 뭔가 부분 부분 비어있는 느낌이 듦으로, 동영상 강의와 같이 보는 것을 추천한다.


Lecture1a - Logistics(실행 계획)

2019/03/27 - [Programming Project/CS294-158] - [한글-0] CS294-158 Deep Unsupervised Learning Spring 2019



이전 글에 적어 놓았으니 참고하기 바란다.


Lecture1b - Motivation

왜 unsupervised learning을 공부해야 하는가?


이번 글은 전반적인 motivation 등에 관련된 내용으로 대략적인 내용만 짚고 넘어가면 된다.


supervised learning은 굉장히 잘 동작하지만, data를 모으는 것이 힘들다.


unsupervised learning은 라벨링이 되어있지 않은 raw data들로부터 아무런 사람의 노동(annotation, giving reward 등) 없이 정답을 배울 수 있다.




unsupervised learning에는 두 가지 큰 접근 방법이 있다.


그 중 하나는 데이터의 확률 분포를 생성하는 generative models - based unsupervised learning 이고 다른 한 종류는 데이터를 이해해서 스스로 새로운 데이터를 생성해내는 self-supervised learning이다. (추후 다시 설명을 할 것)



Geoffery Hinton이 말하길

"인간의 뇌는 10^14 의 synapses를 가지고 있는데, 우리는 단지 10^9초 만을 살아간다. 따라서 데이터보다 너무 많은 parameter을 가지고 있다고 할 수 있다. 이 말은 적어도 1초당 10^5 dimension의 생각(감각을 포함해)을 input으로 받을 수 있는 유일한 곳이므로 우리는 수많은 unsupervised learning을 해야한다는 뜻이 된다."


이라고 했다고 한다.


(번역을 하다 보니 뭔가 문장이 매끄럽지 않아진 것 같지만 여튼 unsupervised learning은 우리가 실생활에서 계속 하고 있는 것이라는 의미이다)



여튼, 요약하자면  unsupervised learning은 다른 모든 것들보다 더 데이터를 얻기 쉽고, 실생활에서 인간이 학습하는 방법과도 가장 유사하기 때문에 중요하다고 할 수 있다는 것이다.





Deep unsupervised learning으로 할 수 있는 것들

- Generate novel data (새로운 데이터 생성)

- Compression (데이터 압축)

- Improve downstream tasks (하층부의 일들 개선)

- Flexible building blocks (다른 문제의 component로 사용 가능한 유연한 블록들)





특히 image생성에 대한 역사를 되짚어보자면 다음과 같다.






위 까지가 GAN 이전 세대의 generative model들이다.



그리고 아래부터가 GAN 이후 세대의 모델들이다.




처음 나온 GAN



DC GAN이 되며 2015년, GAN이 한층 성능이 좋아졌다.




GAN으로 이미지 고해상도 변환도 가능하고



CycleGAN으로 이미지 transfer이 가능해 졌다.


왼쪽이 오리지날 이미지이고 오른쪽이 변환 후의 이미지이다.







최근엔 GAN을 통해 High resolution images를 생성해낼 수 있음을 보인 Big gan도 있다.


아래는 latent space interpolation을 통한 이미지 변환 동영상이다.


https://www.youtube.com/watch?v=sW6D34mckkk




급기야



최근 엔비디아에서 StyleGAN이라는 너무 선명한 고 해상도 이미지를 만들어내기에 이르렀다. 그리고 이전보다 더욱 많은 세부적인 조절을 할 수 있게 되었다.




Wavenet에서는 Audio를 만들어내기도 하며 Video 등도 만들 수 있다.


당연히 Text(글) 등도 만들어낸다.



또한 기존의 이미지 압축보다 성능이 좋다.






Lecture 1c - Likelihood Models

I: Autoregressive Models

이제부터 본격적인 내용이다. 

autoregressive model은 처음으로 배워볼 deep generative model에 대한 친구들이다.
( regressive(회귀) model에 대해 기본적인 내용은 알고 있기를 바라며.. )

얘네들은 train하기도 쉽고 컨셉이 쉽기 때문에 처음 배우기가 좋다.

목차는 다음과 같다.



우선 Simple generative model에 대해 이야기 할 것인데, 이 simple generative models들이 얼마나 성능이 망가지는지에 대해서 이야기 할 것이다.

이를 통해 현대의 모델을이 가지는 구조에 대한 이해를 돕는것이 목적이다.



우리는 어떻게 텍스트, 이미지, 오디오 등의 합성을 할 수 있을까?

혹은 데이터 압축이나 이상 탐지는 어떻게 할 수 있을까?

(데이터 압축이 여기에 들어가는 이유는 이 또한 작은 데이터로 큰 데이터를 만드는 generative model 이기 때문이라고 한다)



Linelihood based model은 data의 joint distribution 이다.


X로부터 뽑은 sample data x1~xn이 있다고 하면 새로운 data y가 이 X에 속할 확률을 구해준다고 생각하면 간단하다.


즉 임의의 x에 대해 p(x)를 구하는 것 이다.



이것이 간단하지만은 않은데, 우리는 복잡한, 높은 차원의 데이터를 상대하기 때문이다.


(128x128x3 image의 경우 ~50000차원의 공간이다.)



또한 연산횟수나 통계적인 부분에서의 효율성 또한 챙기고 싶다.

그러기 위해서는

- 효율적인 학습과 모델 표현

- 표현력(퀄리티?)과 일반화

- 샘플링 품질과 속도

- 압축률과 속도


등과 같이 표현될 수 있는 trade-off에서 효율적이어야 한다.




일단 아까전에 말했듯이 최악의(simple한) generative model부터 생각 해 보자.


다시한번 말하자면, 우리의 goal은 우리가 본 x1~xn data distribution 에 해당하는 확률 분포를 찾는 것이다.


우리가 유한 집합 {1,...,k} 안에서 value를 가지는  sample을 사용한다고 생각 해 보자.

추출한 데이터의 값이 가지는 결과의 종류가 유한하다는 뜻이다.


그렇다면 어떤 모델을 쓸 수 있을까? -> 히스토그램


1~k 를 카운팅하는 히스토그램을 사용하면 된다


pi = (# times i appears in the dataset ) / (# points in the dataset)


이렇게 될 것이다.



그렇다면 우리는 임의의 x에 대해 p(x)를 구하는 것이 가능하게 되었다.




게다가 pi를 알고있기 때문에 이 모델로부터 임의의 1~k사이의 데이터 sampling 을 할 수 있다.



그렇지만 이 방법만으로는 다양한 방법의 결과로 충분하지 못하다.


그 이유는 curse of dimensionality라고도 불리는 문제 때문인데, 실생활의 데이터는 너무나도 많은 dimension을 가지고 있기 때문에 위의 방법처럼 1~k 와 같은 모든 경우의 수로 표현한다면 너무나 많은 데이터가 필요할 것이다.


예를 들어, 제일 간단하다고 하는 MNIST만 해도 28*28 pixel의 이미지인데, 28*28픽셀 이미지로부터 나올 수 있는 모든 경우를 생각 해 보면 2^784 , 근사하면 10^236의 사이즈 크기가 나온다.


이렇게 되면, MNIST에는 6만개의 데이터가 있는데, 이 상황에서 컴퓨터의 한계로 인해 2^784에 비해 너무나 적은 파라미터만이 학습되게 된다.



이를 해결하기 위해서 function approximation을 사용한다.




핵심은 아래의 수식을 만족할 파라미터 θ를 찾자는 것이다.


효율적인 함수를 통해 근사한다면 효율적인 방법이 될 것이다.



다만 이를 어떻게 학습시키냐에 대한 것이 복잡한데, 우리는 파라미터가 정해지면 그 파라미터로 인해 발생하는 p(x)에 대한 결과값만을 알고 있지, 어떤 방법이 최적인지는 알지 못한다.



이를 해결하기 위해서 우리는 문제를 정확하게 정의하도록 한다.


위의 loss 함수를 정의하고 (loss 함수는 주로 얼마나 잘못되었는지를 계산하는 척도이다) 이를 통해서 해결이 가능하다.


loss함수는 Maximum likelihood 함수 등을 통해 정의될 수 있다.



왜 굳이 이렇게 하느냐는 질문에 대한 답으로, 이것이 실제 예제에서 동작하기 때문이라고 한다.


그리고 또한 SGD(Stochastic gradient descent)를 통해 같이 계산하도록 한다.


Maximum likelihood + SGD를 사용하는 이유 또한 큰 데이터셋에서 잘 동작하기 때문이라고 한다.





위의 방법은 전반적인 학습을 위한 세팅이었다.


그렇다면 모델은 뭘 사용하면 좋을까?




Bayes nets란 뉴럴넷과 비슷한 개념을 가진 친구다. 다만 바라보는 시야가 조건부 확률을 통한 output이라는 점이 달라졌다. 







자 그러면 이제 베이즈넷 구조를 가진 모델의 경우, gradient가 충분히 tractable하다. 그렇기 때문에 우리는 maximum likelihood training을 쓸 수 있게 된다!


(강의 내용이 칠판에 설명하는 상황에서 칠판을 안 보여주기 때문에 말로만 설명하기에 한계가 있는 것 같다ㅠㅠ.. 영어이긴 하지만 슬라이드를 잘 읽어보면 이해가 간다...ㅠㅠ)


이 방법을 autoregressive model이라고 부를 수 있을 것이다.


(정리하자면 Bayesian model 사용하고 maximum likelihood training 돌리면 autoregressive model 이라고 한다는 말인 것 같다.)


※ autoregressive model이라고 자꾸 강의에서 언급하고 제대로 된 정의를 말을 안해줘서 다른 링크가서 좀 찾아봤다.


https://datascienceschool.net/view-notebook/e880ecd416554dbf84db6a3e8f426b99/


autoregressive model의 좀더 정확한 설명은, 모델이 시간 t 의 output을 도출할 때에 시간 t-1, t-2 ... 들의 output또한 참고하는 모델이라고 하는 것이 맞을 것이다.

몇개의 이전 timestamp로부터 가져올 것인지는 AR(n)모형의 n에 따라 다르다고 한다.

자세한건 링크 참고





그럼 대충 설계를 해보면



위와 같이 naive하게 설계할 수도 있다.


다만 저렇게되면 mnist같은 경우에는 784개의 input이므로 784번의 확률 계산을 하여야 하므로 역시 좋지 않다는 것을 알 수 있다.






특히 우리가 아웃풋을 생성해낼 때, 매 확률분포에 대하여 새로운 아웃풋을 생성해내므로 높은 dimension에 대해 제한적이다. (mnist만 해도 784개의 새로운 dim을 생성 할 때마다 새로운 확률을 계산 할 테니까, output크기가 커짐에 따라서 파라미터 수가 linear 하게 커지므로 너무 비효율적이다.)


특히 텍스트 생성 등을 할 때를 생각 해 보면, 이전 time으로부터 다음 time까지 이동할 때 전후 맥락 등의 요소는 전혀 고려되지 않으므로 (정보의 이동이 없으므로) 바람직하지 않다. (라고 강의에서 설명 하는데 이건 잘 이해가 안간다)


그 해결책은 conditional distribution에서 파라미터를 sharing 하는 것 이다.


이제 RNN / Masking 등으로 이를 현명하게 풀어간 방법에 대해 배워 볼 것이다.





RNN이 무엇인지에 대해서는 이미 안다고 생각하고,


RNN 은 완벽히 autoregressive model을 풀어나가기에 적절한 구조이다.


물론 단순히 RNN만을 놓고 보면 전혀 확률이나 autoregressive model등과는 상관없는 시퀀스적인 인풋을 받아서 아웃풋을 뱉는 모델이다.


그렇지만 RNN에 input을 x1, x2 ... 를 주고 output으로 각 time마다의 조건부 확률을 뱉어주게 만든다면 우리가 하려는 일과 정확히 일치하게 만들 수 있고 이 방법으로 텍스트 생성 등에서 상당한 성공을 거뒀다.


머신러닝에서는 우스갯 소리로 성능이 안나오면 레이어 개수를 늘려라 라는 말이 있다. 그렇지만 우리는 이제 더 많은 레이어를 쌓는것이 전혀 도움이 되지 않는 예시들을 보게 될 것이다. 그 이유는 통계적 의존성을 잃는 등의 이유 때문인데 이것은 레이어의 추가로 해결할 수 없다.

기존의 통계적인 머신러닝들이 딥 러닝과 반대되는 개념이 아니고, 실제로 그 두가지는 서로 상호보완적인 관계를 이루고 있다.


이 글을 볼 독자들이 이미 멀티 레이어 퍼셉트론이라던지 컨볼루션이라던지, res-net, attention 등등의 supervised learning에 대한 사전 지식이 있다고 생각하며, 이제 앞으로 여러 모델들이 어떻게 deep autogressive model에 적용 되는지 볼 것이다.






우리는 위에서 RNN을 통해 어떻게 deep autoregressive model을 매개변수화(parameterization)하는지 보았다. 그리고 이론적으로 충분히 넓은 RNN을 가지고 있다면 우리는 올바른 approximation을 할 수 있게 된다. 그렇지만 실제로 시도 해 보면 그렇지 못하게 만드는 몇가지 문제가 있는데, 우선 sequential 한 데이터의 처리를 하다보면 속도가 느려진다는 단점이 있다.


기존 컴퓨터들은 한 layer 단위의 병렬 처리에는 최적화 되어 있지만, sequential - linear하게 증가하는 경우 그렇지 못하다. 그래서 우리는 더욱 효과적인 방법으로 병렬적으로 네트워크를 사용할 수 있는 방법에 대해 시도해 볼 것이다.



이번에 배워볼 모델은 Masked Autoencoder for Distribution Estimation 이라는 친구다. 한창 Autoencoder이 주목받고 있던 시절 발표된 논문이다.





오토 인코더는 기본적으로 데이터 x를 인코딩 한 output을 만드는 네트워크와

output을 x로 다시 디코드 하는 네트워크로 이루어져 있다. 그치만 여기서 이것이 어떤 통계학적인 의미를 가지는것에 대해서는 명확하지 않았다고 한다.


이 페이퍼에서 하려고자 하는 것은 오토 인코더를 distribution estimator로 사용할 수 있는 방법에 대해서이다. 다시 말해서 autoregressive model은 주어진 data point X에 대해 likelihood estimation을 리턴해 주며 그 곳에서 샘플링 또한 할 수 있는데 이 기능을 multi-layer perceptron weight를 masking함으로써 구현 해 보자는 이야기이다.



위의 오른쪽(MADE) 그림을 보자.


p(x_2)를 구하고 / p(x_3|x_2)를 구하고 / p(x_1|x_2,x_3)을 구한다. (node에 붙은 번호를 자세히 보자. dependency 와 관련된 번호이다.)


이러한 것들을 masking한 배열을 곱해줌으로써 몇몇 weight를 끊어서 한번 구현 해 보자는 이야기이다.


p(x_2)는 입력 x1 x2 x3의 영향을 전혀 받지 않아야 하므로(어떤것에도 depended 되지 않았으므로) 모든 아래의 model로 부터 떨어져 있고, p(x_3|x_2)는 x2의 영향을 받아야 하므로 맨 아래의 x2 node로 부터 flow가 흘러간다. 마지막으로 p(x_1|x2,x3)의 경우 맨 아래의 x2,x3의 노드로부터 flow가 흘러간다.


이를 구현하기 위해서 임의의 node간의 연결만을 남겨주고, 맨 아래의 경우에는 x1만 볼 것인지, x1 x2를 동시에 볼 것인지 등등에 따라 연결해주면 원하는 output을 받을 수 있다. (이를 mask로 weight를 masking하여서 (0을 곱하면 edge가 사라지는것과 마찬가지이므로)구현한다)



* 모든 autoregressive model 은 order이 있고, 위 그림은 x2 -> x3 -> x1 순서대로 진행하는 것을 보이는 뉴럴 넷 이다.


코드는 아래와 같이 구현이 가능하다.



실제 코드 자체는 굉장히 쉬운데, mask를 param과 곱한 후에 matrix multiplication 해 주면 된다. 파라미터에 대한 설명은 comment에 자세히 되어 있다.



결과가 위와 같다고 한다.




 


이제 다음으로 살펴볼 데이터는 다시 sequence data이다.


우리가 어떤 문장, pixel의 연속 등과 같은 sequence를 가지고 있다고 할 때,


1D convolution 을 사용해서 conditional distribution을 구할 수도 있다.



위 그림과 같은 connection을 연결해준 후, output이 conditional distribution을 예상하도록 한다면 된다.


다만, 이렇게 된다면 limited receptive field (output을 생성하기 위해 수집한 정보의 수집 범위가 제한된다는 뜻 정도로 해석하면 된다)의 문제가 있어서 


위와 같은 connection으로 개선된 receptive field를 만들기도 한다.


위와 같은 방식을 기본적으로 masking으로 처리하게 되면 (모든 커넥션을 만들어놓고 끊는) 굉장히 비 효율적이므로 우리는 convolution layer을 사용해 처리하도록 한다.




2d에서 이를 도전한 방법 중 하나는 PixelCNN이다.



x_i를 예측하는 데에 저 모든 blue 영역을 prev로 하는 conditional distribution이 들어갔으면 좋겠다는 것이다.



그것을 PixelCNN은 masked된 conv filter로 해결하였다. 좌상단부터 차례로 이전 입력을 입력받아 output으로 쓴다. 





PixelCNN같은 경우 문제는 receptive field를 보았을 때, blind spot이 생길 수 있다는 문제가 있다. 필터의 생긴 모양 때문에 우측 상단을 조건부 확률의 조건으로 확인하지 못한다는 문제가 있다.



이를 해결하기 위해 나온 것에 gated pixel cnn이다.




두 가지 input을 받는데, 이전 모든 vertical의 정보를 input으로 받는 input과 왼쪽의 짜다리를 입력으로 받는 horizontal input (1D masked conv를 생각하면 된다)를 받아서 output을 내보내면 짜잔~ blind spot이 사라졌습니다~~


결국 이를 통해서 성능이 좋아졌다고 한다.




추가적으로, 각 conditional distribution에서 더 나은 일반화(generalization)를 위해 softmax를 사용하지 않기로 결정할 수 있다. 근처의 pixel value가 더욱 상호작용할 확률이 높다는 것을 알고 있기 때문이다. (더욱 날것의 input을 그냥 넣어주기 위해서..?)

















---------------------------------------------------

이상으로 Week 1 수업인데요, 


이거 수업 번역하면서 느낀건데 제 글 퀄리티가 넘 처참하네요 ㅠㅠ


수업이 엄청 친절한 편이 아니라서 저 자체가 이해가 70%쯤 밖에 안되어서 내용을 꽉꽉 채우지 못했습니다 ㅠ