CLIP 详解:Stable Diffusion 文本理解的核心机制
什么是 CLIP?
在 Stable Diffusion 的整体体系中,图像的生成由 U-Net 完成,图像的潜空间映射与还原交由 VAE 负责。然而,这一流程能否按照用户的提示词准确执行,取决于另一个关键组件——CLIP(Contrastive Language-Image Pre-training,对比语言-图像预训练)。如果说 VAE 是负责把“数据”变成“图片”的图像翻译官,那么 CLIP 就是负责听懂你说话的语言翻译官,它的职能是理解文本输入,并将语言转化为模型能够处理的语义向量,使得绘图引擎能执行与文本一致的视觉生成。
CLIP 在 Stable Diffusion 中的角色
Stable Diffusion 的生成过程本质上依赖条件扩散,而条件信号便由 CLIP 提供。文本提示词经过 CLIP 的处理后,被映射为固定维度的特征向量,并在 U-Net 的交叉注意力模块中作为控制条件。因此,CLIP 的语言理解能力直接影响生成图像的语义精确性、细节表现与风格倾向。
CLIP 的任务可以概括为两点:
- 将自然语言转化为语义向量
- 向 U-Net 提供语义引导,使图像朝指定方向生成
可以将其视作整个系统的“语言翻译器”,负责把用户的文本提示词转化为可操作的视觉语义信号,告诉 AI "你想要什么样的图片"。
graph LR
%% 定义样式类
classDef input fill:#ff9f43,stroke:#333,stroke-width:2px,color:#fff,rx:5,ry:5;
classDef process fill:#54a0ff,stroke:#333,stroke-width:2px,color:#fff,rx:5,ry:5;
classDef data fill:#5f27cd,stroke:#333,stroke-width:2px,color:#fff,stroke-dasharray: 5 5;
classDef output fill:#1dd1a1,stroke:#333,stroke-width:2px,color:#fff,rx:5,ry:5;
%% 节点定义与连接
A([文本提示词<br/>'a beautiful cat']):::input
--> B[CLIP Text Encoder<br/>文本编码器]:::process
--> C[文本特征向量<br/>77, 768/]:::data
--> D[UNet<br/>噪声预测]:::process
--> E([引导图像生成]):::output
%% 可以在这里添加额外的关联,例如噪声输入
%% Noise[(随机噪声)]:::data -.-> D
CLIP 的工作原理
CLIP 的双塔架构
CLIP 通过对比学习训练而成,由文本编码器与图像编码器组成。训练阶段,模型接收大规模图文对,并学习让匹配样本的特征向量接近,不匹配样本的特征向量远离。 由此,CLIP 建立了稳定的跨模态语义空间。
在 Stable Diffusion 中,实际使用的是 CLIP 的文本编码器部分(图像编码器的核心价值在于预训练阶段 —— 通过 4 亿图文对的对比学习,为文本编码器提供 “语义锚点”,即文本向量的空间分布需与图像向量对齐,这是 CLIP 实现跨模态理解的基础。此外,图像编码器在图像检索、零样本分类等场景中也有重要应用,例如提取图像特征后与文本特征比对,可实现 “按文本搜图”)。
graph TB
A[训练数据:<br/>4亿图文对] --> B[Text Encoder<br/>文本编码器]
A --> C[Image Encoder<br/>图像编码器]
B --> D[文本特征空间]
C --> E[图像特征空间]
D --> F[对齐学习<br/>Contrastive Learning]
E --> F
F --> G[理解文本和图像的关系]
style A fill:#e1f5ff
style D fill:#ff6b6b
style E fill:#4ecdc4
style G fill:#f7b731
训练时,设置一个任务:给定一张图片和一段文字,判断它们是否匹配
正样本中给出匹配的图文对:一只橙色的猫(图片),"an orange cat"(文字),给出结论:特征向量接近
负样本给出不匹配的图文对:一只橙色的猫(图片),"a blue car"(文字),给出结论:特征向量远离
通过大量的训练,CLIP 能够理解文字含义、理解图像内容,并关联文字和图像,通过语义相似性来判断它们是否匹配。
文本编码过程
文本编码过程是 CLIP 模型将输入的文本转换为语义向量的过程。它包括以下几个步骤:
- 分词 (Tokenization)
- 词嵌入 (Token Embedding)
- 位置编码 (Positional Embedding)
- Transformer 编码
graph LR
%% 样式
classDef orange fill:#f0932b,stroke:#333,color:#fff,rx:5;
classDef blue fill:#22a6b3,stroke:#333,color:#fff,rx:5;
classDef purple fill:#be2edd,stroke:#333,color:#fff,rx:5;
classDef dark fill:#130f40,stroke:#fff,color:#fff,rx:5;
%% 流程
In(Input</br>'a beautiful sunset'):::orange --> P1
subgraph Preprocess [预处理阶段]
direction TB
P1[分词</br>Tokenize]:::blue --> P2[IDs: 49406, 320, ...]:::blue
end
Preprocess --> Emb
subgraph Emb [向量化阶段]
direction TB
E1[词嵌入</br>Token Embedding]:::purple
E2[位置编码</br>Positional Embedding]:::purple
E1 & E2 -.-> Sum((+))
end
Sum --> T[Transformer<br/>Encoder]:::dark
T --> Out(Feature Vector<br/>77x768):::dark
%% 连接线
linkStyle default stroke:#333,stroke-width:2px,curvetype:basis;
分词 (Tokenization)
用户输入的文本会被拆解成最多 77 个 token,长度超限将被截断,不足部分以占位符填充(<pad>),首尾添加特殊token。由于 CLIP 按 token 而非单词处理,所以长词可能被拆分。
一个 Token 通常是一个完整的短单词: "cat", "dog", "red",也可能是一个长单词的一部分: "beautiful" 可能是 2个token,也有可能是一个标点符号: ",", "."。
提示词: "a beautiful girl with long hair, wearing white dress, in garden, natural lighting, masterpiece, best quality, highly detailed" 约 25-30 个token,若超过 77 token,末尾的 “best quality, highly detailed” 可能被截断,导致生成图像细节不足。建议优先保留核心描述(主体、场景、风格),次要修饰词用逗号分隔,避免长句拆分关键 token,减少 AI 理解偏差。
graph TB
%% --- 样式 ---
classDef raw fill:#fab1a0,stroke:#e17055,color:#2d3436,stroke-width:2px;
classDef engine fill:#74b9ff,stroke:#0984e3,color:#fff,rx:10;
classDef array fill:#dfe6e9,stroke:#636e72,color:#2d3436,rx:5;
%% --- 流程 ---
Input[fa:fa-keyboard 输入文本<br/>'a beautiful sunset over the ocean']:::raw
Input ==> Process{CLIP<br/>Tokenizer}:::engine
Process ==> Output
subgraph Output [Token Sequence Output]
direction TB
L1["[0] < start >"]:::array
L2["[1] a"]:::array
L3["[2] beautiful"]:::array
L4["[3] sunset ... ocean"]:::array
L5["[7] < end >"]:::array
L6["[8-76] < pad > ..."]:::array
style Output fill:#fff,stroke:#333,stroke-dasharray: 5 5
end
所以在 Stable Diffusion 中文本提示词的长度通常要限制在 77 个 token 以内,越精简越好,因为超出的部分会被截断,导致一些想要的图片效果无法实现。
词嵌入 (Token Embedding)
每个 token 会映射为一个固定维度的向量(例如 768 维),语义相近的词向量在空间中距离较近,如'beautiful' 和 'pretty' 距离近,'ugly' 和 'pretty' 距离远。
graph LR
%% --- 样式定义 ---
classDef token fill:#ff9f43,stroke:#333,stroke-width:2px,color:#fff,rx:5;
classDef vector fill:#5f27cd,stroke:#333,stroke-width:2px,color:#fff,rx:0,font-family:'Courier New';
classDef arrow stroke:#b2bec3,stroke-width:2px;
%% --- 映射关系 ---
T1(Token: 'a'):::token --> V1["[ 0.23, -0.45, 0.67, ... , 0.12 ]<br/><i style='font-size:12px'>Shape: (1, 768)</i>"]:::vector
T2(Token: 'beautiful'):::token --> V2["[ 0.56, 0.34, -0.23, ... , 0.89 ]<br/><i style='font-size:12px'>Shape: (1, 768)</i>"]:::vector
T3(Token: 'sunset'):::token --> V3["[ -0.12, 0.78, 0.45, ... , -0.34 ]<br/><i style='font-size:12px'>Shape: (1, 768)</i>"]:::vector
%% --- 布局调整 ---
linkStyle default stroke:#a29bfe,stroke-width:2px;
位置编码 (Position Embedding)
Transformer 虽然能处理 token 序列,但结构本身对“顺序”毫无概念,位置编码的作用是保留语序,将顺序信息显式注入模型,使模型能够理解句法结构。
为什么需要位置编码? 因为相同的 token 在不同位置的含义不同,如'cat' 在 'cat chasing mouse' 中是主体, 'mouse chasing cat' 中的主体却是 mouse。
在实际模型中,位置编码主要有两类:绝对位置编码(Absolute Position Embedding)和 相对位置编码(Relative Position Embedding)。
绝对位置编码是 CLIP、BERT、ViT 等模型普遍采用的方式,也是 Stable Diffusion 文本编码器使用的方式。其原理非常直接,就是为每个 token 分配一个固定的位置索引,然后将位置索引映射为一个向量,与 token embedding相加,得到最终的位置编码向量。
形式如下:
Embedding(token_i) + Position(i)
其中 Position(i) 与 token 本身无关,只与位置编号相关。
绝对位置编码的特点是简单易实现,模型训练时学习一个固定位置表,例如长度 77,每个位置对应一个固定的向量。绝对位置编码适合固定序列长度的任务,但是不能自然推广到比训练更长的序列,如 CLIP 的 77 token 限制,输入固定为 77 个 token,对应 77 个位置向量,如果超过 77 token 会被截断,因为模型没有更多的位置编码。
相对位置编码主要用于最新模型,如 Transformer-XL、T5、DeBERTa、部分扩散模型的 cross-attention等,这些模型不关心“绝对位置”,而关心“当前位置与另一个位置之间的相对关系”。例如,在一个句子中,“beautiful” 与 “girl” 的距离比与 “sky” 的距离更重要。
相对位置编码提供了相邻性、依赖距离和方向性(前后),可以让模型更自然。
相比绝对位置编码,相对位置编码的优势在于:
- 模型可以自然推广到更长的序列,而不需要额外的位置编码。
- 模型可以更有效地捕捉长距离依赖,因为它考虑了当前 token 与其他 token 之间的相对位置。
- 模型可以更好地处理变长序列,因为它不依赖于固定的位置编码长度。
但 CLIP 并未使用这一机制,因为其设计目标是稳定文本编码,而非长序列理解。
Transformer Encoder(编码器)
在 Stable Diffusion 中,CLIP 文本编码器正是由多层 Transformer Encoder 堆叠而成。
对于 CLIP 而言,Transformer Encoder 的任务可以概括为理解 token 之间的上下文关系、建模长距离依赖(long-range dependency)、从词级、短语级逐步提取语义特征和为每个 token 输出更高层的语义表示。简言之,Transformer 让 CLIP 不仅”识字”,还能“读懂语义”。比如,"apple" 在 "eat an apple" 中是水果,而在 "Apple Inc" 中是公司;"the girl who wore red dress"中"girl" 与 "wore" 之间的关系是“主体-动作”,而 "wore" 与 "red dress" 之间的关系是“动作-对象”。
Transformer Encoder 由多个重复的结构块(Block)组成,每个 Block 包含两大模块:
- 多头自注意力机制(Multi-Head Self-Attention)
- 前馈神经网络(Feed-Forward Network, FFN)
每个模块都带有:
- 残差连接(Residual Connection)
- LayerNorm(层归一化)
整体结构如下:
Input Layer (Token + Position Embedding)
↓
12 × Transformer Block
• Multi-Head Self-Attention (12 heads)
• Feed-Forward Network
• Layer Normalization
• Residual Connections
↓
Output Layer
但是 Transformer 并不是一层就读懂所有语义,而是逐层抽象。CLIP 文本编码器通常为 12 层 Transformer Block。
1–3 层是词汇层:解析词义,建立基本依赖关系,识别简单修饰结构
4–6 层是短语层:形成更复杂的短语结构,识别语法关系(主谓宾、定状补等)
7–9 层是句法层:建立长距离依赖,理解句子整体语义结构
10–12层是语义层:概念抽象,风格理解,表达高级语义(例如“忧郁的氛围”、“未来主义风格”)
在 Stable Diffusion 的 Web UI 中有个参数 CLIP Skip,参数值是 1 ~ 12,对应的就是 12 层 Transformer Block。它的作用是改变Transformer 的“语义抽象程度”,越靠后的层,语义越抽象。
Skip 1 (默认): 最精确的语义理解,可精准捕捉 “photorealistic, skin texture, 8k” 等细节描述,还原真实质感,适合写实风格
Skip 2: 宽松的语义约束,允许更夸张的发型、五官比例,符合动漫风格特性,常用于动漫模型
Skip 3+: 可能导致核心语义偏差,例如 “girl” 被误生成为 “boy”,或 “garden” 变成 “forest”,需避免使用
多层 Transformer 综合上下文与语义关联,最终生成形状为 [77, 768] 的语义向量矩阵。该矩阵将作为 U-Net 的生成条件,直接影响图像结构与内容。
多头注意力机制(Multi-Head Self-Attention)
在 Transformer 中有个很重要的概念,就是多头注意力机制,体现在每个 Transformer Block 中。
每个 Transformer Block 都包含多个头(head)的自注意力机制,每个头都独立计算注意力权重,然后将结果拼接起来。
这样做的好处是,每个头可以关注不同的位置和不同的特征,从而更好地捕捉到序列中的长距离依赖关系。
例如,在 CLIP 中,每个头都关注不同的位置,从而更好地理解句子中的语法关系。
%%{init: {'theme': 'base', 'themeVariables': {'fontSize': '12px'}}}%%
graph TB
%% --- 节点定义 ---
Input([输入: Token 序列<br/>Input Sequence])
%% 定义子图:多头注意力层
subgraph MultiHead [多头注意力层 / Multi-Head Attention Layer]
direction LR
H1[Head 1<br/>关注主语]
H2[Head 2<br/>关注动词]
H3[Head 3<br/>关注宾语]
Hm[...]
H12[Head 12<br/>关注修饰词]
end
Concat[拼接 & 线性变换<br/>Concat & Linear]
Output([综合理解<br/>Contextual Representation])
%% --- 连接关系 ---
Input ==> H1 & H2 & H3 & Hm & H12
H1 & H2 & H3 & Hm & H12 -.-> Concat
Concat ==> Output
%% --- 样式定义 ---
classDef io fill:#37474f,stroke:#263238,stroke-width:2px,color:#fff,font-size:12px
classDef head fill:#e1f5fe,stroke:#039be5,stroke-width:2px,color:#01579b,font-size:12px
classDef process fill:#fff3e0,stroke:#ff9800,stroke-width:2px,color:#e65100,font-size:12px
classDef cluster fill:#f5f5f5,stroke:#bdbdbd,stroke-width:1px,color:#616161,font-size:12px
%% 应用样式
class Input,Output io
class H1,H2,H3,Hm,H12 head
class Concat process
class MultiHead cluster
在处理 "The girl wearing red dress is smiling" 语句时,
Head 1 关注: "girl" ← → "wearing" 理解主语和动作的关系
Head 2 关注: "wearing" ← → "dress" 理解动作和对象
Head 3 关注: "red" ← → "dress" 理解修饰关系
Head 4 关注: "girl" ← → "smiling" 理解主语和状态
综合结果: 完整理解句子的语义结构,生成准确的特征表示
第 2 篇,共 6 篇
相关推荐
Stable Diffusion 的版本演进
深入解析 Stable Diffusion 的版本演进,了解各个版本的特性和差异。
Stable Diffusion 采样器
深入解析 Stable Diffusion 中各类采样器的工作原理、特点和适用场景,帮助你选择最合适的采样器
Stable Diffusion 模型下载指南
详细介绍 Stable Diffusion 模型的下载渠道、文件格式说明以及安装方法