副标题 / 摘要
Self-attention 在同一序列内建模元素关系,Cross-attention 在两个序列之间做对齐。本文用公式、示例与最小可运行代码解释两者差异,并给出工程场景建议。

  • 预计阅读时长:14~18 分钟
  • 标签attentionself-attentioncross-attention
  • SEO 关键词:Self-Attention, Cross-Attention, 注意力机制, Transformer
  • 元描述:系统对比 self-attention 与 cross-attention 的机制差异与应用场景。

目标读者

  • 想理解 Transformer 关键机制的入门读者
  • 需要区分编码器/解码器注意力的工程实践者
  • 从事多模态应用、关注对齐策略的开发者

背景 / 动机

注意力机制是 Transformer 的核心。
但很多工程误用来自于“分不清 self 和 cross”。
理解两者的计算图和适用场景,能直接减少模型设计与性能调优的试错成本。

核心概念

  • Query / Key / Value(Q/K/V):注意力的三元组。
  • Self-attention:Q、K、V 来自同一序列。
  • Cross-attention:Q 来自目标序列,K、V 来自源序列。
  • 对齐(Alignment):跨序列的语义匹配。

A — Algorithm(题目与算法)

用通俗语言说明主题内容

  • Self-attention:自己“看自己”,适合建模序列内部依赖。
  • Cross-attention:一个序列“看另一个序列”,适合对齐或条件生成。

基础示例(1)

  • 机器翻译的解码器在生成当前词时,需要关注源语言句子 → cross-attention。

基础示例(2)

  • 语言模型内部每个 token 关注上下文 → self-attention。

实践指南 / 步骤

  1. 明确是否需要跨序列对齐:是 → cross-attention。
  2. 仅建模单序列依赖:用 self-attention。
  3. 组合使用:编码器 self-attn + 解码器 self-attn + 交叉注意力。

可运行示例(最小注意力计算)

import torch
import torch.nn.functional as F


def attention(q, k, v):
    scores = q @ k.transpose(-2, -1) / (q.size(-1) ** 0.5)
    weights = F.softmax(scores, dim=-1)
    return weights @ v

# Self-attention: Q/K/V 同源
x = torch.randn(2, 4, 8)  # batch, seq, dim
self_out = attention(x, x, x)
print(self_out.shape)

# Cross-attention: Q 来自目标序列, K/V 来自源序列
q = torch.randn(2, 3, 8)
kv = torch.randn(2, 5, 8)
cross_out = attention(q, kv, kv)
print(cross_out.shape)

解释与原理

  • Self-attention 输出与输入序列长度一致。
  • Cross-attention 输出长度与 Query 序列一致。
  • 在编码器-解码器结构中,cross-attn 是桥梁。

C — Concepts(核心思想)

方法类型

Self-attention 属于序列内部建模,cross-attention 属于跨序列对齐

关键公式

给定 Q/K/V:

$ \text{Attention}(Q, K, V) = \text{softmax}(\frac{QK^\top}{\sqrt{d}})V $

区别在于 Q/K/V 的来源:

  • Self-attention:Q=K=V=X
  • Cross-attention:Q=Y, K=V=X

解释与原理

  • Self-attn 学习序列内部结构(语法、长依赖)。
  • Cross-attn 学习序列之间对齐(翻译、图文匹配)。

E — Engineering(工程应用)

场景 1:机器翻译(编码器-解码器)

  • 背景:解码器生成词时需要对齐源语言。
  • 为什么适用:cross-attn 把源序列信息注入目标序列。
  • 代码示例(Python):
import torch

q = torch.randn(1, 4, 16)   # decoder states
kv = torch.randn(1, 6, 16)  # encoder states
scores = q @ kv.transpose(-2, -1)
print(scores.shape)

场景 2:多模态图文对齐

  • 背景:文本需要关注图像区域。
  • 为什么适用:文本 token 作为 Query,视觉特征作为 Key/Value。
  • 代码示例(Python):
import torch

text = torch.randn(2, 10, 32)
image = torch.randn(2, 49, 32)
attn = text @ image.transpose(-2, -1)
print(attn.shape)

场景 3:检索增强生成(RAG)

  • 背景:模型需要对齐外部文档。
  • 为什么适用:query 序列对检索文档做 cross-attn。
  • 代码示例(Python):
import torch

query = torch.randn(1, 8, 64)
doc = torch.randn(1, 50, 64)
scores = query @ doc.transpose(-2, -1)
print(scores.shape)

R — Reflection(反思与深入)

  • 时间复杂度
    • Self-attn:O(n^2)(序列长度 n)。
    • Cross-attn:O(n*m)(目标长度 n,源长度 m)。
  • 空间复杂度:注意力矩阵同样为 O(n^2)O(n*m)
  • 替代方案
    • 局部注意力或稀疏注意力降低成本。
    • 用检索或缓存缩短源序列。
  • 工程可行性:跨序列对齐是必须成本,优化重点是序列长度。

常见问题与注意事项

  • 误用 cross-attn 会导致模型“看错对象”。
  • 不同序列的维度必须对齐(或通过线性投影对齐)。
  • 长序列 cross-attn 容易成为瓶颈。

最佳实践与建议

  • 先明确 Q/K/V 的来源,再写结构。
  • 用可视化检查注意力矩阵是否合理。
  • 长序列任务优先考虑稀疏或分块注意力。

S — Summary(总结)

核心收获

  • Self-attention 解决单序列依赖建模问题。
  • Cross-attention 解决跨序列对齐问题。
  • 两者差异来自 Q/K/V 的来源与注意力矩阵维度。
  • 工程落地时优先关注序列长度带来的成本。

推荐延伸阅读

  • Attention Is All You Need
  • The Annotated Transformer
  • 多模态 Transformer 相关综述

参考与延伸阅读

小结 / 结论

理解 self-attention 与 cross-attention 的差异,就是理解 Transformer 的核心计算图。
这也是多模态与生成系统设计的第一原则。

行动号召(CTA)

把你的任务写成 Q/K/V 关系图,再决定用哪类注意力结构。