这一课完成什么
让模型能够区分一个字位于句子中的哪里。汉字表示表回答“是什么字”;位置表示表提供“处于第几个位置”的信息。本项目采用可学习的位置表,保持计算直接可见。
字告诉模型“是谁”,位置告诉它“在哪”
把字向量与位置向量逐格相加。交换两个字,会改变每个位置收到的组合;模型因此有条件区分先后顺序。
用文字逐步读这张图
- 字向量:“春” → [0.2, 0.4];同字先查同一行
- 位置 0:[0.1, −0.2];第一格位置
- 合在一起:[0.3, 0.2];逐项相加
- 位置 1:[−0.3, 0.2];换一个位置
- 同字放这里:[−0.1, 0.6];组合随位置变化
- 连成序列:字与位置共同决定;送入注意力的数字
为什么只提供一袋字不够?
一袋字丢掉了顺序,而同样几个字按不同顺序组合可以有不同意思。
两张表相加
若第一个位置是“明”,汉字向量假设为 [0.2,0.4],位置 0 的向量为 [0.1,-0.2],最终得到 [0.3,0.2]。第二个位置同样出现“明”,汉字向量相同,但加上位置 1 的另一行,因此输入表示不同。
positions = torch.arange(length, device=tokens.device)
hidden = self.characters(tokens) + self.positions(positions)汉字部分尺寸 [B,T,C],位置部分尺寸 [T,C]。位置向量会在每条练习题中共用,对应相同的序列位置,这种自动适配外层维度叫广播。相加后尺寸仍为 [B,T,C],不会变为两倍宽度。
运行并交换顺序
./poet lesson 9
.venv/bin/python lessons/09/experiment.py实验比较编号 [1,2,3] 和 [2,1,3]。它们使用相同的三个位置编号,但前两个位置的汉字改变,最终每一行输入也随之改变。你可以打印第 3 行,确认没有变化。
如果把所有字向量简单平均,交换顺序后平均值会相同,会丢失大量顺序信息。完整 GPT 还有限制只能看前文的结构,因此它的顺序信息不只来自位置表;这一课关注显式位置表示如何工作,不把所有顺序效应归结于单一部件。
前文长度是什么限制
本项目位置表默认准备 64 行,表示一次模型调用最多处理 64 个位置,包括特殊标记、关键词和标点。四句五言诗有 20 个汉字、4 个标点;四句七言有 28 个汉字、4 个标点,还要留出条件区空间。
这个长度不同于“模型记住了多少首诗”。训练中见过许多作品被浓缩进参数,而某次生成只能直接利用本次传入的有限前文。增加前文长度还会扩大注意力分数表;长度翻倍,完整两两匹配表的格子数量会变为四倍。
验收与排错
- 位置与汉字向量宽度一致才能相加。
- 位置从 0 数到
length-1,不能超出位置表。 - CPU 与 MPS 上的数字不能直接混用;
torch.arange明确放在与输入相同的设备上。 - 想增加前文长度,需要对应修改配置并重新训练。已有位置表不能凭空提供新行的已学参数。
小练习与答案
上下文长度为 64,表示宽度为 128,位置表有多少参数?为什么不必乘以批数量?
查看答案
共有 64×128=8192 项参数。所有诗共用这张位置表,批数量只是同时处理多少条题目,不创建独立参数。输入序列里关键词也占位置,因此正文第一个字的位置编号不一定总是同一个值。