为 Transformer 实现形式化算法,第 1 部分:注意力

为 Transformer 实现形式化算法,第 1 部分:注意力

边做边学的机器学习。使用 Deep Mind 的伪代码从头开始编写多头注意力的教学实现

2017年的论文中介绍了transformer架构 注意力就是你所需要的 .从那时起,已经引入了数百种关于通过注意力将令牌表示上下文化的中心主题的变体(有关最近的广角视图,请参见 变压器调查 自然语言处理的有效方法:调查 __ )。

大型语言模型可能是最广为人知的转换器类型,但该架构已迅速扩散到机器学习的每个角落。卢卡斯·拜尔最近发表了一篇 一组漂亮的幻灯片 涵盖了文本、视觉、语音和强化学习中的应用,同时强调了 Transformer 架构周围的“社区统一”。

无论您是刚刚了解转换器还是修改它们以处理全新类型的数据,对基础知识有一个扎实的理解总是有帮助的。在这篇文章中,我们将研究 Deep Mind 的 Mary Phuong 和 Marcus Hutter 于 2022 年发表的论文 , Transformer 的形式化算法 (PH22)。 然后我们将使用他们提供的伪代码算法 在 PyTorch 中实现转换器的注意力组件 .

这篇文章假设您对 Transformer 架构有一定的了解。如果您是变压器世界的新手,请考虑查看 更多资源 这篇文章末尾的部分。

Transformer 的形式化算法

PH22 论文的主要贡献是一组对变压器算法的简明伪代码描述。作者通过说来激励他们的工作,

Transformer 是具有(自)注意力机制的深度前馈人工神经网络。他们在自然语言处理任务和其他领域取得了巨大的成功。自 5 年前 [VSP+17] 成立以来,已经提出了许多变体 [LWLQ21]。描述通常是图形的、口头的、部分的或增量的。尽管它们很受欢迎,但似乎从未为任何变体发布过伪代码。将此与计算机科学的其他领域进行对比……

基本上完整的伪代码大约有 50 行,而实际的真实源代码则有数千行。我们相信这些形式化算法对于需要紧凑、完整和精确公式的理论家、对从头实现 Transformer 感兴趣的实验研究人员以及鼓励作者使用形式化 Transformer 算法(第 2 节)扩充他们的论文或教科书很有用。

这种具有明确算法的统一且自包含的方法对于从头开始编写实现非常有帮助。简洁的伪代码描述也填补了变压器文献中存在的空白。下面,我们将看到中心注意力算法可以用相对较少的代码来表达。

一些实施说明

矩阵乘法约定

在他们的 符号 部分,作者描述了他们在编写矩阵乘法时的约定。

我们使用数学中更常见的矩阵×列向量约定,与转换器文献中的默认行向量×矩阵相比,即我们的矩阵是转置的。

这里介绍的实现将使用“行向量×矩阵”约定。我发现这个约定在 PyTorch 中更自然,但绝对有可能实现任何一种方式。幸运的是,作者将他们的 LaTeX 文件上传到 arXiv,我能够在 背页 .

批量输入的处理

伪代码算法不处理输入的批量维度。这使算法更清晰、更易于阅读,但在将它们与本文中的代码片段和 github 中的完整实现进行比较时,需要牢记这一点。

填充和遮罩

随着批处理维度的处理,由于填充而对掩码令牌进行了处理。这与自回归语言模型(例如 GPT)中使用的单向或“因果”掩码不同,但可以使用相同的掩码张量来完成两者。

伪代码和代码代码

这篇文章将介绍单查询、单头和多头注意力算法。对于每一个,我们将检查 PH22 算法的转置版本以及代码片段。代码片段只是一个草图,但完整的实现可在 galtay/formal-algos-transformers github repo .通过将它们并排放置,我希望传达创建的伪代码 PH22 的表现力。

单查询注意

作者展示了从嵌入到训练再到推理的 Transformer 的全貌,我建议通读整篇论文以从他们自包含的演示文稿中受益。然而,这篇文章专注于注意力机制,所以我们将跳转到第一个基于注意力的算法:单查询注意力。

在该算法中,我们采用单个主令牌嵌入并通过关注一系列上下文嵌入来创建新嵌入。在许多变压器实现中 d_x , d_z , 和 d_out 彼此相等,但这不是必需的。

Single-query attention (left or top) algorithm from PH22 but with “row vector × matrix” convention and renaming to match later algorithms. (right or bottom) PyTorch sketch. Full implementation at fat_single_query_attention.py

单头注意力

在单头注意力算法中,我们以几种方式扩展了单查询实现。

  • 我们允许一系列主令牌嵌入而不是单个主令牌嵌入
  • 我们仍然有一系列上下文标记嵌入,但我们将它们收集到单个张量而不是张量列表中
  • 我们在代码片段中引入了批处理维度
  • 我们引入一个掩码张量来处理填充和单向注意力

注意力算法独立应用于每个批次。 mask张量用于防止token t_x **X** 从参加到象征 t_z **Z** .在 PH22 中,掩码用于自回归模型中,以防止令牌按顺序处理在它们之前的其他令牌。批处理引入了对填充标记的需求,我们可以使用相同的掩码来防止注意力机制将这些标记上下文化。在我们的实现中,用户传入一个形状为 ( b , l_x , l_z )。

我们利用[ 火炬.einsum](https://pytorch.org/docs/stable/generated/torch.einsum.html) 模块来做批量矩阵乘法。阅读和编写这些表达式可能需要一些时间来适应,但它们可以跨多个框架使用(例如[ numpy.einsum](https://numpy.org/doc/stable/reference/generated/numpy.einsum.html)[ tf.einsum](https://www.tensorflow.org/api_docs/python/tf/einsum) )。 Tim Rocktäschel 的教程 是开始学习的好地方。

Single-head attention (left) algorithm from PH22 but with “row vector × matrix” convention. (right) PyTorch sketch. Full implementation at fat_single_head_attention.py

多头注意力

在多头注意力算法中,我们以几种方式扩展了单头实现。

  • 主要和上下文嵌入通过 H 独立的注意力机制。
  • H 注意输出被连接起来,然后通过另一个参数化的仿射变换传递 **W_o** **b_o** .

Multi-head attention (left) algorithm from PH22 but with “row vector × matrix” convention. (right) PyTorch sketch. Full implementation at fat_multi_head_attention.py

变压器的其余部分

在第一篇文章中,我们只介绍了转换器的核心注意力算法。在下一篇文章中,我们将介绍完整的编码器、解码器和编码器-解码器架构。

使用无状态函数调用的单元测试

这篇文章中链接的 github repo 带有一个 一组单元测试 .测试策略依赖于单查询注意力的黄金实现,如果用户信任单查询实现,则允许用户信任单头和多头实现。

这些测试利用 PyTorch 1.12 中引入的一个新特性,该特性提供 无状态函数调用 .此功能允许临时更换 火炬.nn.module 参数和缓冲区与用户提供的。在实践中,这为我们提供了一种方法来确保上述注意力模块的两个实例对给定的计算使用相同的权重和偏差集。你可以在他们的文章中看到一个简洁的例子 领英帖子 .

更多资源

实现

讲座/教程

独自的

  • 这里的实现使用了 einsum。这提供了一种与平台无关的方式来编写张量操作(即,您可以在 numpy、tensorflow 或 pytorch 中使用相同的字符串)。您可以阅读有关 einsum 的更多信息 Tim Rocktäschel 的教程

中码

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/37396/17571802

posted @   哈哈哈来了啊啊啊  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示