Stable Diffusion
Stable Diffusion์ ์ด๋ฏธ์ง ์์ฑ ๋ชจ๋ธ ์ค์์๋ ๊ฐ์ฅ ํต์ฌ์ ์ธ ์์น๋ฅผ ์ฐจ์งํ๊ณ ์๋ ์คํ์์ค ๋ชจ๋ธ์ด๋ค.
2022๋
์ ์ฒ์ ๋์๊ณ , Stability AI๋ผ๋ ๊ธฐ์
์์ ๋ง๋ค์๋ค.
๋๊ธฐ์ ๋ค์ ํ์ํ ๋ชจ๋ธ์ ์ ์ธํ๊ณ ์คํ์์ค ๋ชจ๋ธ ์ค์์๋ ์๋์ ์ธ ์์น๋ฅผ ์ฐจ์งํ๊ณ ์๋ค. ์ฑ๋ฅ๋ ๊ฐ์ฅ ์ข๊ณ , ์๋๋ ๋น ๋ฅด๋ค.
๋จ, ๋ฌด๋ฃ์ด๊ธด ํ๋ฐ, ์ด๊ฑด ๋น์์ ์ฉ์ ํ์ ํ ๊ฒ์ด๋ค. ์์ ์ฉ์ผ๋ก ์ฌ์ฉํ๋ ค๋ฉด ๋น์ฉ์ ๋ด์ผ ํ๋ค.
๋์ ์๋ฆฌ
Stable Diffusion์ ํฌ๊ฒ 3๊ฐ์ง ๋ถ๋ถ์ผ๋ก ๋๋๋ค.
์คํ ์์๋๋ก CLIP, UNet, VAE(Variational Auto Encoder)๋ค.
์ฒซ๋ฒ์งธ, CLIP(Contrastive Language-Image Pre-training)์ ์ ์ ์ ํ
์คํธ๋ฅผ ๋ฐ์์ ๋ชจ๋ธ ๋ด๋ถ์์ ์ดํดํ ์ ์๋ ๋ฒกํฐ ์๋ฒ ๋ฉ์ผ๋ก ๋ณํํ๋ ์ญํ ์ ํ๋ค. ๋ฒกํฐ์ ์ฐจ์(๊ธธ์ด)์ ๋ชจ๋ธ๋ง๋ค ๋ค๋ฅด๋, ๋ณดํต 768์ด๋ 1024 ์ ๋๋ค.
CLIP์์ ๋ง๋ค์ด์ง ๋ฒกํฐ๋ UNet์ผ๋ก ์ ๋ฌ๋ผ์ ์ด๋ฏธ์ง ์์ฑ์ ์ํ ์
๋ ฅ๊ฐ์ผ๋ก ์ฌ์ฉ๋๋ค.
UNet์ CLIP์ด ๋ง๋ ๋ฒกํฐ ๊ฐ์ ๋ฐ์์ ์ด๋ฏธ์ง ์์ฑ์ ์์ํ๋ค.
๋ชจ๋ธ๋ต๊ฒ ๋์ ๋ฐฉ์ ์์ฒด๋ ์ ํ์ ์ด์ง ์๋ค. ๊ตณ์ด ์ค๋ช
์ ํ์๋ฉด, "๋๋ค ๋
ธ์ด์ฆ"๋ฅผ ์ต์ด ํ๋ฒ ์ด๊ธฐํํ ๋ค์์, ๊ณ์ํด์ ๋ฃจํ๋ฅผ ๋๋ฉด์ ๋
ธ์ด์ฆ๋ฅผ ์ค์ธ๋ค.
์ด ๋
ธ์ด์ฆ๋ฅผ ์ค์ด๋ ๊ฒ ์์ฒด๊ฐ ์ฌ์ ํ์ต๋ ํจํด์ ๋ฐ๋ผ์ ๋ฒกํฐ ์
๋ ฅ์ ๊ธฐ๋ฐ์ผ๋ก ์ํ๋๋ ๊ฒ์ด๊ณ , ๋
ธ์ด์ฆ๊ฐ ์ถฉ๋ถํ ์ค์ด๋ค์๋ค๊ณ ํ๋จํ๋ฉด ๋
ธ์ด์ฆ๊ฐ ์ต์ํ๋ ๊ฒฐ๊ณผ๋ฌผ์ ๋ค์ ์คํ
์ธ VAE์ ๋๊ธฐ๋ ๊ฒ์ด๋ค.
์ฌ๋์ด ๊ทธ๋ฆฌ๋ ๊ฒ์ฒ๋ผ ๋ํ์ง์์ ๊ทธ๋ ค๋๊ฐ๋๊ฒ ์๋๋ผ, ๋๋ฌ์ด ๋์ํ์ ์ง์ฐ๊ฐ์ ์ฐํ์ ์จ์ ๊ทธ๋ฆผ์ ์์ฑํ๋ ์ ์ด๋ค.
VAE(Variational Auto Encoder)๋ UNet์ ๊ฒฐ๊ณผ๋ฌผ์ ๋ฐ์์ ์ง์ง ์ด๋ฏธ์ง(PNG) ๋ฑ์ผ๋ก ๋ณํํ๋ ์ญํ ์ ํ๋ค.
๊ตฌ์ฒด์ ์ผ๋ก ์๋ฅผ ๋ค๋ฉด, UNet์ด 64ร64ร4 ํฌ๊ธฐ์ ์์ถ๋ latent ํํ์ VAE์ ๋์ง๋ฉด, VAE Decoder๋ ๊ทธ๊ฑธ 512ร512ร3 ํฌ๊ธฐ์ ์ค์ ํฝ์
์ด๋ฏธ์ง๋ก ๋ณํํ๋ค.
์ค์ ๋ก ๋ง๋ค์ด์ง๋ ์ด๋ฏธ์ง ํฌ๊ธฐ์ ๋นํด์ UNet์์ ์ฐ์ฐํ๋ ์ด๋ฏธ์ง์ ํฌ๊ธฐ๋ ๋งค์ฐ ์์ ํธ์ด๊ณ , ๊ทธ๋์ ์ฝ๊ฐ์ ์์ค์ด ์์ ์๋ ์์ง๋ง ์๋๋ฅผ ๋น ๋ฅด๊ฒ ๋์ด์ฌ๋ฆด ์ ์๋ ๊ตฌ์กฐ๋ฅผ ์ป์ ์ ์์๋ค.
๋ก์ปฌ์์ ์ฌ์ฉํด๋ณด๊ธฐ
StableDiffusion์ ์คํ ๋ชจ๋ธ์ด๊ธฐ ๋๋ฌธ์, ๊ทธ๋ฅ ์์ ๋กญ๊ฒ ๋๊ตฌ๋ ๋ค์ด๋ฐ์์ ์ฌ์ฉํ ์ ์๋ค.
GPU๊ฐ ์์ด๋ ์คํ์ ํ ์ ์์ง๋ง ๋ช๋ถ ์ ๋๋ก ๋๋ฆฌ๋ค.
uv์ python์ ์จ์ ๊ฐ๋จํ๊ฒ ์คํ์ ํด๋ณด๊ฒ ๋ค.
ํ์ํ ์ข
์์ฑ์ ๋ค์๊ณผ ๊ฐ๋ค. uv pyproject๋ค.
[project]
name = "just-test"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
"diffusers>=0.30.0",
"torch>=2.0.0",
"transformers>=4.30.0",
"accelerate>=0.20.0",
"safetensors>=0.3.0",
"pillow>=10.0.0",
]
์ฝ๋๋ ๋ค์๊ณผ ๊ฐ๋ค.
from diffusers import StableDiffusionPipeline
import torch
from datetime import datetime
<br>
def main():
print("=== Stable Diffusion CPU ํ
์คํธ ===\n")
print("1. ๋ชจ๋ธ ๋ก๋ฉ ์ค... (์ฒซ ์คํ ์ 4-5GB ๋ค์ด๋ก๋๋ฉ๋๋ค)")
print(" ๊ฒฝ๋ ๋ชจ๋ธ ์ฌ์ฉ: runwayml/stable-diffusion-v1-5")
# CPU์ฉ ๋ชจ๋ธ ๋ก๋
pipe = StableDiffusionPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
torch_dtype=torch.float32, # CPU๋ float32 ์ฌ์ฉ
safety_checker=None, # ์๋ ํฅ์์ ์ํด safety checker ๋นํ์ฑํ
use_auth_token=False, # ์ธ์ฆ ์์ด ๊ณต๊ฐ ๋ชจ๋ธ ์ฌ์ฉ
)
pipe = pipe.to("cpu")
# ๋ฉ๋ชจ๋ฆฌ ์ต์ ํ
pipe.enable_attention_slicing()
print("โ ๋ชจ๋ธ ๋ก๋ฉ ์๋ฃ!\n")
# ํ๋กฌํํธ
prompt = "a serene mountain landscape at sunset, beautiful colors, digital art, highly detailed"
print(f"2. ์ด๋ฏธ์ง ์์ฑ ์ค...")
print(f" ํ๋กฌํํธ: {prompt}")
print(f" ํด์๋: 512x512")
start_time = datetime.now()
# ์ด๋ฏธ์ง ์์ฑ
image = pipe(
prompt,
height=512,
width=512,
num_inference_steps=20, # ์๋๋ฅผ ์ํด ์ค์
guidance_scale=7.5,
).images[0]
end_time = datetime.now()
elapsed = (end_time - start_time).total_seconds()
# ์ ์ฅ
output_filename = f"output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
image.save(output_filename)
print(f"โ ์์ฑ ์๋ฃ!")
print(f" ์์ ์๊ฐ: {elapsed:.1f}์ด ({elapsed / 60:.1f}๋ถ)")
print(f" ์ ์ฅ ์์น: {output_filename}")
<br>
if __name__ == "__main__":
main()
์์ ๊ฐ์ด ํ๋กฌํํธ๋ฅผ ๋ฃ๊ณ ์คํํ๋ฉด

์กฐ๊ธ ๊ฑธ๋ ค์ ์ด๋ ๊ฒ ์ด๋ฏธ์ง๋ฅผ ๋ง๋ค์ด์ค๋ค.
์ฐธ์กฐ
https://aws.amazon.com/ko/what-is/stable-diffusion/
https://medium.com/@onkarmishra/stable-diffusion-explained-1f101284484d
https://en.wikipedia.org/wiki/Stable_Diffusion