8.5 KiB
8.5 KiB
SDXL
概述
SDXL(Stable Diffusion XL)是Stability AI发布的文生图扩散模型,是Stable Diffusion系列的最新一代产品。SDXL在架构上进行了重大升级,包括更大的UNet、Refiner模块和CLIP文本编码器组合,显著提升了生成图像的质量和细节。
1. SDXL整体结构
1.1 模型架构概览
SDXL采用两阶段生成架构:
文本提示 → CLIP编码器(双)→ UNet(base)→ 潜空间 → Refiner → 图像
↓
扩散去噪过程
核心组件:
- OpenCLIP ViT-L/14 文本编码器(主体)
- OpenCLIP ViT-g/14 文本编码器(补充)
- Base UNet(基础生成)
- 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 架构改进
模型尺寸:
# 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 注意力机制
多尺度注意力:
# 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 时间步条件
改进的时间编码:
# 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控制:
# 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架构
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 级联生成策略
# 两阶段推理流程
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
# 参数量:428M
# 特征维度:768
# 作用:提供主要的文本理解能力
辅助编码器:OpenCLIP ViT-g/14
# 参数量:1.3B
# 特征维度:1024
# 作用:增强复杂文本理解
4.2 文本嵌入融合
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 潜空间扩散
# 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支持灵活的图像分辨率:
# 训练时随机采样分辨率
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 量化优化
# INT8量化
quantized_model = quantize(model, bits=8)
# 内存优化
model.enable_xformers() # 使用Flash Attention
model.enable_attention_slicing() # 切片注意力
7. 使用指南
7.1 基本推理代码
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 高级参数
# 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等快速采样模型奠定了基础。