从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (一)
本文属于图神经网络的系列文章,文章目录如下:
- 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (一)
- 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (二)
- 从图(Graph)到图卷积(Graph Convolution):漫谈图神经网络模型 (三)
笔者最近看了一些图与图卷积神经网络的论文,深感其强大,但一些Survey或教程默认了读者对图神经网络背景知识的了解,对未学过信号处理的读者不太友好。同时,很多教程只讲是什么,不讲为什么,也没有梳理清楚不同网络结构的区别与设计初衷(Motivation)。
因此,本文试图沿着图神经网络的历史脉络,从最早基于不动点理论的图神经网络(Graph Neural Network, GNN)一步步讲到当前用得最火的图卷积神经网络(Graph Convolutional Neural Network, GCN), 期望通过本文带给读者一些灵感与启示。
- 本文的提纲与叙述要点主要参考了3篇图神经网络的Survey,分别是来自IEEE Fellow的A Comprehensive Survey on Graph Neural Networks[1] 来自清华大学朱文武老师组的Deep Learning on Graphs: A Survey[7],以及来自清华大学孙茂松老师组的Graph Neural Networks: A Review of Methods and Applications[14],在这里向三篇Survey的作者表示敬意。
- 同时,本文关于部分图卷积神经网络的理解很多都是受到知乎问题[8]高赞答案的启发,非常感谢他们的无私分享!
- 最后,本文还引用了一些来自互联网的生动形象的图片,在这里也向这些图片的作者表示感谢。本文中未注明出处的图片均为笔者制作,如需转载或引用请联系本人。
历史脉络
在开始正文之前,笔者先带大家回顾一下图神经网络的发展历史。不过,因为图神经网络的发展分支非常之多,笔者某些叙述可能并不全面,一家之言仅供各位读者参考:
- 图神经网络的概念最早在2005年提出。2009年Franco博士在其论文 [2]中定义了图神经网络的理论基础,笔者呆会要讲的第一种图神经网络也是基于这篇论文。
- 最早的GNN主要解决的还是如分子结构分类等严格意义上的图论问题。但实际上欧式空间(比如像图像 Image)或者是序列(比如像文本 Text),许多常见场景也都可以转换成图(Graph),然后就能使用图神经网络技术来建模。
- 2009年后图神经网络也陆续有一些相关研究,但没有太大波澜。直到2013年,在图信号处理(Graph Signal Processing)的基础上,Bruna(这位是LeCun的学生)在文献 [3]中首次提出图上的基于频域(Spectral-domain)和基于空域(Spatial-domain)的卷积神经网络。
- 其后至今,学界提出了很多基于空域的图卷积方式,也有不少学者试图通过统一的框架将前人的工作统一起来。而基于频域的工作相对较少,只受到部分学者的青睐。
- 值得一提的是,图神经网络与图表示学习(Represent Learning for Graph)的发展历程也惊人地相似。2014年,在word2vec [4]的启发下,Perozzi等人提出了DeepWalk [5],开启了深度学习时代图表示学习的大门。更有趣的是,就在几乎一样的时间,Bordes等人提出了大名鼎鼎的TransE [6],为知识图谱的分布式表示(Represent Learning for Knowledge Graph)奠定了基础。
图神经网络(Graph Neural Network)
首先要澄清一点,除非特别指明,本文中所提到的图均指图论中的图(Graph)。它是一种由若干个结点(Node)及连接两个结点的边(Edge)所构成的图形,用于刻画不同结点之间的关系。下面是一个生动的例子,图片来自论文[14]:
状态更新与输出
最早的图神经网络起源于Franco博士的论文[2], 它的理论基础是不动点理论。给定一张图 \(G\),每个结点都有其自己的特征(feature), 本文中用\(\mathbf{x}_v\)表示结点v的特征;连接两个结点的边也有自己的特征,本文中用\(\mathbf{x}_{(v,u)}\)表示结点v与结点u之间边的特征;GNN的学习目标是获得每个结点的图感知的隐藏状态 \(\mathbf{h}_v\)(state embedding),这就意味着:对于每个节点,它的隐藏状态包含了来自邻居节点的信息。那么,如何让每个结点都感知到图上其他的结点呢?GNN通过迭代式更新所有结点的隐藏状态来实现,在\(t+1\)时刻,结点\(v\)的隐藏状态按照如下方式更新:
上面这个公式中的 \(f\) 就是隐藏状态的状态更新函数,在论文中也被称为局部转移函数(local transaction function)。公式中的\(𝐱_𝑐𝑜[𝑣]\)指的是与结点\(v\)相邻的边的特征,\(𝐱_𝑛𝑒[𝑣]\)指的是结点\(v\)的邻居结点的特征,\(𝐡^t_𝑛𝑒[𝑣]\)则指邻居结点在\(t\)时刻的隐藏状态。注意 \(f\) 是对所有结点都成立的,是一个全局共享的函数。那么怎么把它跟深度学习结合在一起呢?聪明的读者应该想到了,那就是利用神经网络(Neural Network)来拟合这个复杂函数 \(f\)。值得一提的是,虽然看起来 \(f\) 的输入是不定长参数,但在 \(f\) 内部我们可以先将不定长的参数通过一定操作变成一个固定的参数,比如说用所有隐藏状态的加和来代表所有隐藏状态。我们举个例子来说明一下:
假设结点\(5\)为中心结点,其隐藏状态的更新函数如图所示。这个更新公式表达的思想自然又贴切:不断地利用当前时刻邻居结点的隐藏状态作为部分输入来生成下一时刻中心结点的隐藏状态,直到每个结点的隐藏状态变化幅度很小,整个图的信息流动趋于平稳。至此,每个结点都“知晓”了其邻居的信息。状态更新公式仅描述了如何获取每个结点的隐藏状态,除它以外,我们还需要另外一个函数 \(g\) 来描述如何适应下游任务。举个例子,给定一个社交网络,一个可能的下游任务是判断各个结点是否为水军账号。
在原论文中,\(g\) 又被称为局部输出函数(local output function),与 \(f\) 类似,\(g\) 也可以由一个神经网络来表达,它也是一个全局共享的函数。那么,整个流程可以用下面这张图表达:
仔细观察两个时刻之间的连线,它与图的连线密切相关。比如说在 \(T_1\) 时刻,结点 1 的状态接受来自结点 3 的上一时刻的隐藏状态,因为结点 1 与结点 3相邻。直到 \(T_n\) 时刻,各个结点隐藏状态收敛,每个结点后面接一个 \(g\) 即可得到该结点的输出 \(\mathbf{o}\)。
对于不同的图来说,收敛的时刻可能不同,因为收敛是通过两个时刻\(p\)-范数的差值是否小于某个阈值 \(\epsilon\)来判定的,比如:
实例:化合物分类
下面让我们举个实例来说明图神经网络是如何应用在实际场景中的,这个例子来源于论文[2]。假设我们现在有这样一个任务,给定一个环烃化合物的分子结构(包括原子类型,原子键等),模型学习的目标是判断其是否有害。这是一个典型的二分类问题,一个训练样本如下图所示:
由于化合物的分类实际上需要对整个图进行分类,在论文中,作者将化合物的根结点的表示作为整个图的表示,如图上红色的结点所示。Atom feature 中包括了每个原子的类型(Oxygen, 氧原子)、原子自身的属性(Atom Properties)、化合物的一些特征(Global Properties)等。把每个原子看作图中的结点,原子键视作边,一个分子(Molecule)就可以看作一张图。在不断迭代得到根结点氧原子收敛的隐藏状态后,在上面接一个前馈神经网络作为输出层(即\(g\)函数),就可以对整个化合物进行二分类了。
当然,在同构图上根据策略选择同一个根结点对结果也非常重要。但在这里我们不关注这部分细节,感兴趣的读者可以阅读原文。
不动点理论
在本节的开头我们就提到了,GNN的理论基础是不动点(the fixed point)理论,这里的不动点理论专指巴拿赫不动点定理(Banach's Fixed Point Theorem)。首先我们用 \(F\) 表示若干个 \(f\) 堆叠得到的一个函数,也称为全局更新函数,那么图上所有结点的状态更新公式可以写成:
不动点定理指的就是,不论\(\mathbf{H}^0\)是什么,只要 \(F\) 是个压缩映射(contraction map),\(\mathbf{H}^{0}\)经过不断迭代都会收敛到某一个固定的点,我们称之为不动点。那压缩映射又是什么呢,一张图可以解释得明明白白:
上图的实线箭头就是指映射 \(F\), 任意两个点 \(x,y\) 在经过 \(F\) 这个映射后,分别变成了 \(F(x),F(y)\)。压缩映射就是指,\(𝑑(𝐹(𝑥),𝐹(𝑦))≤𝑐𝑑(𝑥,𝑦), 0≤𝑐<1\)。也就是说,经过 \(F\) 变换后的新空间一定比原先的空间要小,原先的空间被压缩了。想象这种压缩的过程不断进行,最终就会把原空间中的所有点映射到一个点上。
那么肯定会有读者心存疑问,既然 \(f\) 是由神经网络实现的,我们该如何实现它才能保证它是一个压缩映射呢?我们下面来谈谈 \(f\) 的具体实现。
具体实现
在具体实现中, \(f\) 其实通过一个简单的前馈神经网络(Feed-forward Neural Network)即可实现。比如说,一种实现方法可以是把每个邻居结点的特征、隐藏状态、每条相连边的特征以及结点本身的特征简单拼接在一起,在经过前馈神经网络后做一次简单的加和。
那我们如何保证 \(f\) 是个压缩映射呢,其实是通过限制 \(f\) 对 \(\mathbf{H}\) 的偏导数矩阵的大小,这是通过一个对雅可比矩阵(Jacobian Matrix)的惩罚项(Penalty)来实现的。在代数中,有一个定理是: \(f\) 为压缩映射的等价条件是 \(f\) 的梯度/导数要小于1。这个等价定理可以从压缩映射的形式化定义导出,我们这里使用 \(||x||\) 表示 \(x\) 在空间中的范数(norm)。范数是一个标量,它是向量的长度或者模,\(||x||\) 是 \(x\) 在有限空间中坐标的连续函数。这里把 \(x\) 简化成1维的,坐标之间的差值可以看作向量在空间中的距离,根据压缩映射的定义,可以导出:
推广一下,即得到雅可比矩阵的罚项需要满足其范数小于等于\(c\)等价于压缩映射的条件。根据拉格朗日乘子法,将有约束问题变成带罚项的无约束优化问题,训练的目标可表示成如下形式:
其中\(\lambda\)是超参数,与其相乘的项即为雅可比矩阵的罚项。
模型学习
上面我们花一定的篇幅搞懂了如何让 \(f\) 接近压缩映射,下面我们来具体叙述一下图神经网络中的损失 \(Loss\) 是如何定义,以及模型是如何学习的。
仍然以社交网络举例,虽然每个结点都会有隐藏状态以及输出,但并不是每个结点都会有监督信号(Supervision)。比如说,社交网络中只有部分用户被明确标记了是否为水军账号,这就构成了一个典型的结点二分类问题。
那么很自然地,模型的损失即通过这些有监督信号的结点得到。假设监督结点一共有 \(p\) 个,模型损失可以形式化为:
那么,模型如何学习呢?根据前向传播计算损失的过程,不难推出反向传播计算梯度的过程。在前向传播中,模型:
- 调用 \(f\) 若干次,比如 \(T_n\)次,直到 \(\mathbf{h}^{T_{n}}_v\) 收敛。
- 此时每个结点的隐藏状态接近不动点的解。
- 对于有监督信号的结点,将其隐藏状态通过 \(g\) 得到输出,进而算出模型的损失。
根据上面的过程,在反向传播时,我们可以直接求出 \(f\) 和 \(g\) 对最终的隐藏状态 \(\mathbf{h}^{T_{n}}_v\) 的梯度。然而,因为模型递归调用了 \(f\) 若干次,为计算 \(f\) 和 \(g\) 对最初的隐藏状态 \(\mathbf{h}_v^0\) 的梯度,我们需要同样递归式/迭代式地计算 \(T_n\) 次梯度。最终得到的梯度即为 \(f\) 和 \(g\) 对 \(\mathbf{h}_v^0\) 的梯度,然后该梯度用于更新模型的参数。这个算法就是 Almeida-Pineda 算法[9]。
GNN与RNN
相信熟悉 RNN/LSTM/GRU 等循环神经网络的同学看到这里会有一点小困惑,因为图神经网络不论是前向传播的方式,还是反向传播的优化算法,与循环神经网络都有点相像。这并不是你的错觉,实际上,图神经网络与到循环神经网络确实很相似。为了清楚地显示出它们之间的不同,我们用一张图片来解释这两者设计上的不同:
假设在GNN中存在三个结点\(x_1\),\(x_2\),\(x_3\),相应地,在RNN中有一个序列\((x_1,x_2,x_3)\)。笔者认为,GNN与RNN的区别主要在于4点:
- GNN的基础理论是不动点理论,这就意味着GNN沿时间展开的长度是动态的,是根据收敛条件确定的,而RNN沿时间展开的长度就等于序列本身的长度。
- GNN每次时间步的输入都是所有结点 \(v\) 的特征,而RNN每次时间步的输入是该时刻对应的输入。同时,时间步之间的信息流也不相同,前者由边决定,后者则由序列的读入顺序决定。
- GNN采用 AP 算法反向传播优化,而RNN使用BPTT(Back Propogation Through Time)优化。前者对收敛性有要求,而后者对收敛性是没有要求的。
- GNN循环调用 \(f\) 的目标是得到每个结点稳定的隐藏状态,所以只有在隐藏状态收敛后才能输出;而RNN的每个时间步上都可以输出,比如语言模型。
不过鉴于初代GNN与RNN结构上的相似性,一些文章中也喜欢把它称之为 Recurrent-based GNN,也有一些文章会把它归纳到 Recurrent-based GCN中。之后读者在了解 GCN后会理解为什么人们要如此命名。
GNN的局限
初代GNN,也就是基于循环结构的图神经网络的核心是不动点理论。它的核心观点是通过结点信息的传播使整张图达到收敛,在其基础上再进行预测。收敛作为GNN的内核,同样局限了其更广泛的使用,其中最突出的是两个问题:
- GNN只将边作为一种传播手段,但并未区分不同边的功能。虽然我们可以在特征构造阶段(\(\mathbf{x}_{(u,v)}\))为不同类型的边赋予不同的特征,但相比于其他输入,边对结点隐藏状态的影响实在有限。并且GNN没有为边设置独立的可学习参数,也就意味着无法通过模型学习到边的某些特性。
- 如果把GNN应用在图表示的场景中,使用不动点理论并不合适。这主要是因为基于不动点的收敛会导致结点之间的隐藏状态间存在较多信息共享,从而导致结点的状态太过光滑(Over Smooth),并且属于结点自身的特征信息匮乏(Less Informative)。
下面这张来自维基百科[13]的图可以形象地解释什么是 Over Smooth,其中我们把整个布局视作一张图,每个像素点与其上下左右以及斜上下左右8个像素点相邻,这决定了信息在图上的流动路径。初始时,蓝色表示没有信息量,如果用向量的概念表达即为空向量;绿色,黄色与红色各自有一部分信息量,表达为非空的特征向量。在图上,信息主要从三块有明显特征的区域向其邻接的像素点流动。一开始不同像素点的区分非常明显,但在向不动点过渡的过程中,所有像素点都取向一致,最终整个系统形成均匀分布。这样,虽然每个像素点都感知到了全局的信息,但我们无法根据它们最终的隐藏状态区分它们。比如说,根据最终的状态,我们是无法得知哪些像素点最开始时在绿色区域。
在这里笔者再多说几句。事实上,上面这个图与GNN中的信息流动并不完全等价。从笔者来看,如果我们用物理模型来描述它,上面这个图代表的是初始时有3个热源在散发热量,而后就让它们自由演化;但实际上,GNN在每个时间步都会将结点的特征作为输入来更新隐藏状态,这就好像是放置了若干个永远不灭的热源,热源之间会有互相干扰,但最终不会完全一致。
门控图神经网络(Gated Graph Neural Network)
我们上面细致比较了GNN与RNN,可以发现它们有诸多相通之处。那么,我们能不能直接用类似RNN的方法来定义GNN呢? 于是乎,门控图神经网络(Gated Graph Neural Network, GGNN) [10]就出现了。虽然在这里它们看起来类似,但实际上,它们的区别非常大,其中最核心的不同即是门控神经网络不以不动点理论为基础。这意味着:\(f\) 不再需要是一个压缩映射;迭代不需要到收敛才能输出,可以迭代固定步长;优化算法也从 AP 算法转向 BPTT。
状态更新
与图神经网络定义的范式一致,GGNN也有两个过程:状态更新与输出。相比GNN而言,它主要的区别来源于状态更新阶段。具体地,GGNN参考了GRU的设计,把邻居结点的信息视作输入,结点本身的状态视作隐藏状态,其状态更新函数如下:
如果读者对GRU的更新公式熟悉的话,对上式应该很好理解。仔细观察上面这个公式,除了GRU式的设计外,GGNN还针对不同类型的边引入了可学习的参数\(\mathbf{W}\)。每一种 \(edge\) 对应一个 \(\mathbf{W}_{edge}\),这样它就可以处理异构图。
但是,仔细对比GNN的GGNN的状态更新公式,细心的读者可能会发现:在GNN里需要作为输入的结点特征 \(\mathbf{x}_v\) 没有出现在GGNN的公式中! 但实际上,这些结点特征对我们的预测至关重要,因为它才是各个结点的根本所在。
为了处理这个问题,GGNN将结点特征作为隐藏状态初始化的一部分。那么重新回顾一下GGNN的流程,其实就是这样:
- 用结点特征初始化各个结点的(部分)隐藏状态。
- 对整张图,按照上述状态更新公式固定迭代若干步。
- 对部分有监督信号的结点求得模型损失,利用BPTT算法反向传播求得\(\mathbf{W}_{edge}\)和GRU参数的梯度。
实例1:到达判断
为了便于理解,我们举个来自论文[10]的例子。比如说给定一张图\(G\),开始结点 \(S\),对于任意一个结点 \(E\),模型判断开始结点是否可以通过图游走至该结点。同样地,这也可以转换成一个对结点的二分类问题,即可以到达
和不能到达
。下图即描述了这样的过程:
图中的红色结点即开始结点\(S\),绿色结点是我们希望判断的结点\(E\),我们这里称其为结束结点。那么相比于其他结点,这两个结点具有一定特殊性。那我们就可以使用第1维为1来表示开始结点,第2维为1来表示结束结点。最后在对结束结点分类时,如果其隐藏状态的第1维被赋予得到了一个非0的实数值,那意味着它可以到达。
从初始化的流程我们也可以看出GNN与GGNN的区别:GNN依赖于不动点理论,所以每个结点的隐藏状态即使使用随机初始化都会收敛到不动点;GGNN则不同,不同的初始化对GGNN最终的结果影响很大。
实例2:语义解析
上面这个例子非常简单形象地说明了GNN与GGNN的不同,由于笔者比较关注Semantic Parsing(语义解析)相关的工作,所以下面我们借用ACL 2019的一篇论文[11]来讲一下GGNN在实际中如何使用,以及它适用于怎样的场景。
首先为不了解语义解析的读者科普一下,语义解析的主要任务是将自然语言转换成机器语言,在这里笔者特指的是SQL(结构化查询语言,Structured Query Language),它就是大家所熟知的数据库查询语言。这个任务有什么用呢?它可以让小白用户也能从数据库中获得自己关心的数据。正是因为有了语义解析,用户不再需要学习SQL语言的语法,也不需要有编程基础,可以直接通过自然语言来查询数据库。事实上,语义解析放到今天仍然是一个非常难的任务。除去自然语言与程序语言在语义表达上的差距外,很大一部分性能上的损失是因为任务本身,或者叫SQL语言的语法太复杂。比如我们有两张表格,一张是学生的学号与其性别,另一张表格记录了每个学生选修的课程。那如果想知道有多少女生选修了某门课程,我们需要先将两张表格联合(JOIN),再对结果进行过滤(WHERE),最后进行聚合统计(COUNT)。这个问题在多表的场景中尤为突出,每张表格互相之间通过外键相互关联。其实呢,如果我们把表格中的Header看作各个结点,表格内的结点之间存在联系,而外键可以视作一种特殊的边,这样就可以构成一张图,正如下图中部所示:
论文[11]就是利用了表格这样的特性,利用GGNN来解决多表问题。下面我们先介绍一下一般的语义解析方法,再介绍[11]是如何将图跟语义解析系统联系在一起的。就笔者知道的而言,目前绝大部分语义解析会遵循Seq2seq(序列到序列,Sequence to sequence)的框架,输入是一个个自然语言单词,输出是一个个SQL单词。但这样的框架完全没有考虑到表格对SQL输出暗含的约束。比如说,在单个SELECT子句中,我们选择的若干Header都要来自同一张表。再举个例子,能够JOIN的两张表一定存在外键的联系,就像我们刚刚举的那个学生选课的例子一样。
那么,GGNN该如何结合到传统的语义解析方法中去呢?在论文[11]中,是通过三步来完成的:
- 首先,通过表格建立对应的Graph。再利用GGNN的方法计算每个Header的隐藏状态。
- 然后,在Seq2seq模型的编码阶段(Encoding),用每个输入的自然语言单词的词向量对表格所有Header的隐藏状态算一个Attention,利用Attention作为权重得到了每个自然语言单词的图感知的表示。
- 在解码阶段(Decoding),如果输出的是表格中的Header/Table这类词,就用输出的向量与表格所有Header/Table的隐藏状态算一个分数,这个分数由\(F\)提供的。\(F\)实际上是一个全连接层,它的输出实际上是SQL单词与表格中各个Header/Table的联系程度。为了让SQL的每个输出都与历史的信息一致,每次输出时都用之前输出的Header/Table对候选集中的Header/Table打分,这样就利用到了多表的信息。
最终该论文在多表上的效果也确实很好,下面放一个在Spider[12]数据集上的性能对比:
Model | Acc | Single | Multi |
---|---|---|---|
No GNN | 34.9% | 52.3% | 14.6% |
GNN | 40.7% | 52.2% | 26.8% |
GNN与GGNN
GGNN目前得到了广泛的应用,相比于GNN,其最大的区别在于不再以不动点理论为基础,虽然这意味着不再需要迭代收敛,但同时它也意味着GGNN的初始化很重要。从笔者阅读过的文献来看,GNN后的大部分工作都转向了将GNN向传统的RNN/CNN靠拢,可能的一大好处是这样可以不断吸收来自这两个研究领域的改进。但基于原始GNN的基于不动点理论的工作非常少,至少在笔者看文献综述的时候并未发现很相关的工作。
但从另一个角度来看,虽然GNN与GGNN的理论不同,但从设计哲学上来看,它们都与循环神经网络的设计类似。
- 循环神经网络的好处在于能够处理任意长的序列,但它的计算必须是串行计算若干个时间步,时间开销不可忽略。所以,上面两种基于循环的图神经网络在更新隐藏状态时不太高效。如果借鉴深度学习中堆叠多层的成功经验,我们有足够的理由相信,多层图神经网络能达到同样的效果。
- 基于循环的图神经网络每次迭代时都共享同样的参数,而多层神经网络每一层的参数不同,可以看成是一个层次化特征抽取(Hierarchical Feature Extraction)的方法。
而在下一篇博客中,我们将介绍图卷积神经网络。它摆脱了基于循环的方法,开始走向多层图神经网络。在多层神经网络中,卷积神经网络(比如152层的ResNet)的大获成功又验证了其在堆叠多层上训练的有效性,所以近几年图卷积神经网络成为研究热点。
参考文献
[1]. A Comprehensive Survey on Graph Neural Networks, https://arxiv.org/abs/1901.00596
[2]. The graph neural network model, https://persagen.com/files/misc/scarselli2009graph.pdf
[3]. Spectral networks and locally connected networks on graphs, https://arxiv.org/abs/1312.6203
[4]. Distributed Representations of Words and Phrases and their Compositionality, http://papers.nips.cc/paper/5021-distributed-representations-of-words-andphrases
[5]. DeepWalk: Online Learning of Social Representations, https://arxiv.org/abs/1403.6652
[6]. Translating Embeddings for Modeling Multi-relational Data, https://papers.nips.cc/paper/5071-translating-embeddings-for-modeling-multi-relational-data
[7]. Deep Learning on Graphs: A Survey, https://arxiv.org/abs/1812.04202
[8]. 如何理解Graph Convolutional Network(GCN)? https://www.zhihu.com/question/54504471
[9]. Almeida–Pineda recurrent backpropagation, https://www.wikiwand.com/en/Almeida–Pineda_recurrent_backpropagation
[10]. Gated graph sequence neural networks, https://arxiv.org/abs/1511.05493
[11]. Representing Schema Structure with Graph Neural Networks for Text-to-SQL Parsing, https://arxiv.org/abs/1905.06241
[12]. Spider1.0 Yale Semantic Parsing and Text-to-SQL Challenge, https://yale-lily.github.io/spider
[13]. https://www.wikiwand.com/en/Laplacian_matrix
[14]. Graph Neural Networks: A Review of Methods and Applications, https://arxiv.org/pdf/1812.08434