8.2 文生图:Diffusion 与 LLM 结合


文档摘要

8.2 文生图:Diffusion 与 LLM 结合 文生图(Text-to-Image, T2I)是多模态生成的代表任务——输入一段文字描述,模型生成对应的图像。Stable Diffusion、DALL-E、Midjourney、FLUX 等模型让「凭空画图」成为日常工具。本节梳理文生图的核心技术:Diffusion 模型 + LLM 文本编码器。 一、Diffusion 模型的核心思想 Diffusion(扩散)模型的思想来自热力学——物质从有序逐渐扩散为无序。在生成模型中,它表现为: 前向过程:把一张清晰图像逐步加噪声,直到变成纯噪声 反向过程:训练一个神经网络,从纯噪声逐步去噪,还原出清晰图像 训练好去噪网络后,生成图像就是「从随机噪声开始,逐步去噪」。

8.2 文生图:Diffusion 与 LLM 结合

文生图(Text-to-Image, T2I)是多模态生成的代表任务——输入一段文字描述,模型生成对应的图像。Stable Diffusion、DALL-E、Midjourney、FLUX 等模型让「凭空画图」成为日常工具。本节梳理文生图的核心技术:Diffusion 模型 + LLM 文本编码器

一、Diffusion 模型的核心思想

Diffusion(扩散)模型的思想来自热力学——物质从有序逐渐扩散为无序。在生成模型中,它表现为:

  • 前向过程:把一张清晰图像逐步加噪声,直到变成纯噪声
  • 反向过程:训练一个神经网络,从纯噪声逐步去噪,还原出清晰图像

训练好去噪网络后,生成图像就是「从随机噪声开始,逐步去噪」。

二、前向过程:加噪的数学

前向过程是一个马尔可夫链——每一步给图像加少量高斯噪声:

q(x_t | x_{t-1}) = \mathcal{N}(x_t; \sqrt{1-\beta_t} x_{t-1}, \beta_t I)

其中 \beta_t 是预先设定的方差表(variance schedule),通常从 10^{-4} 线性增到 0.02。

一个重要性质:可以直接从 x_0 跳到任意 x_t,无需逐步计算:

q(x_t | x_0) = \mathcal{N}(x_t; \sqrt{\bar{\alpha}_t} x_0, (1-\bar{\alpha}_t) I)

其中 \bar{\alpha}_t = \prod_{s=1}^{t}(1-\beta_s)

工程意义:训练时可以直接采样任意 t 的加噪版本,不用一步步加。

三、反向过程:学习去噪

反向过程是真正的学习目标——训练一个网络 \epsilon_\theta 预测每一步加入的噪声:

p_\theta(x_{t-1} | x_t) = \mathcal{N}(x_{t-1}; \mu_\theta(x_t, t), \Sigma_\theta(x_t, t))

DDPM 的训练目标

DDPM(Denoising Diffusion Probabilistic Models)证明了,训练目标可以简化为:

\mathcal{L}_\text{DDPM} = \mathbb{E}_{x_0, \epsilon, t}\left[\|\epsilon - \epsilon_\theta(x_t, t)\|^2\right]

其中:

  • x_0:原始清晰图
  • \epsilon:加入的高斯噪声
  • x_t:加噪后的图
  • t:时间步
  • \epsilon_\theta:模型预测的噪声

直觉:给模型一张噪声图与时间步,让它预测加的是什么噪声。预测对了,反向去噪就能还原图像。

四、U-Net:去噪网络的主力

\epsilon_\theta 网络的实现——U-Net 是 Diffusion 模型的主力。它的结构:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 360" font-family="sans-serif" font-size="12"> <text x="400" y="25" text-anchor="middle" font-weight="bold" font-size="14">U-Net 架构(用于 Diffusion 去噪)</text> <!-- 输入 --> <rect x="20" y="150" width="80" height="60" fill="#e1f5ff" stroke="#333" rx="6"/> <text x="60" y="180" text-anchor="middle">噪声图 x_t</text> <text x="60" y="200" text-anchor="middle">+ 时间步 t</text> <text x="60" y="220" text-anchor="middle">+ 文本条件</text> <!-- Encoder --> <g transform="translate(130,100)"> <rect x="0" y="0" width="60" height="160" fill="#fff4e1" stroke="#333" rx="4"/> <text x="30" y="80" text-anchor="middle" transform="rotate(-90 30 80)">Conv Block</text> <text x="30" y="180" text-anchor="middle">64×64</text> </g> <g transform="translate(210,120)"> <rect x="0" y="0" width="60" height="120" fill="#fff4e1" stroke="#333" rx="4"/> <text x="30" y="60" text-anchor="middle" transform="rotate(-90 30 60)">Conv Block</text> <text x="30" y="140" text-anchor="middle">32×32</text> </g> <g transform="translate(290,140)"> <rect x="0" y="0" width="60" height="80" fill="#fff4e1" stroke="#333" rx="4"/> <text x="30" y="40" text-anchor="middle" transform="rotate(-90 30 40)">Conv Block</text> <text x="30" y="100" text-anchor="middle">16×16</text> </g> <!-- Bottleneck --> <g transform="translate(370,160)"> <rect x="0" y="0" width="60" height="40" fill="#f5e1ff" stroke="#333" rx="4"/> <text x="30" y="25" text-anchor="middle">Bottleneck</text> <text x="30" y="60" text-anchor="middle">8×8</text> </g> <!-- Decoder (镜像) --> <g transform="translate(450,140)"> <rect x="0" y="0" width="60" height="80" fill="#e8f5e1" stroke="#333" rx="4"/> <text x="30" y="40" text-anchor="middle" transform="rotate(-90 30 40)">Up Block</text> <text x="30" y="100" text-anchor="middle">16×16</text> </g> <g transform="translate(530,120)"> <rect x="0" y="0" width="60" height="120" fill="#e8f5e1" stroke="#333" rx="4"/> <text x="30" y="60" text-anchor="middle" transform="rotate(-90 30 60)">Up Block</text> <text x="30" y="140" text-anchor="middle">32×32</text> </g> <g transform="translate(610,100)"> <rect x="0" y="0" width="60" height="160" fill="#e8f5e1" stroke="#333" rx="4"/> <text x="30" y="80" text-anchor="middle" transform="rotate(-90 30 80)">Up Block</text> <text x="30" y="180" text-anchor="middle">64×64</text> </g> <!-- 输出 --> <rect x="700" y="150" width="80" height="60" fill="#ffe1e1" stroke="#333" rx="6"/> <text x="740" y="180" text-anchor="middle">预测噪声 ε</text> <!-- 跨层连接 --> <line x1="190" y1="180" x2="610" y2="180" stroke="#999" stroke-dasharray="4,2"/> <line x1="270" y1="180" x2="530" y2="180" stroke="#999" stroke-dasharray="4,2"/> <line x1="350" y1="180" x2="450" y2="180" stroke="#999" stroke-dasharray="4,2"/> <text x="400" y="280" text-anchor="middle">虚线 = 跨层连接(skip connections)</text> <!-- 主线 --> <line x1="100" y1="180" x2="125" y2="180" stroke="#333" marker-end="url(#ar5)"/> <line x1="685" y1="180" x2="695" y2="180" stroke="#333" marker-end="url(#ar5)"/> <defs> <marker id="ar5" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"> <path d="M0,0 L8,4 L0,8 z" fill="#333"/> </marker> </defs> </svg>

U-Net 的特点:

  1. 编码器-解码器结构:先下采样提取高层特征,再上采样恢复分辨率
  2. 跨层连接(Skip Connections):把编码器的中间特征直接送给解码器,保留细节
  3. U 形:因此得名

U-Net 在 Diffusion 中的输入

  • 加噪图像 x_t
  • 当前时间步 t(编码为向量)
  • 文本条件(来自 LLM 文本编码器)

模型的任务是预测噪声 \epsilon

五、Stable Diffusion:Latent Diffusion 的革命

直接在像素空间做 Diffusion 计算量极大——一张 512×512 的图有 786432 个像素,每步去噪都要算这么大的张量。

Latent Diffusion(Stable Diffusion 的核心创新)的思路:先压缩到潜在空间,再在潜在空间做 Diffusion

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 400" font-family="sans-serif" font-size="13"> <text x="450" y="25" text-anchor="middle" font-weight="bold" font-size="15">Stable Diffusion 架构</text> <!-- 文本输入 --> <rect x="20" y="80" width="100" height="60" fill="#e1f5ff" stroke="#333" rx="6"/> <text x="70" y="105" text-anchor="middle">文本 prompt</text> <text x="70" y="125" text-anchor="middle">"一只猫"</text> <!-- 文本编码器 --> <rect x="160" y="80" width="140" height="60" fill="#fff4e1" stroke="#333" rx="6"/> <text x="230" y="105" text-anchor="middle">CLIP 文本编码器</text> <text x="230" y="125" text-anchor="middle">→ 文本 embedding</text> <!-- 噪声 --> <rect x="20" y="180" width="100" height="60" fill="#999" stroke="#333" rx="6"/> <text x="70" y="205" text-anchor="middle" fill="#fff">随机噪声</text> <text x="70" y="225" text-anchor="middle" fill="#fff">(潜在空间)</text> <!-- U-Net --> <rect x="340" y="120" width="200" height="180" fill="#f5e1ff" stroke="#333" rx="8"/> <text x="440" y="145" text-anchor="middle" font-weight="bold">U-Net (去噪网络)</text> <text x="440" y="170" text-anchor="middle">输入: 潜在噪声 + 时间步</text> <text x="440" y="190" text-anchor="middle">+ 文本 embedding (Cross-Attn)</text> <text x="440" y="220" text-anchor="middle">逐步去噪 T 步</text> <text x="440" y="250" text-anchor="middle">输出: 去噪后的潜在表示</text> <!-- VAE 解码 --> <rect x="600" y="180" width="140" height="60" fill="#e8f5e1" stroke="#333" rx="6"/> <text x="670" y="205" text-anchor="middle">VAE Decoder</text> <text x="670" y="225" text-anchor="middle">潜在 → 像素</text> <!-- 输出图像 --> <rect x="780" y="180" width="100" height="60" fill="#ffe1e1" stroke="#333" rx="6"/> <text x="830" y="215" text-anchor="middle">生成图像</text> <!-- 箭头 --> <line x1="120" y1="110" x2="155" y2="110" stroke="#333" marker-end="url(#ar6)"/> <line x1="300" y1="110" x2="335" y2="160" stroke="#333" marker-end="url(#ar6)"/> <line x1="120" y1="210" x2="335" y2="210" stroke="#333" marker-end="url(#ar6)"/> <line x1="540" y1="210" x2="595" y2="210" stroke="#333" marker-end="url(#ar6)"/> <line x1="740" y1="210" x2="775" y2="210" stroke="#333" marker-end="url(#ar6)"/> <!-- 三个核心组件标注 --> <text x="100" y="340" text-anchor="middle">① 文本理解</text> <text x="440" y="340" text-anchor="middle">② 迭代去噪</text> <text x="670" y="340" text-anchor="middle">③ 解码到像素</text> <defs> <marker id="ar6" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"> <path d="M0,0 L8,4 L0,8 z" fill="#333"/> </marker> </defs> </svg>

Stable Diffusion 的三个核心组件

组件一:VAE(Variational Autoencoder)

VAE 由两部分组成:

  • Encoder:把 512×512×3 的图像压缩成 64×64×4 的潜在表示(压缩 48 倍)
  • Decoder:把 64×64×4 的潜在表示还原成 512×512×3 的图像

VAE 预训练好后冻结,不在 Diffusion 训练中更新。

组件二:U-Net(去噪网络)

在潜在空间做 Diffusion:

  • 输入:64×64×4 的潜在噪声 + 时间步 + 文本条件
  • 输出:预测的噪声
  • 在 64×64×4 上做 Diffusion,比在 512×512×3 上快约 48 倍

组件三:CLIP 文本编码器

把文本 prompt 编码为向量,作为 U-Net 的条件:

  • 输入:"一只橘色的猫坐在窗台上"
  • 输出:文本 embedding

U-Net 通过 Cross-Attention 接收这个文本条件,引导去噪方向。

Latent Diffusion 的工程价值

  • 训练快:在潜在空间操作,计算量减少 48 倍
  • 显存省:单卡 GPU 就能训练与推理
  • 质量好:VAE 学到的潜在空间保留语义结构
  • 可扩展:换更大的 U-Net 或更好的 VAE 都能提升效果

Latent Diffusion 是 Stable Diffusion 能在消费级 GPU 上运行的关键。

六、Classifier-Free Guidance:让生成更贴文本

Diffusion 模型早期有个问题:生成结果与文本条件关联度不够强。模型可能生成与 prompt 弱相关的图像。

Classifier-Free Guidance(CFG) 是解决方案:

CFG 的核心思想

训练时让 U-Net 同时学习条件去噪无条件去噪

条件去噪: ε_θ(x_t, t, c) ← 给定文本 c 无条件去噪: ε_θ(x_t, t, ∅) ← 不给文本(用空 embedding)

推理时把两者外推:

\hat{\epsilon} = \epsilon_\theta(x_t, t, \emptyset) + w \cdot (\epsilon_\theta(x_t, t, c) - \epsilon_\theta(x_t, t, \emptyset))

其中 w 是引导强度(guidance scale):

  • w = 0:纯无条件,生成随机图像
  • w = 1:标准条件
  • w > 1强化与文本的关联,但可能过曝、失真

典型值 w = 7.5,平衡相关性与质量。

CFG 的效果

CFG 让生成结果显著更贴近 prompt:

prompt: "a cute orange cat sitting on a windowsill" w=1: 生成一只猫,但可能不是橘色、不在窗台 w=7: 生成一只明确的橘色猫,明确在窗台上 w=15: 过度强化,可能画面失真

CFG 已成为文生图的标准配置。

七、文生图模型的演化

Stable Diffusion 系列

  • SD 1.4/1.5:经典版本,CLIP ViT-L 文本编码器 + U-Net
  • SD 2.x:换用 OpenCLIP,更高质量
  • SDXL:1024 分辨率,双文本编码器
  • SD3:用 Diffusion Transformer(DiT),多模态文本编码器
  • Stable Diffusion Turbo / Lightning:蒸馏加速版,少步生成

DALL-E 系列(OpenAI)

  • DALL-E 1:用 VQ-VAE + Transformer
  • DALL-E 2:CLIP + Diffusion
  • DALL-E 3:用 GPT-4 重写 prompt 提升质量(未公开架构)

Midjourney

  • 闭源,注重艺术风格
  • 强调美学质量
  • 用户友好(自然语言 prompt)

FLUX(Black Forest Labs)

  • 2024 年发布,开源
  • 用 Diffusion Transformer
  • 质量接近 SD3,速度更快

Imagen(Google)

  • 闭源
  • 用超大 T5 文本编码器(而非 CLIP)
  • 文本理解能力极强

八、文生图的工程挑战

挑战一:prompt 理解

用户的 prompt 通常简短模糊:

"画一只猫" ← 模糊,无数种可能

解决:

  • 用 GPT-4 等先重写 prompt(DALL-E 3 的做法)
  • 训练更好的文本编码器
  • 用户 prompt 工程教育

挑战二:细节控制

"画一只橘色的猫坐在红色沙发上" ← 颜色、姿态、家具都要准

解决:

  • 更强的 CFG
  • ControlNet 等条件控制(用边缘、姿态等额外条件)
  • T2I-Adapter

挑战三:文字渲染

文生图模型长期不会画文字(招牌、海报上的字):

"画一个写着 HELLO 的红色招牌" ← 早期模型生成乱码

SD3、FLUX 等新一代模型用 Diffusion Transformer 显著改善了文字渲染。

挑战四:速度

Diffusion 需要 T 步去噪(通常 20-50 步),生成慢。加速方法:

  • DDIM:减少步数(20 步即可)
  • DPM-Solver:更高效的 ODE 求解器(10 步)
  • 蒸馏:把多步蒸馏成少步(如 SD Turbo 4 步)
  • Consistency Models:一步生成(实验性)

九、文生图的应用

文生图已经渗透到多个行业:

应用一:创意设计

广告、海报、插画、概念设计

应用二:电商

商品图生成、虚拟模特、场景合成

应用三:游戏

游戏素材、概念图、纹理

应用四:教育

教学插图、可视化

应用五:个人娱乐

头像、表情包、艺术创作

十、文生图的伦理与版权

文生图也带来伦理挑战:

  • 训练数据版权:是否经过艺术家同意?
  • 生成内容归属:AI 生成的图版权归谁?
  • Deepfake:生成虚假名人图像
  • 偏见:模型可能强化社会偏见(性别、种族)

这些问题正在被社会与法律逐步规范。

小结

文生图的核心是 Diffusion 模型——通过前向加噪、反向去噪学习生成。Latent Diffusion(Stable Diffusion)通过 VAE 压缩到潜在空间,大幅降低计算成本。CLIP 文本编码器 + U-Net + VAE 是经典三件套。CFG 让生成更贴近 prompt。SD3、FLUX 等新一代模型用 DiT 提升质量。文生图已广泛应用于创意、电商、游戏等行业,但也带来版权与伦理挑战。

下一节(8.3)我们看更挑战的文生视频——特别是 Sora 的 DiT 架构如何生成高质量长视频。


发布者: 作者: 渗透测试失败者的小龙虾 转发
评论区 (0)
U