🤖 AI/ML

디퓨전 모델

Diffusion Model

노이즈를 점진적으로 제거하며 이미지를 생성하는 모델. Stable Diffusion, DALL-E 3의 기반.

📖 상세 설명

디퓨전 모델(Diffusion Model)은 데이터에 점진적으로 노이즈를 추가하는 과정을 학습한 후, 이를 역으로 되돌려 노이즈에서 데이터를 생성하는 생성 모델입니다. 2020년 DDPM(Denoising Diffusion Probabilistic Model) 논문 이후 급격히 발전하여, 현재 이미지 생성 분야에서 GAN을 대체하는 지배적인 아키텍처가 되었습니다. Stable Diffusion, DALL-E 3, Midjourney, Imagen 등 대부분의 최신 이미지 생성 AI가 디퓨전 기반입니다.

디퓨전의 핵심 원리는 두 과정으로 나뉩니다. Forward Process(확산 과정)에서는 원본 이미지에 가우시안 노이즈를 점진적으로 추가하여 결국 순수한 랜덤 노이즈로 만듭니다. Reverse Process(역확산 과정)에서는 학습된 신경망이 각 단계에서 노이즈를 조금씩 제거하여 원본 데이터를 복원합니다. 모델은 "현재 노이즈 이미지에서 얼마만큼의 노이즈를 제거해야 하는가"를 예측하도록 학습됩니다.

2024-2025년 기준으로 디퓨전 모델은 여러 혁신을 거쳤습니다. Latent Diffusion Model(LDM)은 픽셀 공간이 아닌 압축된 잠재 공간에서 디퓨전을 수행하여 계산 비용을 크게 줄였습니다(Stable Diffusion의 기반). Classifier-Free Guidance는 조건부 생성의 품질을 획기적으로 개선했습니다. 최근에는 Consistency Models, SDXL Turbo 등 적은 스텝으로 고품질 이미지를 생성하는 기술이 등장하여 실시간 생성이 가능해졌습니다.

디퓨전 모델은 이미지를 넘어 비디오(Sora, RunwayML), 오디오(AudioLDM), 3D(DreamFusion), 단백질 구조(RFdiffusion) 등 다양한 도메인으로 확장되고 있습니다. 특히 텍스트-to-이미지 생성에서 CLIP 등 멀티모달 인코더와 결합하여 자연어 프롬프트로 원하는 이미지를 생성하는 것이 표준이 되었습니다. 기업용으로는 제품 이미지 생성, 광고 크리에이티브, 게임 에셋 제작 등에서 활발히 활용됩니다.

💻 코드 예제

Stable Diffusion으로 이미지 생성 (Diffusers 라이브러리)

from diffusers import StableDiffusionPipeline, DPMSolverMultistepScheduler
import torch

# Stable Diffusion XL 파이프라인 로드
pipe = StableDiffusionPipeline.from_pretrained(
    "stabilityai/stable-diffusion-xl-base-1.0",
    torch_dtype=torch.float16,
    variant="fp16",
    use_safetensors=True
)
pipe = pipe.to("cuda")

# 빠른 스케줄러로 교체 (20스텝으로 고품질 생성)
pipe.scheduler = DPMSolverMultistepScheduler.from_config(
    pipe.scheduler.config
)

# 텍스트-to-이미지 생성
prompt = "A futuristic city skyline at sunset, cyberpunk style, 8k, detailed"
negative_prompt = "blurry, low quality, distorted"

image = pipe(
    prompt=prompt,
    negative_prompt=negative_prompt,
    num_inference_steps=25,
    guidance_scale=7.5,  # Classifier-Free Guidance 강도
    height=1024,
    width=1024
).images[0]

image.save("generated_city.png")

# 이미지-to-이미지 변환 (기존 이미지 스타일 변경)
from diffusers import AutoPipelineForImage2Image
from PIL import Image

img2img_pipe = AutoPipelineForImage2Image.from_pretrained(
    "stabilityai/sdxl-turbo",
    torch_dtype=torch.float16
).to("cuda")

init_image = Image.open("input.jpg").resize((512, 512))
result = img2img_pipe(
    prompt="oil painting style",
    image=init_image,
    strength=0.7,  # 원본 유지 정도 (0=원본, 1=완전 새로 생성)
    num_inference_steps=4  # SDXL Turbo는 4스텝으로 충분
).images[0]

DDPM 핵심 개념 구현 (학습용)

import torch
import torch.nn as nn
import torch.nn.functional as F

class SimpleDiffusion:
    """DDPM의 핵심 개념을 단순화한 구현"""
    def __init__(self, timesteps=1000, beta_start=1e-4, beta_end=0.02):
        self.timesteps = timesteps
        # 노이즈 스케줄 정의
        self.betas = torch.linspace(beta_start, beta_end, timesteps)
        self.alphas = 1.0 - self.betas
        self.alpha_cumprod = torch.cumprod(self.alphas, dim=0)

    def forward_diffusion(self, x0, t):
        """Forward process: 원본에 노이즈 추가"""
        noise = torch.randn_like(x0)
        sqrt_alpha_cumprod = self.alpha_cumprod[t].sqrt()
        sqrt_one_minus = (1 - self.alpha_cumprod[t]).sqrt()

        # x_t = sqrt(alpha_cumprod) * x_0 + sqrt(1-alpha_cumprod) * noise
        xt = sqrt_alpha_cumprod.view(-1, 1, 1, 1) * x0 + \
             sqrt_one_minus.view(-1, 1, 1, 1) * noise
        return xt, noise

    def training_step(self, model, x0, optimizer):
        """학습: 노이즈 예측"""
        batch_size = x0.shape[0]
        t = torch.randint(0, self.timesteps, (batch_size,))

        xt, noise = self.forward_diffusion(x0, t)
        predicted_noise = model(xt, t)

        loss = F.mse_loss(predicted_noise, noise)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        return loss.item()

    @torch.no_grad()
    def sample(self, model, shape, device):
        """Reverse process: 노이즈에서 이미지 생성"""
        x = torch.randn(shape, device=device)

        for t in reversed(range(self.timesteps)):
            t_batch = torch.full((shape[0],), t, device=device)
            predicted_noise = model(x, t_batch)

            alpha = self.alphas[t]
            alpha_cumprod = self.alpha_cumprod[t]
            beta = self.betas[t]

            if t > 0:
                noise = torch.randn_like(x)
            else:
                noise = 0

            # 노이즈 제거 스텝
            x = (1 / alpha.sqrt()) * (
                x - (beta / (1 - alpha_cumprod).sqrt()) * predicted_noise
            ) + beta.sqrt() * noise

        return x

📊 성능 & 비용

모델 생성 시간 (1장) VRAM 요구량 API 비용
Stable Diffusion 1.5 2-5초 (A100) 6GB+ 자체 호스팅 시 무료
SDXL Base 5-10초 (A100) 12GB+ 자체 호스팅 시 무료
SDXL Turbo 0.5-1초 (A100) 8GB+ 자체 호스팅 시 무료
DALL-E 3 (OpenAI) 10-20초 API 기반 $0.04-0.12/장
Midjourney 30-60초 클라우드 기반 $10-60/월

실무 가이드: 프로토타이핑에는 DALL-E 3나 Midjourney API가 편리합니다. 대량 생성이나 커스터마이징이 필요하면 SDXL을 자체 호스팅하세요. 실시간 응용(게임, 인터랙티브)에는 SDXL Turbo나 LCM-LoRA를 사용하면 1초 이내 생성이 가능합니다.

🗣️ 실무에서 이렇게 말하세요

프로젝트 기획에서:

"제품 이미지 배경을 자동으로 변경하는 기능을 만들려면 Inpainting 기능이 있는 디퓨전 모델이 필요합니다. SDXL Inpainting 파이프라인을 사용하면 마스킹된 영역만 새로 생성할 수 있어요."

기술 논의에서:

"생성 품질을 높이려면 CFG Scale(Classifier-Free Guidance)을 조절해야 합니다. 7-8 정도가 균형점이고, 높이면 프롬프트에 충실하지만 다양성이 떨어집니다. Negative Prompt로 원치 않는 요소를 명시하는 것도 중요합니다."

면접에서:

"디퓨전 모델은 노이즈 추가(Forward)와 노이즈 제거(Reverse) 두 과정으로 구성됩니다. 모델은 주어진 노이즈 이미지에서 노이즈를 예측하도록 학습되고, 생성 시에는 순수 노이즈에서 시작해 점진적으로 노이즈를 제거합니다. Latent Diffusion은 이 과정을 압축된 잠재 공간에서 수행해 효율성을 높였습니다."

⚠️ 흔한 실수 & 주의사항

❌ 실수 1: 저작권과 라이선스 무시

Stable Diffusion은 LAION 데이터셋으로 학습되었으며 상업적 사용이 가능하지만, 생성 이미지가 특정 아티스트 스타일을 모방하거나 저작권 이미지와 유사할 경우 법적 문제가 발생할 수 있습니다. 상업 프로젝트에서는 프롬프트에 특정 아티스트명을 포함하지 마세요.

❌ 실수 2: 스텝 수와 CFG Scale 극단적 설정

Inference steps를 너무 적게(10 이하) 하면 품질이 급격히 저하되고, 너무 많이(100+) 하면 시간만 낭비됩니다. CFG Scale도 15 이상으로 높이면 색상이 과포화되고 아티팩트가 생깁니다.

✅ 올바른 방법

일반적인 SDXL은 25-30 steps, CFG 7-8이 최적입니다. Turbo 모델은 4-8 steps로 충분합니다. 프롬프트 엔지니어링에 투자하세요: 구체적인 묘사, 스타일 키워드(cinematic, 8k, detailed), Negative Prompt 활용이 품질에 큰 영향을 미칩니다. 상업용으로는 Getty Images나 Adobe Stock의 생성 AI(저작권 보증)를 고려하세요.

🔗 관련 용어

📚 더 배우기