오늘 끝나면
Diffusion Models
- ✓Diffusion Models의 핵심 문제를 한 문장으로 설명한다
- ✓오른쪽 실습에서 Diffusion이 어떻게 움직이는지 관찰한다
- ✓다음 강의와 이어지는 한계를 말할 수 있다
실습 미션
노이즈에서 그림으로 — DDPM → Stable Diffusion → Sora 이 문장이 실제로 무슨 뜻인지 실습에서 한 번 손으로 확인한다.
성공 조건
- □실습의 기본값을 먼저 관찰
- □입력값이나 모드를 한 번 이상 바꿔 결과 비교
- □왜 결과가 바뀌었는지 한 문장으로 설명
AI · Day 18 / 생성 모델
노이즈에서
이미지를
2022년 이미지 생성을 뒤집은 기술이 Diffusion이다. 아이디어는 노이즈를 천천히 넣었다가 거꾸로 되돌리는 것 하나다. 무에서 그림을 만드는 이미지 AI의 핵심이다. 수학부터 Stable Diffusion까지 해부한다.
GAN은 왜 조연으로 밀려났나
2022년 4개월 만에 DALL·E 2, Imagen, Midjourney, Stable Diffusion이 연달아 공개됐다. 사람이 그린 것과 구별하기 어려운 이미지가 한꺼번에 쏟아졌다.
2020년까지 이미지 생성의 주류는 GAN이었다. StyleGAN2, BigGAN이 학회를 지배했다. 그런데 top-tier 논문에서 GAN이 빠르게 사라졌다.
GAN은 Generator와 Discriminator의 minimax 게임이라 학습이 극도로 불안정하다. 같은 얼굴만 찍는 mode collapse가 있고, 텍스트 조건을 붙이기도 어렵다.
Diffusion은 이걸 다 정반대로 푼다. 단일 네트워크에 단순한 MSE를 쓰고, scale이 먹힌다. 키울수록 좋아진다.
| 축 | GAN | Diffusion |
|---|---|---|
| 학습 | minimax · 불안정 | 단순 MSE · 안정 |
| 다양성 | mode collapse | 확률적 · 풍부 |
| 조건 | 텍스트 어려움 | cross-attn 강력 |
| Scale | 안 먹힘 | 키울수록 좋음 |
네 항목 모두에서 Diffusion이 GAN보다 유리하다
Forward: 이미지를 천천히 죽이는 법
출발점은 1905년 아인슈타인의 브라운 운동이다. 잉크를 물에 떨구면 시간이 지나며 퍼져 균일한 회색이 된다. 망가뜨리는 과정이다.
선명한 사진 x_0에 약한 가우시안 노이즈를 조금씩 반복해 뿌린다.T=1000번 반복하면 x_T는 원본 흔적이 전혀 없는 완전한 난수 노이즈가 된다. 이 과정은 학습이 전혀 필요 없다. 수식으로 정의하면 된다.
가우시안 성질 덕에 1000번 반복하지 않고 임의의 t로 한 번에 점프하는 closed-form이 있다. 아래 한 줄이 DDPM의 절반이다.
파이썬 코드 보기
# 임의의 t로 한 방에 점프 (reparameterization) a_bar = alpha_bars[t] # 누적 곱 noise = torch.randn_like(x0) # 진짜 노이즈 e x_t = sqrt(a_bar) * x0 + sqrt(1 - a_bar) * noise # a_bar -> 0 이면 x_t 는 N(0, I) 로 수렴
x_0, 원본, 노이즈 0
Reverse: 끝까지 풀면 MSE가 나온다
Forward가 이미지에서 노이즈로 가는 길이면, Reverse는 노이즈에서 이미지로 되감는 길이다. 이 되감기를 U-Net으로 학습한다. 그런데 학습 목표가 충격적이다.
원래 목표는 로그 우도 최대화(ELBO)였다. 전개하면 가우시안 사이 KL 발산의 합이 나온다. 2020년 Ho는 평균 대신 노이즈를 예측하도록 reparameterize하고 앞 계수를 모두 떼어냈다. 남는 건 이것뿐이었다.
L = ‖ε − ε_θ(x_t, t)‖². 진짜 노이즈 ε와 U-Net이 예측한 노이즈 ε_θ의 거리, 곧 MSE다. minimax도 ELBO도 아니고, 3줄짜리 PyTorch면 된다.
파이썬 코드 보기
def training_step(x0):
t = torch.randint(0, T, (B,)) # 랜덤 timestep
noise = torch.randn_like(x0) # 랜덤 노이즈
x_t = q_sample(x0, t, noise) # forward closed-form
pred = model(x_t, t) # 노이즈 예측
return F.mse_loss(pred, noise) # 끝복잡한 이론도 끝까지 전개하면 단순한 공식으로 정리되곤 한다.DDPM의 손실 함수가 그 사례다.
복잡한 ELBO를 끝까지 전개하면 단순한 MSE로 정리된다
Stable Diffusion은 조립품이다
DDPM에 치명적 약점이 있었다. 너무 느렸다. 512×512 픽셀 공간에서 1000 스텝을 돌리면 한 장에 수십 초가 걸리고, 학습엔 GPU 수천 장이 필요했다.
뮌헨 Rombach 팀의 해법은 diffusion을 픽셀이 아닌 압축된 공간에서 돌리는 것이다.이미지를 VAE로 64×64×4 latent로 압축하고 거기서 diffusion을 돌린다. 공간 해상도는 8분의 1, 연산량은 1/64로 줄어든다. 이게 Stable Diffusion의 실체다.
그래서 SD는 사전 학습된 세 모듈의 조립품이다.CLIP Text Encoder는 텍스트를 임베딩으로 바꾸고,VAE는 픽셀과 latent를 오가며,U-Net + Cross-Attention은 latent에서 노이즈를 예측한다.
학습 대상은 U-Net 하나뿐이고, 나머지 둘은 frozen 상태다. 텍스트는 cross-attention의 Key·Value로 들어간다. 각 픽셀이 어느 단어에 주목할지를 계산하는 구조다.
여기에 Classifier-Free Guidance가 더해진다. 조건부 예측과 무조건부 예측의 차이를 w배 증폭해 텍스트 충실도를 조절한다. 기본값은 w=7.5다. 너무 키우면 색이 튀고 artifact가 생긴다.
CLIP + VAE + U-Net 조립, 학습은 파란 U-Net 하나뿐
ControlNet, LoRA, Sora, 그리고 비즈니스
DDPM(2020)은 멋졌지만 쓸모는 제한적이었다. 비즈니스로 폭발한 건 제어 기술이 나온 뒤다. 무엇을 만드느냐보다 얼마나 의도대로 만드느냐가 중요하다.
ControlNet은 U-Net encoder를 복제해 edge, pose, depth 맵을 주입한다. 외곽선만 주면 구조는 두고 스타일만 바꾼다.
LoRA는 7GB 모델을 다시 학습하는 대신 수MB짜리 저랭크 adapter만 학습한다. 강아지 사진 10장이면 충분하다.
Sora는 이걸 시간 축으로 확장한 것이다. spacetime patch와 DiT로 비디오까지 만든다.
샘플러도 진화했다. 원조 DDPM의 1000 스텝이 결정론적 DDIM에서 50 스텝으로, DPM-Solver++에서 10–20 스텝으로, LCM/Turbo에서 1–4 스텝까지 줄었다.
디자이너를 고용할 돈이 없어도, 디자이너급 취향을 가진 1인이 경쟁력을 갖는다.Diffusion은 취향 있는 사람에게 무한 생산 능력을 준다. 무엇이 좋은지 판단할 수 있으면 직접 만들 수 있다.
Q. Stable Diffusion이 픽셀이 아니라 latent 공간에서 diffusion하는 이유는?
연산량과 메모리를 아끼기 위해서다.512×512×3 픽셀을 64×64×4 latent로 압축하면 연산량이 1/64로 줄어 U-Net이 훨씬 작아지고 샘플링도 빨라진다.
사전 학습된 VAE가 픽셀과 latent 사이 변환을 맡고, diffusion 본체인 U-Net은 작은 latent 공간에서만 돈다.
| 샘플러 | 연도 | Steps | 특징 |
|---|---|---|---|
| DDPM | 2020 | 1000 | 원조 · 느림 |
| DDIM | 2020 | 50 | 결정론적 |
| DPM++ | 2022 | 10–20 | 현재 기본 |
| LCM/Turbo | 23–24 | 1–4 | distill 가속 |
1000 → 4 스텝, 250배 가속, 품질은 거의 그대로