오늘 끝나면
Diffusion Models
- ✓Diffusion Models의 핵심 문제를 한 문장으로 설명한다
- ✓오른쪽 실습에서 Diffusion이 어떻게 움직이는지 관찰한다
- ✓다음 강의와 이어지는 한계를 말할 수 있다
실습 미션
노이즈에서 그림으로 — DDPM → Stable Diffusion → Sora 이 문장이 실제로 무슨 뜻인지 실습에서 한 번 손으로 확인한다.
성공 조건
- □실습의 기본값을 먼저 관찰
- □입력값이나 모드를 한 번 이상 바꿔 결과 비교
- □왜 결과가 바뀌었는지 한 문장으로 설명
AI · Day 18 / 생성 모델
노이즈에서
이미지를
2022년 디자인 업계에 운석 떨어짐. 정체는 Diffusion. 아이디어는 하나임 — 노이즈를 천천히 넣었다가 거꾸로 되돌림. 무에서 그림 만드는 이미지 AI의 왕. 수학부터 Stable Diffusion까지 해부함.
GAN은 왜 조연으로 밀려났나
2022년 여름, 디자이너 Slack에 한 문장 퍼짐. "이거 사람이 그린 거 아니래."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이 이긴다 — 그래서 왕이 바뀌었다
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의 진짜 교훈
Stable Diffusion은 조립품이다
DDPM에 치명적 약점 있었음. 너무 느림. 512×512 픽셀 공간에서 1000 스텝 돌리면 한 장에 수십 초, 학습엔 GPU 수천 장 필요했음.
뮌헨 Rombach 팀이 답 냄 — 비싼 공간에서 싼 공간으로 옮기자.
이미지를 VAE로 64×64×4 latent로 압축하고 거기서 diffusion 돌림.
공간 해상도 1/8, 연산량 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배 가속 — 품질은 거의 그대로