
이전 글에서는 Generative Model taxonomy에서의 왼쪽 절반을 다루었다. 이번 글에서는 나머지 반인 GAN과 Diffusion Model에 대해 알아보려고 한다.
이전에 우리가 살펴본 Generative Model들은 Autoregressive model과 VAE였다. 이들에 대해 간단하게 복습하고 넘어가자.
- Autoregressive Model : training data의 likelihood를 direct하게 maximize한다.
- VAE : latent z를 도입하고, ELBO를 maximize한다.

지금부터 우리가 배울 GAN, 즉 Generative Adversarial Network는 의 분포를 모델링 하는 것을 포기하지만, 에서 sampling은 할 수 있는 방법을 제시한다.
이전에도 이야기했듯이, 우리가 사는 우주가 특정 분포(여기서는 를 따른다고 하자. 우리는 이 분포에서 data를 sampling하고 싶은 것이다. 이를 위해 GAN은 latent variable 를 도입하고, prior 분포 는 unit gaussian으로 설정한다. 분포 에서 를 sampling하고, 이를 Generator Network 에 넘긴다. 이때 는 Generator Distribution 에서 sampling한 sample이다. 우리가 원하는 최종적인 목표는 Generator Distribution 과 가 비슷해지는 것이다. 현실과 비슷한 이미지를 생성하는 Generator Network를 만들겠다는 의미이다. (Generator에 대한 설명은 추후에 하겠다. 여기서는 그냥 이미지를 생성하는 네트워크라고만 이해하고 넘어가자.)

GAN은 Generator Network와 Discriminator Network, 이 두 가지의 네트워크로 구성된다. Generator와 Discriminator는 서로 속고 속이는 관계의 네트워크이다. Generator 네트워크는 로부터 fake data(새로운 이미지) 를 생성하고, Discriminator가 real data라고 착각하도록 만드는 것이 목표이다. 여기서 fake data는 모델이 생성한 이미지, real data는 원본 이미지라고 생각하면 될 것 같다. 반면 Discriminator는 Generator가 생성한 fake data와 real data를 구분하는 것이 목표이다. 따라서 Generator는 자신이 생성한 이미지가 진짜라고 믿도록 Discriminator를 속여야 하는 것이고, Discriminator는 이에 속아 넘어가지 않고 real image와 fake image를 제대로 판별해야 하는 것이다. Generator와 Discriminator는 jointly train되는 관계를 가진다.
저자들은 Generator와 Discriminator가 서로 싸우는 환경을 만들어 놓음으로써 Generator가 더 좋은 퀄리티의 fake data를 생성하도록 유도한 것이다. 학습이 계속될수록 Discriminator는 속이기 더 까다로워질 것이고, 그에 따라 Generator도 더 좋은 퀄리티의 이미지를 만들기 위해 노력할 것이기 때문이다. 참고로, Generator와 Discriminator는 모두 Neural Network이고, 대부분 CNN 구조를 사용했다.
&nsbp 이제 GAN의 training objective를 살펴보자. 
이렇게 Generator(이하 G)와 Discriminator(이하 D)를 동시에 training하기 때문에 위에서 jointly train이라는 표현을 사용한 것이다. 이 식은 G와 D의 관점에서 따로따로 봐야 이해하기가 편하다. 들어가기 전에 G는 minimize, D는 maximize한다는 것을 알고 들어가자.
G를 고정시켜 놓고 D의 관점에서 식을 해석해보자. 먼저, 는 이미지가 real인지 fake인지에 대한 확률을 알려준다.
-> 즉, 는 이미지가 real data일 확률을 의미한다.
따라서 은 이미지가 real이라는 뜻이고, 은 이미지가 fake라는 의미이다.

D의 입장에서는 에서 온 real data에 대해서는 을 원하고, G가 생성한 fake data에 대해서는 을 원한다.
위의 식에서 첫 번째 항인 부터 살펴보자. 항을 보면 를 우리의 세계, 즉 true distribution에서 sampling하는 것을 확인할 수 있다. 이를 maximize하면 에 가까워지기 때문에 real data로 판별할 확률이 올라가는 것이다.
두 번째 항인 은 조금 다른 의미를 가진다. 먼저 를 에서 sampling한다. 또, 가 의미하는 바를 살펴보아야 한다. 는 generator가 생성한 sampledmf 나타내기 때문에, 는 G가 생성한 sample이 진짜일 확률을 의미한다. Discriminator 입장에서는 이를 fake로 판별해야 하기 때문에 (즉, minimize하는 것)을 원할 것이다. 그러나 우리는 통일성 있게 D를 maximize하고 싶기 때문에 여기에 (-) 부호를 만들어서 Maximize를 하게 해주면 된다.
우리가 이전에 얘기했던 대로 D는 real data는 real data로(첫 번째 항), G가 생성한 data는 fake로(두 번째 항) 판별하고 싶어하는 것이 objective에도 녹아 있는 것이다.
다음은 Generator이다. D를 고정시켜 놓고 G의 관점에서 식을 해석해보자.

첫 번째 항은 G와 관련이 없기 때문에 두 번째 항 만 살펴보면 된다. G의 입장에서는 D가 를 real data라고 판별하도록 만들고 싶을 것이다. 즉, 를 유도하고 싶어한다는 의미이다. 그렇게 되면 log 값이 으로 가까이 가기 때문에 minimize가 되는 것이다.
이러한 식을 가지고 GAN을 훈련시키게 되는데, 구체적인 update rule은 아래의 사진과 같다.

D는 Maximize 해야 하기 때문에 gradient ascent, G는 minimize 해야 하기 때문에 gradient Descent를 사용한다. 식을 간단히 써서 로 표현할 수 있는데, 이 loss function은 정확한 loss value가 아니기 때문에 loss 그래프를 보는 것이 의미가 없다. 그렇기 때문에 학습하기가 어렵고, 학습이 잘 되어가고 있는지 알 방법도 딱히 없다.
그나마 사용할 수 있는 방법이 있다. 학습 초반에 G의 성능은 아직 좋지 않을 것이기 때문에 D는 굉장히 쉽게 G가 생성한 이미지를 가짜라고 판별할 것이다. 따라서 에 가까울 것이다.
이러한 training objective는 수학적으로 증명해봐도 의미가 있다고 하지만, 실제로 학습시킬 때에는 수렴시키기 어렵다는 단점이 있다. 또, 데이터셋이 변하지 않는 일반적인 classification 문제와 다르게 GAN은 Generator에 의해 dataset이 계속 변하기 때문에 이것 또한 어려움을 만드는 문제들 중 하나이다.
또, G의 Gradient를 업데이트 하려면 D를 반드시 거쳐야 한다는 것도 문제들 중 하나이다.
GAN 논문이 나온 이후 이러한 architecture를 사용한 많은 연구들이 진행되었다. 그 중에 몇 개를 소개하려고 한다.

DC-GAN은 non-toy data에서 연구된 첫 번째 GAN architecture model이었다.

StyleGAN은 조금 더 복잡한 구조를 사용하지만, GAN보다는 더 좋은 결과를 만들었다고 한다. 너무 깊게 들어가지 않고, 이런 게 있구나 하는 정도로만 이해하고 넘어가자.
GAN의 또 하나의 특징이라고 한다면 latent space가 smooth하다는 것이다. 만약 두 개의 latent vector 이 주어진다면, 이 두 개의 vector를 interpolate 해서 smooth하게 이미지 결과값을 조절할 수 있다.


지금까지 살펴본 GAN의 내용들을 정리해보자. GAN은 D&G를 같이 훈련 시키는 minimax game을 하며, 간단한 식과 좋은 이미지 퀄리티를 가진다는 장점이 있지만, loss 그래프를 볼 수 없다는 것과 불안정한 training, 그리고 큰 모델들과 데이터에 적합하지 않다는 단점이 있다. GAN은 2016~2021년까지 가장 많이 사용되는 generative model이었지만, Diffusion model들의 등장으로 요새는 많이 사용되지 않는다고 한다.
요즘까지도 많이 사용되고, 굉장히 다양한 연구가 진행되고 있는 Diffusion Model에 대해서 알아보자. 수식이 굉장히 복잡하기 때문에 강의에서는 수식 위주의 수업보다는 Diffusion의 기초와 깔끔한 수식을 가지고 있는 diffusion 모델을 위주로 살펴본다고 한다.

Diffusion의 기본적인 컨셉은 noise distribution에서 이미지 sample을 만들어 내는 것이다. 이를 위해 먼저 noise distribution 를 설정한다. (대부분 는 unit gaussian으로 정의한다.) data 는 t단계의 노이즈를 거쳐 noisy data 가 되는 것이고, 이때의 는 이다. 이면 노이즈가 없는 상태, 그리고 이면 full noise 상태이다. 0에서 1로 갈수록 노이즈가 더 많이 추가되는 것이라고 생각하면 된다.
우리는 여기서 한 번에 조금씩 노이즈를 제거하는 neural network 를 학습시킨다. inference 때는 로 full noise를 sampling한 뒤, 에 이를 여러 번(iterative procedure) 먹여서 noise가 없는 sample 를 얻는다. 개의 단계가 data distribution(noiseless)과 noise distribution을 smootgh하게 이어준다고도 해석할 수 있다.
물론 여러 종류의 diffusion model들이 있지만, 이 정도가 diffusion model들에 대한 high-level의 이야기가 될 것 같다.
Rectified Flow는 여러 Diffusion model 중 하나이다.

간단한 (gaussian) 분포 와 에서 sampling한 sample들이 있다고 하자. 각 iteration마다 다음을 반복한다.
- 를 sampling한다.
- 로 정의한다.
그리고 neural network를 학습시켜 를 예측한다. loss function MSE를 사용하며, 아래와 같다.
위의 사진 속 그래프는 rectified flow가 어떤 과정을 거치는지 보여주기 위한 2D 그림이다. 실제로 데이터는 multi-dimension이라는 것을 알고 넘어가자. 그래프를 보면 알 수 있듯이 일단 sampling한 를 바탕으로 를 계산한다. 그리고 모델은 를 받아 ground truth라고 할 수 있는 와의 MSE loss를 통해 loss를 계산하는 것이다. 여기서 는 에서 방향을 가리키고 있는 벡터이다. 는 라는 벡터 위의 한 점으로, 간의 linear interpolation으로 볼 수 있다. 앞서 intuition에서 본 것과 매칭을 해보면, 는 원본 이미지, 는 full noise image (), 는 사이의 noise가 어느 정도 추가된 sample이다. 이렇게 보면 Loss function이 인 것도 자연스럽게 이해가 된다. 모델이 data -> noise 로 가는 최적의 경로인 를 최대한 따라가도록 유도하는 식인 것이다. 여기서, training 시에는 diffusion model이 data sample -> noise image로 가면서 학습한다는 것을 알아두자.
기본적인 내용은 이게 다이기 때문에 training 시에 사용하는 코드도 굉장히 간결하다.

또한, Rectified flow는 loss curve를 해석할 수 있고, loss가 작아지면 보통 더 좋은 성능으로 이어지기 때문에 Loss를 봐도 의미 있는 해석을 할 수 없는 GAN에 비하면 너무나 좋은 상황이다. 단, inference 시에는 GAN보다 조금 더 복잡한 절차를 가지고 있다는 것이 단점이다.
앞서 training 때는 data -> noise의 방향으로 학습을 진행한다고 했는데, sampling 때는 그 반대로 진행한다. noise-> data sample의 방향인 것이다.
- 먼저 step 수 T를 먼저 정한다. (보통 이는 T=50 정도로 설정한다고 한다.)
- distribution에서 를 sampling한다. ()
- T step 동안 neural network 가 예측한 를 계산한다.
- step을 하나 나아가며 update를 진행한다.
위의 과정을 그래프로 표현하면 아래와 같다.








Rectified Flow의 좋은 점은 무엇일까? 좋은 퀄리티의 sample, training이 잘 되어가고 있는지 확인할 지표가 있고, 큰 모델과 dataset에도 적용이 가능하다는 것, 그리고 코드 구현이 간단하다는 것 정도가 있을 것 같다.
다음에 나올 내용은 강의 중간에 누군가 질문을 한 것 같은데, Generative Model들을 많이 보고 있는 시점에 정리를 하고 넘어가면 좋을 것 같아 생뚱맞지만 적어보려고 한다. 지금까지 우리가 살펴본 Generative Model들의 근본적인 문제는 '어떻게 하면 를(: 우리가 sampling할 줄 아는prior dist., : 우리가 생성하고 싶어하는 data dist.) 잘 연관 지을 것이냐?'이다. 우리가 배운 모델들은 이러한 문제를 각기 다른 방식으로 해결한다.
VAE에서는 모델이 를 predict하고, 이를 이용해 도 predict하는 방식이었다. 이때, 를 우리가 아는 분포로 강제해서 해결했었다. 이 방식은 그닥 잘 작동하진 않았다.
GAN에서는 와 의 관계를 우리가 supervise하는 방식을 사용하진 않았다. Generator가 알아서 Discriminator가 제공하는 objective에 맞게 distribution에서 사이의 mapping을 뽑아내는 방식이었다.
마지막으로 Diffusion에서는 이러한 방법들을 하나로 합쳐서 문제를 해결한다. (이는 뒤에서 더 자세히 설명하겠다.)

저번 글에서 우리가 사용하는 Generative Model들은 대부분 conditional generative model이라고 이야기 했었다. Rectified Flow도 이에 따라 Conditional 한 버전을 알아보자. 먼저 안에 여러 개의 category가 있다고 하고, 이들의 label을 y라고 표현하자. 간단히 말하면, 안에서 여러 개의 subpart들로 나뉘어 있다고 생각해보자고 하는 것이다. 위의 그래프에서는 세모 class와 네모 class가 있다. 또, 그래프 옆에 코드를 보면 dataset에 를 받고, model에게도 를 넘겨주는 것을 볼 수 있다. 하나 더 눈여겨 볼 것은 y는 사실 user input이라는 점이다. user가 원하는 대로 모델이 controllable하고, 그에 따라 user가 요구한 sample을 생성할 수 있다면 좋을 것이다. 그런데 naive하게 그냥 훈련을 시킨다면, 우리가 원하는 대로 모델이 conditioning을 따르진 않는다. 그래서 우리는 CFG(Classifier-Free Guidance)라는 방법을 사용해 conditioning이 잘 작동하도록 training loop를 살짝 바꿔준다.

대부분의 내용은 같지만, 각 iteration에서 50%의 확률로 conditioning을 지워주는 코드를 추가해준다. 이렇게 하면 모델은 두 가지 종류의 벡터를 학습하도록 강제된다.
만약 conditioning이 없는 y=null 상태라면, 이때의 , 즉 는 혹은 를 가리킨다. 그리고 conditioning이 있다면 이때의 , 는 를 가리키고 있다. 이런 상황에서 의 Linear combination을 해주고, 쪽에 더 weight를 많이 주어 쪽으로 최종적인 인 가 더 치우칠 수 있도록 해준다. 참고로 y=null은 결과적으로 unconditional generative model인 것이고, y가 있다면 conditional generative model이 되는 것이다.

sampling 시에는 에 따라 업데이트를 진행한다. CFG는 다양한 diffusion model들에서 굉장히 많이 사용되지만, sampling을 일반적인 방법보다 두 배 더 해야 하는 것은 단점이다.
이번에는 distribution을 변형시키는 방법에 대해 알아보자. 우리는 아까 로 설정했다. 이는 모든 noise level에 똑같은 emphasis를 준다는 의미인데, 과연 이것이 최적의 방법일까? 문제가 되는 구간은 중간 단계의 noise level들이다. 만약 의 경우라면 문제는 오히려 쉽다.
일 경우 noise가 없는 상태이기 때문에 최적의 는 의 평균이다. 비슷하게 인 경우, full noise 상태이기 때문에 최적의 는 의 평균이다. 그러나 이 사이에 있는 값들이 굉장히 애매하다. 따라서 이러한 noise level들에 non-uniform noise schedule을 줘서 이 문제를 해결하려는 시도들이 있었다.

보통은 logit-normal sampling을 해결책으로 많이 사용한다. 분포의 모양이 gaussian과 같이 생겼다. 0,1에 적은 weight를 주고, 중간에 더 많은 weight를 주는 방식이다.
지금까지 Rectified Flow를 통해 Diffusion model이 어떻게 작동하는지에 대해 알아봤다. 그러나 Naive한 Diffusion Model은 high resolution data에서는 훈련시키기가 어렵다. 그래서 등장한 것이 요즘 거의 모든 곳에 사용되는 Diffusion Model인 Latent Diffusion Model(LDM)이다.
LDM은 요즘 가장 핫한 Diffusion 계열의 모델이다. 가장 큰 특징으로는 multi-stage procedure가 있다.
첫 번째 stage는 encoder와 decoder를 학습시키는 것이다. 여기서의 Encoder와 Decoder는 이전에 보던 것과 별반 다르지 않다.

encoder는 input image를 어떤 latent space로 mapping해준다. 이때 input image는 의 factor로 downsampling 되고, channel의 수가 로 늘어나게 된다. Decoder는 다시 이 latent space에서 image로의 mapping을 책임지게 된다. 이때 encoder와 decoder는 모두 attention이 가미된 CNN이다.
LDM의 가장 큰 특징이라고도 할 수 있는데, Diffusion Model의 학습이 raw pixel에서 진행되지 않고 이전 stage에서 encoder/decoder 학습을 할 때 얻어진 latent space에서 이루어진다. 
이 stage에서는 encoder를 freeze하고 진행한다.
- frozen encoder에 input image를 넣어 latent space에서의 representation을 얻는다.
- latent에 noise를 추가하고, 이 noisy latent를 denoise하기 위한 diffusion을 학습한다.

Inference 때는 random latent를 sampling하고 이를 diffusion model에 여러 번 돌려 clean latent sample을 얻고, 이를 다시 decoder에 넣어 clean image sample을 얻는다. 정리하자면, 최종적인 pipeline은 아래와 같다.
image -> frozen encoder -> latent -> latent noise -> diffusion model -> denoised clean latent -> decoder -> clean image
그렇다면 encoder와 decoder는 어떻게 훈련시킬까? VAE를 사용하면 된다. 그러나 VAE는 흐릿한 output을 내는 경우가 많다. 이는 좋은 퀄리티의 sample을 만드는 데 치명적일 수 있다. 그래서 GAN의 구조도 가져와 discriminator를 추가한다. 그래서 최종적으로 Modern LDM은 VAE + GAN + Diffusion의 측면이 다 있다고 볼 수 있는 것이다. 글 초반에 'Diffusion에서는 이러한 방법들을 하나로 합쳐서 문제를 해결한다.'라고 한 것이 이런 의미이다.

Diffusion은 Standard transformer block에 자연스럽게 적용될 수 있고, 심지어 성능도 좋다. 이렇게 Transformer에 Diffusion이 추가된 모델을 DiT 혹은 Diffusion Transformer라고 한다. DiT에서의 관건은 Transformer block에 conditioning을 어떻게 반영할지이다. 일단 Diffusion은 noised latent와 time step, text와 같은 user input y를 input으로 받아야 한다. 반영하는 여러 가지 방법들이 있는데, 첫 번째로 predict scale/shift는 diffusion block 내의 중간 단계의 activation을 scale, shift하는 방법이다. 가장 많이 사용되는 방법이기도 하다. 그 외에 Cross-Attention, Joint attention은 text나 다른 conditional 신호들을 주입하기 위해 사용된다.

Text-to-Image model은 T5와 CLIP과 같은 pretrained text encoder를 text embedding에 사용하고, DiT에는 text embedding과 noisy latent가 input으로 들어간다. 다른 diffusion model들과 같이 iterative하게 여러 번 모델에 돌려서 clean latent를 만들고, 이를 decoder에 돌려서 clean output image를 얻는다. Modern LDM pipeline을 그대로 따라가는 것을 알 수 있다. 이런 모델들의 예시로는 FLUX.1이 있다.

Text-to-Video model은 image와 비슷하다. Text-to-Image 모델에 time dimension만 추가된 것이라고 보면 된다. 예시로는 Meta의 MovieGen이 있다. Video Diffusion 역시 요즘 굉장히 핫한 주제이다.

Diffusion을 사용하면 sampling시에 모델을 여러 번 돌려야 한다. rectified flow의 경우는 30~50번 정도 돌려야 한다고 한다. 이는 모델의 속도가 굉장히 느려지는 결과를 초래할 수 있다.

이러한 문제는 distillation을 사용해 step 수를 줄임으로써 해결될 수 있다. step 수는 줄이고 sample의 퀄리티는 유지할 수 있는 방법이다. 이렇게 Efficiency를 주제로 하는 연구도 활발히 진행되고 있다.

우리는 지금까지 rectified flow의 notation을 기반으로 diffusion을 살펴봤다. 그런데 이를 더 general하게 표현하면 위와 같다. 다양한 diffusion model들의 notation들이 여기서 크게 벗어나지 않는다.
다양한 Diffusion 모델들을 바라보는 관점에 대해서도 공부해보면 좋을 것 같다. 강의에서 추천한 블로그 링크를 공유한다.
https://sander.ai/2023/07/20/perspectives.html