🔎大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流🔎
📝个人主页-Sonhhxg_柒的博客_CSDN博客 📃
🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝
📣系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
🖍foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟👋
文章目录
在本章中,我们将了解一些新兴的神经网络( NN ) 设计。它们尚未成熟,但具有未来潜力,因为它们试图解决现有 DL 算法的基本限制。如果有一天这些技术中的任何一种被证明是成功的并且对实际应用有用,那么我们可能会离通用人工智能更近一步。
我们需要记住的一件事是结构化数据的性质。到目前为止,在本书中,我们一直专注于处理图像或文本——换句话说,就是非结构化数据。这不是巧合,因为 NN 在寻找像素或文本序列组合中的结构这一看似复杂的任务中表现出色。另一方面,ML 算法(例如梯度提升树或随机森林)在处理结构化数据(例如社交网络图或大脑连接)时似乎与 NN 相当或更好。在本章中,我们将介绍图 NN 来处理任意结构化图。
另一个 NN 限制体现在循环网络( RNN ) 上。理论上,这些是最强大的 NN 模型之一,因为它们是图灵完备的,这意味着 RNN 在理论上可以解决任何计算问题。在实践中往往不是这种情况。RNN(甚至长短期记忆( LSTM ))可能难以在较长时间内携带信息。一种可能的解决方案是使用外部可寻址存储器扩展 RNN。我们将在本章中了解如何做到这一点。
本章中的主题与本书中的其他主题并没有分离。事实上,我们将看到我们将看到的新网络架构基于我们已经介绍过的许多算法。这些包括卷积、RNN 和注意力模型,以及其他。
本章将涵盖以下主题:
- 介绍图 NN
- 介绍记忆增强神经网络
介绍图神经网络
在学习图NN (GNN)之前,让我们先看看为什么我们需要图网络。我们将首先定义一个图,它是一组对象(也称为节点或顶点),其中一些对象对在它们之间具有连接(或边)。
图表具有以下属性:
- 我们将图表示为,其中V是节点集,E是边集。
- 该表达式描述了两个节点之间的一条边,。
- 邻接矩阵 ,其中n是图节点的数量。这被写成好像边缘存在,如果它不存在。
- 当边有方向时,图可以是有向的,而没有方向时是无向的。无向图的邻接矩阵是对称的,即。有向图的邻接矩阵是不对称的——即。
- 图可以是循环的或非循环的。顾名思义,循环图至少包含一个循环,即只有第一个和最后一个节点相同的节点的非空路径。无环图不包含循环。
- 图边和节点都可以有关联的属性,称为特征向量。我们将用 表示节点v的d维特征向量。如果一个图有n 个节点,我们可以将它们表示为一个矩阵。类似地,每个边缘属性是一个c维特征向量,表示为,其中v和u是节点。我们可以将图的边属性集表示为矩阵。
下图显示了一个有五个节点的有向图及其对应的邻接矩阵:
图是一种通用的数据结构,非常适合在许多现实世界场景中组织数据的方式。以下是示例的非详尽列表:
- 我们可以使用图来表示社交网络中的用户(节点)和他们的朋友组(边)。事实上,这就是 Facebook 对他们的社交图谱所做的事情(The Anatomy of the Facebook Social Graph,https://arxiv.org/abs/1111.4503)。
- 我们可以将分子表示为图,其中节点是原子,边缘是它们之间的化学键。
- 我们可以将街道网络(一个经典示例)表示为图,其中街道是边,它们的交叉点是节点。
- 在在线商务中,我们可以将用户和物品都表示为节点,将它们之间的关系表示为边。
接下来,让我们讨论一下我们可以用图解决的任务类型。它们大致分为三类:
- 以节点为中心:单个节点的C分类和回归。例如,在著名的 Zachary 空手道俱乐部问题 ( https://en.wikipedia.org/wiki/Zachary%27s_karate_club ) 中,我们有许多空手道俱乐部成员(节点)和他们之间的友谊(边缘)。最初,俱乐部只有一名教练,所有成员在该教练的带领下作为一个小组进行训练。后来,俱乐部分成两组,由两名独立的教练组成。假设除了一个俱乐部成员之外的所有成员都选择加入两个组中的一个,目标是确定哪个组将选择最后一个未决定的成员(分类),因为它与其他成员的友谊集。
- Edge-focused :图的各个边缘的C分类和回归。例如,我们可以预测社交网络中的两个人相互认识的可能性。换句话说,任务是确定两个图节点之间是否存在边。
- Graph-focused:全图的 C分类和回归。例如,给定一个表示为图形的分子,我们可以预测该分子是否有毒。
接下来,让我们概述一下 GNN 的主要训练框架:
- 监督:所有训练数据都被标记。我们可以在节点、边和图级别应用监督学习。
- 无监督:这里的目标是学习某种形式的图嵌入——例如,使用自动编码器(我们将在本章后面讨论这个场景)。我们可以在节点、边和图级别应用无监督学习。
- 半监督:这通常应用于节点级别,其中一些图节点被标记而一些没有。半监督学习特别适用于图,因为我们可以做出简单(但通常是正确的)假设,即相邻节点可能具有相同的标签。例如,假设我们有两个相邻的连接节点。其中一个包含汽车的图像,另一个包含卡车的图像。假设卡车节点被标记为车辆,而汽车节点未标记。我们可以安全地假设汽车节点也是车辆,因为它靠近另一个车辆节点(卡车)。我们可以通过多种方式在 GNN 中利用此图属性。我们将概述其中两个(它们不是相互排斥的):
- 通过将图的邻接矩阵作为网络的输入来隐式使用此属性。网络将发挥它的魔力,并希望推断出相邻节点可能具有相同的标签,从而通过附加信息提高预测的准确性。我们将在本章中讨论的大多数 GNN 都使用这种机制。
- 标签传播,我们可以使用标记节点作为种子,根据它们与标记节点的接近程度将标签分配给未标记节点。我们可以通过以下步骤以迭代的方式实现收敛:
- 从种子标签开始。
- 对于所有图节点(除了种子),根据其相邻节点的标签分配标签。此步骤为整个图创建一个新的标签配置,其中一些节点可能需要一个新标签,基于修改后的邻居的标签。
- 如果满足收敛标准,则停止标签传播;否则,重复步骤 2。
我们将使用这个对图的简短介绍作为接下来几节的基础,我们将在其中讨论各种类型的以图为中心的 NN 模型。GNN领域相对较新,在计算机视觉中没有完全完美的模型卷积网络( CNN )。相反,我们有具有不同属性的不同模型。它们中的大多数都属于几个一般类别,并且有人尝试创建一个足够通用的框架来组合它们。本书的目的不是发明新模型或模型分类法,而是;相反,我们将向您介绍一些现有的。
循环 GNN
我们将从查看图神经网络(GraphNNs;参见图神经网络模型,https ://ieeexplore.ieee.org/document/4700287)开始本节。尽管论文的作者将模型缩写为 GNN,但我们将使用 GraphNN 的首字母缩写来引用它,以避免与 GNN 的缩写发生冲突,GNN 的缩写是为通用类图网络保留的。这是最早提出的 GNN 模型之一。它扩展了现有的神经网络来处理图形结构数据。就像我们使用单词的上下文(即其周围的单词)来创建嵌入向量(第 6 章,语言建模),我们可以使用一个节点的相邻图节点来做同样的事情。GraphNNs 旨在基于该节点的邻域创建节点v的s维向量状态。与语言建模类似,向量状态可以作为其他任务的输入,例如节点分类。
通过反复交换邻域信息来更新节点的状态,直到达到稳定的平衡。让我们用u表示邻域节点v的集合和该邻域的单个节点。使用以下公式循环更新节点的隐藏状态:
这里,f是参数函数(例如,前馈 NN ( FFNN )),每个状态都是随机初始化的。参数函数f将v的特征向量、其邻居u的特征向量、连接u和v的边的特征向量以及u在步骤t-1的状态向量作为输入。换句话说,f使用了关于v邻域的所有已知信息。表达式是f的总和 应用于所有相邻节点,这允许 GraphNN 独立于邻居的数量及其排序。对于过程的所有步骤,函数f是相同的(即具有相同的权重)。
请注意,我们有一个迭代(或循环)过程,其中步骤t的状态基于直到t-1的步骤数,如下所示:
该过程继续进行,直到达到稳定的平衡。为此,函数f必须是收缩映射。让我们澄清一下:当应用于任意两个点(或值)A 和 B 时,收缩映射函数f满足条件,其中 γ 是标量值,而。换句话说,收缩映射缩小了映射后两点之间的距离。这确保了对于任何初始值,系统都会(以指数方式快速)收敛到平衡状态向量。我们可以将 NN 修改为收缩函数,但这超出了本书的范围。
现在我们有了隐藏状态,我们可以将它用于节点分类等任务。我们可以用下面的公式来表达:
在这个等式中,是达到平衡后的状态,g是参数函数——例如,用于分类任务的带有 softmax 激活的全连接层。
接下来,让我们看看如何训练 GraphNN,给定一组或所有图节点的训练标签t i和大小为m的 mini-batch 。要训练 GraphNN,请执行以下步骤:
1.按照我们刚刚描述的循环过程,对所有m个节点计算和ov 。
2.计算成本函数(t i是节点i的标签):
3.向后传播成本。请注意,将步骤 1 的节点状态更新与当前步骤的梯度传播交替进行,允许 GraphNN 处理循环图。
4.更新组合网络g(f)的权重。
GraphNN 有几个限制,其中之一是计算平衡状态向量效率不高。此外,正如我们在本节前面提到的,GraphNN 使用相同的参数(权重)来更新所有步骤t。相比之下,其他 NN 模型可以使用具有不同权重集的多个堆叠层,这使我们能够捕获数据的层次结构。它还允许我们在单个前向传递中进行计算。最后,值得一提的是,虽然计算是一个循环过程,但 GraphNN 并不是循环网络。
门控图 NN模型(GGNN,https : //arxiv.org/abs/1511.05493)试图在门控循环单元(或GRU)的帮助下克服这些限制,如一个循环函数。我们可以将GGNN定义如下:
在前面的公式中,。澄清一下,GGNN 根据同一步骤t的相邻状态及其先前的隐藏状态更新状态。
从历史的角度来看,GraphNN 是最早的 GNN 模型之一。但正如我们所提到的,它们有一些局限性。在下一节中,我们将讨论卷积图网络,这是最近的发展。
卷积图网络
卷积图网络( ConvGNN ) 使用一堆特殊的图卷积层 (Gconv*) 在更新状态向量时对图的节点执行卷积。与 GraphNN 类似,图卷积采用节点的邻居并产生其向量表示。但是,虽然 GraphNN在计算的所有步骤t上使用相同的层(即相同的权重集),但 ConvGNN 在每一步都使用不同的层。两种方法之间的区别如下图所示:
使用 ConvGNN,步数t由网络的深度定义。尽管我们将从一个稍微不同的角度讨论这个问题,但 ConvGNN 的行为类似于常规FFNN,但具有图卷积。通过堆叠多个层,每个节点的最终隐藏表示从更远的邻域接收消息,如下图所示:
该图显示了两种情况:
-
节点级(顶部),其中每个卷积层(包括最后一个)的输出是图的每个节点的向量。我们可以对这些向量执行节点级操作。
-
图级(底部),交替进行图卷积和池化操作,并以读出层结束,然后是几个全连接层,它们汇总整个图以产生单个输出。
现在我们对ConvGNN有了一个高级概述,在下一节中,我们将讨论图卷积(然后,我们将讨论读出层和池化层)。
基于光谱的卷积
有多种类型的图卷积(查看A Comprehensive Survey on Graph Neural Networks),但在本节中,我们将讨论图卷积网络的半监督分类算法(https://arxiv.org/abs/ 1609.02907)。我们将用 GCN 表示这个卷积,以避免与一般的 ConvGNN 表示法混淆,后者通常指的是图卷积网络。GCN是ConvGNNs的所谓基于谱的类别的代表 . 这些算法通过从图信号处理的角度引入滤波器来定义图卷积,其中图卷积操作被解释为从图信号中去除噪声。
在图神经网络部分,我们定义了隐藏节点状态,并注意到在 GGNN 的情况下。让我们通过将图中所有节点的隐藏向量状态堆叠在一个矩阵中来扩展这个符号,其中n是图中节点的总数,d是特征向量的大小。矩阵的每一行代表单个节点的隐藏状态。然后,我们可以在步骤l+1定义单个 GCN 层的通用公式,如下所示:
这里,A是邻接矩阵,f是非线性激活,比如ReLU,和(特征向量矩阵)。由于和具有相同的大小,因此具有与节点特征矩阵X相同的维度(请参阅图神经网络部分)。然而,其中z是隐藏状态向量的大小,不一定与初始d相同。
让我们继续使用GCN的简化但具体的版本:
这里,是一个权重矩阵,σ 是 sigmoid 函数。由于邻接矩阵A以矩阵形式表示图,我们可以在单个操作中计算层的输出。该操作允许每个节点从其相邻节点接收输入(它还允许 GCN 处理有向图和无向图)。让我们通过一个例子来看看它是如何工作的。我们将使用我们在图神经网络部分介绍的五节点图。 为了便于阅读,我们将为每个节点分配一个一维向量隐藏状态 ,其值等于节点编号。然后我们可以使用以下公式计算示例:
我们可以看到它是如何从节点 2、3 和 5 接收输入的。如果有更多维度,那么输出向量的每个单元格将是输入节点状态向量的相应单元格的总和:
这里,是邻接矩阵的单元。
虽然这个解决方案很优雅,但它有两个限制:
- 并非所有节点都从它们自己的先前状态接收输入。在前面的示例中,只有节点 2 从自身获取输入,因为它有一个循环边(这是将节点连接到自身的边)。这个问题的解决方案是通过将沿邻接矩阵主对角线的所有值设置为 1 来人为地为所有节点创建循环边:。在这个等式中,I是单位矩阵,沿主对角线具有 1,在所有其他单元格中具有 0。
- 由于A未归一化,因此与具有较少邻居数量的节点相比,具有大量邻居的节点的状态向量将以不同的方式改变其规模。我们可以在前面的示例中看到这一点,与其他节点相比,其中更大,因为节点 4 在其附近有 3 个节点。解决这个问题的方法是对邻接矩阵进行归一化,使得一行中所有元素的总和等于 1: 。我们可以通过将A乘以逆度数矩阵D -1来实现这一点。度矩阵D是一个对角矩阵(即除了主对角线之外的所有其他元素都是零),其中包含有关每个节点的度数的信息。我们将节点的邻居数称为该节点的度数。例如,我们示例图的度数矩阵如下:
因此,D -1 A变为:
该机制为每个相邻节点分配相同的权重。在实践中,该论文的作者发现使用对称归一化效果更好。
在我们合并这两个改进之后,GCN公式的最终形式可以写成如下:
请注意,我们刚刚描述的 GCN 仅包含节点的直接邻域作为上下文。每个堆叠层有效地将节点的感受野增加 1,超过其直接邻居。ConvGNN 的第二层的感受野包括直接邻居,第二层的感受野包括距离其两跳的节点当前节点等。
在下一节中,我们将介绍第二大类图卷积操作,称为基于空间的卷积。
带注意力的基于空间的卷积
第二个ConvGNN类别是基于空间的方法,其灵感来自计算机视觉卷积(第 2 章,理解卷积网络 )。我们可以将图像视为一个图形,其中每个像素都是一个节点,直接连接到其相邻像素(下图中的左侧图像)。例如,如果我们使用 3 × 3 作为过滤器,则每个像素的邻域由 8 个像素组成。在图像卷积中,这个 3 × 3 加权滤波器应用于 3 × 3 补丁,结果是所有 9 个像素的强度的加权和。类似地,基于空间的图卷积将中心节点的表示与其相邻节点的表示进行卷积,以得出中心节点的更新表示,如下图右侧的图像所示:
通用的基于空间的卷积有点类似于 GCN,因为这两种操作都依赖于图邻居。GCN 使用逆度矩阵为每个邻居分配权重。空间卷积将卷积滤波器用于相同目的。两者的主要区别在于,在 GCN 的情况下,权重是固定的并且是归一化的,而空间卷积的滤波器权重是可学习的,而不是归一化的。在某种意义上,我们也可以将 GCN 视为一种基于空间的方法。
我们将使用一种特定类型的基于空间的模型继续本节,称为图形注意网络( GAT )(有关更多信息,请访问https://arxiv.org/abs/1710.10903),它使用特殊的方法实现图形卷积图自注意力层。GAT 不是学习卷积滤波器或使用平均邻接矩阵作为 GCN,而是使用自注意力机制的注意力分数来为每个相邻节点分配权重。GAT 层是图注意力网络的主要构建块,由多个堆叠的 GAT 层组成。与 GCN 一样,每个附加层都会增加目标节点的感受野。
与 GCN 类似,GAT 层将一组节点特征向量作为输入,正在上传…重新上传取消并输出一组不同的特征向量,不一定具有相同的基数。按照我们在第 8 章“序列到序列模型和注意力”中概述的过程,该操作首先计算特征向量和邻域的每两个节点之间的对齐分数:
这里,正在上传…重新上传取消是一个权重矩阵,将输入向量转换为输出向量的基数,并提供必要的可学习参数。f a表达式是一个简单的FFN,具有单层和 LeakyReLU 激活,由权重向量参数化并实现加性注意机制:
这里,
带注意力的基于空间的卷积
第二个ConvGNN类别是基于空间的方法,其灵感来自计算机视觉卷积(第 2 章,理解卷积网络 )。我们可以将图像视为一个图形,其中每个像素都是一个节点,直接连接到其相邻像素(下图中的左侧图像)。例如,如果我们使用 3 × 3 作为过滤器,则每个像素的邻域由 8 个像素组成。在图像卷积中,这个 3 × 3 加权滤波器应用于 3 × 3 补丁,结果是所有 9 个像素的强度的加权和。类似地,基于空间的图卷积将中心节点的表示与其相邻节点的表示进行卷积,以得出中心节点的更新表示,如下图右侧的图像所示:
通用的基于空间的卷积有点类似于 GCN,因为这两种操作都依赖于图邻居。GCN 使用逆度矩阵为每个邻居分配权重。空间卷积将卷积滤波器用于相同目的。两者的主要区别在于,在 GCN 的情况下,权重是固定的并且是归一化的,而空间卷积的滤波器权重是可学习的,而不是归一化的。在某种意义上,我们也可以将 GCN 视为一种基于空间的方法。
我们将使用一种特定类型的基于空间的模型继续本节,称为图形注意网络( GAT )(有关更多信息,请访问https://arxiv.org/abs/1710.10903),它使用特殊的方法实现图形卷积图自注意力层。GAT 不是学习卷积滤波器或使用平均邻接矩阵作为 GCN,而是使用自注意力机制的注意力分数来为每个相邻节点分配权重。GAT 层是图注意力网络的主要构建块,由多个堆叠的 GAT 层组成。与 GCN 一样,每个附加层都会增加目标节点的感受野。
与 GCN 类似,GAT 层将一组节点特征向量作为输入,并输出一组不同的特征向量,不一定具有相同的基数。按照我们在第 8 章“序列到序列模型和注意力”中概述的过程,该操作首先计算特征向量和邻域的每两个节点之间的对齐分数:
这里,是一个权重矩阵,将输入向量转换为输出向量的基数,并提供必要的可学习参数。f a表达式是一个简单的FFN,具有单层和 LeakyReLU 激活,由权重向量参数化并实现加性注意机制:
这里,表示串联。如果我们不施加任何限制,每个节点将能够关注图中的所有其他节点,而不管它们与目标节点的距离如何;但是,我们只对相邻节点感兴趣。GAT 的作者建议通过使用 masked attention 来解决这个问题,其中 mask 覆盖了不是目标节点直接邻居的所有节点。我们将用 表示节点i的直接邻居。
接下来,我们使用 softmax 计算注意力分数。以下是通用公式和带有f a的公式(仅适用于直接邻居):
一旦我们有了注意力分数,我们就可以使用它们来计算每个节点的最终输出特征向量(我们在第 8 章,序列到序列模型和注意力中将其称为上下文向量),这是一个加权组合所有邻居的输入特征向量:
这里,σ 是 sigmoid 函数。该论文的作者还发现多头注意力有利于模型的性能:
这里,k是每个head的索引(总共K个head),是每个attention head的attention score,是每个attention head的权重矩阵。由于 是串联的结果,它的基数将为 k × z l+1。因此,在网络的最终注意力层中不可能进行连接。为了解决这个问题,论文的作者建议你应该平均最后一层注意力头的输出(用索引L表示):
下图显示了 GAT 上下文中的常规注意力和多头注意力之间的比较。在左图中,我们可以看到应用在两个节点i和j之间的常规注意机制。在右图中,我们可以看到节点1的k = 3个头及其邻域的多头注意力。聚合的特征要么是连接的(对于所有隐藏的 GAT 层),要么是平均的(对于最终的 GAT 层):
一旦我们有了最终 GAT 层的输出,我们就可以将其用作下一个特定任务层的输入。例如,这可能是一个全连接层,具有用于节点分类的 softmax 激活。
在结束本节专门讨论 ConvGNN 之前,让我们讨论一下我们尚未解决的两个最终组件。第一个是我们在卷积 图 网络部分开头的图级分类示例中介绍的读出层。它将最后一个图卷积层 H ( L )的所有节点状态作为输入,并输出一个概括整个图的向量。我们可以将其正式定义如下:
这里,G代表图节点的集合,R是读出函数。有多种实现方法,但最简单的是采用所有节点状态的元素总和或平均值。
我们将看到的下一个(也是最后一个)ConvGNN 组件是池化操作。再一次,有多种使用方法,但最简单的方法之一是使用与我们在计算机视觉卷积中所做的相同的最大/平均池化操作:
这里,p表示池化窗口的大小。如果池化窗口包含整个图,则池化变得类似于读数。
这结束了我们关于 ConvGNN 的讨论。在下一节中,我们将讨论图形自动编码器,它提供了一种生成新图形的方法。
图形自动编码器
让我们快速回顾一下我们在第 5 章“生成模型”中首次介绍 的自动编码器。自编码器是一个FFN,它试图重现其输入(更准确地说,它试图学习一个恒等函数)。我们可以将自动编码器视为两个组件的虚拟组合——编码器,它将输入数据映射到网络的内部潜在特征空间(表示为向量z),以及解码器,它试图从网络的内部重构输入数据表示。我们可以通过最小化损失函数(称为重建误差)以无监督的方式训练自动编码器,该损失函数测量原始输入与其重建之间的距离。
图自动编码器( GAE ) 类似于自动编码器,区别在于编码器将图节点映射到自动编码器潜在特征空间,然后解码器尝试从中重建特定的图特征。在本节中,我们将讨论变分图自动编码器( https://arxiv.org/abs/1611.07308 ) 中介绍的 GAE 变体,它还概述了 GAE 的变分版本 ( VGAE )。下图显示了一个示例 GAE:
编码器是我们在基于光谱的卷积 部分定义的 GCN 模型,用于计算图节点的网络嵌入,其中 n 个节点中的每一个的嵌入是一个 d维向量 z 。它将邻接矩阵A和一组节点特征向量X作为输入(就像我们在本章中讨论的其他 GNN 模型一样)。编码器由以下公式表示:
这里,W 1和W 2是两个 GCN 图卷积的可学习参数(权重),f是非线性激活函数,类似于 ReLU。该论文的作者使用了两个图卷积层,尽管所提出的算法可以适用于任意数量的层。
解码器尝试重建图邻接矩阵:
这里,σ 是 sigmoid 函数。它首先计算Z与其转置之间的点(或内)积:。为澄清起见,此操作计算每个节点i的向量嵌入z i与图的每个其他节点j的向量嵌入z j的点积,如以下示例所示:
正如我们在第 1 章“神经网络的基本要素”中提到的,我们可以将点积视为向量之间的相似性度量。因此,测量每对可能的节点之间的距离。这些距离是重建工作的基础。在此之后,解码器应用非线性激活函数并继续重建图邻接矩阵。我们可以通过最小化真实重构邻接矩阵之间的差异来训练 GAE。
接下来,让我们关注变分图自动编码器(VGAE)。与我们在第 5 章“生成模型”中讨论的变分自动编码器(VAE)非常相似,VGAE 是一种可以生成新图(更具体地说,是新的邻接矩阵)的生成模型。为了理解这一点,让我们先简要回顾一下 VAE。与常规自动编码器不同,VAE 瓶颈层不会直接输出潜在状态向量。相反,它将输出两个向量,它们描述了潜在向量z分布的均值μ和方差σ 。 我们将使用它们从高斯分布中采样一个与z维度相同 的随机向量ε 。更具体地说,我们将通过潜在分布的均值μ移动 ε 并通过潜在分布的方差σ对其进行缩放:
这种技术被称为重新参数化技巧,它允许随机向量具有与原始数据集相同的均值和方差。
我们可以将 VGAE 视为 GAE 和 VAE 的组合,因为它与图形输入(如 GAE)一起工作,并遵循相同的原则来生成新数据(如 VAE)。首先,让我们关注编码器,它分为两个路径:
这里,权重W 0在路径之间共享,是对称归一化的邻接矩阵,μ是均值向量μ i的矩阵,σ是每个图节点的方差矩阵σ i。然后,全图的编码器推理步骤被定义为所有图节点i的潜在表示的内积:
在这个公式中,n是图中的节点数,表示编码器对真实概率分布的逼近,其中φ是网络参数(这里,我们保留了第 5 章,生成模型的符号)。近似值是具有节点特定平均值μi 和对角协方差值的高斯分布:
接下来,我们定义生成步骤,它创建新的邻接矩阵。它是随机潜在向量的内积:
这里,表示两个节点i 和j 之间是否存在边,表示解码器对真实概率 的近似。我们可以使用已经熟悉的 VAE 成本来训练 VGAE:
这里,第一项是 Kullback-Leibler 散度,第二项是重建成本。
我们对 GAE 和 VGAE 的描述到此结束。在下一节中,我们将讨论另一种图学习范式,它可以将结构化和非结构化数据混合作为网络输入。
神经图学习
在本节中,我们将描述神经图学习范式 ( NGL )(有关更多信息,请参阅神经图学习:使用图训练神经网络https://storage.googleapis.com/pub-tools-public-publication- data/pdf/bbd774a3c6f13f05bf754e09aa45e7aa6faa08a8.pdf),这使得基于结构化信号的非结构化数据增强训练成为可能。更具体地说,我们将讨论基于 TensorFlow 2.0 并实现这些原则的神经结构化学习框架 ( NSL )(有关更多信息,请访问https://www.tensorflow.org/neural_structured_learning/ )。
为了了解 NGL 的工作原理,我们将使用 CORA 数据集 ( Dataset ),该数据集包含2,708 篇科学出版物,分为 7 类中的 1 类(这是非结构化部分数据集)。数据集中所有出版物(即词汇表)中的唯一词数为 1,433。每个出版物都被描述为一个单一的多热编码向量。这是一个大小为 1,433(与词汇表相同)的向量,其中单元格值为 0 或 1。如果出版物包含词汇表的第i个单词,则第i个该出版物的 one-hot 编码向量的第 th 个单元格设置为 1。如果该单词不存在于出版物中,则该单元格设置为 0。此机制保留有关文章中出现的单词的信息,但不保留有关他们的订单。该数据集还包含 5,429 次引用的有向图,其中节点是出版物,它们之间的边表示出版物v是否引用了出版物u(这是数据集的结构化部分)。
接下来,让我们关注 NGL 本身,从下图开始:
它作为常规 NN 训练框架的一种包装器,可以应用于任何类型的网络,包括 FFN 和 RNN。例如,我们可以有一个常规的 FFN,它将 multihot 编码的发布向量作为输入,并尝试使用 softmax 输出将其分类为 7 个类之一,如上图中用绿色不间断线所示。NGL 允许我们使用引用提供的结构化数据来扩展这个网络,如黄色虚线所示。
让我们看看这是如何工作的。我们首先假设图中的相邻节点有些相似。我们可以将这个假设转移到 NN 域,假设样本 i 的 NN 生成的嵌入向量(嵌入是最后一个隐藏层的输出)应该与样本j的嵌入有点相似,前提是两个样本是关联图中的邻居。在我们的示例中,我们可以假设出版物i的嵌入向量应该与出版物j的嵌入相似,前提是其中一个引用了另一个(即,它们是引用图中的邻居)。在实践中,我们可以通过以下步骤来实现:
- 从包含非结构化数据(多热编码出版物)和结构化数据(引文图)的数据集开始。
- 构建特殊类型的复合训练样本(分批组织),其中每个复合样本由单个常规输入样本(一个多热编码出版物)和其相邻样本的K个(引用或被引用的多热编码出版物)组成。初始样本)。
- 将复合样本馈送到 NN 并为初始样本及其邻居生成嵌入。尽管上图显示了两条并行运行的路径,但事实并非如此。该图旨在说明网络同时处理中心样本及其邻居,但实际的 NN 并不知道这种安排——它只是将所有多热编码输入作为单个批次的一部分并处理它们。相反,常规 NN 之上的 NSL 部分区分了这两个组件。
- 计算一种特殊类型的复合损失函数,由两部分组成:常规监督损失和正则化邻居损失,它使用度量来衡量初始样本嵌入与其邻居嵌入之间的距离。邻居损失是允许我们用结构化信号增强非结构化训练数据的机制。复合损失定义如下:
该公式具有以下特点:
- n是小批量中的复合样本数。
- 是监督损失函数。
- f θ是权重为 θ 的 NN 函数。
- α是一个标量参数,它决定了两个损失分量之间的相对权重。
- 是样本x i的图邻居集。请注意,邻居损失迭代图的所有节点的所有邻居(两个总和)。
- 是样本i和j之间图边的权重。如果任务没有权重的概念,我们可以假设所有的权重都是 1。
- 是样本i和j的嵌入向量之间的距离度量。
由于邻居损失的正则化性质,NGL 也被称为图正则化。
5.向后传播误差并更新网络权重θ。
现在我们对图正则化有了一个概述,让我们来实现它。
实现图正则化
在本节中,我们将借助 NSL 框架在 Cora 数据集上实现图正则化。此示例基于https://www.tensorflow.org/neural_structured_learning/tutorials/graph_keras_mlp_cora上提供的教程。在我们继续实施之前,我们必须满足一些先决条件。首先,我们需要 TensorFlow 2.0 和neural-structured-learning1.1.0 包(可通过 获取pip)。
一旦我们满足这些要求,我们就可以继续实施:
1.我们将从包导入开始:
-
import neural_structured_learning
as nsl
-
import tensorflow
as tf
2.我们将继续使用程序的一些常量参数(希望常量名称和注释说明一切):
-
# Cora 数据集路径
-
TRAIN_
DATA_PATH
=
'data/train_merged_examples.tfr'
-
TEST_
DATA_PATH
=
'data/test_examples.tfr'
-
# 用于识别输入中相邻特征的常量
-
NBR_FEATURE_PREFIX
=
'NL_nbr_'
-
NBR_WEIGHT_SUFFIX
=
'_weight'
-
# 数据集参数
-
NUM_CLASSES
=
7
-
MAX_SEQ_
LENGTH
=
1433
-
# 在复合损失函数中要考虑的邻居数
-
NUM_NEIGHBORS
=
1
-
# 训练参数
-
BATCH_
SIZE
=
128
包含Cora 数据集和标签下的文件,TRAIN_DATA_PATH并以 TensorFlow 友好格式进行了预处理。TEST_DATA_PATH
3.接下来,让我们加载数据集。这个过程是通过使用两个函数来实现的:make_dataset构建整个数据集,以及parse_example解析单个复合样本(内部make_dataset使用parse_example)。我们将从make_dataset:
-
def make_dataset(
file_path: str, training
=
False) -
> tf.
data.TFRecordDataset:
-
dataset
= tf.
data.TFRecordDataset([
file_path])
-
if training:
-
dataset
= dataset.shuffle(
10000)
-
dataset
= dataset.map(parse_example).batch(BATCH_
SIZE)
-
-
return dataset
请注意,dataset.map(parse_example)内部适用parse_example于数据集的所有样本。让我们继续定义parse_example,从声明开始:
def parse_example(example_proto: tf.train.Example) -> tuple:
该函数feature_spec为单个复合样本创建表示一种模板的字典,该样本稍后会填充来自数据集的实际数据。首先,我们填充f或feature_spec的占位符实例,它表示一个多热编码的出版物,以及,它表示出版物的类别(请记住缩进,因为此代码仍然是 的一部分):tf.io.FixedLenFeature'words' 'label'parse_example
-
feature_spec
= {
-
'words':
-
tf.io.FixedLenFeature(shape
=[MAX_SEQ_
LENGTH],
-
dtype
=tf.int
64,
-
default_
value
=tf.
constant(
-
value
=
0,
-
dtype
=tf.int
64,
-
shape
=[MAX_SEQ_
LENGTH])),
-
'label':
-
tf.io.FixedLenFeature((), tf.int
64,
default_
value
=-
1),
-
}
然后,我们迭代第一个NUM_NEIGHBORS邻居并将它们的多热向量和边缘权重分别添加到和键feature_spec下:nbr_feature_keynbr_weight_key
-
for i
in range(NUM_NEIGHBORS):
-
nbr_feature_
key
=
'{}{}_{}'.
format(NBR_FEATURE_PREFIX, i,
'words')
-
nbr_weight_
key
=
'{}{}{}'.
format(NBR_FEATURE_PREFIX, i, NBR_WEIGHT_SUFFIX)
-
feature_spec[nbr_feature_
key]
= tf.io.FixedLenFeature(
-
shape
=[MAX_SEQ_
LENGTH],
-
dtype
=tf.int
64,
-
default_
value
=tf.
constant(
-
value
=
0, dtype
=tf.int
64, shape
=[MAX_SEQ_
LENGTH]))
-
-
feature_spec[nbr_weight_
key]
= tf.io.FixedLenFeature(
-
shape
=[
1], dtype
=tf.float
32,
default_
value
=tf.
constant([
0.0]))
-
-
features
= tf.io.parse_single_example(example_proto, feature_spec)
-
-
labels
= features.pop(
'label')
-
return features, labels
请注意,我们使用以下代码片段从数据集中使用真实样本填充模板:
features = tf.io.parse_single_example(example_proto, feature_spec)
4.现在,我们可以实例化训练和测试数据集:
-
train_dataset
= make_dataset(TRAIN_
DATA_PATH, training
=
True)
-
test_dataset
= make_dataset(
TEST_
DATA_PATH)
5.接下来,让我们实现模型,它是一个简单的 FFN,有两个隐藏层和 softmax 作为输出。该模型将多热编码的发布向量作为输入并输出发布类。它独立于 NSL,可以通过简单的监督方式进行训练,作为一个分类:
-
def
build_model(
dropout_rate):
-
"""创建一个顺序多层感知器模型。"""
-
return tf.keras.Sequential([
-
# one-hot 编码输入
-
tf.keras.layers.InputLayer(
-
input_shape=(MAX_SEQ_LENGTH,), name=
'words'),
-
-
# 2 全连接层 + dropout
-
tf.keras.layers.Dense(
64, activation=
'relu'),
-
tf.keras.layers.Dropout(dropout_rate),
-
tf.keras.layers.Dense(
64, activation=
'relu'),
-
tf.keras.layers.Dropout(dropout_rate),
-
-
# Softmax 输出
-
tf.keras.layers.Dense(NUM_CLASSES, activation=
'softmax')
-
])
6.接下来,让我们实例化模型:
model = build_model(dropout_rate=0.5)
7.我们拥有使用图正则化所需的所有要素。我们将从model使用 NSL 包装器包装 开始:
-
graph_reg_config
= nsl.configs.make_graph_reg_config(
-
max_neighbors
=NUM_NEIGHBORS,
-
multiplier
=
0.1,
-
distance_
type
=nsl.configs.DistanceType.L
2,
-
sum_over_axis
=-
1)
-
graph_reg_model
= nsl.keras.GraphRegularization(model,
-
graph_reg_config)
我们用图正则化参数实例化graph_reg_config对象( 的一个实例):是要使用的邻居的数量,相当于我们在神经结构化学习部分中介绍的复合损失的参数α ,并且是相邻节点嵌入。nsl.configs.GraphRegConfigmax_neighbors=NUM_NEIGHBORSmultiplier=0.1distance_type=nsl.configs.DistanceType.L2
8.接下来,我们可以构建一个训练框架并启动 100 个 epoch 的训练:
-
graph_reg_model.compile(
-
optimizer
=
'adam',
-
loss
=
'sparse_categorical_crossentropy',
-
metrics
=[
'accuracy'])
-
-
# 急切运行以防止 epoch 警告
-
graph_reg_model.
run_eagerly
=
True
-
-
graph_reg_model.fit(train_dataset, epochs
=
100, verbose
=
1)
9.训练完成后,我们可以在测试数据集上运行训练好的模型:
-
eval_results = dict(
-
zip(
graph_reg_model.metrics_names,
-
graph_reg_model.evaluate(
test_dataset)))
-
print('Evaluation accuracy: {}'.format(
eval_results['accuracy']))
-
print('Evaluation loss: {}'.format(
eval_results['loss']))
如果一切顺利,程序的输出应该是:
Evaluation accuracy: 0.8137432336807251 Evaluation loss: 1.1235489577054978
我们关于 GNN 的讨论到此结束。正如我们所提到的,有多种类型的 GNN,我们在这里只包括了一小部分。如果您有兴趣了解更多信息,我建议您参考我们在本节开头介绍的调查论文或在https://github.com/thunlp/GNNPapers查看以下 GNN 相关论文的精选列表。
在下一节中,我们将讨论一种使用外部存储器存储信息的新型 NN。
介绍记忆增强神经网络
我们已经在 NN 中看到了记忆的概念(尽管形式很奇怪)——例如,LSTM 单元可以在输入和遗忘门的帮助下添加或删除关于其隐藏单元状态的信息。另一个例子是注意力机制,其中表示编码源序列的向量集可以被视为由编码器写入并由解码器读取的外部存储器。但是这种能力有一些限制。一方面,编码器只能写入单个内存位置,即序列的当前元素。它也不能更新以前写的向量。另一方面,解码器只能从数据库中读取,而不能写入。
在本节中,我们将把记忆的概念更进一步,看看解决了这些限制的记忆增强神经网络( MANN )。这是一类新的算法,仍处于早期阶段,与已经存在数十年的更主流的 NN 类型(例如卷积和 RNN)不同。我们将讨论的第一个 MANN 网络是神经图灵机。
神经图灵机
MANN 的概念最初是与神经图灵机( NTM ) 的概念一起引入的(有关更多信息,请访问 https://arxiv.org/abs/1410.5401)。NTM 有两个组件:
- 一个神经网络控制器。
- 一个外部存储器,表示为一个矩阵。该矩阵包含n行d维向量。
下图提供了 NTM 架构的概述:
NTM 以顺序方式工作(如 RNN),其中控制器获取输入向量并生成输出向量作为响应。它还借助多个并行读/写头读取和写入内存。
让我们专注于读取操作,这与我们在第 8 章,序列到序列模型和注意力中看到的注意力机制非常相似。读取头始终读取完整的内存矩阵,但它通过关注具有不同强度的不同内存向量来做到这一点。为此,读取头发出一个n维向量(在步骤t处),具有以下约束:
实现了一种注意力机制,其中向量的每个单元格i表示第i个记忆向量(即矩阵M的第i行)在形成输出时的权重。步骤t的读取操作的输出是d维向量r t,定义为所有内存向量的加权和:
这个操作类似于我们在第 8 章,序列到序列模型和注意力中讨论的软注意力机制。软注意力(与硬注意力不同)是可微的,这个操作也是如此。通过这种方式,整个 NTM(控制器和内存)是一个单一的可微系统,这使得使用梯度下降和反向传播来训练它成为可能。
接下来,让我们关注写入操作,它由两个步骤组成:擦除后添加。写头发出与读头相同类型的注意力向量。它还发出另一个擦除向量,其值都在 (0, 1) 范围内。我们可以根据这两个向量和步骤t-1的内存状态,将内存中单行i上的步骤t的擦除操作定义为:
这里,1是 1 的d维向量,并且擦除分量之间的乘法是基于元素的。根据这个公式,只有当权重和e t都非零时,才能擦除内存位置。这种机制可以与以任意顺序写入的多个注意力头一起使用,因为乘法是可交换的。
擦除操作之后是添加操作。写头产生一个添加向量,在擦除后将其添加到内存中,以在步骤t产生最终的内存状态:
我们现在已经熟悉了读写操作,但是我们仍然不知道如何产生注意力向量(我们将省略上标索引,因为下面的描述适用于读写头)。NTM 使用两种互补的寻址机制来做到这一点:基于内容的和基于位置的。
我们将从基于内容的寻址开始,其中每个头(读取和写入)都会发出一个密钥向量。使用相似性度量将该向量与每个内存向量进行比较。NTM 作者建议使用余弦相似度,定义如下:
然后,我们将基于内容的寻址向量的单个单元定义为对所有内存向量的相似性结果的 softmax:
这里,是一个标量值键强度,它扩大或缩小了焦点的范围。对于较小的值,注意力将分散到所有内存向量上,对于较大的值,注意力将仅集中在最相似的内存向量上。
NTM 的作者认为,在某些问题中,基于内容的注意力是不够的,因为变量的内容可以是任意的,但它的地址必须是可识别的。他们引用算术问题作为此类问题之一:两个变量x和y可以取任意两个值,但仍应定义过程f(x, y) = x × y 。此任务的控制器可以获取变量x和y的值,将它们存储在不同的地址中,然后检索它们并执行乘法算法。在这种情况下,变量是按位置而不是按内容寻址的,这将我们带到了基于位置的寻址机制。它适用于随机存取内存跳转和跨位置的简单迭代。它通过将注意力权重向前或向后移动一步来做到这一点。
例如,如果当前权重完全集中在单个位置,旋转 1 会将焦点转移到下一个位置。负移将使权重向相反方向移动。
内容和位置寻址结合使用,如下图所示:
让我们一步一步看看它是如何工作的:
- 内容寻址根据内存、密钥向量和密钥强度生成内容寻址向量。
- 插值是位置寻址机制中三个步骤中的第一步,它发生在实际的权重转移之前。每个磁头(读或写)在 (0, 1) 范围内发出一个标量插值门 g t 。g t 指示是保留头部在步骤t-1产生的权重还是将其替换为当前步骤t 的基于内容的权重。插值定义如下:
如果g t = 0,那么我们将完全保留先前的寻址向量。或者,如果g t = 1,我们将只使用基于内容的寻址向量。
- 下一步是卷积移位,它需要插值注意力并确定如何移位。让我们假设头部注意力可以向前(+1)、向后(-1)或保持不变(0)。每个头发出一个班次权重s t,它定义了允许班次上的归一化分布。在这种情况下,s t将具有三个元素,它们表示执行-1、0 和1 的移位的程度。如果我们假设内存向量索引是基于 0 的(从 0 到n-1),那么我们可以将s t的旋转定义为循环卷积:
请注意,尽管我们遍历所有内存索引,但s t将仅在允许的位置具有非零值。
- 最后的寻址步骤是锐化步骤。一方面,在多个方向上同时以不同程度移动的能力的影响是注意力可能会模糊。例如,假设我们以 0.6 的概率向前移动(+1),以 0.2 的概率向后移动(-1),以 0.2 的概率不移动(0)。当我们应用移位时,最初的注意力将在三个位置之间模糊。为了解决这个问题,NTM 的作者建议您修改每个头以发出另一个标量,这将使用以下公式锐化最终结果:
现在我们知道寻址是如何工作的,让我们关注控制器,我们可以使用 RNN(例如 LSTM)或 FFN。NTM 的作者认为,LSTM 控制器具有内部存储器,它与外部存储器互补,还允许控制器混合来自多个时间步的信息。然而,在 NTM 的上下文中,FFN 控制器可以通过在每一步读取和写入相同的内存位置来模仿 RNN。此外,FFN 更透明,因为它的读/写模式比内部 RNN 状态更容易解释。
该论文的作者说明了 NTM 如何处理多个任务,其中之一是复制操作,其中 NTM 必须将输入序列复制为输出。该任务说明了模型长时间存储和访问信息的能力。输入序列具有 1 到 20 之间的随机长度。序列的每个元素都是一个具有八个二进制元素(代表一个字节)的向量。首先,模型逐步获取输入序列,直到达到一个特殊的分隔符。然后,它开始生成输出序列。在生成阶段不提供额外的输入,以确保模型可以在没有中间帮助的情况下生成整个序列。作者比较了基于 NTM 和 LSTM 的模型的性能,并注意到 NTM 在训练期间收敛速度更快,并且与 LSTM 相比可以复制更长的序列。基于这些结果,并在检查控制器和内存的交互之后,他们得出结论,NTM 不只是简单地记住输入序列。相反,它学习了一种复制算法。我们可以用以下伪代码描述算法的操作顺序:
接下来,我们从控制器和内存交互的角度来关注拷贝算法,如下图所示:
左列显示输入相位。左上图表示 8 位二进制向量的输入序列,左中图表示添加到内存中的向量,左下图表示每一步的内存写入注意力权重。右列显示输出相位。右上图表示生成的 8 位二进制向量的输出序列,右中图表示从内存中读取的向量,右下图表示每一步的内存读取注意力权重。底部图像说明了写入和读取操作期间磁头位置的增量移位。请注意,注意力权重显然集中在单个内存位置。同时,每个时间步从同一位置读取的输入和输出序列,读向量和写向量是等价的。这表明输入序列的每个元素都存储在单个内存位置。
在结束本节之前,让我们提一下 NTM 的作者已经发布了一种改进的内存网络架构,称为差分神经计算机( DNC )(有关更多信息,请参阅使用具有动态外部内存的神经网络的混合计算,网址为https:// www.nature.com/articles/nature20101)。DNC 对 NTM 进行了多项改进:
- 该模型仅使用基于内容的寻址(与 NTM 中的内容和位置相反)。
- 该模型通过在链表中添加和删除位置来维护可用内存位置的列表(这仍然是可微的),从而使用动态内存分配。这种机制允许模型仅在标记为空闲的位置写入新数据。
- 该模型通过维护有关控制器写入的内存位置顺序的信息来使用时间内存链接,这允许它在不同的内存位置存储顺序数据。
我们对 NTM 架构的描述到此结束。在下一节中,我们将讨论在One-shot Learning with Memory-Augmented Neural Networks论文 ( https://arxiv.org/abs/1605.06065 ) 中介绍的对 NTM 的改进。我们将使用 MANN* 表示改进的架构,以避免与 MANN 首字母缩写词混淆,该首字母缩写词引用了一般类的内存网络。
MANN*
MANN* 读取操作与 NTM 读取操作非常相似,不同之处在于它不包含密钥强度参数。另一方面,MANN* 引入了一种新的基于内容的写入寻址机制,称为最近最少使用访问( LRUA ),以替代组合的内容/位置 NTM 寻址机制 . LRUA 写操作写入最少使用的内存位置或最近使用的内存位置。实现这一点有两个原因:通过将新内存写入最不使用的位置来保存最近存储的信息,以及通过将新数据写入最后使用的位置,新信息用作对先前写入状态的一种更新. 但是模型如何知道要使用这两个选项中的哪一个呢?MANN* 寻址机制通过引入使用权重向量在两个选项之间进行插值。这些权重在每个时间步更新,方法是将步骤t-1的使用权重与当前的读写注意力权重相加:
这里,标量 γ 是一个衰减参数,它决定了方程的两个分量之间的平衡。MANN* 还引入了最近最少使用的权重向量,其中向量的每个元素定义如下:
这里,是向量的第n个最小元素,n等于内存读取的次数。此时,我们可以计算写入权重,这是读取权重和步骤t-1中最近最少使用的权重之间的插值:
这里,σ 是 sigmoid 函数,α 是一个可学习的标量参数,表示如何在 2 个输入权重之间进行平衡。现在,我们可以将新数据写入内存,这分两步完成:第一步是使用权重计算最近最少使用的位置。第二步是实际的写法:
这里,是我们在讨论 NTM 时定义的关键向量。
MANN* 论文更详细地介绍了控制器与输入数据和读/写头交互的方式(与原始 NTM 论文相比)。该论文的作者指出,他们表现最好的模型使用 LSTM (参见第7章,理解循环网络)控制器。因此,以下是 LSTM 控制器如何插入 MANN* 系统:
- 步骤t的控制器输入是级联向量,其中 xt 是输入数据,yt-1 是步骤t-1的系统输出。在分类任务中,输出yt 是 one-hot 编码的类表示。
- 步骤t的控制器输出是连接的,其中ht 是 LSTM 单元隐藏状态,rt 是读取操作的结果。对于分类任务,我们可以使用ot 带有 softmax 输出的全连接层作为输入,得到表达式,其中Wo 是全连接层的权重。
- 作为读/写操作的注意力权重Kt 的基础的关键向量是 LSTM 单元状态ct 。
这结束了我们对 MANN 的讨论,实际上也结束了这一章。
概括
在本章中,我们介绍了两类新兴的 NN 模型——GNN 和 MANN。我们从对图的简短介绍开始,然后研究了几种不同类型的 GNN,包括 GraphNN、图卷积网络、图注意力网络和图自动编码器。我们通过查看 NGL 结束了图表部分,并使用基于 TensorFlow 的 NSL 框架实现了一个 NGL 示例。然后我们专注于内存增强网络,我们研究了 NTM 和 MANN* 架构。