5D Library › 算法之镜 · English

第二章 自注意力的几何

查询、键与值

瓦斯瓦尼(Vaswani)等人 2017 年提出的 Transformer 架构,以注意力为核心:它让序列中的每个位置都能从所有其他位置收集信息 (Vaswani et al. 2017)。每个词元的内部向量被投影成三种向量:查询(query)、键(key)和值(value)。查询发问,键标明自己是什么,两者的匹配程度决定从每个值中收集多少:

Attention(Q,K,V)=softmax(QK𝖳dk)V.\text{Attention}(Q,K,V) = \text{softmax}\!\left(\frac{QK^{\mathsf T}}{\sqrt{d_k}}\right)V.

QK𝖳QK^{\mathsf T} 的每一行是一个查询与所有键的点积;softmax 把它们变成和为一的权重;结果是各个值的加权平均。多头注意力并行运行多个这样的运算,各有自己的投影,使不同的头能关注不同类型的关系;这样的层再层层堆叠 (Vaswani et al. 2017)。

为什么要除以维度的平方根

推导

对随机的查询和键,点积的方差随维度 dkd_k 增大。程序在 16 个键上,比较除以和不除以 dk\sqrt{d_k} 时注意力权重的熵。

import math, random

# Why divide by √d_k: dot products of random d-dimensional vectors have variance d,
# so without scaling the softmax over 16 keys becomes nearly one-hot as d grows.
random.seed(1)
def softmax_entropy(scores):
    m = max(scores)
    w = [math.exp(s - m) for s in scores]
    z = sum(w)
    return -sum((x / z) * math.log2(x / z) for x in w if x > 0)

for d in (16, 64, 256, 1024):
    raw, scaled = [], []
    for _ in range(200):
        q = [random.gauss(0, 1) for _ in range(d)]
        ks = [[random.gauss(0, 1) for _ in range(d)] for _ in range(16)]
        s = [sum(a * b for a, b in zip(q, k)) for k in ks]
        raw.append(softmax_entropy(s))
        scaled.append(softmax_entropy([x / math.sqrt(d) for x in s]))
    print(f"d_k = {d:4d}: attention entropy without scaling {sum(raw) / 200:4.2f} bits, "
          f"with 1/√d_k {sum(scaled) / 200:4.2f} bits (maximum 4.00)")
# d_k =   16: attention entropy without scaling 1.40 bits, with 1/√d_k 3.44 bits (maximum 4.00)
# d_k =   64: attention entropy without scaling 0.63 bits, with 1/√d_k 3.43 bits (maximum 4.00)
# d_k =  256: attention entropy without scaling 0.26 bits, with 1/√d_k 3.40 bits (maximum 4.00)
# d_k = 1024: attention entropy without scaling 0.16 bits, with 1/√d_k 3.41 bits (maximum 4.00)

不做缩放,随着维度增大,权重几乎变成独热:softmax 饱和,几乎全部权重落在一个键上,梯度消失,学习变慢。除以 dk\sqrt{d_k} 使权重的分散程度大致保持不变。这正是原作者给出的缩放理由 (Vaswani et al. 2017)。

一个关于问题「射程」的玩具模型

在训练好的模型中,相关概念的向量往往指向相近的方向。下面的玩具模型有三个「领域」,每个是 12 维空间中的一小簇键;它考察一次注意力运算对三种查询收集到什么:一个指向某一领域内部,一个指向两个领域之间,一个没有特定方向。

推导

从零写出的缩放点积注意力,键分布在三个簇中。

import math, random

random.seed(4)
D = 12                                    # embedding dimension
def unit(v):
    n = math.sqrt(sum(x * x for x in v))
    return [x / n for x in v]

# Three "fields", each a cluster of 4 keys around its own direction in a 12-d space.
fields = {"acoustics": 0, "control theory": 4, "Buddhist texts": 8}
keys, labels = [], []
for name, start in fields.items():
    centre = [1.0 if start <= i < start + 4 else 0.0 for i in range(D)]
    for _ in range(4):
        keys.append(unit([c + random.gauss(0, 0.25) for c in centre]))
        labels.append(name)
values = keys                             # let each key carry its own content

def attention(q, scale=3.0):
    """Softmax of scaled dot products. With unit vectors, 'scale' stands in for the
    learned length of the projected queries and keys divided by √d_k."""
    s = [scale * sum(a * b for a, b in zip(q, k)) for k in keys]
    m = max(s)
    w = [math.exp(x - m) for x in s]
    z = sum(w)
    return [x / z for x in w]

def report(name, q):
    w = attention(q)
    per = {f: sum(wi for wi, l in zip(w, labels) if l == f) for f in fields}
    out = [sum(wi * v[i] for wi, v in zip(w, values)) for i in range(D)]
    print(f"{name:34s} weight by field: " + ", ".join(f"{f} {per[f]:.2f}" for f in fields)
          + f" | weight entropy {-sum(x * math.log2(x) for x in w):.2f} bits")
    return out

q1 = unit([1.0 if i < 4 else 0.0 for i in range(D)])                       # one field only
q2 = unit([1.0 if i < 4 else (1.0 if 4 <= i < 8 else 0.0) for i in range(D)])  # two fields
q3 = unit([1.0] * D)                                                        # everything at once
for n, q in (("query inside acoustics", q1), ("query spanning acoustics + control", q2),
             ("query with no direction", q3)):
    report(n, q)
# query inside acoustics             weight by field: acoustics 0.87, control theory 0.07, Buddhist texts 0.07 | weight entropy 2.69 bits
# query spanning acoustics + control weight by field: acoustics 0.42, control theory 0.49, Buddhist texts 0.10 | weight entropy 3.31 bits
# query with no direction            weight by field: acoustics 0.26, control theory 0.32, Buddhist texts 0.42 | weight entropy 3.53 bits
玩具模型中三种查询从各领域收集到的注意力权重。指向一个领域内部的查询停留在那里;指向两个领域之间的查询同时取用两者;没有方向的查询把权重摊在所有地方。

三种情况都有直观的含义。位于一个领域内部的查询,几乎只从这个领域收集。在两个领域方向上都有分量的查询,大致均等地取用两者,它返回的加权平均是一种混合,两个簇单独都不包含。没有特定方向的查询,权重分得最均匀,返回的东西接近一切的平均:这就是注意力版本的「泛泛的回答」。

注

这是在手工构造的向量上做的一次注意力运算,用来说明几何关系,而不是训练好的 Transformer 如何组合想法的模型。真实模型堆叠几十层、许多个头、学得的投影和其他组件,它们如何组合信息是一个活跃的研究领域 (Elhage et al. 2021)。

撞钟

原典

善待问者如撞钟,叩之以小者则小鸣,叩之以大者则大鸣,待其从容,然后尽其声。(佚名, n.d.)

(《礼记·学记》)

《学记》把老师而不是学生比作钟;这段话讲的是好老师如何按问题的大小作答。与玩具模型并读,它给查询向量的作用提供了一个意象:回应取决于钟被怎样敲、敲得多重。

假说 · 尚未验证

尚未确立。 明确点出两个或更多相距遥远的领域的概念,并说明要考察它们之间什么关系的提示,比局限于一个领域的提示,更常使语言模型产生在其训练数据中没有一起出现过的组合。该假说预测:在匹配的主题上,独立评审在检索文献后,更常判定跨领域提示之后输出的核心组合「此前未见发表」。如果在一项至少五十个主题的盲法比较中,两者的比例没有差别,假说就被推翻。

参考文献

Elhage, Nelson, Neel Nanda, Catherine Olsson, et al. 2021. A Mathematical Framework for Transformer Circuits. Transformer Circuits Thread. https://transformer-circuits.pub/2021/framework/index.html.
Vaswani, Ashish, Noam Shazeer, Niki Parmar, et al. 2017. “Attention Is All You Need.” Advances in Neural Information Processing Systems 30.
佚名. n.d. 礼记·学记.

Fan, Y. (2026). The Algorithmic Mirror: Self-Attention Geometry, Ashby's Requisite Variety and Cognitive Projection in Information Theory and East Asian Philosophy of Mind [算法之镜] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23723557 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).