文章目录

本文通过直观的比喻和极简的 PyTorch 代码,彻底拆解文生图模型里的一个关键魔法:Cross-Attention(交叉注意力)。它到底是怎么做到“文本控制图像局部”的?为什么一句提示词里的“红色”“猫”“戴帽子”会分别跑到不同区域生效?


一、先问一个最关键的问题:文本为什么能控制图像局部?

很多人第一次接触文生图时,脑子里都会有个强烈疑问:

一句话明明只是一些词,为什么模型最后能把“红色帽子”放到头上,而不是乱涂在背景上?

这背后最核心的机制之一,就是 Cross-Attention

如果粗暴地用一句话概括它:

Cross-Attention 就是让图像里的每个位置,主动去文本里“查词典、找说明书、问老师”。

也就是说,不是文本自己跑去涂图,而是:

图像特征图里的每个局部位置,在生成过程中都会不断问:“我这里应该参考提示词里的哪几个词?”

一旦你把这句话吃透,cross-attention 的本质就通了。


二、先回忆 Self-Attention:自己人开会

在普通 Self-Attention 里:

  • Q 来自输入本身
  • K 来自输入本身
  • V 来自输入本身

如果输入是一串文本 token,那就是:

词和词之间自己开会。

如果输入是一组图像 patch / latent token,那就是:

图像位置和图像位置之间自己开会。

所以 Self-Attention 解决的是:

同一模态内部,大家怎么互相交流。


三、Cross-Attention:不是自己人开会,而是“图像去问文本”

Cross-Attention 和 Self-Attention 的最大差别在于:

  • Q 来自图像
  • K、V 来自文本

这三个角色一换,意义就完全变了。

1. 核心比喻:画图工人拿着问题,去问文字说明书

想象你在搭一幅大型广告牌。

图像里的每个位置,都是一个现场工人。

比如:

  • 左上角区域的工人
  • 中间主体区域的工人
  • 右下角背景区域的工人

而提示词则像一份文字说明书:

  • “a girl”
  • “red hat”
  • “blue sky”
  • “standing in a field”

现在每个图像位置的工人,都拿着自己的问题去读说明书:

  • “我这个位置更该参考哪个词?”
  • “我是背景,还是人物身体,还是帽子?”
  • “我和哪个词关系最大?”

这就是 Cross-Attention。

它的本质不是“文本直接画图”,而是:

图像位置主动检索文本信息。


四、Q、K、V 在 Cross-Attention 里到底分别代表什么?

这一段你一定要建立直觉。

1. Q:来自图像位置,表示“我现在需要什么”

图像 latent 里的某个位置,比如脸部附近一个 token,它的 Query 可能在“想”:

  • “我这里像人物主体的一部分,那我应该查哪些词?”
  • “我需要确认自己是不是眼睛、脸、头发,还是帽子边缘?”

所以 Q 代表的是:

当前图像位置的需求。

2. K:来自文本 token,表示“我是哪个词、我能提供什么线索”

提示词经过文本编码器后,每个词都会变成一个向量 token。

比如:

  • girl
  • red
  • hat
  • field

这些 token 会各自产生自己的 Key。

Key 就像每个词的“标签牌”:

  • “我是人物相关词”
  • “我是颜色词”
  • “我是帽子词”
  • “我是背景场景词”

3. V:来自文本 token,表示“如果你关注我,我真正能给你的内容”

如果某个图像位置和某个词匹配度高,那么它最终吸收的就是这个词的 Value。

所以 V 代表的是:

这个词真正携带的语义信息。


五、最关键的一句话:谁在“查词”?

很多初学者会下意识想成:

  • 文本 token 在决定图像每个位置该长什么样

这话不能算错,但不够准确。

更准确的说法是:

图像每个位置自己在查文本。

也就是:

  • 每个图像 token 产生自己的 Q
  • 用这个 Q 去和所有文本 token 的 K 算相似度
  • 然后根据相似度,加权吸收文本 token 的 V

这就意味着:

同一句提示词,对不同图像位置的影响完全可以不同。

比如同样是词 red

  • 帽子区域可能高度关注它
  • 草地区域可能几乎不关注它

这就是“文本控制图像局部”的根本原因。


六、把过程想象成一张“词语热力图”

Cross-Attention 非常适合用热力图来想。

假设提示词是:

  • a girl wearing a red hat in a green field

那么对图像里的不同位置来说,它们对各个词的注意力权重会不同。

1. 头顶区域的热力图可能是这样

  • hat:权重很高
  • red:权重很高
  • girl:中等
  • field:很低

2. 脸部区域的热力图可能是这样

  • girl:很高
  • hat:中等
  • red:较低
  • field:很低

3. 背景草地区域的热力图可能是这样

  • field:很高
  • green:很高
  • girl:较低
  • hat:几乎没有

所以 Cross-Attention 并不是一个“全图统一施法”的全局广播。

它更像是:

每个空间位置都有自己的一张“该关注哪些词”的热力图。


七、数学上它到底怎么发生?

如果图像 token 记作 X X X,文本 token 记作 T T T,那么在 Cross-Attention 中:

Q = X W Q , K = T W K , V = T W V Q = XW_Q,\quad K = TW_K,\quad V = TW_V Q=XWQ,K=TWK,V=TWV

注意这里:

  • Q 来自图像
  • K、V 来自文本

然后计算注意力:

Attn ( X , T ) = softmax ( Q K T d k ) V \text{Attn}(X, T) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attn(X,T)=softmax(dk QKT)V

1. 为什么这能实现“局部控制”?

因为 softmax 的输入矩阵形状大致是:

( 图像位置数 ) × ( 文本 token 数 ) (\text{图像位置数}) \times (\text{文本 token 数}) (图像位置数)×(文本 token )

也就是说:

  • 每一行对应一个图像位置
  • 每一列对应一个文本词

于是矩阵里的每个元素,表示的就是:

“图像位置 i 对文本词 j 的注意力有多高。”

这已经天然是一张“局部位置 vs 词语”的对应表了。


八、为什么一个词能影响一片区域,而不是单个像素?

这也是一个很重要的直觉点。

Cross-Attention 通常并不是在像素级别直接操作,而是在:

  • latent 空间
  • feature map 空间
  • patch/token 空间

也就是说,一个“图像 token”往往代表的是一小块区域,而不是单个像素。

于是一个词的影响天然就会扩散到一片局部区域。

比如 hat 这个词,可能会主要影响:

  • 头顶附近的一片 latent 区域
  • 而不是严格到某一个像素点

这也是为什么 cross-attention 控制通常是:

区域级、语义级的精确控制,而不是 CAD 软件式的像素级硬控制。


九、为什么一个词的影响能越来越清晰?因为它不只作用一次

这点非常重要。

很多人以为文本只在某一层“注入”一次,后面就没了。

实际上在很多文生图架构里,cross-attention 会在多个层、多个分辨率、多个时间步反复出现。

这意味着什么?

1. 不是“一次决定”,而是“反复校正”

采样不是一步成图,而是几十步甚至上百步逐渐去噪。

在这个过程中,模型会反复做这样的事:

  • 当前图像局部看起来像什么?
  • 它应该参考哪些词?
  • 这一轮应该往哪个方向修正?

于是词语影响不是一次打进去就结束,而是:

一轮轮采样里持续施加。

2. 前期更像“定大轮廓”,后期更像“修细节”

在早期噪声还很重时,cross-attention 更多是在帮模型决定:

  • 这里应该是人还是背景?
  • 这里有没有帽子?
  • 整体颜色基调是什么?

在后期图已经比较清晰时,cross-attention 更像是在帮模型修:

  • 帽子该更红一点
  • 草地该更绿一点
  • 人脸不要跑偏到背景语义去

所以它对“局部控制”的实现,不是一次暴力指定,而是:

逐步塑形,反复校正。


十、为什么 Multi-Head Cross-Attention 更强?

单头注意力只能用一种标准去看文本和图像的关系。

但实际文生图里,不同词和图像区域之间的关系是很多维的:

  • 有的头更关注主体类别
  • 有的头更关注颜色词
  • 有的头更关注空间关系
  • 有的头更关注风格词

于是多头机制就很自然了。

1. 直观比喻:多个不同专长的审核员

同一个图像位置在问文本时,不是只有一个专家在判断,而是有多个专家同时看:

  • 一个专家看“这是不是人物词”
  • 一个专家看“这是不是颜色词”
  • 一个专家看“这是不是背景词”
  • 一个专家看“这是不是风格词”

最后多个头的信息再融合。

这就使得 Cross-Attention 不只是“找到相关词”,而是:

能从多个语义维度把词义灌进图像局部。


十一、为什么说 Cross-Attention 不是“绝对定位器”?

这里必须防止一个误解。

Cross-Attention 很强,但它不是说:

  • 文本词 hat 一定精确对应到某个固定矩形框
  • 文本词 red 一定只染一个严格边界区域

现实里它更像是一种:

软对齐(soft alignment)机制。

1. 它给的是概率式关注,不是刚性坐标

注意力权重不是“0 或 1”的硬分配,而是连续概率。

这意味着:

  • 一个图像位置可以同时参考多个词
  • 一个词也可以同时影响多个位置

所以它天然是柔性的。

2. 局部精确控制来自“多层 + 多步 + 网络先验”的共同作用

真正让“帽子出现在头上”的,不只是 cross-attention 单独一个模块,还包括:

  • U-Net / DiT 本身的图像结构建模能力
  • 卷积或图像 token 的空间先验
  • 多层 cross-attention 反复施加
  • 整个采样过程逐步收敛

所以更准确地说:

Cross-Attention 提供词语到空间区域的软对齐桥梁,而不是单独负责几何摆放的一切。


十二、那它和 CFG 是什么关系?

如果你已经学过 CFG,这里正好可以连起来。

1. Cross-Attention 负责“文本信息怎么进网络”

它回答的是:

  • 文本 token 怎样影响图像 token
  • 哪些词被哪些区域重点参考

2. CFG 负责“条件影响要不要再放大”

它回答的是:

  • 文本条件已经进网络了
  • 现在要不要把“有条件”和“无条件”的差值再放大

所以你可以把它们理解成:

  • Cross-Attention:文本进入图像局部的通道
  • CFG:把这条通道带来的条件影响再放大

两者不是替代关系,而是上下游关系。


十三、极简 PyTorch:Cross-Attention 骨架长什么样?

下面这段代码是最小化理解版,不是工业实现,但足够你把结构串起来。

import torch
import torch.nn as nn
import torch.nn.functional as F
import math


class CrossAttention(nn.Module):
    def __init__(self, dim, context_dim):
        super().__init__()
        self.to_q = nn.Linear(dim, dim, bias=False)
        self.to_k = nn.Linear(context_dim, dim, bias=False)
        self.to_v = nn.Linear(context_dim, dim, bias=False)
        self.to_out = nn.Linear(dim, dim, bias=False)

    def forward(self, x, context):
        """
        x: 图像 token, shape = (B, N_img, D)
        context: 文本 token, shape = (B, N_txt, D_ctx)
        """
        Q = self.to_q(x)         # 来自图像
        K = self.to_k(context)   # 来自文本
        V = self.to_v(context)   # 来自文本

        attn_scores = Q @ K.transpose(-2, -1) / math.sqrt(Q.shape[-1])
        attn_weights = F.softmax(attn_scores, dim=-1)

        out = attn_weights @ V
        out = self.to_out(out)
        return out

这段代码最值得你盯住的一点是:

  • Q = self.to_q(x) 来自图像
  • K = self.to_k(context)V = self.to_v(context) 来自文本

这就已经把“图像去问文本”这个本质写出来了。


十四、如果把 attention map 可视化,你会看到什么?

在很多研究和可视化工作里,人们会把 cross-attention map 画出来。

你通常会看到类似现象:

  • cat 对应主体猫的区域最亮
  • red 对应红色物体区域更亮
  • sky 对应上半部分背景区域更亮

这说明:

模型真的在学“哪个区域该重点看哪个词”。

这也是为什么 cross-attention map 经常被拿来做:

  • prompt-to-prompt 编辑
  • 局部替换
  • 文本引导的区域控制

因为这张图本身就隐含了“词和区域的对应关系”。


十五、为什么 prompt 改一个词,局部往往会跟着变?

比如你把:

  • a red hat

改成:

  • a blue hat

为什么通常主要变的是帽子颜色,而不是整张图全部乱掉?

因为 cross-attention 里:

  • hat 主要影响帽子区域
  • red/blue 主要影响和帽子属性相关的区域

所以当你只替换颜色词时,模型的注意力对齐关系大体还在,只是那部分局部语义被换了。

这也是很多 prompt 编辑方法能成立的基础。


十六、但为什么它有时也会失控?

你可能也遇到过这种情况:

  • 改一个词,整张图都跟着乱了
  • 多个物体关系混乱
  • 属性绑定错误,比如“红色的狗”和“蓝色的帽子”串了

这是因为 Cross-Attention 虽然强,但不是完美的符号推理器。

1. 多对象、多属性绑定本来就难

比如:

  • a red cube and a blue sphere

模型需要同时解决:

  • 谁是 cube
  • 谁是 sphere
  • 红色该绑给谁
  • 蓝色该绑给谁

这对注意力来说并不是一个简单任务。

2. 注意力只是软分配,不是逻辑引擎

它擅长学习统计对应关系,但不保证严格一一绑定。

所以在复杂 prompt 下,常出现:

  • 属性串位
  • 实体混淆
  • 局部污染

这也是为什么文生图控制一直是活跃研究方向。


十七、你必须真正记住的 6 句话

如果这篇很长,你至少要把下面 6 句话记住:

  1. Cross-Attention 不是文本直接去画图,而是图像位置主动去查文本。

  2. 在文生图里,通常是:Q 来自图像,K/V 来自文本。

  3. 每个图像位置都可以对不同词有不同注意力,所以同一句话能控制不同局部区域。

  4. 它实现的是词语和空间区域之间的软对齐,不是刚性的几何定位。

  5. 多层、多头、多时间步反复施加,使词语影响逐渐从粗轮廓落实到细节。

  6. CFG 和 Cross-Attention 不是一个东西:前者放大条件影响,后者提供文本进入图像局部的通道。


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐