GCN原理回顾论文导读

Cora_dataset description

Cora数据集是一个常用的学术文献用网络数据集,用于研究学术文献分类和图网络分析等任务。
该数据集由机器学习领域的博士论文摘要组成,共计2708篇论文,涵盖了7个不同的学科领域。每篇论文都有一个唯一的ID,并且被分为以下7个类别之一:Case_Based、Genetic_Algorithms、Neural_Networks、Probabilistic_Methods、Reinforcement_Learning、Rule_Learning和Theory。

除了论文之间的引用关系外,Cora数据集还包含了每篇论文的词袋表示,即将每篇论文表示为一个词频向量(0-1嵌入,每行有多个1,非one-hot vector,feature of node)。这些词频向量表示了论文中出现的单词及其在该论文中的出现频率。

Cora数据集常用于图神经网络的研究和评估,可以用于学术文献分类、引文网络分析、节点嵌入等任务。

print cora

dataset = Planetoid("./tmp/Cora", name="Cora", transform=T.NormalizeFeatures())
num_nodes = dataset.data.num_nodes
# For num. edges see:
# - https://github.com/pyg-team/pytorch_geometric/issues/343
# - https://github.com/pyg-team/pytorch_geometric/issues/852

num_edges = dataset.data.num_edges // 2
train_len = dataset[0].train_mask.sum()
val_len = dataset[0].val_mask.sum()
test_len = dataset[0].test_mask.sum()
other_len = num_nodes - train_len - val_len - test_len
print(f"Dataset: {dataset.name}")
print(f"Num. nodes: {num_nodes} (train={train_len}, val={val_len}, test={test_len}, other={other_len})")
print(f"Num. edges: {num_edges}")
print(f"Num. node features: {dataset.num_node_features}")
print(f"Num. classes: {dataset.num_classes}")
print(f"Dataset len.: {dataset.len()}")

在这里插入图片描述

GCN原理与实现

卷积公式: f ∗ g = F − 1 ( F ( f ) ⋅ F ( g ) ) f*g=F^{-1}(F(f)·F(g)) fg=F1(F(f)F(g))
给定一个图信号x和一个卷积核, x ∗ g = U ( U T x ⊙ U T g ) = U ( U T x ⊙ g θ ) = D ~ − 0.5 A ~ D ~ − 0.5 X Θ x*g=U(U^Tx\odot U^Tg)=U(U^Tx\odot g_{\theta})=\widetilde D^{-0.5}\widetilde A\widetilde D^{-0.5}X\Theta xg=U(UTxUTg)=U(UTxgθ)=D 0.5A D 0.5XΘ
其中A为图的邻接矩阵,D为图的度数矩阵,
D ~ = D + γ I , A ~ = A + γ I \widetilde D=D+\gamma I,\widetilde A=A+\gamma I D =D+γI,A =A+γI,添加自环以缩小 λ \lambda λ(Laplace matrix)

1.computation of D ~ − 0.5 A ~ D ~ − 0.5 \widetilde D^{-0.5}\widetilde A\widetilde D^{-0.5} D 0.5A D 0.5

def gcn_norm(edge_index, edge_weight=None, num_nodes=None,
add_self_loops=True, flow="source_to_target", dtype=None):
fill_value = 1.
num_nodes = maybe_num_nodes(edge_index, num_nodes)
if add_self_loops: #添加自环
edge_index, edge_weight = add_remaining_self_loops(
edge_index, edge_weight, fill_value, num_nodes)
edge_weight = torch.ones((edge_index.size(1), ), dtype=dtype,
device=edge_index.device)
row, col = edge_index[0], edge_index[1]
idx = col
deg = scatter(edge_weight, idx, dim=0, dim_size=num_nodes, reduce='sum')
deg_inv_sqrt = deg.pow_(-0.5)
deg_inv_sqrt.masked_fill_(deg_inv_sqrt == float('inf'), 0)
edge_weight = deg_inv_sqrt[row] * edge_weight * deg_inv_sqrt[col]
return edge_index, edge_weight

代码解释

edge_index, edge_weight = add_remaining_self_loops(edge_index, edge_weight,fill_value, num_nodes)
D ~ = D + γ I , A ~ = A + γ I \widetilde D=D+\gamma I,\widetilde A=A+\gamma I D =D+γI,A =A+γI;
deg = scatter(edge_weight, idx, dim=0, dim_size=num_nodes, reduce='sum')
根据edge_weight和idx=edge_index[1]得到度数矩阵,deg=D

  • explantation:edge_weight是要放入的对角阵,

deg_inv_sqrt = deg.pow_(-0.5):require D − 0.5 D^{-0.5} D0.5
deg_inv_sqrt.masked_fill_(deg_inv_sqrt == float('inf'), 0)
由于D非对角元=0,其-0.5次幂=∞,需要转化为0,
edge_weight = deg_inv_sqrt[row] * edge_weight * deg_inv_sqrt[col]
输出归一化后的edge_index

2. PairNorm

在这里插入图片描述

3.GCNConv的实现如下(删改自torch_geometric.nn.GCNConv)

class myGCNConv2(MessagePassing):
    def __init__(self, in_channels: int, out_channels: int,
                 add_self_loops: bool = True,bias: bool = True):
        super().__init__()

        self.in_channels = in_channels
        self.out_channels = out_channels
        self.add_self_loops = add_self_loops

        self.lin = Linear(in_channels, out_channels, bias=False,
                          weight_initializer='glorot')

        if bias:
            self.bias = Parameter(torch.Tensor(out_channels))
        else:
            self.register_parameter('bias', None)

        self.reset_parameters()

    def reset_parameters(self):
        super().reset_parameters()
        self.lin.reset_parameters()         #卷积层
        zeros(self.bias)                    #偏置层

    def forward(self, x: Tensor, edge_index: Adj,
                edge_weight: OptTensor = None) -> Tensor:

        edge_index, edge_weight = gcn_norm(  # yapf: disable
            edge_index, edge_weight, x.size(self.node_dim),
            self.add_self_loops, self.flow, x.dtype)

        x = self.lin(x)

        # propagate_type: (x: Tensor, edge_weight: OptTensor)
        out = self.propagate(edge_index, x=x, edge_weight=edge_weight,
                             size=None)

        if self.bias is not None:
            out = out + self.bias

        return out

    def message(self, x_j: Tensor, edge_weight: OptTensor) -> Tensor:
        return x_j if edge_weight is None else edge_weight.view(-1, 1) * x_j

    def message_and_aggregate(self, adj_t: SparseTensor, x: Tensor) -> Tensor:
        return spmm(adj_t, x, reduce=self.aggr)

代码解释

x = self.lin(x) X ′ = X Θ , X ∈ R n ∗ d 1 , Θ ∈ R d 1 ∗ d 2 X'=X\Theta,X\in R^{n*d1},\Theta \in R^{d1*d2} X=XΘXRnd1ΘRd1d2,对X降维
out = self.propagate(edge_index, x=x, edge_weight=edge_weight,size=None)
out= A ′ X ′ = D ~ − 1 2 A ~ D ~ − 1 2 X Θ A'X'=\widetilde D^{-\frac 1 2}\widetilde A \widetilde D^{-\frac 1 2 } X \Theta AX=D 21A D 21XΘ
Converge {x1’,…,xn’} ,each of which be a sampled vector,into target form.

message&message_and_aggregate为MessagePassing.propagate的相关函数,
经测试,删除后,val acc下降,故予以保留

4.Net(GCN)的实现

class GCN(torch.nn.Module):
def __init__(
self,
num_node_features: int,
num_classes: int,
hidden_dim: int = 16,
dropout_rate: float = 0.5,
) -> None:
super().__init__()
self.dropout1 = torch.nn.Dropout(dropout_rate)
self.conv1 = myGCNConv2(num_node_features,
hidden_dim,add_self_loops=True)
self.relu = torch.nn.ReLU(inplace=True)
self.dropout2 = torch.nn.Dropout(dropout_rate)
self.conv2 = myGCNConv2(hidden_dim, num_classes,add_self_loops=True)
self.pn=PairNorm()
def forward(self, x: Tensor, edge_index: Tensor) -> torch.Tensor:
x = self.pn(x)
x = self.dropout1(x)
x = self.conv1(x, edge_index)
x = self.relu(x)
x = self.dropout2(x)
x = self.conv2(x, edge_index)
return x

代码解释

x = self.pn(x):对x作PairNorm处理,之后xi~N(0,s2),各节点特征范数大小平衡,作用不明显;
采用2层GCN卷积层,中间用relu激活,dropout避免过拟合

DropEdge Realization的手动实现

  • idea
  1. 首先把有向图的边,转化为无向图的边,保存在single_edge_index中,实现时先用single_edge字
    典存储每条无向边(key-value 任意)1次,再把single_edge转化成无向图的边集索引(2-dim tensor
    array)
#single_edge_index
single_edge={}
for i in range(len(dataset.data.edge_index[0])):
    if(((dataset.data.edge_index[0][i],dataset.data.edge_index[1][i]) not in single_edge.items()) and 
        ((dataset.data.edge_index[1][i],dataset.data.edge_index[0][i]) not in single_edge.items())):
        single_edge[dataset.data.edge_index[0][i]]=dataset.data.edge_index[1][i]

single_edge_index=[[],[]]

for key,value in single_edge.items():
    single_edge_index[0].append(key)
    single_edge_index[1].append(value)        

single_edge_index=torch.tensor(single_edge_index)
  1. 再把无向边集舍去dropout_rate比例的部分,之后转成有向边集索引
def drop_edge(single_edge_index, dropout_rate):
    # 计算需要丢弃的边数
    num_edges = single_edge_index.shape[1]
    num_drop = int(num_edges * dropout_rate)

    # 随机选择要丢弃的边
    remain_indices = torch.randperm(num_edges)[num_drop:]
    remain_single_edges = single_edge_index[:, remain_indices]
    reverse_edges = torch.stack([remain_single_edges[1],remain_single_edges[0]],dim=0)
    remain_edges=torch.cat([remain_single_edges,reverse_edges],dim=1)

    return remain_edges

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

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

相关文章

c++之旅——第四弹

大家好啊,这里是c之旅第三弹,跟随我的步伐来开始这一篇的学习吧! 如果有知识性错误,欢迎各位指正!!一起加油!! 创作不易,希望大家多多支持哦! 本篇文章的主…

【css面试题】BFC

参考文章1 参考文章2 什么是BFC BFC全称是Block Formatting Context,意思就是块级格式化上下文。你可以把BFC看做一个容器,容器里边的元素不会影响到容器外部的元素。 BFC的特性 BFC是一个块级元素,块级元素在垂直方向上依次排列。 BFC是…

QT 网络编程 8

1 基础知识 udp tcp 2 UDP 框架 客户端: QUdpSocket x; qint64 writeDatagram( const char *data, qint64 size, const QHostAddress &address, quint16 port );服务器: void Server::initSocket(){udpSocket new QUdpSocket(this);udpSocket->bind(QHostAddress…

【Redis | 第七篇】Redis过期策略、内存淘汰策略

文章目录 7.Redis过期策略、内存淘汰策略7.1过期策略7.2内存淘汰策略 7.Redis过期策略、内存淘汰策略 7.1过期策略 我们在set key的时候,可以给它设置一个过期时间,比如expire key 60。指定这key60s后过期。 60s后,redis是如何处理的嘛&am…

性别和年龄的视频实时监测项目

注意:本文引用自专业人工智能社区Venus AI 更多AI知识请参考原站 ([www.aideeplearning.cn]) 性别和年龄检测 Python 项目 首先介绍性别和年龄检测的高级Python项目中使用的专业术语 什么是计算机视觉? 计算机视觉是使计算机能…

ER-NeRF实时对话数字人模型训练与部署

ER-NeRF是基于NeRF用于生成数字人的方法,可以达到实时生成的效果。 下载源码 cd D:\Projects\ git clone https://github.com/Fictionarry/ER-NeRF cd D:\Projects\ER-NeRF 下载模型 准备面部解析模型 wget https://github.com/YudongGuo/AD-NeRF/blob/master/…

如何预估系统的瓶颈

如何预估系统的瓶颈 1 CPU1.1 CPU和同吞吐量 2 内存3 磁盘IO4 网络宽带5 数据库服务器6 APP服务端 CPU 使用率、内存占用、网络流量、磁盘 IO等指标,异常或者持续高位的情况下,都可能是系统瓶颈的表现。 1 CPU CPU使用率正常在70%左右,如果…

力扣hot100:42.接雨水

一、从单个水柱本身考虑 下标为i的水柱能接的雨水,取决于它左边最高的水柱 和 右边最高的水柱的最小值(包括它本身)。 为了理解这一性质,我们可以这样想象:取出左边最高和最边最高的水柱,将其比作一个碗的边…

绘制一下包络线

clear clc close all % 生成衰减信号 % 生成衰减曲线带有随机信号 fs 50; % 采样率 t 0:1/fs:100; % 时间向量,总时长为5秒 frequency0.5; signal exp(-0.05* t).*sin(2*pi*frequency*t); % 衰减曲线带有随机信号 % 计算包络线 [upper_envelope, lower_…

基于springboot+vue的教师工作量管理系统

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

ImageGlass:重塑你的图片查看体验,探索视觉艺术

名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 目录 一、什么是ImageGlass?①ImageGlass…

Python 编辑工具 Jupyter notebook

Jupyter notebook Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算:开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍 官网:Project Jupyter | Home Jupyter Notebook 是一个开源的交互式计算环境&#…

数据结构——lesson5栈和队列详解

hellohello~这里是土土数据结构学习笔记🥳🥳 💥个人主页:大耳朵土土垚的博客 💥 所属专栏:数据结构学习笔记 💥对于顺序表链表有疑问的都可以在上面数据结构的专栏进行学习哦~感谢大家的观看与…

Java电梯模拟

Java电梯模拟 文章目录 Java电梯模拟前言一、UML类图二、代码三、测试 前言 此程序为单线程简单模拟电梯(初版),如果存在问题或者设计不合理的地方,请大家帮忙指出。 一、UML类图 二、代码 电梯调度器 package cn.xx.evevator;import java.util.*;pub…

【间说八股】面试官:我看你这里用到了模板模式?你能不能说一下什么是模板模式

模板模式 行为模式:这类模式负责对象间的高效沟通和职责委派。 模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 模板方法模式是一种行为设计模式,其核心思想…

下载github项目到pycharm

一、下载git 1.下载git链接 https://git-scm.com/ 2.一路点击next,最后finish 二、使用git 1.安装成功后在开始菜单栏会找到如下内容,其中常用的是Git Bash 2.点击Git Bash 3.这里就可以克隆github上的代码了 点击复制,在命令行输入…

H264的打包,nal,es,pes,pts,dts,ps,ts

编码层次 视频编码层:预测、变换、量化、熵编码等操作slice层:将视频帧分割成若干个编码单元,包含一定数量的宏块,提高编解码的并行性和容错性。NAL层:提升对网络传输和数据存储的亲和性 视频编码层 基准-Baseline …

盘点实用又有意思的工具网站-搜嗖工具箱

生命倒计时 www.thismuchlonger.com 这是一个相哇塞的网站,可以让我们静下心来好好想想我们来这个世界究竟为了什么,因为当我们作为命运的主宰者。敲打键盘设定好自己一生长度的时候,我们的剩余寿命已经成绝对值,一旦生命变为了绝…

飞天使-学以致用-devops知识点4-SpringBoot项目CICD实现(实验失败,了解大概流程)

文章目录 代码准备创建jenkins 任务测试推送使用项目里面的jenkinsfile 进行升级操作 文字版本流程项目构建 代码准备 推送代码到gitlab 代码去叩叮狼教育找 k8s 创建jenkins 任务 创建一个k8s-cicd-demo 流水线任务 将jenkins 里面构建时候的地址还有token, 给到…

基于分位数回归的长短期记忆神经网络(QRLSTM)的MATLAB实现(源代码)

分位数回归的长短期神经记忆网络介绍: QRLSTM(Quantile Regression Long Short-Term Memory)分位数回归神经网络是一种结合了长短期记忆(LSTM)神经网络和分位数回归的模型。这种神经网络结构旨在对数据的不同分位数进行…