01 / 从图像来到文本
词有顺序,长度也不一定相同
图像张量常用 (B,C,H,W);文本先被切成一个个 Token,再把每个 Token 变成整数 ID。一批文本的 ID 常排成 (B,T):B 是句子条数,T 是批次中的序列长度。顺序很重要:“小猫 追 小狗”和“小狗 追 小猫”包含相同词,意思却不同。
本节从七句人工编写的玩具语料学习机制。它不是一个能理解自然语言的大模型;训练结果仅说明代码确实执行了序列预测。
02 / 先决定什么算一个 Token
分词规则决定 ID 的含义
“小猫 喜欢 小鱼”按空格切成 3 个词级 Token;如果去掉空格并逐字切,就有 6 个字级 Token。这里的空格是我们事先标注的词边界,不是自动中文分词。实际系统还常用子词 Token,边界由其分词器和词表决定。
<UNK>,真实分词器可能用子词拆开。03 / 查表,而不是对整数做算术
Embedding 把一个 ID 变成一行向量
词表有 V=15 行。为了容易看清查表,本页用 D=3 的固定演示表;运行模型另外使用可训练的 D=8 向量。点击表中的行,观察选中 ID 如何索引出向量。演示表里的 0.1、0.2 等数字是人为设定的,没有语义。
从数学上看,取一行也等价于一个 one-hot 行向量乘矩阵 E;实际使用时可直接按 ID 查表,不必造出稀疏的 one-hot 数组。
同一个 Token 的 ID 每次都相同;训练会调整这一行的向量值,让它更有利于任务。<PAD> 的演示向量为全零,模型也用 padding_idx=0。
04 / 长短句如何放在一批
补齐、移位和有效位置
输入前放 <BOS> 表示开始,末尾放 <EOS> 表示结束。短句少一个位置,用 <PAD> 补齐。训练下一个 Token 时,输入和目标错开一格;点击任意目标位置。
PyTorch 批次实际是 x.shape=y.shape=(7,4),共 28 个目标格,其中 27 个有效,1 个是 <PAD>。损失设 ignore_index=PAD_ID,跳过这个目标格;只是把 Embedding 的 PAD 向量置零,不会自动让损失忽略 PAD。
05 / 语言模型究竟在学什么
给定前文,预测下一个 Token
在第 t 个位置,模型只能根据已输入的前文输出对 V 个候选 Token 的 logits,softmax 后得到一个分布。训练目标提高真实下一个 Token 的概率;同一句的每个有效位置都贡献损失。
例如只看到 <BOS> 时,还不知道主角是谁;看到 小猫 后,下一词在玩具语料里可能是“喜欢”或“追”。模型学的是条件分布,不要求每个位置都有唯一必然的答案。
06 / 顺序从哪里进入模型
RNN 带着状态逐步读入
同一个 RNN 单元依次处理向量 eₜ 与上一时刻的状态 hₜ₋₁。输出 hₜ 再预测下一词。这里的状态有 16 个数;点击下一步看实际训练模型在第一句各位置的状态和预测。
展示的是训练后的实际数值;每个时刻 16 维状态只列前 4 维。即使第一句真实是“小猫…”,只看到 <BOS> 时,模型也可能更偏向语料中出现次数多的“小鸟”。这不是未来信息泄漏。
07 / 为什么还出现 LSTM
普通 RNN 的长距离记忆困难
普通 RNN 把前面的信息压进一个不断更新的状态;训练时梯度也要沿时间反向传递。序列很长时,早期信息可能难以保留,梯度也可能变得很小或很大。LSTM 增加细胞状态 cₜ以及门,学习什么时候保留、写入或输出信息。
决定旧细胞状态的哪些部分继续保留。
决定本步候选信息写入多少。
决定细胞状态的哪些部分形成对外状态 hₜ。
LSTM 有助于处理较长依赖,但不保证无限记忆;RNN/LSTM 的时间步仍有先后依赖,难以把整条长序列的所有位置完全并行计算。下一节会看注意力怎样直接建立不同位置之间的联系。PyTorch LSTMCell 定义。
08 / 确认代码真的跑过
小语料训练曲线与形状核对
代码在 7 句玩具语料上训练一个 Embedding(15,8) → RNN(8,16) → Linear(16,15)。下面是实际 CPU PyTorch 运行产生的训练损失;这里只是在训练语料上检查机制,没有独立测试集,不能称作泛化能力。
训练准确率不可能简单要求 100%:同一个前文在这些句子里可能对应不同后续词。模型的输出是分布;非零损失也有合理的不可预测部分。
09 / 自己核对张量
本地 PyTorch 练习
程序只用当前项目的 CPU PyTorch,语料直接写在代码中,不下载数据或模型。HTML 已嵌入一次真实运行的结果,直接打开不会重新训练,也无需服务。
uv run python lessons/lesson-10-text.py- 切换词级与字级 Token,记录“词表大小”和同一句的 Token 数为何变化。
- 手动写出两句话的
<BOS>、<EOS>、x、y 和<PAD>,与图解核对。 - 查一个 Token ID 的演示向量,说明为什么查表输出会增加一个 D 轴。
- 把代码的 Embedding 维度从 8 改为 12,同时调整 RNN 的 input_size;预测哪些张量形状改变、哪些不变,再运行验证。
- 解释模型在
<BOS>后不能确定第一词;不要把本节训练集成绩当成真实语言理解成绩。
10 / 自测