Stable Diffusion with Python 파이썬으로 배우는 확산 모델
Chapter 02 목차
제1부 · 빠른 소개 — 3장

몇 줄의 코드로 이미지를 부른다

Diffusers 파이프라인에 프롬프트 한 줄을 건네면 이미지가 태어난다. 시드·스케줄러·가이던스 스케일 — 생성을 손에 쥐는 네 개의 손잡이를 다룬다.

Diffusers Pipeline Seed Scheduler CFG

Section 01파이프라인 로드

Stable Diffusion으로 이미지를 만드는 일은 놀랍도록 간결하다. Hugging Face Hub에서 모델을 내려받아 파이프라인 객체를 만들고, 자연어 프롬프트 하나를 건네면 끝이다.

먼저 StableDiffusionPipeline.from_pretrained로 모델을 로드한다. 모델 캐시에 없으면 Diffusers가 자동으로 내려받는다.

stable-diffusion-v1-5 로드 및 GPU 이동
import torch
from diffusers import StableDiffusionPipeline

text2img_pipe = StableDiffusionPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5",
    torch_dtype = torch.float16
).to("cuda:0")
Intuition — 왜 cuda:0 인가 to("cuda")가 아니라 to("cuda:0")를 쓰는 이유는 다중 GPU 환경 때문이다. CUDA 인덱스를 바꾸면 특정 GPU를 지정할 수 있다. 두 번째 GPU로 생성하려면 to("cuda:1")이면 된다.
프롬프트 한 줄로 이미지 생성
# 이미지 생성
prompt = "high resolution, a photograph of an astronaut riding a horse"
image = text2img_pipe(
    prompt = prompt
).images[0]
image

같은 코드를 두 번 실행하면 동일한 이미지가 나오지 않는다. 비슷한 모양과 느낌의 이미지가 보일 확률이 99.99%다. 생성을 일관되게 만들려면 generator 매개변수가 필요하다.

Section 02생성 시드

Stable Diffusion에서 시드(seed)는 생성 프로세스를 초기화하는 난수다. 시드는 노이즈 tensor를 만드는 데 쓰이고, 그 노이즈 tensor에서 모델이 이미지를 끌어낸다. 동일한 시드 + 동일한 프롬프트 + 동일한 설정이면 일반적으로 동일한 이미지가 나온다.

시드 → 노이즈 → 이미지 STEP 01 / 4
space 재생 · → 다음 · R 리셋
Concept시드가 필요한 두 가지 이유

재현성 — 동일한 시드로 동일한 설정·프롬프트를 쓰면 똑같은 이미지를 일관되게 다시 만들 수 있다.

탐색 — 시드 번호를 바꾸며 다양한 변형을 발견한다. 새롭고 흥미로운 이미지가 종종 이 과정에서 떠오른다.

수동 시드를 지정한 결정론적 생성
my_seed = 1234
generator = torch.Generator("cuda:0").manual_seed(my_seed)

prompt = "high resolution, a photograph of an astronaut riding a horse"
image = text2img_pipe(
    prompt = prompt,
    generator = generator
).images[0]
display(image)

시드 번호를 주지 않으면 Diffusers가 생성마다 자동으로 난수를 만든다. torch.Generator 객체에 manual_seed를 건네면, 같은 이미지를 몇 번이고 재현할 수 있다.

Section 03샘플링 스케줄러

원래 Diffusion 모델의 한 가지 단점은 느린 역방향 노이즈 제거다. 무작위 노이즈를 일관된 이미지로 바꾸는 데 보통 1,000단계가 필요하다. 연구자들의 발상은 단순했다 — 1,000단계를 모두 밟는 대신 샘플을 취해 핵심 단계만 수행한다면? 그리고 그것은 작동했다.

Diffusers에서는 이 구성 요소를 스케줄러(scheduler)라 부른다. 다른 자료에서는 샘플러(sampler)라는 용어를 만날 수도 있다. 기본값은 PNDMScheduler이며, text2img_pipe.scheduler로 현재 값을 확인할 수 있다.

1,000단계 → 20단계로 압축 STEP 01 / 4
space 재생 · → 다음 · R 리셋
Euler 스케줄러, 20단계 추론
from diffusers import EulerDiscreteScheduler

text2img_pipe.scheduler = EulerDiscreteScheduler.from_config(
    text2img_pipe.scheduler.config)

generator = torch.Generator("cuda:0").manual_seed(1234)

image = text2img_pipe(
    prompt = prompt,
    generator = generator,
    num_inference_steps = 20
).images[0]
display(image)
Key — 스케줄러 비교 20단계로 비교하면, Euler 스케줄러는 말의 네 다리를 모두 정확히 그려내는 반면 PNDM은 세부 묘사가 풍부하지만 다리 하나를 놓치기도 한다. 각 스케줄러에는 장단점이 있어, 직접 써 보며 가장 잘 맞는 것을 찾아야 한다. num_inference_steps를 높이면 보통 품질이 좋아진다.

Section 04모델 교체

번성하는 커뮤니티 덕분에, V1.5를 기반으로 미세 조정된 수많은 모델이 존재한다. Hugging Face에 호스팅된 모델이라면 식별자만 바꾸면 즉시 다른 모델로 전환할 수 있다.

Hugging Face 모델 / 로컬 파일 로드
# Hugging Face Hub 모델 교체
text2img_pipe = StableDiffusionPipeline.from_pretrained(
    "stablediffusionapi/deliberate-v2",
    torch_dtype = torch.float16
).to("cuda:0")

# civitai.com 등에서 받은 로컬 safetensors / ckpt 파일
text2img_pipe = StableDiffusionPipeline.from_single_file(
    "path/to/deliberate-v2.safetensors",
    torch_dtype = torch.float16
).to("cuda:0")

핵심 차이는 함수다. 로컬 파일은 from_pretrained 대신 from_single_file로 로드한다. 다양한 모델을 실험하면 특정 사용 사례에 맞는 개선, 고유한 예술적 스타일, 더 나은 호환성을 발견할 수 있다.

Section 05가이던스 스케일

가이던스 스케일, 또는 분류기 없는 가이던스(CFG)는 생성된 이미지가 텍스트 프롬프트에 얼마나 부합하는지를 제어하는 매개변수다. 높은 값은 이미지를 프롬프트에 더 강하게 묶고, 낮은 값은 모델이 이미지에 무엇을 넣을지 스스로 결정할 여지를 넓혀준다.

Table 3.1 — guidance_scale 값에 따른 효과
특성비고
낮음 (≈3)모델 자유도 높음, 프롬프트 약하게 반영예측 불가능, 창의적
권장 (7~8.5)프롬프트 준수와 자연스러움 균형7.5가 좋은 기본값
높음 (≈10+)채도·대비 증가, 프롬프트 강하게 준수너무 높으면 이미지가 흐려질 수 있음
서로 다른 가이던스 스케일 비교
generator = torch.Generator("cuda:0").manual_seed(123)
prompt = "a photograph of an astronaut riding a horse on mars"

image_7 = text2img_pipe(
    prompt = prompt,
    num_inference_steps = 30,
    guidance_scale = 7,
    generator = generator
).images[0]
Intuition — 단 몇 줄의 마법 시드·스케줄러·모델·가이던스 스케일. 이 네 손잡이만으로 단 몇 줄의 코드가 이미지를 만들어낸다. 다음 두 장에서는 이 매끄러운 표면 아래의 수학 — Diffusion 모델의 이론과 Stable Diffusion의 작동 원리를 파헤친다. 그러면 PNDMScheduler 객체의 낯선 필드들도 익숙해질 것이다.