第 16 天 · 数据怎么排列,会改变模型学得好不好
一句话
论文用实验说明,seq2seq 对输入和输出的排列顺序很敏感。对无序的输入,作者提出读-处理-写结构,用多步注意力得到与顺序无关的集合表示。对无序的输出,作者提出在训练中搜索最佳顺序的损失。
论文讲了什么
问题。seq2seq 把输入和输出都当作序列。但很多数据本来是集合:一组待排序的数、平面上的一堆点、分子里的原子。把集合排成序列时,必须选一种顺序。n 个元素有 n! 种排法。作者提出 2 个问题:顺序会不会影响学习?如果会,该怎么办?
顺序确实重要。论文先列证据。翻译中,把源句倒序输入,LSTM 的效果明显变好,这是 Sutskever 等人 2014 年的发现。句法分析中,把句法树按深度优先或广度优先线性化,结果也不同。理论上,链式法则对任何顺序都成立:p(x1, x2) = p(x1) p(x2|x1) = p(x2) p(x1|x2)。但模型容量有限,优化也不完美,所以有的顺序明显更好学。
输入是集合:读-处理-写。
- 读(Read):每个元素单独经过一个小网络,得到记忆向量
m_i。这一步不看其他元素,所以和顺序无关。 - 处理(Process):一个不接收外部输入的 LSTM 运行 T 步。每一步,它用当前状态
q_t对所有m_i做内容注意力,读出加权和r_t,再把[q_t, r_t]作为下一步的输入状态。加权和不关心元素先后,所以整个处理过程对排列不变。T 越大,模型在输出前"思考"的步数越多。 - 写(Write):用指针网络(第 18 天)逐步指向输入元素,生成输出序列。
作者用排序任务验证这个结构。输入是 [0, 1] 区间的随机实数,输出是从小到大排列的下标。实验比较了 5、10、15 个数的情况。对照模型用 LSTM 按给定顺序读入。增加处理步数可以提高排序准确率,数越多任务越难。
输出是集合:搜索顺序。如果目标没有天然顺序,作者让训练过程自己挑顺序。对每个样本,在候选顺序中选出当前模型概率最高的一个,用它计算损失。只取最大值容易过早锁定一个差的顺序,所以训练前期要采样多种顺序做探索。作者在一个人造任务上验证了这个方法:估计未知图模型中多个变量的联合分布。
直觉例子。让模型输出一句话里出现的所有人名。答案"张三、李四"和"李四、张三"一样对。如果训练标签随机给其中一种,模型会在两个答案之间摇摆。固定一种规则(例如按出现顺序),或让模型自己挑,学习都会更稳。
关键概念
- 排列不变性(Permutation Invariance)
- 打乱输入元素的顺序,输出保持不变。求和、求平均和注意力加权和都满足这一点,LSTM 顺序读入则不满足。
- 读-处理-写(Read-Process-Write)
- 本文为集合输入设计的三段式结构:逐元素编码、多步注意力处理、指针网络输出。处理块后来常被称为 Set2Set。
- 内容注意力(Content-Based Attention)
- 用查询向量与每个记忆向量的相似度决定权重,不使用位置信息。因此读出结果不受元素排列影响。
- 处理步数(Process Steps)
- 处理块中 LSTM 运行的步数 T。每一步重新读一次全部记忆,步数越多,集合表示被反复修正的次数越多。
- 链式法则分解(Chain Rule Factorization)
- 把联合概率拆成逐个元素的条件概率连乘。拆法有 n! 种,数学上等价,但对神经网络来说难度不同。
- 输出顺序搜索(Order Search)
- 训练时不固定标签顺序,而是在候选顺序里挑模型当前最认可的一个计算损失,让模型和顺序一起被优化。
历史位置:为什么值得读
这篇论文和第 18 天的指针网络出自同一位第一作者 Vinyals,发表时间晚几个月。指针网络解决了"输出是输入元素"的问题,但输入仍按序列读入。本文进一步追问:输入本来没有顺序时怎么办?
它的影响主要有 3 条:
- 图神经网络:第 21 天的消息传递神经网络(MPNN)用本文的处理块做读出层,把一张图所有节点的向量汇总成一个图向量。
- 集合学习理论:2017 年的 Deep Sets 证明,排列不变函数都可以写成"逐元素变换、求和、再变换"的形式。2019 年的 Set Transformer 用自注意力处理集合。
- 无序输出:2020 年的目标检测模型 DETR 把检测框当集合输出,用二分图匹配找标签和预测的对应关系。这是"输出顺序问题"的另一种解法。
清单把这篇放在注意力和记忆的系列里,因为处理块本质上是"多次读取一块记忆"。这和第 17 天神经图灵机的读头思路一致。
学前准备
- 先看第 15 天,理解加性注意力怎么打分
- 建议先读第 18 天指针网络,本文的写模块就是它
- 理解 LSTM 的状态更新
- 知道排列和 n! 的含义
在原仓库怎么学
- 读 README.md,看读、处理、写 3 个模块分别对应代码里的哪一部分。
- 对照 PAPER_NOTES.md 读原论文第 4 节,重点看处理块的公式。
- 读 implementation.py,依次看
SetEncoder、PointerNetwork和组合起来的ReadProcessWrite。 - 做 exercises/ 里的 5 个练习:
exercise_1.py写指针注意力,exercise_2.py写排列不变的集合编码器并验证打乱输入后输出不变,exercise_3.py训练排序,exercise_4.py求凸包,exercise_5.py近似求解旅行商问题。凸包和旅行商问题是第 18 天论文的任务,这里用来练习写模块。答案在 exercises/solutions/。 - 运行 train.py,它支持 sorting、convex_hull 和 tsp 3 种任务。数据生成方式见 data/README.md。
- 用 visualization.py 画指针的注意力热力图和几何结果。
- 用 notebook.ipynb 串一遍,用 CHEATSHEET.md 复习。
今天再看
本文的两个问题,今天都还在:
- 集合输入:去掉位置编码的自注意力天然对排列等变,所以 Transformer 本身就能处理集合。点云、分子和图数据的模型普遍利用这一点。Perceiver 一类模型用一组可学习的查询向量反复读取输入集合,和本文的处理块思路相近。
- 顺序敏感:大语言模型同样受顺序影响。2021 年 Lu 等人发现,只改变少样本示例的排列,准确率就可能在接近随机和接近最好之间变化。2023 年的"反转诅咒"研究发现,模型学了"A 是 B",不一定能回答"B 是谁"。
- 输出顺序:思维链让模型先写推理再写答案,本质上也是选择更好学的输出顺序。
本文最值得带走的一句判断:对神经网络来说,数学上等价的分解,学习难度可以完全不同。
容易卡住的地方
- 混淆排列不变和排列等变:不变是打乱输入后输出完全相同,例如集合的总和。等变是输出跟着输入一起重新排列,例如每个元素各自的编码。
- 实现处理块时给 LSTM 接上外部输入:处理块的 LSTM 没有输入,只靠自身状态和读出的 r_t 运行。接上元素序列就破坏了排列不变性。
- 验证排列不变性时直接用 == 比较:浮点加法顺序不同会有微小误差。建议用 torch.allclose,容差设为 1e-5。
- 以为输出顺序搜索要遍历 n! 种顺序:n = 10 时已有 3628800 种。实际做法只在少量候选中挑选,或通过采样探索。
延伸阅读
- 原论文:Order Matters: Sequence to sequence for sets
- 原仓库第 16 天目录:16_order_matters/ —— 代码、笔记本、练习与答案(英文)
- Deep Sets(Zaheer et al. 2017) —— 排列不变函数的统一形式
- Set Transformer(Lee et al. 2019) —— 用自注意力处理集合输入
- Neural Message Passing for Quantum Chemistry —— 第 21 天,用 Set2Set 做读出层
- Fantastically Ordered Prompts(Lu et al.) —— 示例顺序对大模型准确率的影响