Datawhale 图神经网络 Task02消息传递图神经网络

这次我一开始真的看懵了,不知道我要干什么,消息传递图神经网络读起来也怪怪的。
直到快要交作业的时候,我貌似有些明白标题的意思了(好多次都是这样,到节点才开始……)
我的理解是这样的,所谓消息传递(MessagePassing)的目的是为了将每个节点生成node embedding,这就很像transformer里的注意力机制了。
这个embedding的过程大约是:
我是我,
我不是我,
我还是我。
即一开始,图中的节点从描述了实际的情况,但是这么直白的描述所包含的信息太孤立了,这种情况下做图训练和做CV估计都差不多了,我们希望每个节点所包含的信息是不仅有自身的属性,还有联系的属性,毕竟哲学告诉我们世界是联系的。
然后,就使用消息传递范式用节点周围的节点和边(可选)与该节点来个“糅合”,打太极的那种,混的越玄乎说不定效果越好。
在这里插入图片描述
之后,当每个节点都被”糅合“了以后,大家就包含了互相的信息,这是我还是我,但是我不仅有我,我心里还有大家。

这个”糅合“ 的过程是convolution operator,也就是卷积运算,所以”卷“这个东西虽然折磨人吧,但是用它去折磨数据还是挺有益的。

torch-geometry官方一开始只是用符号描述了convoluntion operator的概念(大佬都是搭框架的,并且搭出来还很好用),然后具体介绍了两种方法,GCN layer from Kipf and Welling和EdgeConv layer from Wang et al.
在这里插入图片描述
让我们看一下总概念公式和两个具体的公式,这样就清晰多了。
在这里插入图片描述
这两个公式如何实现呢?
torch-geometry已经写好了MessagePassing的类,继承过来相应改下就Ok了。

GCN layer

import torch
from torch_geometric.nn import MessagePassing
from torch_geometric.utils import add_self_loops, degree

class GCNConv(MessagePassing):
    def __init__(self, in_channels, out_channels):
        super(GCNConv, self).__init__(aggr='add')  # "Add" aggregation (Step 5).
        self.lin = torch.nn.Linear(in_channels, out_channels)

    def forward(self, x, edge_index):
        # x has shape [N, in_channels]
        # edge_index has shape [2, E]

        # Step 1: Add self-loops to the adjacency matrix.
        edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))

        # Step 2: Linearly transform node feature matrix.
        x = self.lin(x)

        # Step 3: Compute normalization.
        row, col = edge_index
        deg = degree(col, x.size(0), dtype=x.dtype)
        deg_inv_sqrt = deg.pow(-0.5)
        deg_inv_sqrt[deg_inv_sqrt == float('inf')] = 0
        norm = deg_inv_sqrt[row] * deg_inv_sqrt[col]

        # Step 4-5: Start propagating messages.
        return self.propagate(edge_index, x=x, norm=norm)

    def message(self, x_j, norm):
        # x_j has shape [E, out_channels]

        # Step 4: Normalize node features.
        return norm.view(-1, 1) * x_j

关于这一步“# Step 1: Add self-loops to the adjacency matrix.”,群里有人说是为了把自己的信息保留住,防止自身信息丢失。

edge convolution layer

import torch
from torch.nn import Sequential as Seq, Linear, ReLU
from torch_geometric.nn import MessagePassing

class EdgeConv(MessagePassing):
    def __init__(self, in_channels, out_channels):
        super(EdgeConv, self).__init__(aggr='max') #  "Max" aggregation.
        self.mlp = Seq(Linear(2 * in_channels, out_channels),
                       ReLU(),
                       Linear(out_channels, out_channels))

    def forward(self, x, edge_index):
        # x has shape [N, in_channels]
        # edge_index has shape [2, E]

        return self.propagate(edge_index, x=x)

    def message(self, x_i, x_j):
        # x_i has shape [E, in_channels]
        # x_j has shape [E, in_channels]

        tmp = torch.cat([x_i, x_j - x_i], dim=1)  # tmp has shape [E, 2 * in_channels]
        return self.mlp(tmp)

如下将edge convolution 升级为动态的convolution

from torch_geometric.nn import knn_graph

class DynamicEdgeConv(EdgeConv):
    def __init__(self, in_channels, out_channels, k=6):
        super(DynamicEdgeConv, self).__init__(in_channels, out_channels)
        self.k = k

    def forward(self, x, batch=None):
        edge_index = knn_graph(x, self.k, batch, loop=False, flow=self.flow)
        return super(DynamicEdgeConv, self).forward(x, edge_index)

本次组队学习的教程还讲了如何覆写propagate,message,update以及官网介绍貌似没有说的aggregate与message_and_aggragate函数,应该都是在公式上进行个性化制定。 本次作业也是MessagePassing这几个函数的覆写,我刚刚看懂,比较吃力,还是留着以后再研究吧
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值