当前位置: 首页 > news >正文

GraphSAGE的基础理论

文章目录

  • GraphSAGE原理(理解用)
    • GraphSAGE工作流程
  • GraphSAGE的实用基础理论(编代码用)
    • 1. GraphSAGE的底层实现(pytorch)
      • PyG中NeighorSampler实现节点维度的mini-batch + GraphSAGE样例
      • PyG中的SAGEConv实现
    • 2. GraphSAGE的实例
  • 引用

GraphSAGE原理(理解用)

引入:

GCN的缺点:

  • 从大型网络中学习的困难:GCN在嵌入训练期间需要所有节点的存在。这不允许批量训练模型。
  • 推广到看不见的节点的困难:GCN假设单个固定图,要求在一个确定的图中去学习顶点的embedding。但是,在许多实际应用中,需要快速生成看不见的节点的嵌入。而GCN无法直接泛化到在训练过程没有出现过的顶点,即属于一种直推式(transductive)的学习。

GraphSAGE:其核心思想是通过学习一个对邻居顶点进行聚合表示的函数来产生目标顶点的embedding向量。

GraphSAGE工作流程

  1. 对图中每个顶点的邻居顶点进行采样。模型不使用给定节点的整个邻域,而是统一采样一组固定大小的邻居。
  2. 根据聚合函数聚合邻居顶点蕴含的信息。
  3. 得到图中各顶点的向量表示供下游任务使用。
  1. 对图中每个顶点的邻居顶点进行采样

    • 考虑计算效率的情况下:对每个顶点采样一定数量的邻居顶点作为待聚合信息的顶点。设采样数量为k,若顶点邻居数少于k,则采用有放回的抽样方法,直到采样出k个顶点。若顶点邻居数大于k,则采用无放回的抽样。
    • 不考虑计算效率的情况下:完全可以对每个顶点利用其所有的邻居顶点进行信息聚合,这样是信息无损的。

    具体来说:

    在第 kkk 层时,对每个顶点 vvv,首先使用顶点 vvv 的邻居顶点的 k−1k-1k1 层的 embedding 表示来产生其邻居顶点的第 kkk 层聚合表示 hN(v)kh_{N(v)}^khN(v)k,之后将 hN(v)kh_{N(v)}^khN(v)k 和顶点 vvv 的第 k−1k-1k1 层表示 hvk−1h_v^{k-1}hvk1进行拼接(concat),经过一个非线性变换产生顶点 vvv 的第 kkk 层 embedding 表示。一般而言,可用公式可表示为(只是为了说明流程,具体还要看聚合函数的选取):hN(v)k=aggregatek({huk−1,∀u∈N(v)})h_{N(v)}^k = aggregate_k(\{h_u^{k-1}, \forall u \in N(v)\})hN(v)k=aggregatek({huk1,uN(v)})hvk=σ(Wk⋅concat(hvk−1,hN(v)k))h_v^k = \sigma (W^k \cdot concat(h_v^{k-1},h_{N(v)}^k) ) hvk=σ(Wkconcat(hvk1,hN(v)k))

  2. 根据聚合函数聚合邻居顶点蕴含的信息

    聚合函数的选取:

    • MEAN aggregator:
      hvk=σ(W⋅MEAN({hvk−1}∪{huk−1,∀u∈N(v)}))h_v^k = \sigma (W \cdot MEAN(\{h_v^{k-1}\}\cup\{h_u^{k-1},\forall u \in N(v)\}))hvk=σ(WMEAN({hvk1}{huk1,uN(v)}))
    • Pooling aggregator:
      hN(v)k=pooling_method({σ(Whuk+b),∀u∈N(v)})h_{N(v)}^k = pooling\_method(\{\sigma(Wh_u^k+b), \forall u \in N(v)\})hN(v)k=pooling_method({σ(Whuk+b),uN(v)})注意这里是hN(v)k,而不是hvk;其中pooling_method∈{max,mean}注意这里是h_{N(v)}^k,而不是h_v^k;其中pooling\_method \in \{max,mean\}注意这里是hN(v)k,而不是hvk;其中pooling_method{max,mean}
    • LSTM aggregator:
      中心节点的邻居节点随机打乱作为输入序列,将 所得向量表示 hN(v)kh_{N(v)}^khN(v)k中心节点的向量hvk−1h_v^{k-1}hvk1 表示分别经过非线性变换后拼接,得到中心节点在该层的向量表示。LSTM 本身用于序列数据,而邻居节点没有明显的序列关系,因此输入到 LSTM 中的邻居节点需要随机打乱顺序
  3. 参数的学习

    • 无监督学习

      基于图的损失函数希望邻近的顶点具有相似的向量表示,同时让分离的顶点的表示尽可能不同。 目标函数如下:JG(zu)=−log(σ(zuTzv))−Q⋅Evn∼Pn(v)log(σ(−zuTzvn))J_G(z_u) = -log(\sigma(z_u^Tz_v))-Q\cdot E_{v_n ∼ P_n(v) }log(\sigma(-z_u^Tz_{v_n}))JG(zu)=log(σ(zuTzv))QEvnPn(v)log(σ(zuTzvn))其中 vvv 是在定长随机游走中在 uuu 附近同时出现的节点,σσσsigmoid函数sigmoid函数sigmoid函数PnP_nPn是一个负抽样分布,QQQ定义了负抽样的数量。

      与DeepWalk不同的是,这里的顶点表示向量是通过聚合顶点的邻接点特征产生的,而不是简单的进行一个embedding lookup操作得到。

    • 监督学习

      监督学习形式根据任务的不同直接设置目标函数即可,如最常用的节点分类任务使用交叉熵损失函数。

GraphSAGE的实用基础理论(编代码用)

1. GraphSAGE的底层实现(pytorch)

PyG中NeighorSampler实现节点维度的mini-batch + GraphSAGE样例

参考博客:https://blog.csdn.net/weixin_39925939/article/details/121458145

PyG中的SAGEConv实现

原论文中实现方法:xi′=W⋅concat(Aggregatej∈N(i)xj,xi)x_i' = W \cdot concat(Aggregate_{j\in N(i)}x_j,x_i)xi=Wconcat(AggregatejN(i)xj,xi)

PyG中实现方法:xi′=W1xi+W2⋅Aggregatej∈N(i)xjx_i' = W_1x_i + W_2 \cdot Aggregate_{j\in N(i)}x_jxi=W1xi+W2AggregatejN(i)xj

这两种方式是一样的,但是不同的是:

SAGEConv代码中的邻居就是你传入的邻居,不管是使用NeighborSampler等方式对邻居进行采样过的邻居还是未采样的所有邻居,它只管接收你传入的邻居,邻居采样不在这里实现。

  • init函数

    参数说明:

    • in_channels: Union[int, Tuple[int, int]]:输入原始特征或者隐含层embedding的维度。如果是-1,则根据传入的x来推断特征维度。注意in_channels可以是一个整数,也可以是两个整数组成的tuple,分别对应source节点和target节点的特征维度。
    • source节点: 中心节点的邻居节点。{xj,∀j∈N(i)}\{x_j, \forall j\in N(i)\}{xj,jN(i)}
    • target节点:中心节点。xix_ixi
    • in_channels[0]:参数W2W_2W2的shape[0],点乘source节点聚合后的特征矩阵
    • in_channels[1]:参数W1W_1W1的shape[0],点乘对应target节点的特征矩阵
    • out_channels:输出embedding的维度
    • normalize:是否对输出进行 l2l_2l2归一化,默认为False
    • bias:偏差,默认为True
    • root_weight:输出是否会加上节点自身特征转换维度后的值,默认是True
    • kwargs.setdefault('aggr', 'mean'):邻域聚合方式,默认aggr='mean',其余方式还有aggr='max'aggr='add'
    class SAGEConv(MessagePassing):    def __init__(self, in_channels: Union[int, Tuple[int, int]],out_channels: int, normalize: bool = False,root_weight: bool = True,bias: bool = True, **kwargs):  # yapf: disablekwargs.setdefault('aggr', 'mean')super(SAGEConv, self).__init__(**kwargs)self.in_channels = in_channelsself.out_channels = out_channelsself.normalize = normalizeself.root_weight = root_weightif isinstance(in_channels, int):in_channels = (in_channels, in_channels)self.lin_l = Linear(in_channels[0], out_channels, bias=bias)if self.root_weight:self.lin_r = Linear(in_channels[1], out_channels, bias=False)self.reset_parameters()
  • forward函数

    参数说明:

    • x:Union[Tensor, OptPairTensor]:可以是Tensor,也可以是OptPairTensor (pyg定义的tuple of Tensor)。

    当图是bipartite的时候,x是OptPairTensor,为了和init函数中定义的in_channel对应,要使得:

    • source节点(邻居节点)特征对应x[0] ,在代码中赋值给x_lin_channel[0]W2W_2W2)定义为lin_l
    • target节点(中心节点)特征对应x[1],在代码中赋值给 x_rin_channel[1]W1W_1W1)定义为lin_r
    • edge_index: Adj: Adj是pyg定义的邻接矩阵类型,可以是Tensor,也可以是SparseTensor。
    def forward(self, x: Union[Tensor, OptPairTensor], edge_index: Adj,size: Size = None) -> Tensor:""""""if isinstance(x, Tensor):x: OptPairTensor = (x, x)# propagate_type: (x: OptPairTensor)out = self.propagate(edge_index, x=x, size=size)out = self.lin_l(out)x_r = x[1]if self.root_weight and x_r is not None:out += self.lin_r(x_r)if self.normalize:out = F.normalize(out, p=2., dim=-1)return out
  • 消息传递函数(message函数)

    forward函数中使用self.propagate时调用,传入的edge_index不算显式参数。

    参数说明:

    • edge_index为Tensor
      edge_index为Tensor的时候,propagate调用message和aggregate实现消息传递和更新。这里message函数对邻居特征没有任何处理,只是进行了传递,所以最终propagate函数只是对邻居特征进行了aggregate
    • edge_index为SparseTensor
      edge_index为SparseTensor的时候,propagate函数会在message_and_aggregate被定义的情况下被优先调用,代替message和aggregate。
      这里message_and_aggregate直接调用类似矩阵计算matmul(adj_t, x[0], reduce=self.aggr)。x[0]是source节点的特征。matmul来自于torch_sparse,除了类似常规的矩阵相乘外,还给出了可选的reduce,这里可以实现add,mean和max聚合。
    def message(self, x_j: Tensor) -> Tensor:return x_jdef message_and_aggregate(self, adj_t: SparseTensor,x: OptPairTensor) -> Tensor:adj_t = adj_t.set_value(None, layout=None)return matmul(adj_t, x[0], reduce=self.aggr)
    

2. GraphSAGE的实例

import torch
import torch.nn.functional as F
from torch_geometric.nn.conv import SAGEConvclass SAGE(torch.nn.Module):def __init__(self, in_channels, hidden_channels, out_channels, dropout=0.):super(SAGE, self).__init__()self.convs = torch.nn.ModuleList()self.convs.append(SAGEConv(in_channels, hidden_channels))self.convs.append(SAGEConv(hidden_channels, out_channels))self.dropout = dropoutdef reset_parameters():for conv in self.convs:conv.reset_parameters()def forward(self, x, edge_index):x = self.convs[0](x, edge_index)x = F.relu(x)x = F.dropout(x, p=self.dropout, training=self.training)x = self.convs[1](x, edge_index)return x.log_softmax(dim=-1)
#读取数据
from torch_geometric.datasets import Planetoid
import torch_geometric.transforms as Ttransform = T.ToSparseTensor()
# 这里加上了ToSparseTensor(),所以边信息是以adj_t形式存储的,如果没有这个变换,则是edge_index
dataset = Planetoid(name='Cora', root=r'./dataset/Cora', transform=transform)
data = dataset[0]
data.adj_t = data.adj_t.to_symmetric()model = SAGE(in_channels=dataset.num_features, hidden_channels=128, out_channels=dataset.num_classes)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)def train():model.train()optimizer.zero_grad()out = model(data.x, data.adj_t)[data.train_mask] #前面我们提到了,SAGE是实现了edge_index和adj_t两种形式的loss = F.nll_loss(out, data.y[data.train_mask])loss.backward()optimizer.step()return loss.item()@torch.no_grad()
def test():model.eval()out = model(data.x, data.adj_t)y_pred = out.argmax(axis=-1)correct = y_pred == data.ytrain_acc = correct[data.train_mask].sum().float()/data.train_mask.sum()valid_acc = correct[data.val_mask].sum().float()/data.val_mask.sum()test_acc = correct[data.test_mask].sum().float()/data.test_mask.sum()return train_acc, valid_acc, test_acc #跑10个epoch看一下模型效果
for epoch in range(20):loss = train()train_acc, valid_acc, test_acc = test()print(f'Epoch: {epoch:02d}, 'f'Loss: {loss:.4f}, 'f'Train_acc: {100 * train_acc:.3f}%, 'f'Valid_acc: {100 * valid_acc:.3f}% 'f'Test_acc: {100 * test_acc:.3f}%')

引用

文章参考了:

  1. https://blog.csdn.net/weixin_39925939/article/details/121343538
  2. https://zhuanlan.zhihu.com/p/79637787
  3. https://zhuanlan.zhihu.com/p/336195862

相关文章:

GraphSAGE的基础理论

文章目录GraphSAGE原理(理解用)GraphSAGE工作流程GraphSAGE的实用基础理论(编代码用)1. GraphSAGE的底层实现(pytorch)PyG中NeighorSampler实现节点维度的mini-batch GraphSAGE样例PyG中的SAGEConv实现2. …...

Windows 安装 GDAL C++库

Windows 安装 GDAL C库1. 方法1:下载配置网友编译的GDAL版本1.1 下载1.2 配置1.3 测试1.4 缺点2. 方法2:自己编译3. 参考1. 方法1:下载配置网友编译的GDAL版本 1.1 下载 CSDN: GDAL,geos联合编译的库,版本为1.8.0&am…...

二叉树基础概念

1.二叉树种类 1.1 满二叉树 满二叉树:如果一棵二叉树只有度为 0 0 0 的结点和度为 2 2 2 的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 如图所示: 这棵二叉树为满二叉树,也可以说深度为 k k k&…...

【MySQL】(1)数据库基础,库与表的增删查改,数据库的备份与还原

文章目录服务器,数据库,表关系MySQL 数据存储逻辑SQL 分类存储引擎库的操作查看数据库创建数据库查看创建语句删除数据库选择(切换)数据库查看当前选择的数据库修改数据库字符集和排序规则表的操作创建表查询表查询表结构插入数据…...

Python基础-01 变量

注释 注释的分类 在Python中,支持单行及多行注释 单行注释 使用#对代码进行说明,#右边的所有内容就是注释的内容,起辅助说明作用 # #右边的都是注释,解析器会忽略 print(hello world) #在控制台里打印一段话多行注释 多行注释中,允许换行,使用三个单引号开始,三个单引号结…...

springcloud2.1.0整合seata1.5.2+nacos2.10(附源码)

springcloud2.1.0整合seata1.5.2nacos2.10(附源码) 1.创建springboot2.2.2springcloud2.1.0的maven父子工程如下,不过多描述: 搭建过程中也出现很多问题,主要包括: 1.seataServer.properties配置文件的组…...

map原理

map源码结构体: type hmap struct {count int // 元素的个数B uint8 // buckets 数组的长度就是 2^B 个overflow uint16 // 溢出桶的数量​buckets unsafe.Pointer // 2^B个桶对应的数组指针oldbuckets unsafe.Pointer // 发生扩容时&#xff0…...

[Ext JS]3.6 Ext JS 表格(Grid)概览

Grid, 翻译过来是网格, 也就是表格。 Grid 的基本构成 面板 :Ext.grid.Panel表格视图 :Ext.view.Table。 不直接使用, 通过面板的viewConfig配置项进行配置。比如可以用来配置表格中行是否跳色显示列: Ext.grid.column.Column。 表格中的列定义store , 表格的数据示例代码…...

关于使用云渲染的五大优势

在不影响质量或性能的情况下节省时间、金钱和资源,对于需要在通常较短且严格的期限内创建高质量 3D 内容的专业人士来说,云渲染都是最好的选择!云渲染作为数字媒体生产的最新趋势,与传统的渲染农场和机器相比具有许多优势&#xf…...

CSS基础样式

1.高度和宽度 .c1{height:300px;width:500px; } 注意事项: 宽度,支持百分比 行内标签:默认无效 块级标签:默认有效(右侧区域就算是空白,也不给占用) 2.块级和行内标签 css样式:标签…...

第03章_流程控制语句

第03章_流程控制语句 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 本章专题与脉络 流程控制语句是用来控制程序中各语句执行顺序的语句,可以把语句组合成能完成一定功能的小逻辑模…...

配电网电压调节及通信联系研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

stegano(图片隐写、摩斯密码)

附件是PDF,我们在选择内容时发现光标溢出了文本 说明这里还存在一些我们看不到的内容 直接CtrlA全选,CtrlC复制后新建一个纯文本文件 将复制的东西粘贴过去 粘贴后发现果然多出来了一些东西,提取出来 BABA BBB BA BBA ABA AB B AAB ABAA A…...

wsl安装torch_geometric

在官网选择需要的版本 选择安装途径,选择runfile 执行第一行,会下载一个文件到目录下 需要降低C的版本,否则 执行sudo sh cuda_11.1.0_455.23.05_linux.run,会出现 查看对应的文件,会有 可以加上override参数之后,…...

ASP.NET Core - 依赖注入(二)

2,NET Core 依赖注入的基本用法 话接上篇,这一章介绍 .NET Core 框架自带的轻量级 Ioc 容器下服务使用的一些知识点,大家可以先看看上一篇文章 [ASP.NET Core - 依赖注入(一)] 2.3 服务解析 通过 IServiceCollection 注册了服务之后&#xf…...

Scala之集合(1)

目录 ​​​​​​​集合介绍: 不可变集合继承图:​编辑 可变集合继承图 数组: 不可变数组: 样例代码: 遍历集合的方法: 1.for循环 2.迭代器 3.转换成List列表: 4.使用foreach()函数&a…...

公网使用SSH远程登录macOS服务器【内网穿透】

文章目录前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址5. 使用固定TCP端口地址ssh远程前言…...

PVE相关的各种一键脚本(一键安装PVE)(一键开设KVM虚拟化的NAT服务器-自带内外网端口转发)

PVE 原始仓库:https://github.com/spiritLHLS/pve 前言 建议debian在使用前尽量使用最新的系统 非debian11可使用 debian一键升级 来升级系统 当然不使用最新的debian系统也没问题,只不过得不到官方支持 请确保使用前机器可以重装系统,…...

CSDN目录博客(zhaoshuangjian)

总目录 一、Java1.1 高并发1.2 多线程1.3 集合1.4 I/O1.5 异常1.6 事务1.7 锁机制1.8 JVM 二、数据库2.1 mysql2.1.1 mysql索引2.1.1 mysql锁2.1.1 mysql事务2.1.1 2.2 oracle2.3 postgresql2.4 达梦2.5 人大金仓kingbase 三、设计模式四、中间件4.1 缓存中间件-redis4.2 缓存中…...

uniapp人脸识别解决方案

APP端: 因为APP端无法使用uni的camera组件,最开始考虑使用内嵌webview的方式,通过原生dom调用video渲染画面然后通过canvas截图。但是此方案兼容性在ios几乎为0,如果app只考虑安卓端的话可以采用此方案。后面又想用live-pusher组件…...

hashlib模块

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 hashlib模块专栏:《python从入门到实战》 哈希算法,也叫摘要算法。 加密&…...

NC65合并报表如何取消上报并退回以及注意事项和相关问题总结

NC65合并报表如何取消上报并退回? 在【企业绩效管理】-【合并报表】-【合并】-【合并执行】节点中,点击〖数据中心〗按钮,在弹出的〖合并报表数据中心〗界面中,点击〖报送管理〗-〖合并方案请求退回〗,然后到【合并综…...

28岁,终于从字节退休了...

大厂一直是每个程序员都向往职业目标,大厂意味着薪资高、福利好、倍有面儿,而且发展空间也大。甚至有人调侃不想进大厂的程序员不是好程序员。 而在网上,也有各个网友分享自己在大厂的经历,在某平台还有一个近2600万浏览的话题&a…...

数据的表示和存储——

目录 浮点数的编码表示 浮点数类型 ​编辑 浮点数的表示 (1)浮点数(Float Point)的表示范围 (2)规格化数形式 (3)IEEE 754标准 其他形式的机器数表示 个人总结 浮点数的编码表…...

springboot零基础到项目实战

推荐教程: springboot零基础到项目实战 SpringBoot这门技术课程所包含的技术点其实并不是很多,但是围绕着SpringBoot的周边知识,也就是SpringBoot整合其他技术,这样的知识量很大,例如SpringBoot整合MyBatis等等。因此…...

自媒体都在用的5个素材网站,视频、音效、图片全部免费下载~

推荐几个自媒体必备的素材库,免费可商用,建议收藏! 1、菜鸟图库 视频素材下载_mp4视频大全 - 菜鸟图库 国内超大的素材库,在这里你可以找到设计、办公、图片、视频、音频等各种素材。视频素材就有上千个,全部都很高清…...

开放式耳机新巅峰!南卡OE Pro兼备澎湃音质、舒适佩戴、创新设计

众所周知,当初苹果带来TWS耳机新时代以后,后面有许多的蓝牙耳机相继跟随和模仿,但NANK南卡却独辟蹊径,将在近日重磅推出首款0压无感全开放无线耳机——南卡OE Pro,走向开放式TWS耳机的新时代。 31度黄金倾斜受力面&…...

1700页,卷S人的 Java《八股文》PDF手册,涨薪跳槽拿高薪就靠它了

大家好,最近有不少小伙伴在后台留言,又得准备面试了,不知道从何下手! 不论是跳槽涨薪,还是学习提升!先给自己定一个小目标,然后再朝着目标去努力就完事儿了! 为了帮大家节约时间&a…...

普通人是否能从ChatGPT中分一杯羹?

ChatGPT3.0刚刚推出,最开始的时候,人们只是将ChatGPT看作一个很会聊天的机器人,无论问题多么天马行空,它的答案看上去都有理有据。后来,像打开潘多拉魔盒一样,很多人开始拿它编大纲、撰写文案、编代码、创作…...

SpringBoot自动装配原理(附面试快速答法)

文章目录SpringBoot自动装配原理1. 从调用SpringApplication构造器方法开始2. 解析启动类4.按需装配4.1 分析dubbo自动装配5. 如果定义自己的starter6. 面试答法SpringBoot自动装配原理 之前面试被问到这个题目,只会答一些spi、AutoConfigration注解、Import之类的&…...