2024/7/7周报

news2025/1/4 10:51:58

文章目录

  • 摘要
  • 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。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows密码凭证获取

Windows HASH HASH简介 hash ,一般翻译做散列,或音译为哈希,所谓哈希,就是使用一种加密函数进行计算后的结果。这个 加密函数对一个任意长度的字符串数据进行一次数学加密函数运算,然后返回一个固定长度的字符串。…

C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用

C# 异步编程Invoke、beginInvoke、endInvoke的用法和作用 一、Invoke Invoke的本质只是一个方法,方法一定是要通过对象来调用的。 一般来说,Invoke其实用法只有两种情况: Control的Invoke Delegate的Invoke 也就是说,Invoke前…

动态规划|剑指 Offer II 093. 最长斐波那契数列

如果数组 arr 中存在三个下标 i、j、k 满足 arr[i]>arr[j]>arr[k] 且 arr[k]arr[j]arr[i],则 arr[k]、arr[j] 和 arr[i] 三个元素组成一个斐波那契式子序列。由于数组 arr 严格递增,因此 arr[i]>arr[j]>arr[k] 等价于 i>j>k。 把这道题…

7.7作业

搭建一个场景: 将学生的信息,以顺序表的方式存储(堆区),并且实现封装函数 : 1】顺序表的创建 2】判满 3】判空 4】往顺序表里增加学生 5】遍历 6】任意位置插入学生 7】任意位置删除学生 8】修改 9】查找&a…

刷题之删除有序数组中的重复项(leetcode)

删除有序数组中的重复项 这题简单题&#xff0c;双指针&#xff0c;一个指针记录未重复的数的个数&#xff0c;另一个记录遍历的位置。 以下是简单模拟&#xff0c;可以优化&#xff1a; class Solution { public:int removeDuplicates(vector<int>& nums) {int l0…

PyTorch中的多进程并行处理

PyTorch是一个流行的深度学习框架&#xff0c;一般情况下使用单个GPU进行计算时是十分方便的。但是当涉及到处理大规模数据和并行处理时&#xff0c;需要利用多个GPU。这时PyTorch就显得不那么方便&#xff0c;所以这篇文章我们将介绍如何利用torch.multiprocessing模块&#x…

含并行连结的网络

一、Inception块 1、白色部分通过降低通道数来控制模型复杂度&#xff0c;蓝色做特征提取工作&#xff0c;每条路上的通道数可能不同&#xff0c;大概我们会把更重要的那部分特征分配更多的通道数 2、Inception只改变高宽&#xff0c;不改变通道数 3、在不同的情况下需要选择…

渐开线花键测量学习笔记分享

大家好&#xff0c;继续渐开线花键的相关内容&#xff0c;本期是渐开线花键测量相关的学习笔记分享&#xff1a; 花键检测项目有花键大径和小径检验&#xff1b;内花键齿槽宽和外花键齿厚&#xff0c;以及渐开线终止圆 和起始圆直径检测&#xff1b;齿距累计误差 、齿形误差 、…

MySQL—统计函数和数学函数以及GROUP BY配合HAVING

合计/统计函数 count -- 演示 mysql 的统计函数的使用 -- 统计一个班级共有多少学生&#xff1f; SELECT COUNT(*) FROM student -- 统计数学成绩大于 90 的学生有多少个&#xff1f; SELECT COUNT(*) FROM student WHERE math > 90 -- 统计总分大于 250 的人数有多少&…

Centos新手问题——yum无法下载软件

起因&#xff1a; 最近在学习centos7&#xff0c;在VM上成功安装后&#xff0c;用Secure进行远程登陆。然后准备下载一个C编译器&#xff0c;看网络上的教程&#xff0c;都是用yum来下载&#xff0c;于是我也输入了命令&#xff1a; yum -y install gcc* 本以为会自动下载&a…

数据统计与数据分组18-25题(30 天 Pandas 挑战)

数据统计与数据分组 1. 知识点1.18 分箱与统计个数1.19 分组与求和统计1.20 分组获取最小值1.21 分组获取值个数1.22 分组与条件查询1.23 分组与条件查询及获取最大值1.24 分组及自定义函数1.25 分组lambda函数统计 2. 题目2.18 按分类统计薪水&#xff08;数据统计&#xff09…

《python程序语言设计》2018版第5章第52题利用turtle绘制sin函数

这道题是送分题。因为循环方式已经写到很清楚&#xff0c;大家照抄就可以了。 但是如果说光照抄可是会有问题。比如我们来演示一下。 import turtleturtle.penup() turtle.goto(-175, 50 * math.sin((-175 / 100 * 2 * math.pi))) turtle.pendown() for x in range(-175, 176…

5款屏幕监控软件精选|电脑屏幕监控软件分享

屏幕监控软件在现代工作环境中扮演着越来越重要的角色&#xff0c;无论是为了提高员工的工作效率&#xff0c;还是为了保障企业数据的安全&#xff0c;它们都成为了不可或缺的工具。 下面&#xff0c;让我们以一种新颖且易于理解的方式&#xff0c;来介绍五款备受好评的屏幕监…

前端JS特效第21集:HTML5响应式多种切换效果轮播大图切换js特效代码

HTML5响应式多种切换效果轮播大图切换js特效代码&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下(全部代码在文章末尾)&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-t…

灵活视图变换器:为扩散模型设计的革新图像生成架构

在自然界中&#xff0c;图像的分辨率是无限的&#xff0c;而现有的图像生成模型在跨任意分辨率泛化方面存在困难。虽然扩散变换器&#xff08;DiT&#xff09;在特定分辨率范围内表现出色&#xff0c;但在处理不同分辨率的图像时却力不从心。为了克服这一限制&#xff0c;来自上…

MySQL篇三:数据类型

文章目录 前言1. 数值类型1.1 tinyint类型1.2 bit类型1.3 小数类型1.3.1 float1.3.2 decimal 2. 字符串类型2.1 char2.2 varchar2.3 char和varchar比较 3. 日期类型4. enum和set 前言 数据类型分类&#xff1a; 1. 数值类型 1.1 tinyint类型 在MySQL中&#xff0c;整型可以指…

MPS---MPQ86960芯片layout设计总结

MPQ86960 是一款内置功率 MOSFET 和栅极驱动的单片半桥。它可以在宽输入电压 (VIN) 范围内实现高达 50A 的连续输出电流 (IOUT)&#xff0c;通过集成MOSFET 和驱动可优化死区时间 (DT) 并降低寄生电感&#xff0c;从而实现高效率。 MPQ86960 兼容三态输出控制器&#xff0c;另…

[附源码]基于Flask的演唱会购票系统

摘要 随着互联网技术的普及和发展&#xff0c;传统购票方式因其效率低下、流程繁琐等问题已难以满足现代社会的需求。本文设计并实现了一个基于Flask框架的演唱会购票系统&#xff0c;该系统集成了用户管理、演唱会信息管理、票务管理以及数据统计与分析等功能模块&#xff0c…

如何让代码兼容 Python 2 和 Python 3?Future 库助你一臂之力

目录 01Future 是什么? 为什么选择 Future? 安装与配置 02Future 的基本用法 1、兼容 print 函数 2、兼容整数除法 3、兼容 Unicode 字符串 03Future 的高级功能 1. 处理字符串与字节 2. 统一异常处理…

nullptr和NULL

nullptr 既不是整型类型&#xff0c;也不是指针类型&#xff0c;nullptr 的类型是 std::nullptr_t&#xff08;空指针类型&#xff09;&#xff0c;能转换成任意的指针类型。 NULL是被定义为0的常量&#xff0c;当遇到函数重载时&#xff0c;就会出现问题。避免歧义 函数重载…