当前位置:首页 > 技术 > 正文内容

超越Transformer:PyNeuraLogic的神经符号编程探索

访客 技术 2026年6月26日 1
  • 深入理解神经符号编程的优势

  1. 简介

在过去的几年里,我们见证了基于Transformer的模型在自然语言处理和计算机视觉等领域的广泛应用。本文将探讨一种简洁、可解释且可扩展的方式来表达深度学习模型,特别是Transformer,通过混合架构的方式,即结合深度学习与符号人工智能。为此,我们将在名为PyNeuraLogic的Python神经符号框架中实现模型。

将符号表示与深度学习相结合,弥补了当前深度学习模型在可解释性和推理技术方面的不足。值得注意的是,增加模型参数的数量并不总是实现预期结果的最佳途径,就像增加相机像素数量并不一定能提升拍照质量一样。

PyNeuraLogic框架基于逻辑编程——逻辑程序包含可微分的参数。该框架特别适合处理小型结构化数据(如分子)和复杂模型(如Transformer和图神经网络)。然而,PyNeuraLogic并不是处理非结构化数据和大型张量数据的最佳选择。

框架的核心是一个可微分的逻辑程序,我们称之为模板。模板由逻辑规则组成,这些规则以抽象方式定义神经网络的结构——可以将模板视为模型架构的设计蓝图。然后将模板应用于每个输入数据实例,以生成针对每个样本独有的神经网络。这种动态架构生成的方式与传统预定义架构的框架有本质区别。

  1. 符号化Transformer

我们通常将深度学习模型实现为对批量输入张量的张量操作。这是合理的,因为深度学习框架和硬件(如GPU)通常针对处理更大的张量而非形状和大小多变的张量进行了优化。Transformer也不例外,通常将单个标记向量批量处理为一个大矩阵,并将模型表示为对这些矩阵的操作。然而,这种实现方式掩盖了各个输入标记之间的相互关联,这一点在Transformer的注意力机制中尤为明显。

  1. 注意力机制

注意力机制构成了所有Transformer模型的核心。其经典版本使用了所谓的多头缩放点积注意力。让我们以一个头为例,将缩放点积注意力分解为一个简单的逻辑程序。

注意力机制的目的是决定网络应该关注输入的哪些部分。通过计算值V的加权和来实现,其中权重反映了输入键K和查询Q的兼容性。在这个特定版本中,权重由查询Q和键K的点积除以d_k的平方根后,通过softmax函数计算得到。

(X.weights(X_i, X_j) <= (X.d_k, X.k(X_j).T, X.q(X_i))) | [F.product, F.softmax_agg(agg_terms=[X_j])],
(X.attention(X_i) <= (X.weights(X_i, X_j), X.v(X_j)) | [F.product]

在PyNeuraLogic中,我们可以通过上述逻辑规则充分捕捉注意力机制。第一条规则表示权重的计算——它计算维度的平方根倒数与转置的第j个键向量和第i个查询向量的乘积。然后我们用softmax聚合给定i和所有可能的j的所有结果。

第二条规则计算该权重向量与相应的第j个值向量之间的乘积,并对每个第i个标记的不同j的结果求和。

  1. 注意力屏蔽

在训练和评估过程中,我们通常限制输入标记可以相互关注的内容。例如,我们希望限制标记向前看和关注即将到来的单词。流行的框架,如PyTorch,通过屏蔽实现这一点,即将缩放的点积结果的元素子集设置为一个非常低的负数。这些数字强制softmax函数将零指定为相应标记对的权重。

(X.weights(X_i, X_j) <= (
    X.d_k, X.k(X_j).T, X.q(X_i), X.special.leq(X_j, X_i)
)) | [F.product, F.softmax_agg(agg_terms=[X_j])],

使用我们的符号表示,我们可以通过简单地添加一个约束条件来实现这一点。在计算权重时,我们限制第j个指标小于或等于第i个指标。与掩码相反,我们只计算所需的缩放点积。

  1. 非标准注意力

当然,符号化的"掩蔽"可以是完全任意的。我们大多数人听说过基于稀疏Transformer的GPT-3⁴(或其应用,例如ChatGPT)⁵。稀疏Transformer的注意力(跨步版本)有两种类型的注意力头:

  • 一个只关注前n个标记 (0 ≤ i − j ≤ n)
  • 一个只关注每第n个前一个标记 ((i − j) % n = 0)

两种类型头的实现都只需要微小的改变(例如,对于n = 5)。

(X.weights(X_i, X_j) <= (
    X.d_k, X.k(X_j).T, X.q(X_i),
    X.special.leq(X.D, 5), X.special.sub(X_i, X_j, X.D),
)) | [F.product, F.softmax_agg(agg_terms=[X_j])],
(X.weights(X_i, X_j) <= (
    X.d_k, X.k(X_j).T, X.q(X_i),
    X.special.mod(X.D, 5, 0), X.special.sub(X_i, X_j, X.D),
)) | [F.product, F.softmax_agg(agg_terms=[X_j])],

我们可以走得更远,将对类似图形(关系)输入的注意力进行概括,就像在关系注意力中一样。⁶这种类型的注意力在图形上运行,其中节点只关注它们的邻居(由边连接的节点)。查询Q、键K和值V是边嵌入与节点向量嵌入相加的结果。

(X.weights(X_i, X_j) <= (X.d_k, X.k(X_i, X_j).T, X.q(X_i, X_j))) | [F.product, F.softmax_agg(agg_terms=[X_j])],
(X.attention(X_i) <= (X.weights(X_i, X_j), X.v(X_i, X_j)) | [F.product,

X.q(X_i, X_j) <= (X.n(X_i)[W_qn], X.e(X_i, X_j)[W_qe]),
X.k(X_i, X_j) <= (X.n(X_j)[W_kn], X.e(X_i, X_j)[W_ke]),
X.v(X_i, X_j) <= (X.n(X_j)[W_vn], X.e(X_i, X_j)[W_ve]),

在我们的例子中,这种类型的注意力与之前显示的缩放点积注意力几乎相同。唯一的区别是添加了额外的术语来捕获边缘。将图作为注意力机制的输入似乎很自然,这并不奇怪,因为Transformer是一种图神经网络,作用于完全连接的图(未应用掩码时)。在传统的张量表示中,这并不是那么明显。

  1. 编码器

现在,当我们展示注意力机制的实现时,构建整个Transformer编码器块的缺失部分相对简单。

我们已经在关系注意力中看到了如何实现嵌入。对于传统的Transformer,嵌入将非常相似。我们将输入向量投影到三个嵌入向量中——键、查询和值。

X.q(X_i) <= X.input(X_i)[W_q],
X.k(X_i) <= X.input(X_i)[W_k],
X.v(X_i) <= X.input(X_i)[W_v],

查询嵌入通过跳过连接与注意力的输出相加。然后将生成的向量归一化并传递到多层感知机(MLP)。

(X.norm1(X_i) <= (X.attention(X_i), X.q(X_i))) | [F.norm],

对于MLP,我们将实现一个具有两个隐藏层的全连接神经网络,它可以优雅地表达为一个逻辑规则。

(X.mlp(X_i)[W_2] <= (X.norm(X_i)[W_1])) | [F.relu],

最后一个带有规范化的跳过连接与前一个相同。

(X.norm2(X_i) <= (X.mlp(X_i), X.norm1(X_i))) | [F.norm],

我们已经构建了构建Transformer编码器所需的所有部分。解码器使用相同的组件;因此,其实施将是类似的。让我们将所有块组合成一个可微分逻辑程序,该程序可以嵌入到Python脚本中并使用PyNeuraLogic编译到神经网络中。

X.q(X_i) <= X.input(X_i)[W_q],
X.k(X_i) <= X.input(X_i)[W_k],
X.v(X_i) <= X.input(X_i)[W_v],

X.d_k[1 / math.sqrt(embed_dim)],
(X.weights(X_i, X_j) <= (X.d_k, X.k(X_j).T, X.q(X_i))) | [F.product, F.softmax_agg(agg_terms=[X_j])],
(X.attention(X_i) <= (X.weights(X_i, X_j), X.v(X_j)) | [F.product],

(X.norm1(X_i) <= (X.attention(X_i), X.q(X_i))) | [F.norm],
(X.mlp(X_i)[W_2] <= (X.norm(X_i)[W_1])) | [F.relu],
(X.norm2(X_i) <= (X.mlp(X_i), X.norm1(X_i))) | [F.norm],

总结

在本文中,我们分析了Transformer架构并演示了它在名为PyNeuraLogic的神经符号框架中的实现。通过这种方法,我们能够实现各种类型的Transformer,只需对代码进行微小的更改,说明每个人都可以如何快速转向和开发新颖的Transformer架构。它还指出了各种版本的Transformers以及带有GNN的Transformers的明显相似之处。

本文由mdnice多平台发布

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。