你已经知道 token 如何变成向量,也实现了因果注意力。现在把这些组件连起来。先做一个小 GPT,让每一层的输入和输出都能被检查,再考虑扩大模型。
从 token ID 到位置表示
模型接收 [B,T] 的整数 ID,查表得到 [B,T,C]。它还需要表示顺序。教学版 GPT 可以使用学习得到的位置 embedding,把第几个位置的信息加到 token embedding 上;其他模型可能采用不同位置机制。
“token 是什么”和“token 在哪里”解决不同问题。位置表示也有长度约束,不能只把上下文配置改大,就假设旧权重一定适用于新长度。
Transformer block 怎样连接
一个常见的教学结构采用前置归一化:先归一化,再进入因果注意力,把结果加回原输入;然后归一化、进入前馈网络,再做一次残差相加。下面是连接示意,组件需要先实现。
# x 的形状一直保持 [B, T, C]。
x = x + attention(layer_norm_1(x))
x = x + feed_forward(layer_norm_2(x))
残差连接给信息与梯度提供一条直接路径;前馈网络则在每个位置上进一步转换表示。不同模型的归一化、激活和前馈形式可能不同,跟练时应固定所选实现。
输出分数怎样接到损失
最后把每个位置的 C 维表示映射成 V 个词表分数,得到 [B,T,V] 的 logits。训练时可以展平为 [B×T,V],把向后移动一位的目标展平为 [B×T],再计算交叉熵。
交叉熵的常用接口接收原始 logits,不需要你先做一次 softmax。重复归一化会改变计算。生成阶段则从最后一个位置的分布采样,把新 token 接到输入后,再预测下一步。
模型“能跑”以后检查什么
至少检查四件事:logits 的维度与词表一致;未来输入不影响过去输出;损失和梯度都是有限数;一次优化器更新后,可训练参数真的变化。若做过拟合极小批次的实验,要把它明确标成调试,不能当作泛化证据。
观看 Karpathy 的 GPT 视频时,可以用本站文章记录组件与形状,再用 Raschka 的实现章节核对结构。下一课会把这个前向过程放进训练循环,处理验证、检查点和恢复。