目录
3.1 Diffusion-Convolution Neural Network
3.2 Diffusion Graph Convolution
摘要
本周我初步学习了GNN的基础知识,明白了什么是GNN。GNN的输入数据类型是图结构的数据,而现实世界中就存在着大量的图结构数据,这些数据同样可以用GNN来对节点做预测,做分类等等。同样GNN也有许多不同的方法来处理数据,比如说DCNN、DGC、GAT等。本周我使用代码定义了一个GAT的模型,我还阅读了一篇关于多变量时间序列预测的论文,通过这篇论文我大致理解了多变量时间序列的预测方式。
ABSTRACT
This week, I have started learning the fundamentals of GNN and gained an understanding of what GNN is. GNN takes graph-structured data as input, and in the real world, there is a wealth of graph-structured data. These data can also be used with GNN for tasks such as node prediction and classification. Additionally, GNN offers various methods for data processing, such as DCNN, DGC, GAT, etc. During this week, I defined a GAT model using code. I also read a paper on multivariate time series prediction, which gave me a rough understanding of how multivariate time series prediction works.
1 文献阅读
论文摘要:本文提出了一种基于深度学习的多变量时间序列预测模型TEDGER,可以提取隐藏在单个时间序列中的序列模式和隐藏在多变量时间序列中的全局特征,并将序列模式和全局特征进行融合,通过残差预测的方式实现时间序列的预测,并在实验中展示了其优越性和可解释性。
论文背景:时间序列在现实生活中具有广泛的应用,通过时间序列预测模型可以预测序列的未来变化趋势,为决策提供支持。
过去方案:早期的统计学方法,如自回归模型和指数平滑模型,只能建模特征之间的线性关系,限制了模型的预测精度。随着深度学习的引入,模型可以建模特征之间的非线性关系,具有更强的学习能力。但是过去的多变量时间序列预测方法存在一些问题,如不能同时考虑时间序列本身和协变量(影响预测变量结果的其他变量)的信息,忽略了多变量时间序列中的全局信息,以及无法对预测结果进行解释等。
论文方案:本文提出了一种名为TEDGER的新型基于深度学习的多变量时间序列预测模型。TEDGER主要由四个模块构成:编码器、解码器、残差序列捕获模块和趋势预测模块。历史时间序列 经残差序列捕获模块和趋势预测模块处理之后得到原时间序列的残差序列,作为编码器的输入,编码器对残差序列和协变量进行编码后得到序列的隐状态,输入解码器得到未来时间步的残差预测。趋势预测模块捕获历史时间序列的全局特征和未来变化趋势模式。最后,结合未来残差的预测和变化趋势的预测得到最终的预测结果。
解决问题:考虑一个变量数为的历史时间序列矩阵,其中序列是第个变量的时间序列。已知在过去个时间步的值为,与此同时,已知和相关的协变量张量,其中是协变量的个数,每个子矩阵都是随时间变化的序列,代表与序列相关的协变量矩阵。与时间序列不同,假设所有的协变量在未来的时间步上是已知的或者是可以被推断出来的,故可以在预测时使用。
本文的目标是学习一个模型,可以利用过去的时间序列,以及过去和未来的协变量,预测出未来个时间步的时间序列,即,是模型的参数。与此同时,模型能够对预测结果进行解释。
编码器与解码器:编码器用于对历史时间序列的残差序列的每个时间步进行编码,捕获每个时间步的隐状态,解码器则根据编码器获得的隐状态预测未来多个时间步的残差值。编码器-解码器基于张量长短期记忆网络(Tensorized Long Short-Term Memory network,TLSTM)构建,以避免每个时间步的不同协变量中的信息被混合,且保持普通的编码器-解码器框架在时间序列预测任务的精度。
趋势预测模块:为了捕获多变量时间序列间的关系,本文使用时序正则化矩阵分解(Temporal Regularized Matrix Factorization,TRMF)来提取跨序列的全局演化趋势。将已知的时间序列矩阵作为输入,矩阵分解技术可以将其分解为两个低秩矩阵和,矩阵中的每一行表示第个序列的特征,矩阵中的每一列表示的是时刻的全局时序特征。如下图所示,传统的矩阵分解技术缺乏预测未来的能力,TRMF可以通过引入时序依赖,由已知的时序特征推断出未来的时序特征。
残差序列捕获模块:
TEDGER I:对于序列,给定TRMF得到的序列特征和全局特征,首先以为权重,得到合成的趋势序列:,随后将原始序列减去趋势序列得到残差序列:,并将残差序列代替原始序列输入编码器,相应的,在预测阶段解码器也仅预测未来序列的残差:,随后通过时序依赖计算未来的全局特征及趋势序列:,累加未来的趋势序列与预测的残差序列得到最终的预测结果为:。
本文认为全局特征实际上是若干个所有序列共同遵循的基本趋势,在通过全局特征合成趋势序列之后,只需根据未来的协变量信息,进一步预测未来的真实序列与趋势序列之间的差值(即残差)即可。这样比直接预测未来序列要更为精准,因为趋势序列的应用能够为预测未来的序列提供基本的引导。
TEDGER II:在 TEDGER I 中,由于趋势序列是直接以TRMF得到的序列特征作为权重合成的,而序列特征不随时间变化,这可能导致在计算趋势序列时,未能有效利用时间变化的信息。因此本文设计了另外一种合成趋势序列的方法。利用一 LSTM编码器来编码已知的目标序列,并以此计算将全局特征合成的权重:
此LSTM网络的参数同原有模型的参数一同学习。通过这个额外的编码器能够充分利用原始序列中的时序信息,将TRMF矩阵分解得到的若干基本序列合成为一个趋势序列,使其相比于直接利用序列特征作为权重,能够更符合当前窗口的情况。
模型预测结果的解释:除了给出未来序列在一段时间内的预测结果之外,模型的可解释性非常重要。在现有的可解释性工作中,一个重要的关注点就是试图研究深度学习模型输入与输出的之间的相关性,换句话说,哪部分输入对于预测结果贡献最大。本文尝试从这个角度出发去解释模型的预测结果。
在TEDGER模型中,时序和变量两种注意力机制提供了有关时序和变量对于结果的重要性。具体 来说,可以从模型的参数中提取出时序注意力权重和变量注意力权重。其中分别代表序列、滑动窗口和协变量的索引,而和则分别对应每个滑动窗口中编码器和解码器的时间步数。代表的是对于第个序列的第个滑动窗口中的第个协变量,历史时间步对于解码器中的第个时间步的预测的贡献。而表示的是在第个序列的第个滑动窗口中,协变量对于解码器中的第个时间步 的最终预测结果的贡献。通过这种方式可以得知,在历史输入中,哪些时段的哪些协变量对于与模型的预测结果是最为相关的,以此对解释进行模型。
2 Introduction
之前学习的机器学习知识大多围绕文本,语音,图片这样的简单序列或者平面作为输入,但现实世界中,数据更多地表现为复杂的图结构,比如说社交网络,分子结构等等。如何处理这种图结构的数据就是图神经网络(GNN)所解决的问题。
2.1 Why we need GNN
使用GNN可以处理图结构的数据以此来解决很多问题,比如说分类问题,或者将GNN作为生成模型来产生我们需要的结果等等。
2.1.1 Classification
举一个简单的例子,在一部犯罪悬疑电视剧中,输入一个角色的特征至GNN中,可以得出这个角色是不是凶手。但GNN推断的过程不仅仅只考虑角色的特征,还有这个角色与其他角色之间的关系,以及和其他角色之间产生的其他联系,这种角色与角色之间交织在一起形成了图的结构。
2.1.2 Generation
GNN还能作为生成模型产生我们未知但是迫切需要的结果。比如说开发新药的过程,通过训练GNN作为生成模型,当我们输入想要的针对某一病毒的分子时,它可以生成多个相关的分子结构供给参考。
3 Spacial-based Convolution(GCN)
基于卷积神经网络(CNN),我们可以将卷积的思想加入GNN中,实现在图结构数据中进行卷积操作。也就是说,对前一层图中每个节点的Feature进行卷积,提取出每一个节点更深层次的特征。
Aggregation:
Readout:
3.1 Diffusion-Convolution Neural Network
GNN还可以采用扩散卷积神经网络(Diffusion-Convolution Neural Network,DCNN)的卷积方式。每一层Hidden Layer都是针对输入层进行计算,从距离为1的节点开始,逐渐增加扩散距离,最后提取每一层的特征得到输出结果。
3.2 Diffusion Graph Convolution
GNN也可以采用扩散图卷积(Diffusion Graph Convolution,DGC)的卷积方式。DGC只是在DCNN的基础上改变了特征的提取方式,变成了简单的累加。
3.3 Mixture Model Networks
只是对邻居节点的特征进行求和或者取平均太过简单了些,我们应该使用加权和的方式来替代。这是因为当前节点相连的邻居节点之间的重要性是有差别的,需要考虑重要性来进行Aggregation。重要性定义为某个节点的倒数向量,其中为节点本身所连接的邻居节点数。也就是说,如果一个节点本身就有“众多邻居”,那它对于它的邻居而言就显得没有那么重要,因为它的重要性相对来说过于分散了;如果一个节点本身就“非常专一”,那么它对于它的邻居而言就十分重要。
得到重要性权重之后,MoNET再把这个权重通过一个多层感知器(Multi-Layer Perception,MLP)做非线性变化,然后作为最终的权重将邻居节点的hidden state进行加权求和。
3.4 Graph Attention Network
GAT(Graph Attention Network,GAT)的核心思路其实和MoNET是类似的,即利用加权和的形式将邻居节点embedding的信息进行整合。唯一的区别在于利用attention机制让模型“自己学习”这个权重,而不是人为通过预定义的公式计算权重。
与之间的权重计算如下:首先用权重矩阵对两个节点的hidden state做矩阵相乘,然后再与矩阵相乘得到energy(即),然后经过非线性激活层LeakyReLU,最后经过softmax层得到权重。
3.5 GraphSAGE
GraphSAGE最大的区别在于Aggregation的操作不只有诸如mean、max-pooling这种常规操作,还有LSTM。GraphSAGE每次从graph中sample出一个不同顺序的subgraph,然后让模型通过训练学习到对于graph顺序的不变性。
3.6 Graph Isomorphism Network
GIN(Graph Isomorphism Network)主要是对以往GNN工作的一个总结与理论证明,主要证明了以下几点结论:
① 某个节点的embedding应该是他的邻居节点上一层hidden state之和,以及自身上一层hidden state之间的一个凸组合,在经过一个非线性变换得到。
② sum aggregation优于mean以及max aggregation。
③ 取1就能取得不错的结果,即将自身的embedding和邻居节点总的embedding等权看待。
为什么sum aggregation优于后两者?通过下图进行说明,不同颜色的圆代表不同的数值。(a)中当个数不同但每个数值相同时,mean和max均会得到一样的数值,从而无法区分两个不同的graph而失效;(b)中max会失效,因为两个graph在max aggregation之后数值是相同的;(c)中mean和max也都会失效。
4 相关代码
PyTorch实现GAT网络:
import torch
import torch.nn as nn
import torch.nn.functional as F
class GraphAttentionLayer(nn.Module):
def __init__(self, in_features, out_features, dropout, alpha, concat=True):
super(GraphAttentionLayer, self).__init__()
self.in_features = in_features # 输入特征的维度
self.out_features = out_features # 输出特征的维度
self.dropout = dropout # dropout 概率
self.alpha = alpha # LeakyReLU 的负斜率
self.concat = concat # 是否使用拼接操作
# 初始化权重矩阵
self.W = nn.Parameter(torch.zeros(size=(in_features, out_features)))
nn.init.xavier_uniform_(self.W.data, gain=1.414)
# 初始化注意力机制参数
self.a = nn.Parameter(torch.zeros(size=(2 * out_features, 1)))
nn.init.xavier_uniform_(self.a.data, gain=1.414)
self.leaky_relu = nn.LeakyReLU(self.alpha)
self.dropout = nn.Dropout(self.dropout)
def forward(self, input, adj):
# 对节点特征进行线性变换
h = torch.mm(input, self.W)
N = h.size()[0]
# 创建用于注意力机制的张量
a_input = torch.cat([h.repeat(1, N).view(N * N, -1), h.repeat(N, 1)], dim=1).view(N, -1, 2 * self.out_features)
# 计算注意力系数
e = self.leaky_relu(torch.matmul(a_input, self.a).squeeze(2))
zero_vec = -9e15 * torch.ones_like(e)
# 掩码化注意力:将未连接节点的系数设为一个非常小的值
attention = torch.where(adj > 0, e, zero_vec)
# 应用 softmax 计算注意力得分
attention = F.softmax(attention, dim=1)
# 应用 dropout 到注意力得分
attention = self.dropout(attention)
# 使用注意力得分更新节点表示
h_prime = torch.matmul(attention, h)
# 如果使用拼接,应用 ELU 激活函数
if self.concat:
return F.elu(h_prime)
else:
return h_prime
class GAT(nn.Module):
def __init__(self, nfeat, nhid, nclass, dropout, alpha, nheads):
super(GAT, self).__init__()
self.dropout = dropout
self.attentions = [GraphAttentionLayer(nfeat, nhid, dropout=dropout, alpha=alpha, concat=True) for _ in range(nheads)]
for i, attention in enumerate(self.attentions):
self.add_module('attention_{}'.format(i), attention)
self.out_att = GraphAttentionLayer(nhid * nheads, nclass, dropout=dropout, alpha=alpha, concat=False)
def forward(self, x, adj):
x = F.dropout(x, self.dropout, training=self.training)
# 应用多头注意力
x = torch.cat([att(x, adj) for att in self.attentions], dim=1)
x = F.dropout(x, self.dropout, training=self.training)
# 最后一层使用 ELU 激活函数
x = F.elu(self.out_att(x, adj))
return F.log_softmax(x, dim=1)
# 创建一个示例网络
nfeat = 1433 # 输入特征的维度
nhid = 8 # 隐藏层的维度
nclass = 7 # 输出类别的数量
dropout = 0.6 # dropout的概率
alpha = 0.2 # LeakyReLU 的参数
nheads = 8 # 多头注意力的数量
model = GAT(nfeat, nhid, nclass, dropout, alpha, nheads)
print(model)
运行结果:
总结
GNN是一个强大的工具,它在推动图数据分析领域的发展方面具有巨大的潜力。下一周我将继续GNN相关知识的学习。