364 lines
8.5 KiB
Markdown
364 lines
8.5 KiB
Markdown
# SDXL
|
||
|
||
## 概述
|
||
|
||
SDXL(Stable Diffusion XL)是Stability AI发布的文生图扩散模型,是Stable Diffusion系列的最新一代产品。SDXL在架构上进行了重大升级,包括更大的UNet、Refiner模块和CLIP文本编码器组合,显著提升了生成图像的质量和细节。
|
||
|
||
## 1. SDXL整体结构
|
||
|
||
### 1.1 模型架构概览
|
||
|
||
SDXL采用两阶段生成架构:
|
||
|
||
```
|
||
文本提示 → CLIP编码器(双)→ UNet(base)→ 潜空间 → Refiner → 图像
|
||
↓
|
||
扩散去噪过程
|
||
```
|
||
|
||
**核心组件:**
|
||
1. OpenCLIP ViT-L/14 文本编码器(主体)
|
||
2. OpenCLIP ViT-g/14 文本编码器(补充)
|
||
3. Base UNet(基础生成)
|
||
4. Refiner UNet(细节增强)
|
||
|
||
### 1.2 与SD 1.5/2.1的对比
|
||
|
||
| 特性 | SD 1.5 | SD 2.1 | SDXL |
|
||
|------|--------|--------|------|
|
||
| 参数量(UNet) | 860M | 865M | 3.5B |
|
||
| 文本编码器 | CLIP ViT-L/14 | CLIP ViT-L/14 | OpenCLIP g/14+L/14 |
|
||
| 基础分辨率 | 512×512 | 768×768 | 1024×1024 |
|
||
| latent通道 | 4 | 4 | 4 |
|
||
| 分辨率灵活度 | 固定 | 固定 | 多分辨率 |
|
||
|
||
## 2. UNet升级
|
||
|
||
### 2.1 架构改进
|
||
|
||
**模型尺寸:**
|
||
```python
|
||
# SDXL UNet配置
|
||
config = {
|
||
'in_channels': 4,
|
||
'out_channels': 4,
|
||
'model_channels': 320,
|
||
'num_res_blocks': 2,
|
||
'attention_resolutions': [4, 2, 1],
|
||
'context_dim': 2048, # 更大的context维度
|
||
'use_reentrant': False,
|
||
'guidance_embed': True
|
||
}
|
||
```
|
||
|
||
**Transformer块增强:**
|
||
- 每层注意力头数增加
|
||
- Cross-attention层增强
|
||
- 时间步嵌入改进
|
||
|
||
### 2.2 注意力机制
|
||
|
||
**多尺度注意力:**
|
||
```python
|
||
# SDXL使用三种注意力分辨率
|
||
attention_resolutions = {
|
||
'32x32': 较粗粒度(早期层)
|
||
'16x16': 中等粒度(中间层)
|
||
'8x8': 细粒度(后期层)
|
||
}
|
||
|
||
# Cross-attention用于文本条件注入
|
||
class CrossAttention(nn.Module):
|
||
def __init__(self, d_model, num_heads, context_dim):
|
||
self.query = nn.Linear(d_model, d_model)
|
||
self.key = nn.Linear(context_dim, d_model) # 文本维度:2048
|
||
self.value = nn.Linear(context_dim, d_model)
|
||
self.num_heads = num_heads
|
||
```
|
||
|
||
### 2.3 时间步条件
|
||
|
||
**改进的时间编码:**
|
||
```python
|
||
# Timestep embedding升级
|
||
class TimestepEmbedder(nn.Module):
|
||
def __init__(self, dim, freq_embed_size=256):
|
||
self.mlp = nn.Sequential(
|
||
nn.Linear(dim, freq_embed_size * 4),
|
||
nn.SiLU(),
|
||
nn.Linear(freq_embed_size * 4, freq_embed_size * 4),
|
||
)
|
||
self.freq_embed = nn.Linear(freq_embed_size, dim)
|
||
|
||
def forward(self, t):
|
||
t_freq = self.mlp(t)
|
||
return self.freq_embed(t_freq)
|
||
```
|
||
|
||
### 2.4 条件注入机制
|
||
|
||
**Guidance Scale控制:**
|
||
```python
|
||
# Classifier-Free Guidance
|
||
# 在推理时使用guidance scale控制条件强度
|
||
|
||
def guidance_scale_forward(unet, latents, timestep, cond, cfg_scale=7.5):
|
||
# 条件和无条件同时推理
|
||
cond_output = unet(latents, timestep, cond) # 有条件
|
||
uncond_output = unet(latents, timestep, uncond) # 无条件
|
||
|
||
# 插值
|
||
guided_output = uncond_output + cfg_scale * (cond_output - uncond_output)
|
||
return guided_output
|
||
```
|
||
|
||
## 3. Refiner模块
|
||
|
||
### 3.1 Refiner作用
|
||
|
||
Refiner是SDXL独有的细节增强模块:
|
||
|
||
```
|
||
Base输出 → Refiner输入 → 细节增强 → 最终输出
|
||
(latent) (latent) (噪声细化)
|
||
```
|
||
|
||
**功能:**
|
||
- 提升图像细节质量
|
||
- 改善纹理和边缘
|
||
- 增强全局一致性
|
||
|
||
### 3.2 Refiner架构
|
||
|
||
```python
|
||
class RefinerUNet(nn.Module):
|
||
def __init__(self):
|
||
# 结构与Base UNet类似,但:
|
||
self.in_channels = 4
|
||
self.model_channels = 320
|
||
self.num_res_blocks = 2
|
||
|
||
# 使用相同的时间步条件
|
||
# 使用相同的文本编码器
|
||
|
||
# 区别:
|
||
# 1. 专注于细粒度特征
|
||
# 2. 更强的注意力机制
|
||
# 3. 接受Base输出作为输入
|
||
```
|
||
|
||
### 3.3 级联生成策略
|
||
|
||
```python
|
||
# 两阶段推理流程
|
||
def generate_sdxl(prompt, num_steps=20, cfg_scale=7.5):
|
||
# Stage 1: Base生成
|
||
latents = base_unet.sample(
|
||
num_steps=num_steps,
|
||
prompt_embedding=prompt_emb,
|
||
guidance_scale=cfg_scale
|
||
)
|
||
|
||
# Stage 2: Refiner增强
|
||
refined_latents = refiner_unet.sample(
|
||
num_steps=8, # 较少步数
|
||
latents=latents,
|
||
prompt_embedding=prompt_emb,
|
||
guidance_scale=cfg_scale,
|
||
image_cond=True # 以Base结果为条件
|
||
)
|
||
|
||
# 解码到像素空间
|
||
image = vae.decode(refined_latents)
|
||
return image
|
||
```
|
||
|
||
## 4. CLIP文本编码器组合
|
||
|
||
### 4.1 双编码器设计
|
||
|
||
SDXL使用两个CLIP文本编码器:
|
||
|
||
**主编码器:OpenCLIP ViT-L/14**
|
||
```python
|
||
# 参数量:428M
|
||
# 特征维度:768
|
||
# 作用:提供主要的文本理解能力
|
||
```
|
||
|
||
**辅助编码器:OpenCLIP ViT-g/14**
|
||
```python
|
||
# 参数量:1.3B
|
||
# 特征维度:1024
|
||
# 作用:增强复杂文本理解
|
||
```
|
||
|
||
### 4.2 文本嵌入融合
|
||
|
||
```python
|
||
class DualTextEncoder(nn.Module):
|
||
def __init__(self):
|
||
self.encoder_l = CLIPViT_L() # 768维
|
||
self.encoder_g = CLIPViT_G() # 1024维
|
||
|
||
# 融合层
|
||
self.fusion = nn.Linear(768 + 1024, 2048)
|
||
|
||
def forward(self, text):
|
||
feat_l = self.encoder_l(text) # [B, 768]
|
||
feat_g = self.encoder_g(text) # [B, 1024]
|
||
|
||
# 拼接后投影到统一空间
|
||
combined = torch.cat([feat_l, feat_g], dim=-1) # [B, 1792]
|
||
projected = self.fusion(combined) # [B, 2048]
|
||
return projected
|
||
```
|
||
|
||
### 4.3 文本编码器重要性
|
||
|
||
| 编码器 | 能力提升 |
|
||
|--------|----------|
|
||
| ViT-L/14 | 基础文本-图像对齐 |
|
||
| ViT-g/14 | 复杂语义理解 |
|
||
| 双编码器融合 | 细节描述准确生成 |
|
||
|
||
## 5. 训练技术
|
||
|
||
### 5.1 潜空间扩散
|
||
|
||
```python
|
||
# VAE编码图像到潜空间
|
||
def encode_image(image):
|
||
# image: [B, 3, 1024, 1024]
|
||
latent = vae.encode(image)
|
||
# latent: [B, 4, 128, 128]
|
||
return latent * 0.18215 # 缩放因子
|
||
|
||
# 潜空间噪声
|
||
noise = torch.randn_like(latent)
|
||
|
||
# 扩散过程
|
||
def diffuse(latent, t):
|
||
# 添加噪声
|
||
noisy = sqrt(alpha_bar[t]) * latent + sqrt(1 - alpha_bar[t]) * noise
|
||
return noisy
|
||
```
|
||
|
||
### 5.2 多分辨率训练
|
||
|
||
SDXL支持灵活的图像分辨率:
|
||
|
||
```python
|
||
# 训练时随机采样分辨率
|
||
train_resolutions = [
|
||
(1024, 1024),
|
||
(512, 1024),
|
||
(1024, 512),
|
||
(768, 768),
|
||
(640, 896),
|
||
(896, 640)
|
||
]
|
||
|
||
# 使用aspect ratio bucketing
|
||
def get_aspect_ratio_bucket(target_size):
|
||
ratio = target_size[0] / target_size[1]
|
||
if ratio > 1.3: return 'wide'
|
||
elif ratio < 0.77: return 'tall'
|
||
else: return 'square'
|
||
```
|
||
|
||
### 5.3 训练数据
|
||
|
||
| 数据类型 | 数量 | 处理方式 |
|
||
|----------|------|----------|
|
||
| LAION-5B | 5B | 安全过滤 + 审美过滤 |
|
||
| AAIA | ~600M | 高审美质量筛选 |
|
||
| 内部数据 | 专有 | 高质量标注 |
|
||
|
||
## 6. 推理优化
|
||
|
||
### 6.1 采样器选择
|
||
|
||
| 采样器 | 步数 | 速度 | 质量 |
|
||
|--------|------|------|------|
|
||
| DPM++ 2M Karras | 20-30 | 中 | 高 |
|
||
| Euler a | 20-30 | 快 | 中 |
|
||
| DDIM | 10-20 | 快 | 中 |
|
||
| PLMS | 20 | 中 | 中 |
|
||
|
||
### 6.2 量化优化
|
||
|
||
```python
|
||
# INT8量化
|
||
quantized_model = quantize(model, bits=8)
|
||
|
||
# 内存优化
|
||
model.enable_xformers() # 使用Flash Attention
|
||
model.enable_attention_slicing() # 切片注意力
|
||
```
|
||
|
||
## 7. 使用指南
|
||
|
||
### 7.1 基本推理代码
|
||
|
||
```python
|
||
from diffusers import StableDiffusionXLPipeline
|
||
|
||
pipe = StableDiffusionXLPipeline.from_pretrained(
|
||
"stabilityai/stable-diffusion-xl-base-1.0",
|
||
torch_dtype=torch.float16,
|
||
variant="fp16"
|
||
)
|
||
|
||
prompt = "a photo of an astronaut riding a horse on mars"
|
||
image = pipe(
|
||
prompt=prompt,
|
||
height=1024,
|
||
width=1024,
|
||
num_inference_steps=25,
|
||
guidance_scale=7.5
|
||
).images[0]
|
||
```
|
||
|
||
### 7.2 高级参数
|
||
|
||
```python
|
||
# Refiner使用
|
||
result = pipe(
|
||
prompt=prompt,
|
||
num_inference_steps=25,
|
||
denoise_end=0.8, # Base停止时机
|
||
guidance_scale=7.5,
|
||
negative_prompt="blurry, low quality" # 负提示
|
||
)
|
||
```
|
||
|
||
## 8. 性能评估
|
||
|
||
### 8.1 人类偏好评估
|
||
|
||
| 模型 | 偏好率(vs SD 2.1)|
|
||
|------|-------------------|
|
||
| SDXL | 65% |
|
||
| SD 2.1 | 35% |
|
||
|
||
### 8.2 FID指标
|
||
|
||
| 模型 | FID ↓ | IS ↑ |
|
||
|------|-------|------|
|
||
| SDXL | 6.5 | 120 |
|
||
| SD 2.1 | 8.1 | 105 |
|
||
| SD 1.5 | 10.2 | 95 |
|
||
|
||
## 9. 总结
|
||
|
||
SDXL的主要升级点:
|
||
|
||
| 升级 | 效果 |
|
||
|------|------|
|
||
| UNet规模(3.5B) | 更高生成质量 |
|
||
| 双CLIP编码器 | 更准确的文本理解 |
|
||
| Refiner模块 | 细节增强 |
|
||
| 多分辨率支持 | 灵活尺寸生成 |
|
||
|
||
SDXL代表了开源文生图模型的最高水平,为后续的SDXL-Turbo、SDXL-Lightning等快速采样模型奠定了基础。 |