2024/7/7周报

文章目录

  • 摘要
  • Abstract
  • 文献阅读
    • 题目
    • 问题
    • 本文贡献
    • 问题描述
    • 图神经网络
    • Framework
    • 实验
      • 数据集
      • 实验结果
  • 深度学习
    • MAGNN模型相关代码
    • GNN
    • 为什么要用GNN?
    • GNN面临挑战
  • 总结

摘要

本周阅读了一篇用于多变量时间序列预测的多尺度自适应图神经网络的文章,多变量时间序列(MTS)预测在智能应用的自动化和最优化中发挥着重要作用。这是一项具有挑战性的任务。本文提出了一种多尺度自适应图神经网络(MAGNN)来解决上述问题。MAGNN利用多尺度金字塔网络在不同的时间尺度上保持潜在的时间依赖关系。作者还开发了一个基于尺度的融合模块,有效地促进了不同时间尺度上的协作,并自动捕捉贡献的时间模式的重要性。在六个真实数据集上的实验表明,MAGNN在各种设置下的性能都优于最先进的方法。

Abstract

This week,an article on multi-scale adaptive graph neural network for multivariable time series prediction is readed. Multivariable time series (MTS) prediction plays an important role in the automation and optimization of intelligent applications. This is a challenging task. In this paper, a multi-scale adaptive graph neural network (MAGNN) is proposed to solve the above problems. MAGNN uses multi-scale pyramid network to maintain potential time dependence on different time scales. The author also developed a scale-based fusion module, which effectively promoted the cooperation on different time scales and automatically captured the importance of the contribution time pattern. Experiments on six real data sets show that the performance of MAGNN is better than the most advanced methods in various settings.

文献阅读

题目

Multi-Scale Adaptive Graph Neural Network for Multivariate Time Series Forecasting

问题

1)传统的方法,如向量自回归(VAR)、时间正则化矩阵分解(TRMF)、向量自回归滑动平均(VARMA)和高斯过程(GP),往往依赖于严格的平稳假设,无法捕捉变量之间的非线性相关性。
2)注意机制和基于记忆的网络模型侧重于时间相关性的建模,将MTS的输入处理为向量,并假设单个变量的预测值受所有其他变量的影响,这在实际应用中是不合理的,也是很难满足的。例如,一条街道的TrafficflOWS很大程度上受到邻近街道的影响,而来自远处街道的影响相对较小。
3)现有的GNN模型只考虑了单个时间尺度上的时间依赖关系,这可能不能正确地反映许多现实世界场景中的变化。已有的工作学习共享邻接矩阵来表示丰富的变量间依赖关系,这使得模型偏向于学习一种突出的共享时态模式。

本文贡献

1)提出MAGNN,它学习一种既能综合反映多尺度时态模式又能反映特定尺度变量间依赖关系的时态表示。
2)设计了一个自适应图学习模块,用于探索不同时间尺度下丰富和隐含的变量间依赖关系,以及一个基于尺度的融合模块,用于促进这些特定尺度的时间表示之间的协作,并自动捕获贡献的时间模式的重要性。
3)在六个真实世界的MTS基准数据集上进行广泛的实验。实验结果表明,该方法的性能优于目前最先进的方法。

问题描述

本文主要研究MTS预测。在形式上,给定一个输入的时间序列数据在这里插入图片描述,其中在这里插入图片描述表示时间步t的值,N是变量维度,在这里插入图片描述表示第t个时间步的第i个变量的值,MTS预测的目的是预测未来在时间步t+h的值在这里插入图片描述,其中h表示需要预测的未来时间步数。这个问题可以表述为:在这里插入图片描述。式中F为映射函数,θ表示所有可学习的参数。

然后,存在如下几种关于MTS预测的定义:

定义1:MTS数据用图结构表示。图被定义为G=(V,E),其中V表示节点集,|V|=N,E是边集。假设在这里插入图片描述,将第i个变量视为第i个节点在这里插入图片描述在这里插入图片描述的值是的特征,每条边在这里插入图片描述的都表明vi和vj之间存在变量间的依赖关系。

定义2:加权邻接矩阵。图的加权邻接矩阵在这里插入图片描述是一种用于存储边权重的数学表示方法,其中如果在这里插入图片描述在这里插入图片描述;如果在这里插入图片描述在这里插入图片描述。对于没有任何先验知识的纯MTS数据,需要学习多图的加权邻接矩阵来表示丰富且隐式的变量间依赖关系。据此,MTS预测公式可修改为:在这里插入图片描述。其中在这里插入图片描述表示能被GNN用于MTS预测的图集。

图神经网络

论文方法中应用的图卷积操作定义如下:
在这里插入图片描述
其中G=(V,E,A)是一个带加权邻接矩阵的图,x是节点的表示,σ是一个激活函数,θ是可学习的参数矩阵,A\hat{}=I_{n}+A是具有自连接的邻接矩阵,D\hat{}A\hat{}的对角度矩阵,在这里插入图片描述。通过将图卷积操作多层堆叠,可以聚合多阶的邻居信息。

多尺度GNN,又称分层GNN,通常在细粒度图的基础上分层构建粗粒度图。MAGNN关注时间维度的尺度,与一般的多尺度GNN非常不同,后者主要关注空间维度的尺度。MAGNN引入了一个多尺度金字塔网络,将原始时间序列转换为从较小尺度到较大尺度的特征表示,在该网络上,它学习每个尺度下具有相同大小的特定尺度图,并对每个图使用公式在这里插入图片描述定义的基本GNN。

Framework

下图说明了MAGNN的框架,它包括四个主要部分:a)多尺度金字塔网络,用于在不同的时间尺度上保持底层的时间层次;b)自适应图学习模块,用于自动推断变量间的依赖关系;c)多尺度时间图神经网络,用于捕获各种尺度特定的时间模式;d)尺度级融合模块,用于有效地促进跨不同时间尺度的协作。
在这里插入图片描述
MAGNN框架的4个主要部分组成具体作用如下:(a)两个并行的卷积神经网络和每层的逐点相加将特征表示从较小尺度分层变换到较大尺度;(b)自适应图学习模块将节点嵌入和尺度嵌入作为输入,并输出特定尺度的邻接矩阵;©将每个尺度特定的特征表示和邻接矩阵输入到时序图神经网络(TGNN)中,以获得尺度特定的表示。(d)加权融合特定尺度表示以捕获贡献的时间模式。最终的多尺度表示被送入包括两个卷积神经网络的输出模块以获得预测值。

实验

数据集

为了评估MAGNN的性能,在六个公共基准数据集上进行了实验:太阳能、交通、电力、汇率、纳斯达克和METR-LA。表一汇总了数据集的统计数据,6个公共基准数据集的详细情况如下:
太阳能:此数据集包含从国家可再生能源实验室收集的太阳能,2007年从阿拉巴马州的137个光伏发电厂每10分钟采样一次。
交通:此数据集包含加州交通部的道路使用率(在0到1之间),这些数据是从2015年到2016年旧金山湾区的862个传感器每小时汇总的。
用电量:此数据集包含UCI机器学习存储库的用电量,从2012年到2014年每小时汇总321个客户端的用电量。R汇率:该数据集包含八个国家的汇率,从1990年到2016年每天都进行抽样。
Nasdaq:这个数据集包含82家公司的股票价格,从2016年7月到2016年12月每分钟抽样一次。
METR-LA:此数据集包含洛杉矶县的平均车速,这些车速是从2012年3月至2012年6月高速公路上的207个环路探测器收集的5分钟数据。
将六个数据集按时间顺序分为训练集(60%)、验证集(20%)和测试集(20%)。
在这里插入图片描述
输入窗口大小T设置为168。学习率设置为0.001。使用ADAM优化器,所有可训练的参数都可以通过反向传播进行优化。对于所有数据集,尺度数为4。多尺度金字塔网络中的CNN的核大小从金字塔网络的第一层到最后一层分别设置为1×7、1×6和1×3,所有CNN的步长设置为2。作者分别设置地平线h={3,6,12,24},对于Nasdaq数据集,预测范围被设置为3到24分钟,对于METR-LA数据集,从15到120分钟,对于太阳能数据集,从30到240分钟,对于交通和电力数据集,从3到24小时,对于汇率数据集,从3到24天。预测范围越大,预测就越难。

实验结果

六个数据集上所有方法的结果总结如下表(按RSE表示):
在这里插入图片描述
在六个真实数据集上的实验表明,MAGNN在各种设置下的性能都优于最先进的方法。

深度学习

MAGNN模型相关代码

from layer import *
# from AGCRN import *
import torch
 
class magnn(nn.Module):
    def __init__(self, gcn_depth, num_nodes, device, dropout=0.3, subgraph_size=20, node_dim=40, conv_channels=32, gnn_channels=32, scale_channels=16, end_channels=128, seq_length=12, in_dim=1, out_dim=12, layers=3, propalpha=0.05, tanhalpha=3, single_step=True):
        super(magnn, self).__init__()
 
        self.num_nodes = num_nodes
        self.dropout = dropout
 
        self.device = device
        self.single_step = single_step
        self.filter_convs = nn.ModuleList()
        self.gate_convs = nn.ModuleList()
 
        self.scale_convs = nn.ModuleList()
        self.gconv1 = nn.ModuleList()
        self.gconv2 = nn.ModuleList()
        self.norm = nn.ModuleList()
 
        
        self.seq_length = seq_length
        self.layer_num = layers
 
 
        self.gc = graph_constructor(num_nodes, subgraph_size, node_dim, self.layer_num, device)
 
        
        if self.single_step:
            self.kernel_set = [7, 6, 3, 2]
        else:
            self.kernel_set = [3, 2, 2]
 
 
        self.scale_id = torch.autograd.Variable(torch.randn(self.layer_num, device=self.device), requires_grad=True)
        # self.scale_id = torch.arange(self.layer_num).to(device)
        self.lin1 = nn.Linear(self.layer_num, self.layer_num) 
 
        self.idx = torch.arange(self.num_nodes).to(device)
        self.scale_idx = torch.arange(self.num_nodes).to(device)
 
 
        self.scale0 = nn.Conv2d(in_channels=in_dim, out_channels=scale_channels, kernel_size=(1, self.seq_length), bias=True)
 
        self.multi_scale_block = multi_scale_block(in_dim, conv_channels, self.num_nodes, self.seq_length, self.layer_num, self.kernel_set)
        # self.agcrn = nn.ModuleList()
        
        length_set = []
        length_set.append(self.seq_length-self.kernel_set[0]+1)
        for i in range(1, self.layer_num):
            length_set.append( int( (length_set[i-1]-self.kernel_set[i])/2 ) )
 
 
        for i in range(self.layer_num):
            """
            RNN based model
            """
            # self.agcrn.append(AGCRN(num_nodes=self.num_nodes, input_dim=conv_channels, hidden_dim=scale_channels, num_layers=1) )
            
            self.gconv1.append(mixprop(conv_channels, gnn_channels, gcn_depth, dropout, propalpha))
            self.gconv2.append(mixprop(conv_channels, gnn_channels, gcn_depth, dropout, propalpha))
            
            self.scale_convs.append(nn.Conv2d(in_channels=conv_channels,
                                                    out_channels=scale_channels,
                                                    kernel_size=(1, length_set[i])))
 
 
        self.gated_fusion = gated_fusion(scale_channels, self.layer_num)
        # self.output = linear(self.layer_num*self.hidden_dim, out_dim)
        self.end_conv_1 = nn.Conv2d(in_channels=scale_channels,
                                             out_channels=end_channels,
                                             kernel_size=(1,1),
                                             bias=True)
        self.end_conv_2 = nn.Conv2d(in_channels=end_channels,
                                             out_channels=out_dim,
                                             kernel_size=(1,1),
                                             bias=True)
 
    def forward(self, input, idx=None):
        seq_len = input.size(3)
 
        assert seq_len==self.seq_length, 'input sequence length not equal to preset sequence length'
        
        scale = self.multi_scale_block(input, self.idx)
 
        # self.scale_weight = self.lin1(self.scale_id)
        
        self.scale_set = [1, 0.8, 0.6, 0.5]
 
 
        adj_matrix = self.gc(self.idx, self.scale_idx, self.scale_set)
 
        outputs = self.scale0(F.dropout(input, self.dropout, training=self.training))
 
        out = []
        out.append(outputs)
        
        for i in range(self.layer_num):
            """
            RNN-based model
            """
            # output = self.agcrn[i](scale[i].permute(0, 3, 2, 1), adj_matrix) # B T N D
            # output = output.permute(0, 3, 2, 1)
            
            output = self.gconv1[i](scale[i], adj_matrix[i])+self.gconv2[i](scale[i], adj_matrix[i].transpose(1,0))
            
            
            scale_specific_output = self.scale_convs[i](output)
            
            out.append(scale_specific_output)
 
            # concatenate
            # outputs = outputs + scale_specific_output
 
        # mean-pooling    
        # outputs = torch.mean(torch.stack(out), dim=0)
 
        out0 = torch.cat(out, dim=1)
        out1 = torch.stack(out, dim = 1)
        
        if self.single_step:
            outputs = self.gated_fusion(out0, out1)
        
        x = F.relu(outputs)
        x = F.relu(self.end_conv_1(x))
        x = self.end_conv_2(x)
        
        return x, adj_matrix

网络层定义如下:

from __future__ import division
import torch
import torch.nn as nn
from torch.nn import init
import numbers
import torch.nn.functional as F
import numpy as np
 
 
class nconv(nn.Module):
    def __init__(self):
        super(nconv,self).__init__()
 
    def forward(self,x, A):
        x = torch.einsum('ncvl,vw->ncwl',(x,A))
        return x.contiguous()
 
class dy_nconv(nn.Module):
    def __init__(self):
        super(dy_nconv,self).__init__()
 
    def forward(self,x, A):
        x = torch.einsum('ncvl,nvwl->ncwl',(x,A))
        return x.contiguous()
 
class linear(nn.Module):
    def __init__(self,c_in,c_out,bias=True):
        super(linear,self).__init__()
        self.mlp = torch.nn.Conv2d(c_in, c_out, kernel_size=(1, 1), padding=(0,0), stride=(1,1), bias=bias)
 
    def forward(self,x):
        return self.mlp(x)
 
class layer_block(nn.Module):
    def __init__(self, c_in, c_out, k_size):
        super(layer_block, self).__init__()
        self.conv_output = nn.Conv2d(c_in, c_out, kernel_size=(1, 1), stride=(1, 2))
 
        self.conv_output1 = nn.Conv2d(c_in, c_out, kernel_size=(1, k_size), stride=(1, 1), padding=(0, int( (k_size-1)/2 ) ) )
        self.output = nn.MaxPool2d(kernel_size=(1,3), stride=(1,2), padding=(0,1))
 
        self.conv_output1 = nn.Conv2d(c_in, c_out, kernel_size=(1, k_size), stride=(1, 1) )
        self.output = nn.MaxPool2d(kernel_size=(1,3), stride=(1,2))
        self.relu = nn.ReLU()
        
        
    def forward(self, input):
        conv_output = self.conv_output(input) # shape (B, D, N, T)
 
        conv_output1 = self.conv_output1(input)
        
        output = self.output(conv_output1)
 
        return self.relu( output+conv_output[...,-output.shape[3]:] )
 
        # return self.relu( conv_output )
 
 
class multi_scale_block(nn.Module):
    def __init__(self, c_in, c_out, num_nodes, seq_length, layer_num, kernel_set, layer_norm_affline=True):
        super(multi_scale_block, self).__init__()
 
        self.seq_length = seq_length
        self.layer_num = layer_num
        self.norm = nn.ModuleList()
        self.scale = nn.ModuleList()
 
        for i in range(self.layer_num):
            self.norm.append(nn.BatchNorm2d(c_out, affine=False))
        #     # self.norm.append(LayerNorm((c_out, num_nodes, int(self.seq_length/2**i)),elementwise_affine=layer_norm_affline))
        #     self.norm.append(LayerNorm((c_out, num_nodes, length_set[i]),elementwise_affine=layer_norm_affline))
        
        self.start_conv = nn.Conv2d(c_in, c_out, kernel_size=(1, 1), stride=(1, 1))
 
        self.scale.append(nn.Conv2d(c_out, c_out, kernel_size=(1, kernel_set[0]), stride=(1, 1)))
 
        for i in range(1, self.layer_num):
            
            self.scale.append(layer_block(c_out, c_out, kernel_set[i]))
 
        
    def forward(self, input, idx): # input shape: B D N T
 
        self.idx = idx
 
        scale = []
        scale_temp = input
        
        scale_temp = self.start_conv(scale_temp)
        # scale.append(scale_temp)
        for i in range(self.layer_num):
            scale_temp = self.scale[i](scale_temp)
            # scale_temp = self.norm[i](scale_temp)
            # scale_temp = self.norm[i](scale_temp, self.idx)
 
            # scale.append(scale_temp[...,-self.k:])
            scale.append(scale_temp)
 
        return scale
 
 
class top_down_path(nn.Module):
    def __init__(self, c_in, c_out_1, c_out_2, c_out_3, c_out_4):
        super(top_down_path, self).__init__()
        self.down1 = nn.Conv2d(c_in, c_out_1, kernel_size=(1, 1), stride=(1, 1))
        self.down2 = nn.Conv2d(c_out_1, c_out_2, kernel_size=(1, 7), stride=(1, 2), padding=(0, 2))
        self.down3 = nn.Conv2d(c_out_2, c_out_3, kernel_size=(1, 6), stride=(1, 2))
 
        self.down4 = nn.Conv2d(c_out_3, c_out_4, kernel_size=(1, 3), stride=(1, 2))
 
        self.up3 = nn.ConvTranspose2d(c_out_4, c_out_3, kernel_size=(1,3), stride=(1,2))
        # self.up3 = nn.MaxUnpool2d()
        self.up2 = nn.ConvTranspose2d(c_out_3, c_out_2, kernel_size=(1,6), stride=(1,2), output_padding=(0,1))
        self.up1 = nn.ConvTranspose2d(c_out_2, c_out_1, kernel_size=(1,7), stride=(1,2))
 
    def forward(self, input):
        down_1 = self.down1(input)
        down_2 = self.down2(down_1)
        down_3 = self.down3(down_2)
        down_4 = self.down4(down_3)
 
 
        up_3 = self.up3(down_4)
        output_3 = down_3 + up_3
 
        up_2 = self.up2(output_3)
        output_2 = down_2 + up_2
 
        up_1 = self.up3(output_2)
        output_1 = down_1[:,:,:,1:] + up_1
 
        return down_4, output_3, output_2, output_1
 
class gated_fusion(nn.Module):
    def __init__(self, skip_channels, layer_num, ratio=1):
        super(gated_fusion, self).__init__()
        # self.reduce = torch.mean(x,dim=2,keepdim=True)
        self.dense1 = nn.Linear(in_features=skip_channels*(layer_num+1), out_features=(layer_num+1)*ratio, bias=False)
         
        self.dense2 = nn.Linear(in_features=(layer_num+1)*ratio, out_features=(layer_num+1), bias=False)
 
 
    def forward(self, input1, input2):
 
        se = torch.mean(input1, dim=2, keepdim=False)
        se = torch.squeeze(se)
 
        se = F.relu(self.dense1(se))
        se = F.sigmoid(self.dense2(se))
 
        se = torch.unsqueeze(se, -1)
        se = torch.unsqueeze(se, -1)
        se = torch.unsqueeze(se, -1)
 
        x = torch.mul(input2, se)
        x = torch.mean(x, dim=1, keepdim=False)
        return x
 
class prop(nn.Module):
    def __init__(self,c_in,c_out,gdep,dropout,alpha):
        super(prop, self).__init__()
        self.nconv = nconv()
        self.mlp = linear(c_in,c_out)
        self.gdep = gdep
        self.dropout = dropout
        self.alpha = alpha
 
    def forward(self,x,adj):
        adj = adj + torch.eye(adj.size(0)).to(x.device)
        d = adj.sum(1)
        h = x
        dv = d
        a = adj / dv.view(-1, 1)
        for i in range(self.gdep):
            h = self.alpha*x + (1-self.alpha)*self.nconv(h,a)
        ho = self.mlp(h)
        return ho
 
 
class mixprop(nn.Module):
    def __init__(self,c_in,c_out,gdep,dropout,alpha):
        super(mixprop, self).__init__()
        self.nconv = nconv()
        self.mlp = linear((gdep+1)*c_in,c_out)
        self.gdep = gdep
        self.dropout = dropout
        self.alpha = alpha
 
 
    def forward(self,x,adj):
        adj = adj + torch.eye(adj.size(0)).to(x.device)
        d = adj.sum(1)
        h = x
        out = [h]
        a = adj / d.view(-1, 1)
        for i in range(self.gdep):
            h = self.alpha*x + (1-self.alpha)*self.nconv(h,a)
            out.append(h)
 
        ho = torch.cat(out,dim=1)
 
        ho = self.mlp(ho)
 
        return ho
 
 
class graph_constructor(nn.Module):
    def __init__(self, nnodes, k, dim, layer_num, device, alpha=3):
        super(graph_constructor, self).__init__()
        self.nnodes = nnodes
        self.layers = layer_num
        
        self.emb1 = nn.Embedding(nnodes, dim)
        self.emb2 = nn.Embedding(nnodes, dim)
 
        self.lin1 = nn.ModuleList()
        self.lin2 = nn.ModuleList()
        for i in range(layer_num):
            self.lin1.append(nn.Linear(dim,dim))
            self.lin2.append(nn.Linear(dim,dim))
 
        self.device = device
        self.k = k
        self.dim = dim
        self.alpha = alpha
        
 
    def forward(self, idx, scale_idx, scale_set):
        
        nodevec1 = self.emb1(idx)
        nodevec2 = self.emb2(idx)
 
        adj_set = []
 
        for i in range(self.layers):
            nodevec1 = torch.tanh(self.alpha*self.lin1[i](nodevec1*scale_set[i]))
            nodevec2 = torch.tanh(self.alpha*self.lin2[i](nodevec2*scale_set[i]))
            a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))
            adj0 = F.relu(torch.tanh(self.alpha*a))
            
        
            mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device)
            mask.fill_(float('0'))
            s1,t1 = adj0.topk(self.k,1)
            mask.scatter_(1,t1,s1.fill_(1))
            # print(mask)
            adj = adj0*mask
            adj_set.append(adj)
 
 
        return adj_set
 
 
class graph_constructor_full(nn.Module):
    def __init__(self, nnodes, k, dim, layer_num, device, alpha=3):
        super(graph_constructor_full, self).__init__()
        self.nnodes = nnodes
        self.layers = layer_num
        
        
        self.emb1 = nn.Embedding(nnodes, dim)
        self.emb2 = nn.Embedding(nnodes, dim)
 
        self.lin1 = nn.ModuleList()
        self.lin2 = nn.ModuleList()
        for i in range(self.layers):
            self.lin1.append(nn.Linear(dim,dim))
            self.lin2.append(nn.Linear(dim,dim))
 
        self.device = device
        self.k = k
        self.dim = dim
        self.alpha = alpha
        self.static_feat = static_feat
 
    def forward(self, idx, scale_idx, scale_set):
        
        nodevec1 = self.emb1(idx)
        nodevec2 = self.emb2(idx)
 
 
        adj_set = []
 
        for i in range(self.layers):
            nodevec1 = torch.tanh(self.alpha*self.lin1[i](nodevec1*scale_set[i]))
            nodevec2 = torch.tanh(self.alpha*self.lin2[i](nodevec2*scale_set[i]))
            a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))
            adj0 = F.relu(torch.tanh(self.alpha*a))
            adj_set.append(adj0)
 
        return adj_set
 
class graph_constructor_one(nn.Module):
    def __init__(self, nnodes, k, dim, layer_num, device, alpha=3, static_feat=None):
        super(graph_constructor_one, self).__init__()
        self.nnodes = nnodes
        self.layers = layer_num
        
        self.emb1 = nn.Embedding(nnodes, dim)
        self.emb2 = nn.Embedding(nnodes, dim)
 
        self.lin1 = nn.ModuleList()
        self.lin2 = nn.ModuleList()
        
        self.lin1 = nn.Linear(dim,dim)
        self.lin2 = nn.Linear(dim,dim)
 
        self.device = device
        self.k = k
        self.dim = dim
        self.alpha = alpha
        self.static_feat = static_feat
 
    def forward(self, idx, scale_idx, scale_set):
        
        nodevec1 = self.emb1(idx)
        nodevec2 = self.emb2(idx)
        
 
        adj_set = []
 
        nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1))
        nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2))
        a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))
        adj0 = F.relu(torch.tanh(self.alpha*a))
            
        
        mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device)
        mask.fill_(float('0'))
        s1,t1 = adj0.topk(self.k,1)
        mask.scatter_(1,t1,s1.fill_(1))
 
        adj = adj0*mask
 
 
        return adj

GNN

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在使用图的时候可以简单的将其划分为下面几步:

1.给定一个图,首先将节点转化为递归单元,将边转化为前馈神经网络;
2.对所有节点执行n次邻域聚合(消息传递)。
3.对所有节点的嵌入向量求和得到图表示H。
4.将H传递到更高的层中,或者使用它来表示图形的独特属性。

为什么要用GNN?

GNN与CNN、RNN的比较,为什么不用CNN或RNN,而用GNN?

GNN 是一种专门为图结构数据设计的神经网络。它可以处理不规则的拓扑结构,并且可以捕捉节点之间的复杂关系。GNN可以通过消息传递和聚合机制来处理不同大小和结构的图数据。由于其适应性和灵活性,GNN 在许多领域,如社交网络分析、化学分子识别和推荐系统等,取得了显著的成功。

选择 GNN 而不是 CNN 或 RNN 的主要原因是数据结构和任务类型。当处理图结构数据或需要捕捉复杂的节点关系时,GNNs是更合适的选择。然而,在处理网格结构数据(如图像)或序列数据(如文本)时,CNN和 RNN可能是更好的选择。

GNN简单来说就是Graph + Nerual Networks,关键问题就是将图的结构和图中每个节点和边的特征转化为一般的神经网络的输入(张量)。

GNN面临挑战

目前,GNN面临的挑战主要包括:1)如何有效处理大规模图数据;2)如何增强GNN的表达能力,以捕捉更为复杂的图结构;3)如何解决图数据中的不确定性和噪声问题。

总结

下周将继续学习GNN的一些相关数学知识,从理论上进一步理解GNN。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/781741.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core----基础学习03----开发者异常页面 MVC工作原理及实现

文章目录 1. 开发者异常页面(1)Startup.cs 页面的基础配置(2)自定义显示报错代码的前后XX行 2. MVC 的原理3. MVC 的实现4.默认路由路径5.返回Json字符串 1. 开发者异常页面 (1)Startup.cs 页面的基础配置 namespace ASP.Net_Blank {public class Startup{private readonly IC…

Linux muduo 网络库

主要记录示意图和知识点框架: 1、阻塞、非阻塞、同步、异步 在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO。 2、五种IO模型: 阻塞、非阻塞、IO复用、信号驱动、异步IO 3、muduo网络库 muduo网络库给用…

【python】python当当数据分析可视化聚类支持向量机预测(源码+数据集+论文)【独一无二】

👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉公众号👈:测试开发自动化【获取源码商业合作】 👉荣__誉👈:阿里云博客专家博主、5…

windows 服务器安装svn服务端、迁移svn

svn服务器版本 因为要把旧svn迁移到新的svn,为了保证迁移后的稳定性,安装包使用的旧服务器的svn服务器版本 VisualSVN-Server-3.6.1-x64.msi 安装 配置仓库路径等 其他没截图的就默认配置下一步即可。安装完成先不要启动 迁移 旧的svn服务器直接把…

Windows远程桌面实现之十五:投射浏览器摄像头到xdisp_virt以及再次模拟摄像头(一)

by fanxiushu 2024-07-01 转载或引用请注明原始作者。 本文还是围绕xdisp_virt这个软件展开, 再次模拟成摄像头这个比较好理解,早在很久前,其实xdisp_virt项目中就有摄像头功能, 只是当时是分开的,使用起来…

【SpringBoot】IDEA查看spring bean的依赖关系

前因:在研究springcloud config组件时,我发现config-server包下的EnvironmentController不在扫描的包路径下却可以响应客户端的请求,这吸引了我的注意,我的问题是:EnvironmentController是怎么被添加进bean工厂的。本章…

Golang | Leetcode Golang题解之第218题天际线问题

题目: 题解: type pair struct{ right, height int } type hp []pairfunc (h hp) Len() int { return len(h) } func (h hp) Less(i, j int) bool { return h[i].height > h[j].height } func (h hp) Swap(i, j int) { h[i], h[j]…

26_嵌入式系统网络接口

以太网接口基本原理 IEEE802标准 局域网标准协议工作在物理层和数据链路层,其将数据链路层又划分为两层,从下到上分别为介质访问控制子层(不同的MAC子层,与具体接入的传输介质相关),逻辑链路控制子层(统一的LLC子层,为上层提供统…

CosyVoice多语言、音色和情感控制模型,one-shot零样本语音克隆模型本地部署(Win/Mac),通义实验室开源

近日,阿里通义实验室开源了CosyVoice语音模型,它支持自然语音生成,支持多语言、音色和情感控制,在多语言语音生成、零样本语音生成、跨语言声音合成和指令执行能力方面表现卓越。 CosyVoice采用了总共超15万小时的数据训练&#…

GuitarPro2024音乐软件#创作神器#音乐梦想

嘿,亲爱的朋友们!👋👋👋今天我要给你们安利一款超赞的软件——Guitar Pro。这款软件简直是吉他手的福音啊!🎉🎉🎉 Guitar Pro免费绿色永久安装包下载:&#…

如何快速申请免费SSL证书,实现网站HTTPS安全传输

随着互联网技术的飞速发展,网络安全已成为不可忽视的重要议题。HTTPS协议,作为HTTP协议的安全版本,通过SSL协议加密客户端与服务器之间的数据传输,从而保障信息在传输过程中的安全性。对于网站运营者而言,为网站部署SS…

SpringBoot测试类注入Bean失败的原因

针对SpringBoot的测试类&#xff0c;2.2版本之前和之后是不一样的。 2.2版本之后 导包pom.xml 添加test依赖 <!-- starter-test&#xff1a;junit spring-test mockito --> <dependency><groupId>org.springframework.boot</groupId><artifac…

论文解析——FTRANS: Energy-Efficient Acceleration of Transformers using FPGA

作者及发刊详情 Li B , Pandey S , Fang H ,et al.FTRANS: energy-efficient acceleration of transformers using FPGA[J].ACM, 2020.DOI:10.1145/3370748.3406567. 摘要 正文 主要工作贡献 与CPU和GPU在执行Transformer和RoBERTa相比&#xff0c;提出的FTRANS框架获得了…

ansible常见问题配置好了密码还是报错

| FAILED! > { “msg”: “Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host’s fingerprint to your known_hosts file to manage this host.” } 怎么解决&#xf…

[终端安全]-3 移动终端之硬件安全(TEE)

&#xff08;参考资料&#xff1a;TrustZone for V8-A. pdf&#xff0c;来源ARM DEVELOPER官网&#xff09; TEE&#xff08;Trusted Execution Environment&#xff0c;可信执行环境&#xff09;是用于执行敏感代码和处理敏感数据的独立安全区域&#xff1b;以ARM TrustZone为…

分布式技术栈、微服务架构 区分

1.分布式技术栈 这些技术栈都是为了更好的开发分布式架构的项目。 &#xff08;大营销平台的系统框架如下图&#xff0c;扩展的分布式技术栈&#xff09; &#xff08;1&#xff09;Dubbo——分布式技术栈 DubboNacos注册中心是应用可以分布式部署&#xff0c;并且提供RPC接…

HTML5使用<pre>标签:保留原始排版方式

在网页创作中&#xff0c;一般是通过各种标记对文字进行排版的。但是在实际应用中&#xff0c;往往需要一些特殊的排版效果&#xff0c;这样使用标记控制起来会比较麻烦。解决的方法就是保留文本格式的排版效果&#xff0c;如空格、制表符等。 如果要保留原始的文本排版效果&a…

redis并发、穿透、雪崩

Redis如何实现高并发 首先是单线程模型&#xff1a;redis采用单线程可以避免多线程下切换和竞争的开销&#xff0c;提高cpu的利用率&#xff0c;如果是多核cpu&#xff0c;可以部署多个redis实例。基于内存的数据存储&#xff1a;redis将数据存储在内存中&#xff0c;相比于硬…

回溯算法-以景点门票销售管理系统为例

1.回溯算法介绍 1.来源 回溯算法也叫试探法&#xff0c;它是一种系统地搜索问题的解的方法。 用回溯算法解决问题的一般步骤&#xff1a; 1、 针对所给问题&#xff0c;定义问题的解空间&#xff0c;它至少包含问题的一个&#xff08;最优&#xff09;解。 2 、确定易于搜…

唤醒知识循环,共筑绿色阅读梦——探索旧书回收小程序的无限可能

在这个信息爆炸的时代&#xff0c;书籍作为知识与智慧的载体&#xff0c;其重要性不言而喻。然而&#xff0c;随着电子阅读的兴起和书籍更新换代的加速&#xff0c;大量旧书被束之高阁&#xff0c;甚至面临被遗弃的命运。这不仅是对宝贵文化资源的浪费&#xff0c;也是对环境保…