第 17 天 · 给神经网络装一块可微分的外部内存
一句话
论文给神经网络接上一块外部记忆矩阵,读和写都用连续的权重分布完成,整个系统可以端到端用梯度下降训练。神经图灵机从输入输出样例中学会复制、联想回忆和排序这类简单算法,并能推广到比训练时更长的序列。
论文讲了什么
问题。LSTM 的记忆藏在隐状态里。隐状态大小固定,记忆和计算混在一起。想记住更多内容,就得把整个网络变大。计算机的做法不同:CPU 负责计算,内存负责存储,按地址读写。作者想把这种分工搬进神经网络,同时保持每一步可导,好用梯度下降训练。
结构。神经图灵机分 2 部分:
- 控制器:一个前馈网络或 LSTM。每一步,它读入外部输入和上一步从记忆读到的内容,输出结果和一组读写头参数。
- 记忆矩阵:N 行 M 列,论文实验用 128 × 20。每一行是一个存储单元。
读写头不挑某一行,而是给 N 行一个权重分布 w,权重之和为 1。读操作是加权和 r = sum_i w(i) M(i)。写操作分两步:先用擦除向量 e 擦掉旧内容 M(i) = M(i) * (1 - w(i) e),再加上新内容 M(i) = M(i) + w(i) a。这些操作都可导。
寻址流程。权重 w 经过 4 步算出:
- 内容寻址:键向量
k和每一行算余弦相似度,乘以强度beta后过 softmax。beta越大,焦点越集中。 - 插值:门
g在内容权重和上一步权重之间混合。g = 0时完全沿用上一步的位置。 - 卷积移位:移位分布
s(例如定义在 -1、0、+1 上)对权重做循环卷积,让焦点前移或后移一格。 - 锐化:每个权重取
gamma次方再归一化,抵消卷积带来的模糊。
内容寻址回答"找哪条记录",移位回答"下一条在哪"。两者结合,模型既能按内容查找,也能像指针一样顺序遍历。
结果。论文测试了 5 个任务:复制、重复复制、联想回忆、动态 N 元语法和优先级排序。复制任务的输入是长度 1 到 20 的随机 8 位二进制向量序列。神经图灵机比 LSTM 收敛快,最终误差也更低。测试长度增加到 120 时,神经图灵机仍能大体正确地复制,LSTM 超过 20 后很快出错。作者把读写权重画出来,发现模型学到的过程很像一段程序:写入时读写头逐格前移,读出时先跳回起点,再逐格读出。
关键概念
- 控制器(Controller)
- 神经图灵机里负责计算的网络,可以是前馈网络或 LSTM。它决定读什么、写什么、往哪里移动读写头。
- 记忆矩阵(Memory Matrix)
- N × M 的外部存储,N 是单元个数,M 是每个单元的向量长度。它的大小和控制器参数量无关。
- 内容寻址(Content-Based Addressing)
- 按键向量和记忆行的余弦相似度分配权重,类似按关键词查找记录。思路与注意力中的 Q 和 K 匹配相同。
- 位置寻址(Location-Based Addressing)
- 通过插值门和循环卷积移位,把焦点从上一个位置移到相邻位置。它让模型能顺序遍历记忆。
- 擦除与添加(Erase and Add)
- 写操作的两步:先按权重和擦除向量把旧值按比例清掉,再按权重加上新向量。拆成两步后整体仍然可导。
- 锐化(Sharpening)
- 把权重取 gamma 次方再归一化,gamma ≥ 1。卷积移位会把焦点摊开,锐化把它重新收拢到少数几行。
历史位置:为什么值得读
神经图灵机发表于 2014 年 10 月,作者来自 DeepMind。Graves 此前在手写生成中用过基于位置的软注意力。同一个月,Facebook 的 Weston 等人发表了记忆网络(Memory Networks)。两篇论文从不同方向提出同一个想法:给神经网络加外部记忆。
后续工作沿 3 个方向展开:
- 记忆网络系列:2015 年的端到端记忆网络用软注意力多次读取记忆,用于问答。
- 可微分神经计算机(DNC):Graves 等人 2016 年在 Nature 发表,加入动态内存分配和时间链接,能在图上做路径查找。
- 算法学习:2015 年 Kaiser 和 Sutskever 的 Neural GPU 学习多位数加法和乘法,也追求"训练短、测试长"的推广能力。
和清单的关系:第 15 天的注意力在只读的编码器状态上做软选择,神经图灵机把这种软选择用到可写的记忆上。第 16 天的处理块多次读取一组记忆,第 20 天的关系 RNN 让记忆单元之间用注意力交互。
学前准备
- 理解 LSTM 的隐状态和门控,见第 2 天
- 会算余弦相似度和 softmax
- 知道循环卷积:下标越界时绕回开头
- 了解图灵机或计算机内存按地址读写的概念
在原仓库怎么学
- 读 README.md,找到寻址流程对应的论文第 3.3.1 节。
- 对照 paper_notes.md 读原论文第 3 节,把公式 2 到公式 9 抄在纸上。
- 读 implementation.py,依次看
NTMMemory、NTMHead和NTM3 个类。 - 做 exercises/ 里的 5 个练习:
exercise_01_addressing.py写内容寻址(公式 5),exercise_02_shift.py写循环卷积移位(公式 8),exercise_03_memory.py写擦除和添加(公式 3、4),exercise_04_controller.py准备控制器输入,exercise_05_sharpening.py写锐化(公式 9)。答案在 exercises/solutions/。 - 读 data/README.md 了解复制任务的序列格式,然后运行 train_minimal.py 训练复制任务。
- 用 visualization.py 画读写权重随时间的变化,对照论文的复制任务图。
- 用 notebook.ipynb 串一遍,用 CHEATSHEET.md 复习公式。
今天再看
神经图灵机本身今天很少直接使用。它训练不稳定,速度慢,也难以扩展到大规模数据。DNC 也停留在研究阶段。但它的几个思想活了下来:
- 内容寻址就是注意力:Transformer 的 Q 和 K 匹配,与本文的键向量查找是同一件事。大语言模型的 KV 缓存可以看成一块只追加、不擦除的记忆。
- 外部记忆:检索增强生成(RAG)把文档库当外部记忆,但检索步骤通常不可导。智能体框架让模型把中间结果写进文件或草稿区,再读回来。
- 长度推广:本文强调"训练长度 20,测试长度 120"。Transformer 至今仍不擅长这件事,例如学过短的多位数加法,换成更长的数常常出错。这仍是开放问题。
容易卡住的地方
- 训练出现 NaN 或长期不收敛:这是神经图灵机的常见问题。论文用 RMSProp 并裁剪梯度。建议先用很短的序列(例如长度 1 到 5)训练,再逐步加长。
- 循环卷积的方向写反:用一个 one-hot 权重测试,焦点在第 3 行、移位取 +1 时,结果应该落在第 4 行。最后一行移位后应绕回第 0 行。
- 锐化参数 gamma 小于 1 会让焦点更模糊。实现时用 1 + softplus(x) 保证 gamma ≥ 1,beta 用 softplus 保证非负。
- 记忆初始化为全 0 时,余弦相似度的分母为 0。分母要加一个小常数(例如 1e-8),或把记忆初始化为小的常数。
延伸阅读
- 原论文:Neural Turing Machines
- 原仓库第 17 天目录:17_neural_turing_machines/ —— 代码、笔记本、练习与答案(英文)
- Attention and Augmented Recurrent Neural Networks(Distill) —— 交互图解神经图灵机的读写过程
- Hybrid computing using a neural network with dynamic external memory —— DNC,神经图灵机的后继
- Memory Networks(Weston et al. 2014) —— 同期另一条外部记忆路线
- End-To-End Memory Networks(Sukhbaatar et al. 2015) —— 用软注意力多次读取记忆