CV Day 36 Stable Diffusion 推論實戰
執行需求:Colab T4 可跑。本篇在 Colab 免費 T4(16 GB VRAM)上用 Hugging Face diffusers 0.31 載入 Stable Diffusion 1.5(runwayml/stable-diffusion-v1-5,2024 年仍存在的官方 v1.5 repo,license 為 CreativeML Open RAIL-M),生成一張 512×512 的彩色影像。單張推論時間:DDIM 50 步約 4.5 秒、Euler 30 步約 3.0 秒、DPM++ 20 步約 2.5 秒(實際數字會略有不同);VRAM 占用約 6.0–6.8 GB。CPU 純推論也可以跑(單張約 2 分鐘),但實務上沒人這樣用——Stable Diffusion 的設計前提就是有 GPU。
引言
Day 35 的內容中,我們用一個小型 U-Net 在 MNIST 28×28 上訓練了一個完整的 DDPM/DDIM 流程——加噪、取樣、50 步加速都跑過了。今天我們要跳到「真實世界的 Stable Diffusion」:用 Hugging Face diffusers 0.31 載入 Stability AI 與 RunwayML 合作釋出的 Stable Diffusion 1.5 模型,生成 512×512 的彩色影像。Stable Diffusion 1.5 在 2024 年仍是社群最常用的開源文生圖模型,原因有三:第一,runwayml/stable-diffusion-v1-5 在 Hugging Face Hub 上有完整的 fp16 版本(runwayml/stable-diffusion-v1-5 與 stable-diffusion-v1-5/stable-diffusion-v1-5 兩個相同內容的鏡像),license CreativeML Open RAIL-M 允許商業使用;第二,diffusers 把模型拆成四個子元件(VAE、UNet、text encoder、scheduler),使用者可以單獨換掉任一個;第三,ControlNet、LoRA、IP-Adapter 等所有擴充都是基於這個架構。
Stable Diffusion 不是單純的 DDPM——它是 Latent Diffusion Model(LDM,Rombach 等人,2022),把擴散過程從「像素空間」搬到「潛在空間」。具體設計:先用一個 VAE Encoder 把 512×512×3 影像壓縮到 64×64×4 的潛在向量、再對潛在向量做 DDPM 加噪/去噪、最後用 VAE Decoder 把 64×64×4 解回 512×512×3。這種設計讓擴散的維度從 512×512×3 ≈ 786,432 維降到 64×64×4 = 16,384 維(約 48× 縮小),單次 UNet forward 的時間與記憶體都大幅縮減。代價是 VAE 解碼時會損失一點高頻細節——這也是 Stable Diffusion 影像放大後偶爾會糊的原因之一。
這一篇的核心是「把 diffusers 的 StableDiffusionPipeline 用起來」。我們會展示四個控制參數的影響:negative_prompt(告訴模型不要什麼)、guidance_scale(CFG classifier-free guidance,控制「多認真遵守 prompt」的強度)、seed(隨機數種子,控制可重現性)、num_inference_steps(取樣步數,控制品質與速度的取捨)。讀完這篇你應該能回答:Stable Diffusion 為什麼不在像素空間擴散、要在潛在空間?scheduler、VAE、UNet、text encoder 四個元件各做什麼?guidance_scale 太低太高會怎樣?為什麼 seed 設 42 可以重現別人發的圖?
Stable Diffusion 的潛在空間擴散
Stable Diffusion 的四個核心元件各司其職。VAE(Variational Autoencoder) 負責像素 ↔ 潛在空間的轉換:Encoder 把 512×512×3 的影像壓到 64×64×4 的潛在向量 z,Decoder 把 z 解回像素空間。VAE 的潛在維度比像素空間小約 48 倍,這是 Stable Diffusion 能在消費級 GPU 跑的關鍵。UNet 是擴散模型本身(860M 參數),接收潛在向量 z_t 與時間步 t、預測噪音 ε_θ(z_t, t),跟 Day 35 的 MNIST 小型 U-Net 是同樣的設計、只是通道數從 64/128/256 拉到 320/640/1280。Text encoder 把 prompt 文字編碼成 77×768 的 token embedding(CLIP text encoder),這是「條件式生成」的核心——UNet 同時接收 z_t 與文字 embedding,學會根據文字調整去噪行為。Scheduler 控制加噪/去噪的數學細節:β schedule、DDIM/DDPM 切換、num_inference_steps。
「條件式生成」需要 classifier-free guidance(CFG)。訓練時 UNet 同時學「有條件去噪」(給文字 embedding)與「無條件去噪」(把文字 embedding 換成空字串);推論時把兩個預測線性組合:ε_with_cfg = ε_uncond + guidance_scale · (ε_cond - ε_uncond)。guidance_scale = 1 時退化成純條件生成(影像多樣但「不認真聽話」)、guidance_scale = 7.5 是 Stable Diffusion 1.5 的預設值(平衡品質與多樣性)、guidance_scale = 15–20 時影像會過度飽和(顏色過鮮豔、細節過度銳利)。負面 prompt 則是把「uncond 換成 negative 的文字 embedding」——這個機制來自 SD 1.5 的後續社群微調,現在是 diffusers 的標準介面。
Scheduler 是 Stable Diffusion 最容易踩雷的元件——同一個模型換不同的 scheduler,生成的影像品質、收斂速度、可重現性都會改變。主流選擇有:DDIM(Song 等人,2020,50 步為標準;Stable Diffusion 1.5 原始論文的預設)、EulerDiscrete(Karras 等人,2022,30 步就能達到 DDIM 50 步品質,2024 年的主流預設)、DPMSolverMultistep(Lu 等人,2022,20–25 步品質最佳)、UniPC(Zhao 等人,2023,15–20 步品質逼近 DPMSolver)。實務上要品質優先用 DPMSolverMultistep 25 步、要速度優先用 Euler 20 步、要可重現用 DDIM 50 步。順帶一提,這些 scheduler 之間的「品質」與「步數」關係不是單純線性:DPMSolver 20 步通常比 DDIM 20 步好得多,因為它是高階 ODE 解法;Euler 30 步比 DPMSolver 30 步略差,因為 Euler 是一階方法、需要更多步才能收斂。實務上「scheduler + 步數」必須一起挑,不能單獨調整其中一個。
diffusers 0.31 的 StableDiffusionPipeline 介面
diffusers 0.31 把 Stable Diffusion 包成 StableDiffusionPipeline.from_pretrained(...) 一個 call 就載入四個元件。from_pretrained("runwayml/stable-diffusion-v1-5", torch_dtype=torch.float16) 會從 Hugging Face Hub 下載 VAE、UNet、text encoder、tokenizer、scheduler(總計約 5 GB),並用 fp16 載入(VRAM 從 12 GB 降到 6 GB)。呼叫 pipe(prompt, negative_prompt=..., num_inference_steps=..., guidance_scale=..., generator=...).images[0] 就能拿到一張 PIL Image。
generator 參數是 torch 的隨機數生成器,控制初始雜訊——這就是「為什麼 seed=42 可以重現別人發的圖」的機制。diffusers 0.31 推薦用 torch.Generator(device="cuda").manual_seed(42),把 generator 與裝置綁在一起;如果你寫成 torch.manual_seed(42)(CPU 種子),結果會與 Generator(device="cuda").manual_seed(42) 不一樣——因為 CPU 與 CUDA 的 PRNG 演算法不同。實務上要保證可重現,必須固定 generator 與 device。
另一個常見踩雷點是 safety_checker。Stable Diffusion 1.5 預設帶一個 NSFW 內容過濾器,會把「看起來像裸露」的影像換成全黑圖。這個過濾器在 from_pretrained 時載入、推論時呼叫——對於「想生成工業瑕疵」這種完全無害的應用,反而會誤殺一些「瑕疵 = 黑色斑塊」的影像。關閉方法:pipe.safety_checker = None 或 pipe.safety_checker = lambda images, clip_input, **kwargs: (images, [False] * len(images))。這個改動是合法的(CreativeML Open RAIL-M license 允許關閉過濾器)、但要評估你的應用是否有合規需求。順帶一提,2024 年 10 月 Hugging Face 對 SD v1.5 等部分模型新增「需登入才能下載」的限制——如果你看到 403 Forbidden 或 gated repo,請先在 Hugging Face 帳號設定中接受該模型的使用條款,再執行 huggingface-cli login 重新整理 token。
diffusers 0.31 還提供兩種「記憶體優化」介面。pipe.enable_attention_slicing() 會把 attention 計算切成小塊(例如 512×512 → 256×256),VRAM 從 6 GB 降到 4 GB 左右,速度慢約 15%;pipe.enable_vae_tiling() 會把 VAE 解碼也切成 tile(例如 1024×1024 切成 4 個 512×512),讓 1024×1024 的高解析度生成不會爆 VRAM。這兩個介面都是「trade VRAM for time」的設計——VRAM 小的顯卡(如 RTX 3060 12 GB)會很需要。實務上 T4 / V100 等 16 GB 顯卡可以跳過這些設定,直接用預設 fp16。
完整實作:用 diffusers 0.31 生成 Stable Diffusion 影像
以下範例在 Colab T4 上約 8 分鐘(含下載模型約 1 分鐘、推論約 30 秒 × 6 組實驗)。我們會載入 Stable Diffusion 1.5、用四組 prompt + 不同參數生成影像、視覺化 guidance_scale 與 num_inference_steps 的影響。執行前需安裝:pip install diffusers==0.31 transformers==4.46 accelerate torch safetensors(Colab 預裝 torch、accelerate)。注意 2024 年 12 月 Hugging Face 的認證政策:sd-v1-5 仍可匿名下載,但部分模型需要先執行 huggingface-cli login 並接受 license。
# 1. 安裝 diffusers 0.31 與相關套件(Colab 預設 torch,accelerate 可不安裝)
pip install -q diffusers==0.31 transformers==4.46 safetensors
python -c "import diffusers, transformers; print(f'diffusers {diffusers.__version__}, transformers {transformers.__version__}')"
# 輸出:diffusers 0.31.0, transformers 4.46.0
這段把 diffusers 0.31 與 transformers 4.46 鎖版安裝。diffusers==0.31 是 2024 年底前的穩定版本,內建 StableDiffusionPipeline、DPMSolverMultistepScheduler、EulerDiscreteScheduler 等排程器。transformers 4.46 提供 CLIPTokenizer 與 CLIPTextModel,這是 Stable Diffusion text encoder 的依賴。safetensors 是模型權重的安全格式(避免 pickle 反序列化漏洞),diffusers 0.31 預設從 .safetensors 載入。如果你的 transformers 版本較新,可能需要 pip install transformers==4.46 鎖版。
# 2. 載入 Stable Diffusion 1.5(fp16、約 5 GB VRAM、約 1 分鐘下載)
import torch
from diffusers import StableDiffusionPipeline
model_id = "runwayml/stable-diffusion-v1-5"
pipe = StableDiffusionPipeline.from_pretrained(
model_id,
torch_dtype=torch.float16, # VRAM 從 12 GB 降到 6 GB
safety_checker=None, # 關閉 NSFW 過濾器(瑕疵生成會誤判)
)
pipe = pipe.to("cuda")
print(f"Pipeline 已載入,UNet 參數量:{sum(p.numel() for p in pipe.unet.parameters()) / 1e6:.1f}M")
print(f"VAE 參數量:{sum(p.numel() for p in pipe.vae.parameters()) / 1e6:.1f}M")
# 輸出:Pipeline 已載入,UNet 參數量:860.1M
# 輸出:VAE 參數量:83.6M
這段從 Hugging Face Hub 載入 Stable Diffusion 1.5。torch_dtype=torch.float16 是 T4 / V100 等消費級 GPU 的標準做法——VRAM 從 12 GB 降到 6 GB,VRAM 占用不到 T4 的 16 GB 限制。safety_checker=None 把 NSFW 過濾器關掉,這對「生成工業瑕疵」應用是必要的:瑕疵的暗色斑塊有時會被誤判為裸露。Stable Diffusion 1.5 的權重約 5 GB(包括 fp32 與 fp16 各一份),首次下載約 60–90 秒,第二次執行會從 ~/.cache/huggingface/hub/ 讀取、不到 5 秒。UNet 860M 參數是 Stable Diffusion 1.5 的主體,VAE 83.6M 參數負責潛在空間的編解碼。
# 3. 基本推論:單張影像、DDIM 50 步、guidance_scale=7.5
import time
prompt = "a rusty metal gear with scratches, industrial close-up, soft lighting, 8k"
negative_prompt = "blurry, low quality, distorted, watermark"
torch.manual_seed(42)
generator = torch.Generator(device="cuda").manual_seed(42)
t0 = time.time()
image = pipe(
prompt=prompt,
negative_prompt=negative_prompt,
num_inference_steps=50,
guidance_scale=7.5,
generator=generator,
).images[0]
dt = time.time() - t0
image.save("/content/sd_basic.png")
print(f"生成 1 張影像耗時:{dt:.1f} 秒")
print(f"影像尺寸:{image.size}")
# 輸出(實際數字會略有不同):
# 生成 1 張影像耗時:4.6 秒
# 影像尺寸:(512, 512)
這段是 Stable Diffusion 的最小推論範例。generator 與 torch.manual_seed(42) 雙重保險——把 CUDA 的隨機性也固定住,確保同一個 prompt + seed 永遠產生同一張影像。negative_prompt 把「模糊、低品質、變形、浮水印」這類常見生成瑕疵明確排除,這是 Stable Diffusion 1.5 社群累積出來的「標準負面 prompt 模板」。num_inference_steps=50 是 DDIM 的標準設定,guidance_scale=7.5 是 Stable Diffusion 1.5 原始論文的預設值。整個流程在 T4 上約 4.6 秒,比 Day 35 的 MNIST DDIM 慢約 27 倍(從 28×28 灰階升到 512×512 彩色 + 860M 參數 UNet),但生成品質是「真實可用的產品照」級別。
# 4. Scheduler 比較:DDIM 50 / Euler 30 / DPMSolver 20 的品質與時間
from diffusers import DDIMScheduler, EulerDiscreteScheduler, DPMSolverMultistepScheduler
prompt = "a rusty metal gear with scratches, industrial close-up, soft lighting, 8k"
results = {}
for name, scheduler_cls, steps in [
("DDIM 50 步", DDIMScheduler, 50),
("Euler 30 步", EulerDiscreteScheduler, 30),
("DPMSolver 20 步", DPMSolverMultistepScheduler, 20),
]:
pipe.scheduler = scheduler_cls.from_config(pipe.scheduler.config)
generator = torch.Generator(device="cuda").manual_seed(42)
t0 = time.time()
img = pipe(prompt=prompt, num_inference_steps=steps, guidance_scale=7.5, generator=generator).images[0]
dt = time.time() - t0
img.save(f"/content/sd_{name.split()[0].lower()}.png")
results[name] = dt
for name, dt in results.items():
print(f" {name:18s} 耗時 {dt:.1f} 秒")
# 輸出(實際數字會略有不同):
# DDIM 50 步 耗時 4.6 秒
# Euler 30 步 耗時 2.9 秒
# DPMSolver 20 步 耗時 2.1 秒
這段比較三個主流 scheduler 的推論時間。DDIM 50 步 是 Stable Diffusion 1.5 的原始預設,4.6 秒;Euler 30 步 用 Karras 的 stochastic sampler 達到 DDIM 50 步品質但只花 2.9 秒(37% 加速);DPMSolver 20 步 是 Lu 等人 2022 年的多步解法,達到接近品質但只花 2.1 秒(54% 加速)。實務上如果要批次生成(例如 100 張用於資料增強),DPMSolver 20 步是最佳選擇;如果要可重現的論文實驗,DDIM 50 步是預設。每個 scheduler 都透過 from_config 繼承 Stable Diffusion 原始的 β schedule 參數,再用自己的演算法解軌跡。
# 5. guidance_scale 的影響:1.0 / 4.5 / 7.5 / 12.5 的影像變化
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
prompt = "a rusty metal gear with scratches, industrial close-up, soft lighting, 8k"
fig_images = []
for gs in [1.0, 4.5, 7.5, 12.5]:
generator = torch.Generator(device="cuda").manual_seed(42)
img = pipe(prompt=prompt, num_inference_steps=20, guidance_scale=gs, generator=generator).images[0]
fig_images.append((gs, img))
img.save(f"/content/sd_gs_{gs}.png")
print("guidance_scale 1.0 / 4.5 / 7.5 / 12.5 已存成 4 張圖")
# 輸出:guidance_scale 1.0 / 4.5 / 7.5 / 12.5 已存成 4 張圖
這段實驗 guidance_scale 對生成品質的影響。guidance_scale=1.0 等於「完全不聽 prompt」——生成影像會偏模糊、偏「通用」、與 prompt 文字的對應關係很弱(這是 classifier-free guidance 的退化情況)。guidance_scale=4.5 是「保守聽話」——影像會明顯對應 prompt 文字,但細節較平滑。guidance_scale=7.5 是 Stable Diffusion 1.5 的預設——平衡品質與多樣性,多數場景的最佳選擇。guidance_scale=12.5 是「過度聽話」——影像會過度飽和、邊緣過度銳利、有時會出現 artifacts(如額外的紋理、重複的圖案)。實務上 7–8 是多數 prompt 的甜蜜點;動漫風格建議 9–11、寫實風格建議 5–7。
# 6. negative_prompt 的實驗:空 vs 「blurry」vs 「blurry, low quality」
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
prompt = "a rusty metal gear with scratches, industrial close-up, soft lighting, 8k"
fig_images = []
for neg in [
"",
"blurry",
"blurry, low quality, distorted, watermark",
]:
generator = torch.Generator(device="cuda").manual_seed(42)
img = pipe(prompt=prompt, negative_prompt=neg, num_inference_steps=30, guidance_scale=7.5, generator=generator).images[0]
fig_images.append((neg or "(空)", img))
img.save(f"/content/sd_neg_{neg[:20] or 'empty'}.png")
print("3 種 negative_prompt 已存成 3 張圖")
# 輸出:3 種 negative_prompt 已存成 3 張圖
這段實驗 negative_prompt 的效果。空 negative_prompt 等於「不排除任何特徵」——影像可能出現模糊、雜訊、低解析度等常見瑕疵;加上 "blurry" 排除模糊後影像邊緣明顯變銳利;加上完整的社群標準模板 "blurry, low quality, distorted, watermark" 後影像品質最接近 Stable Diffusion 官方展示照。這證實了負面 prompt 並不是裝飾——它是 classifier-free guidance 中「uncond 文字」的內容;模型會學到「把這些不想要的特徵降低機率」。實務上「寫 prompt 的時間」應該有 30% 花在 negative_prompt 上,這對 2024 年的 Stable Diffusion 1.5 仍是必要投資。
# 7. VRAM 監控:在 T4 上跑 1 張、4 張、16 張 batch,看 VRAM 占用
import torch
pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
prompt = "a rusty metal gear with scratches, industrial close-up, soft lighting, 8k"
for batch in [1, 4, 16]:
prompts = [prompt] * batch
generator = torch.Generator(device="cuda").manual_seed(42)
torch.cuda.reset_peak_memory_stats()
imgs = pipe(prompt=prompts, num_inference_steps=20, guidance_scale=7.5, generator=generator).images
peak = torch.cuda.max_memory_allocated() / 1024 ** 3
print(f" batch={batch:2d} 生成 {len(imgs)} 張 峰值 VRAM:{peak:.2f} GB")
# 輸出(實際數字會略有不同):
# batch= 1 生成 1 張 峰值 VRAM:6.21 GB
# batch= 4 生成 4 張 峰值 VRAM:7.84 GB
# batch=16 生成 16 張 峰值 VRAM:13.62 GB
這段量測不同 batch size 的 VRAM 占用。batch=1 時峰值 6.21 GB(這是 Stable Diffusion 1.5 fp16 的 baseline);batch=4 時 7.84 GB(每張增加 0.4 GB,主要是 UNet 中間特徵圖);batch=16 時 13.62 GB(已經接近 T4 的 16 GB 上限)。這個數字告訴我們:T4 上單卡最多批次生 8–10 張,要生 16 張以上必須加 pipe.enable_model_cpu_offload()(把 UNet 暫時搬到 CPU)或是用多卡。實務上 diffusers 0.31 推薦用 accelerate 的 device_map="balanced" 自動分配。
常見錯誤與踩雷
錯誤一:忘記設 torch_dtype=torch.float16。預設 fp32 載入會讓 VRAM 從 6 GB 升到 12 GB,T4 的 16 GB 剛好會超出,導致 CUDA out of memory。對應排查方向:永遠用 torch_dtype=torch.float16 載入 Stable Diffusion 1.5;如果你是 A100 / H100 等專業卡,可以改用 bf16。
錯誤二:torch.manual_seed(42) 與 Generator(device="cuda").manual_seed(42) 混用。這兩個 seed 設定的內部 PRNG 演算法不同——CPU seed 用 Philox 4×32-10、CUDA seed 用 Philox 4×32-7。如果你只設前者、Generator 沒設,產生的影像與「別人重現你的 seed」不會一樣。對應排查方向:用 generator = torch.Generator(device="cuda").manual_seed(42) 一個 call 就好,不要再額外呼叫 torch.manual_seed。
錯誤三:safety_checker 過濾掉合法影像。Stable Diffusion 1.5 預設的安全過濾器會把「接近裸露」的影像換成全黑——對於「生鏽齒輪」、「黑色瑕疵」這類 prompt 偶爾會誤判。對應排查方向:pipe.safety_checker = None 可以關閉;如果你的應用有合規需求,可以改用更精細的 NSFW 分類器(不會誤殺)。
錯誤四:把 Stable Diffusion 1.5 跑在 CPU。雖然 pipe.to("cpu") 可以強制 CPU 推論,但單張 512×512 影像約 2 分鐘,這對開發迭代完全不可接受。對應排查方向:即使是 Colab 免費 T4 也比 CPU 快 30 倍;如果真的沒 GPU,至少把 pipe.unet 換成 torch.compile(pipe.unet, mode="reduce-overhead") 可以再加速 20%。
錯誤五:把 num_inference_steps 設成 5 以為「夠快就好」。少於 10 步的 Stable Diffusion 影像會出現明顯 artifacts(如條紋、色塊、未收斂的區域)。對應排查方向:最少 15–20 步才有可接受的品質;20 步是 DPMSolver 的甜蜜點;30–50 步是其他 scheduler 的甜蜜點。低於 10 步只適合「快速預覽構圖」的場景,不適合正式輸出。
效能與實務提醒
在 Colab T4 上跑 Stable Diffusion 1.5(fp16、DDIM 50 步)單張約 4.6 秒。T4 的 16 GB VRAM 在 fp16 下能撐到 batch=8(峰值約 11 GB)。如果想再加速三個常用手段:第一,用 torch.compile(pipe.unet, mode="reduce-overhead", fullgraph=True) 把 UNet 編譯成融合 kernel,T4 上可以再加速 25–35%;第二,用 pipe.enable_xformers_memory_efficient_attention() 或 pipe.enable_attention_slicing() 把 attention 切成小塊,VRAM 從 6 GB 降到 4 GB、batch 容量翻倍;第三,用 pipe.enable_vae_tiling() 把 VAE 解碼也切成 256×256 的 tile,可以生 1024×1024 的影像而不爆 VRAM。
如果要部署 Stable Diffusion 做服務,模型權重約 5 GB(fp16),加上快取約 8 GB。最低硬體需求:NVIDIA 顯卡 8 GB VRAM(如 RTX 3060、RTX 4060),CPU 推論約 60 秒一張不建議;Mac M1/M2 用 torch.float16 + mps 後端約 25–35 秒一張(社群實測);AMD 顯卡要用 ROCm 5.7+ + torch.float16,但 diffusers 0.31 的官方支援有限。實務上工業部署最常見的選擇是「租 A100 / L4 雲端」或「用 sd-turbo 之類的蒸餾模型」——stableai 的 sdxl-turbo / stabilityai/sd-turbo 是 1–4 步的蒸餾版,T4 上單張約 0.5 秒、512×512,但品質略低於 SD 1.5。
貫穿專案的角度:MVTec AD 的合成罕見瑕疵任務(Day 39)會大量用到這篇的技術——用 Stable Diffusion 1.5 生成候選瑕疵、用 MVTec 預訓練分類器做品質過濾、最後把高品質瑕疵混入訓練集。比 DCGAN 的優勢是 Stable Diffusion 能直接從文字 prompt 生成「特定紋理」的瑕疵(如「黑色刮痕」、「銅綠氧化」、「裂縫網」),不需要收集對應的瑕疵影像做訓練。但代價是 Stable Diffusion 的單張推論成本比 DCGAN 高 100 倍,且 prompt 工程需要時間投入。實務上 Day 39 會把這兩個方法結合:DCGAN 生成「粗略構圖」、Stable Diffusion 做「細節 refine」。
小結
今天用 diffusers 0.31 載入 Stable Diffusion 1.5,從基本的單張推論、到 scheduler 比較、到 guidance_scale 與 negative_prompt 的影響、到 batch size 與 VRAM 的取捨,完整展示了 Stable Diffusion 推論工作流。重點回顧:第一,Stable Diffusion 是 Latent Diffusion Model,擴散在 VAE 的潛在空間進行,這讓 512×512 影像的擴散時間與記憶體都大幅縮減;第二,diffusers 把 Stable Diffusion 包成四個獨立元件(VAE、UNet、text encoder、scheduler),每個都能單獨換掉;第三,guidance_scale=7.5 是平衡預設、num_inference_steps=20–50 是品質甜蜜點、seed + Generator(device="cuda") 是可重現的關鍵;第四,torch_dtype=torch.float16 是 T4 / 消費級 GPU 的必要設定。明天我們會把 Stable Diffusion 1.5 升級到「可控的」版本——ControlNet 用 canny/depth 邊界控制構圖、LoRA 用 peft 做小樣本風格微調,這是 2024 年 Stable Diffusion 社群最活躍的兩條路線。
結語
今天的重點是把 Stable Diffusion 1.5 的推論工作流跑起來。我們從 diffusers 的 StableDiffusionPipeline.from_pretrained(...) 開始,展示了 prompt、negative_prompt、num_inference_steps、guidance_scale、generator 五個關鍵參數的影響,並用量化的 VRAM 數據討論 batch size 取捨。讀完這篇你應該能回答:Stable Diffusion 為什麼要在潛在空間擴散、不在像素空間?四個核心元件(VAE、UNet、text encoder、scheduler)各做什麼?guidance_scale 太低太高會怎樣?為什麼 seed=42 可以重現別人發的圖?明天,我們會把 Stable Diffusion 升級到「可控的」版本——ControlNet 透過 canny/depth 邊界條件控制構圖、LoRA 透過 peft 的低秩適配器做小樣本風格微調,這是 2024 年 Stable Diffusion 社群最活躍的兩條擴充路線,也是工業瑕疵生成、產品圖生成的標準配備。
延伸資源
- Rombach 等人,2022,High-Resolution Image Synthesis with Latent Diffusion Models(CVPR 2022):
https://arxiv.org/abs/2112.10752,Stable Diffusion 原始論文,VAE + UNet + text encoder 的潛在空間擴散設計。 - Stable Diffusion 1.5 model card(
runwayml/stable-diffusion-v1-5,CreativeML Open RAIL-M license):https://huggingface.co/runwayml/stable-diffusion-v1-5,2024 年仍可下載的官方 v1.5 model 與授權條款。 - diffusers Stable Diffusion 推論教學(v0.31,2024):
https://huggingface.co/docs/diffusers/using-diffusers/text2img,StableDiffusionPipeline、scheduler、enable_xformers_memory_efficient_attention的官方範例。 - Karras 等人,2022,Elucidating the Design Space of Diffusion-Based Generative Models(NeurIPS 2022):
https://arxiv.org/abs/2206.00364,Euler / EDM scheduler 的設計空間分析。 - Lu 等人,2022,DPM-Solver: A Fast ODE Solver for Diffusion Probabilistic Model Sampling(NeurIPS 2022):
https://arxiv.org/abs/2206.00927,DPMSolverMultistep 的數學推導與品質/速度取捨分析。 - Stability AI sd-turbo model card(
stabilityai/sd-turbo,2024):https://huggingface.co/stabilityai/sd-turbo,單步生成的蒸餾 Stable Diffusion,2024 年的速度優選方案。
留言
張貼留言