标题:A Learned Sketch for Subgraph Counting
发表:SIGMOD 2021
链接:地址
作者机构:港中文/武汉大学/腾讯AI Lab
一些需要解释的知识
在本篇论文中,一些频繁出现的必备知识如下:
-
graph isomorphism 图同构
离散数学图论中的知识,两个图G1&G2同构满足:
从G1的结点到G2的结点,存在一个一对一的映上函数
从G1的边到G2的边,存在一个一对一的映上函数
说白了就是两张图实际上是一张,G2只是把G1的结点调换位置而已,他们的邻接矩阵在一定调整下是一样的
-
graph homomorphism 图同态
比同构更宽松,结点不用一一对应。
-
感知机
给定输入x,权重w,和偏移b,感知机输出
o = σ ( < w , x > + b ) σ ( x ) = { 1 if x>0 0 otherwise o = \sigma(<w,x>+b) \quad \sigma(x)= \begin{cases} 1& \text{if x>0}\\ 0& \text{otherwise} \end{cases} o=σ(<w,x>+b)σ(x)={10if x>0otherwise
本质上就是二分类,算法如下initialize w = 0 and b = 0 repeat if yi[<w,xi>+b]<=0 then //wrong classifiesd w <—— w+yixi and b<——b+yi //update w and b end if until all classified correctly
等价于batch size=1的梯度下降
问题:不能拟合XOR函数,因为只能产生线性分割面
多层感知机
其实就是在softmax中加入了隐藏层+激活函数,得到非线性模型
超参数为隐藏层层数和各个隐藏层大小
h = σ ( W 1 x + b 1 ) o = W 2 T h + b 2 y = s o f t m a x ( o ) W 1 ∈ R m ∗ n , b 1 ∈ R m , W 2 ∈ R m ∗ k , b 2 ∈ R k h=\sigma(W_1x+b_1)\\ o=W_2^Th+b_2\\ y=softmax(o)\\ W_1 \in R^{m*n},b_1 \in R^m, W_2\in R^{m*k},b_2 \in R^k h=σ(W1x+b1)o=W2Th+b2y=softmax(o)W1∈Rm∗n,b1∈Rm,W2∈Rm∗k,b2∈Rk
也可以有很多隐藏层,每一个隐藏层都有对应的W矩阵,且必须加激活函数(避免层数塌陷) -
自注意力的目的是对于一个query向量,在一堆key中找到和其它向量之间的关联程度,是一个有偏选择的过程。
摘要
子图计数(subgraph counting)是算法中典型的一类NP-Hard问题,任务是给定一个查询图(query graph),统计在大图中有多少个子图与查询图匹配(同构或同态)。目前存在的方法局限性都比较大,所以我们想提出一种基于机器学习和深度学习的方法来对子图计数。
本文提出的Active Learned Sketch for Subgraph Counting(ALSS),主要由两部分组成:
- Sketch Learned(LSS):用神经网络做回归任务训练;
- Active Learner(AL):挑选一些新的测试查询图来更新模型、提升效果。
我们用一些很大的真实标签图做了一些实验来证明ALSS的效率和准确率,且我们发现ALSS可以帮助查询优化器为多路自连接找到更好的查询计划。
引言
子图计数的目的是统计大图中有多少个子图与查询图匹配(同构或同态)。这个问题在网络分析中应用非常广泛,比如为计算机视觉任务构建概率模型(e.g. 照片剪裁&图像分割)或分析生物化学原子结构(分子成分预测)等等。
然而,精确子图计数(同构情况下)是非常困难的,且不说计数,单单是给定一个查询图,看大图里有没有子图和查询图匹配这个问题就是个典型的NP-C问题(子图匹配-subgraph matching)。现在的方法(SQL/传统算法)在图特别大的时候算不出来,而且复杂度太高,有很多局限性。也有一些学者试图用ML(Machine Learning)和DL(Deep Learning)来解决,但是要么就是限制图结点只能有512个,要么计算复杂度太高。我们想,也许可以优化之前的关系数据库(RDBMS)查询方法,用DL训练,来实现子图模糊计数(也就是说本文不做精确计数)。
本文提出了ALSS,主要包含LSS和AL两部分。
-
Sketch Learned-LSS:通过神经网络训练一个回归模型,主要包含以下几步。
- 将查询图(下面简称q图)分解为一些更小的子结构
- 提取这些子结构的特征,用定长的向量表示
- 通过聚合所有子结构的表示来得到Q图的匹配数
其中,用GNN(Graph Nerual Network)把这些带标签的子结构转换为向量,然后通过自注意机制学一个聚合函数出来,最后跟一个MLP(多层感知机)预测最终的计数结果。
-
Active Learning-AL:由于不可能得到完全的训练集来供模型学习,所以需要提出这个AL模块来学习一个策略,这个策略能基于模型目前的信息量,从未标注数据池中选择一些数据,来扩充训练数据以提升模型效果。
简单来说,我们将一个分类任务合并到LSS中以预测子图计数。于是LSS有两个学习任务:1. 如前所述,给定q图预测匹配数;2. 帮助AL决定如何为未来学习选择测试q图。
本文的AL利用了分类任务的不确定性和关联任务的一致性,无需做梯度计算。相比于消极学习,AL的目的是在同样的数据量下,训练出更好的模型。
问题描述
我 们 建 模 一 个 图 : G = ( V , E , L , Σ ) 我们建模一个图:G=(V,E,L,Σ) 我们建模一个图:G=(V,E,L,Σ)
其中,V为点集,E为边集,Σ为标签集,L为映射函数(把点v映射到标签对应的L(v))。
我们定义,如果q图中的点v没有标签,则代表可以匹配任意点。假设c(q)为真实计数结果,c’(q)为模型预测结果,定义一个q-error来量化真实与预测不同的因素。
q
−
e
r
r
o
r
(
q
)
=
m
a
x
c
(
q
)
c
′
(
q
)
,
c
′
(
q
)
c
(
q
)
(1)
q-error(q)=max{\frac{c(q)}{c'(q)},\frac{c'(q)}{c(q)}}\tag 1
q−error(q)=maxc′(q)c(q),c(q)c′(q)(1)
个人感觉 q-error存在的意义是解决不同数量级的计数之间难以比较与归一的问题
模型概况
如前所述,ALSS由两个主要部分组成,其中LSS是一个神经网络,回归模型来预测q图的匹配数;AL通过一些策略从新到来的测试q图中选择一些有用的q图来扩充训练集。
最初,给定大图G和一堆查询图Q = {(q1,c(q1)),(q2,c(q2))…}将用GNN离线训练LSS。训好的LSS然后用于预测测试图q的计数c’(q),假设Q‘是测试集的预测结果集合。接下来AL将在给定的选择上限下从Q’里选择一些q图,这些q图能有助于提升模型的表现。
直观来讲,AL会选择一些q-error值更大的q图,但是由于这些测试集的真实计数c(q)尚不清楚,所以AL将基于不确定性函数评估不确定性,并对其执行有偏采样。假设QΔ为新选的集合,并算出了真实计数,ALSS将为这些增强了的训练数据(Q∪QΔ)重新优化损失函数。这个步骤不断重复,直到在线测试可以自己自动完成。
LSS
本章为三个部分介绍LSS的具体实现:建模、实现和结点编码。
LSS Modeling
我们把q图分解为一堆子结构,然后聚合子结构的结果得到c’(q)。
c
′
(
q
)
=
ϕ
(
∑
s
i
∈
S
(
q
)
σ
(
s
i
)
⋅
w
(
s
i
)
)
(2)
c'(q)=\phi(\sum_{s_i\in S(q)}\sigma(s_i)·w(s_i))\tag 2
c′(q)=ϕ(si∈S(q)∑σ(si)⋅w(si))(2)
其中,S(q)={s1,…sn}是子结构;函数σ(si)是si的估计匹配计数;w(si)是权重;Σ是一个聚合函数,把带权重的计数聚合起来;最外面套一个校正函数Φ。
目前有一些准确计数算法,这些方法要求q图最多有5个结点;也有一些模糊计数算法,这些方法假设子结构互相独立,因此可以直接把字结构的计数结果求和得到c’(q),但是显然这种假设会造成很大的误差。
于是我们通过使用神经网络来参数化公式(2)中的σ、w和Φ,以学习出估计公式。作为一个回归模型,LSS接收q图,输出一个估计cθ(q)。和公式(2)差不多,LSS是通过在一个有标签训练集合Q上最小化**均方误差(MSE)**来训练的。
L
r
e
g
(
Q
;
Θ
)
=
1
∣
Q
∣
∑
q
∈
Q
∣
l
o
g
c
(
q
)
−
l
o
g
c
Θ
(
q
)
∣
2
=
1
∣
Q
∣
∑
q
∈
Q
l
o
g
2
c
(
q
)
c
Θ
(
q
)
(3)
L_{reg}(Q;\Theta)=\frac{1}{|Q|}\sum_{q\in Q}|log\;c(q)-log\;c_{\Theta}(q)|^2=\frac{1}{|Q|}\sum_{q\in Q}log^2\frac{c(q)}{c_{\Theta}(q)}\tag 3
Lreg(Q;Θ)=∣Q∣1q∈Q∑∣logc(q)−logcΘ(q)∣2=∣Q∣1q∈Q∑log2cΘ(q)c(q)(3)
为了达到平均低一些的相对误差,对c(q)和cΘ(q)取log。值得注意的是最小化log(c(q)/cΘ(q))的平均值和最小化q-error的几何平均值是等价的;且由于平方误差,最小化均方误差(MSE)会进一步对较大的q-error施加更大的权重w。
LSS Architecture
LSS的具体架构如图2所示,我总结成了以下几个步骤:
- q图分解为一系列子结构集合S(q)。为了学习到子结构之间的关系,我们希望不同子结构之间有一些交集。对于选取方法,就是从每一个结点出发做l跳的BFS搜索,例如图2中l=2。于是得到了n个子结构(n是q图的结点个数)。
- 多层的GNN把每一个子结构si转换为一个定长的向量,就是公式(2)中的σ。
- 然后是一个自注意层,用来从n个子结构中学习公式(2)中的权重w。
- 把子结构的编码σ(si)相加,由w(si)加权,获得q图的表示向量。
- 最后,一个多层感知机MLP将这个q图的表示向量作为输入,输出预测计数,也就是公式(2)中的Φ。
LSS前向传播算法如上所示,其输入为q图,输出为预测计数取log值。下面我们按行解读:
-
第2行:把q图分解为子结构集合S(q)
-
第2-7行:一个K层GNN把每一个子结构si转换为子结构表示hsi,GNN遵循邻域聚合范式,通过在K次迭代中聚合其邻居的表示来更新结点的表示(意思大概就是K次迭代中不停update自己的信息,也就是GNN的根本思想)。
对于每一个子结构si,在每一次迭代中(k),对其中每一个结点v,不断通过邻居和上一次的信息更新自己的信息。第5行代表一个聚合函数 fa 将k-1轮得出的v的邻居信息聚合;然后第6行代表一个合并函数 fc 把第k-1轮自己的信息与邻居信息合并(其中 fa 和 fc 都是神经网络)。在最后一次迭代后,第7行通过一个Readout函数将最后一次迭代的结果生成一个整个子结构的表示(也就是说把一些稀碎的结点表示整合为子结构level的表示吧)。作者说该Readout函数是一个简单的置换不变函数,例如求和or池化。
作者团队调查了许多有名的GNN,包括GCN/GAT/GIN,在多重考虑下选择了GIN(Graph Isomorphism Network),主要原因是GIN用了MLP作为fa和fc函数,用sum作为Readout,这样更内射。GIN有非常好的性质,比如如果两个子结构s1和s2是同构的,那么它们的子结构level表示hs1和hs2就是相等的,这个和子图计数的任务目的相匹配。
-
第8-12行:自注意&多层感知机。
在自注意阶段,n个子结构的表示向量被连接为一个矩阵Hq(第8行),然后Hq被自注意机制加工。就像其它自注意一样,其通过评判不同子结构的重要性来得出一个打分矩阵A(第9行)。其中,第9行的矩阵A通过一个没有bias的两层MLP实现,第一层权重矩阵为W1并用tanh激活,第二层权重矩阵为W2并跟一个softmax归一化。第10行中,我们把权重矩阵A和连接后的矩阵Hq相乘,得到一个查询level的表示Eq。Eq的大小与q图无关,仅与超参有关。值得注意的是,自注意力层对子结构集S(q)的排列是不变的。最后,第11行把Eq拍平成一个长向量eq,然后第12行把eq输入MLP来生成预测计数。
Feature Encoding
上文提到的算法中,e/a的k轮迭代很重要。那么求出e or a的最开始初始值也非常重要,这就涉及到下面要提出的特征编码。
普通的GNN编码方式(例如独热码)用来分类结点or预测边,这种非常稀疏的方式不适合子图计数。我们提出了一种基于频率的编码方式和基于嵌入预训练的编码方式来分别编码标签信息与拓扑结构。
基于频率的编码
对于图G,我们定义一个结点标签l的出现次数为F(l),有:
F
(
l
)
=
∣
{
v
∣
l
∈
L
(
v
)
f
o
r
v
∈
V
}
∣
F(l)=|\{v|l\in L(v)\;for \;v\in\;V\}|
F(l)=∣{v∣l∈L(v)forv∈V}∣
初始值e(0)被编码为一个|Σ|维向量(Σ为标签集),其中第i维对应第i个结点标签(Σ集合中的第i个元素)。e(0)[i]的值是G中可以匹配到v的结点的分数。比如,如果点v和结点标签li有关系,那么e(0)[i]就会被置为F(li)/|V|,否则为1。
个人认为,其实就是以此看这个结点 v 是否和标签集中的每一个节点标签 li 有关系,如果有的话第 i 维就置为其频率 / 总数,否则为 1。
基于嵌入的编码
基于频率的编码考虑到了属性频率,但是并没有考虑图G的拓扑结构。因为给GNN练一些预训练和无监督的嵌入可以提升其表现,所以我们给图G预训练一个结点标签嵌入来提升q图编码能力。
G
L
=
(
V
∪
V
L
,
E
∪
E
L
)
G_L=(V∪V_L, E∪E_L)
GL=(V∪VL,E∪EL)
GL是G的结点增强图,其中VL是一堆点,一个点代表Σ中的一个标签,所以VL中有|Σ|个点;EL是一堆边,一条在V中与v相连,一条在VL中与VL相连。图3比较清晰地解释了这个过程。
具体而言,我们用一些任务独立的图嵌入算法来给GL图预训练(比如DeepWalk, node2vec~),期间我们把每个q中的结点都做编码。对于q中的结点v,我们这样定义其初始值e(0):
e
v
(
0
)
=
∑
l
∈
L
(
v
)
e
′
(
l
)
e_v^{(0)}=\sum_{l\in L(v)}e'(l)
ev(0)=l∈L(v)∑e′(l)
其中e’(l)是标签l在GL中的预训练嵌入(如果v有标签l的话),如果结点没有任何标签,则会得到一个全0向量。
合并
最终结点v的编码e(0)是将基于频率的编码和基于预训练嵌入的编码进行连接得到的。
AL
对于普通的机器学习任务来说,就是要通过在训练集上不断减小经验损失来训练一个模型,然后对于给定的测试集Xu,预测其值。那么AL的工作就是当训练数据比较少的时候,通过每次从Xu里选择一些信息量大的数据Xa,然后提升模型的效果。这个过程一直迭代,直到模型达到一个停止的阈值(比如趋于平稳之类的)。因此AL的关键目标就是它用怎样的选择策略,也就是该怎么权衡。那么AL的选取是取决于机器学习任务的——优化目标和数据分布等。
我们用的AL策略是不确定采样,每次选择最不确定的那堆数据。该算法输入LSS模型和一堆没有标签的q图,通过一个不确定衡量函数来评估每一个q图在模型下的信息量。总结一下,AL算法迭代以下4个步骤:
- 用φ(q;Θ)函数计算Q’中每一个q图的不确定值,记为uq;
- AL用归一化过的uq作为权重,从集合Q’中挑选一些q图,记为QΔ集合,同时QΔ中的q图有确切的子图计数值;
- 训练集Q被扩充为Q∪QΔ;
- 训练集送入模型训练,因此LSS模型也被更新。
具体而言,该怎么评估每一个图的不确定值呢?我们采用多任务学习(multi-task learning)。我们把一个分类任务放进LSS模型中,来预测子图计数的大小。那些大小模糊的测试图会有更大的不确定度。
在模型MLP的最后一层,我们加入m个额外的神经元来执行多任务分类。这m个输出通过一个softmax函数,得到概率分布p(y|q),其中p(yi|q)表示c’(q)大小为yi的概率。我们用交叉熵损失函数作为该多分类的模型损失函数,如公式(5)所示。
L
c
l
s
(
Q
;
Θ
)
=
1
∣
Q
∣
∑
q
∈
Q
∑
i
=
1
m
[
−
p
(
y
i
∣
q
)
⋅
l
o
g
p
Θ
(
y
i
∣
q
)
]
(5)
Lcls(Q;\Theta)=\frac{1}{|Q|}\sum_{q\in Q}\sum_{i=1}^m[-p(y_i|q)·log\;p_{\Theta}(y_i|q)] \tag 5
Lcls(Q;Θ)=∣Q∣1q∈Q∑i=1∑m[−p(yi∣q)⋅logpΘ(yi∣q)](5)
模型的总损失函数就是分类+回归的一个加权和,如(6)
L
(
Q
;
Θ
)
=
(
1
−
λ
)
L
r
e
g
(
Q
;
Θ
)
+
λ
L
c
l
a
(
Q
;
Θ
)
(6)
L(Q;\Theta)=(1-\lambda)L_{reg}(Q;\Theta)+\lambda L_{cla}(Q;\Theta) \tag 6
L(Q;Θ)=(1−λ)Lreg(Q;Θ)+λLcla(Q;Θ)(6)
我们的AL对分类任务提供三个不确定函数,对交叉任务提供一个不确定函数:
-
Confidence
φ C O N ( q ; Θ ) = 1 − m a x i P Θ ( y i ∣ q ) \varphi _{CON}(q;\Theta)=1-max_{iP\Theta}(y_i|q) φCON(q;Θ)=1−maxiPΘ(yi∣q)
该公式目的是暗示最优预测(1)和模型的最高后验概率之间的差距。 -
Margin
φ M A R ( q ; Θ ) = p Θ ( y 1 ′ ∣ q ) − p Θ ( y 2 ′ ∣ q ) \varphi _{MAR}(q;\Theta)=p_{\Theta}(y_1'|q)-p_{\Theta}(y_2'|q) φMAR(q;Θ)=pΘ(y1′∣q)−pΘ(y2′∣q)
其中y1’和y2’分别是LSS模型下第一个和第二个最可能的预测值。越高的Margin表明分类器在区分两个类之间存在问题。 -
Entropy
φ E N T ( q ; Θ ) = − ∑ y p Θ ( y ∣ q ) l o g p Θ ( y ∣ q ) \varphi _{ENT}(q;\Theta)=-\sum _yp_{\Theta}(y|q)log\;p_{\Theta}(y|q) φENT(q;Θ)=−y∑pΘ(y∣q)logpΘ(y∣q)
更高的Entropy代表更平滑的分布。 -
Cross-task Consistency
φ C T C ( q ; Θ ) = ∣ y 1 ′ − l o g 10 c Θ ( q ) ∣ 2 \varphi_{CTC}(q;\Theta)=|y_1'-log_{10}\;c_{\Theta}(q)|^2 φCTC(q;Θ)=∣y1′−log10cΘ(q)∣2
y1’是分类任务下最可能的预测值,log10c’(q)是回归任务生成的子图计数值。CTC通过分类与回归任务输出的不一致程度来评估数据的信息量。
以上4个不确定函数用来评估q图的不确定性,
实验
Setup
-
LSS的设置:
GNN为3层,每个隐藏层有64个单元,dropout率为0.5(震惊,50%的dropout是不是太高了…?)
MLP为2层,隐藏层的激活函数为ReLU,输出层用softmax预测概率分布(分类任务)
交叉损失中的参数λ为1/3
q图分解时的BFS跳数设置为3跳
选择传统图嵌入算法ProNE作为LSS的嵌入预训练编码
-
环境设置:
Pytorch框架
使用Adam优化器来降低学习率
对于不同的数据集,学习率/epoch/batch size/Adam L2 penalty不一样
-
数据集:
- aids:生物分子结构
- yeast:生物分子结构
- YouTube:社交网络
- eu2005:网络图
- wordnet:词汇图
- yago:知识图谱
另外:把q图集合分为80%训练&20%测试。
准确率&效率
(这部分我粗糙读了一下,大概意思就是本文提出的方法准确率 & 效率都不错、错误率最低)
总结
这篇文章提出了一种基于深度学习的子图计数方法,可以用于图同构/同态匹配的模糊计数。文章主要两大部分:LSS和AL分别用于预测与提升模型性能(通过不断选择新数据)。最后实验证明不仅该模型速度更快,而且错误率更低。