深度学习(36)—— 图神经网络GNN(1)

深度学习(36)------ 图神经网络GNN(1)

这个系列的所有代码我都会放在git上,欢迎造访

文章目录

1. 基础知识

  • GNN考虑的事当前的点和周围点之间的关系

  • 邻接矩阵是对称的稀疏矩阵,表示图中各个点之间的关系

  • 图神经网络的输入是每个节点的特征和邻接矩阵

  • 文本数据可以用图的形式表示吗?文本数据也可以表示图的形式,邻接矩阵表示连接关系

  • 邻接矩阵中并不是一个N* N的矩阵,而是一个source,target的2* N的矩阵

  • 信息传递神经网络:每个点的特征如何更新??------考虑他们的邻居,更新的方式可以自己设置:最大,最小,平均,求和等

  • GNN可以有多层,图的结构不发生改变,即当前点所连接的点不发生改变(邻接矩阵不发生变化)【卷积中存在感受野的概念,在GNN中同样存在,GNN的感受野也随着层数的增大变大】

  • GNN输出的特征可以干什么?

    • 各个节点的特征组合,对图分类【graph级别任务】
    • 对各个节点分类【node级别任务】
    • 对边分类【edge级别任务】
    • 利用图结构得到特征,最终做什么自定义!

2.使用场景

  • 为什么CV和NLP中不用GNN?
    因为图像和文本的数据格式很固定,传统神经网络格式是固定的,输入的东西格式是固定的
  • 化学、医疗
  • 分子、原子结构
  • 药物靶点
  • 道路交通,动态流量预测
  • 社交网络------研究人
    GNN输入格式比较随意,是不规则的数据结构, 主要用于输入数据不规则的时候

3. 图卷积神经网络GCN

  • 图卷积和卷积完全不同
  • GCN不是单纯的有监督学习,多数是半监督,有的点是没有标签的,在计算损失的时候只考虑有标签的点。针对数据量少的情况也可以训练

(1)基本思想

  • 网络层次:第一层对于每个点都要做更新,最后输出每个点对应的特征向量【一般不会做特别深层的】
  • 图中的基本组成:G(原图)A(邻接)D(度)F(特征)
  • 度矩阵的倒数* 邻接矩阵 *度矩阵的倒数------>得到新的邻接矩阵【左乘对行做归一化,右乘对列做归一化】
  • 两到三层即可,太多效果不佳

4. GNN基本框架------pytorch_geometric

它实现了各种GNN的方法
注意:安装过程中不要pip install,会失败!根据自己的device和python版本去下载scatter,pattern等四个依赖,先安装他们然后再pip install torch_geometric==2.0

这里记得是2.0版本否则会出现 TypeError: Expected 'Iterator' as the return annotation for __iter__ of SMILESParser, but found ty

献上github地址:这里

下面是一个demo

(1)数据

这里使用的是和这个package提供的数据,具体参考:club

python 复制代码
from torch_geometric.datasets import KarateClub

dataset = KarateClub()
print(f'Dataset: {dataset}:')
print('======================')
print(f'Number of graphs: {len(dataset)}')
print(f'Number of features: {dataset.num_features}')
print(f'Number of classes: {dataset.num_classes}')

data = dataset[0]  # Get the first graph object.

在torch_geometric中图用Data的格式,Data的对象:可以在文档中详细了解

其中的属性

  • edge_index:表示图的连接关系(start,end两个序列)
  • node features:每个点的特征
  • node labels:每个点的标签
  • train_mask:有的节点没有标签(用来表示哪些节点要计算损失)

(2)可视化

python 复制代码
from torch_geometric.utils import to_networkx

G = to_networkx(data, to_undirected=True)
visualize_graph(G, color=data.y)

(3)网络定义

GCN layer的定义:
可以在官网的文档做详细了解

卷积层就有很多了:

python 复制代码
import torch
from torch.nn import Linear
from torch_geometric.nn import GCNConv


class GCN(torch.nn.Module):
    def __init__(self):
        super().__init__()
        torch.manual_seed(1234)
        self.conv1 = GCNConv(dataset.num_features, 4) # 只需定义好输入特征和输出特征即可
        self.conv2 = GCNConv(4, 4)
        self.conv3 = GCNConv(4, 2)
        self.classifier = Linear(2, dataset.num_classes)

    def forward(self, x, edge_index):
        h = self.conv1(x, edge_index) # 输入特征与邻接矩阵(注意格式,上面那种)
        h = h.tanh()
        h = self.conv2(h, edge_index)
        h = h.tanh()
        h = self.conv3(h, edge_index)
        h = h.tanh()  
        
        # 分类层
        out = self.classifier(h)

        return out, h

model = GCN()
print(model)

_, h = model(data.x, data.edge_index)
print(f'Embedding shape: {list(h.shape)}')# 输出最后分类前的中间特征shape

visualize_embedding(h, color=data.y)

这时很分散

(4)训练模型(semi-supervised)

python 复制代码
import time

model = GCN()
criterion = torch.nn.CrossEntropyLoss()  # Define loss criterion.
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)  # Define optimizer.

def train(data):
    optimizer.zero_grad()  
    out, h = model(data.x, data.edge_index) #h是两维向量,主要是为了画图方便 
    loss = criterion(out[data.train_mask], data.y[data.train_mask])  # semi-supervised
    loss.backward()  
    optimizer.step()  
    return loss, h

for epoch in range(401):
    loss, h = train(data)
    if epoch % 10 == 0:
        visualize_embedding(h, color=data.y, epoch=epoch, loss=loss)
        time.sleep(0.3)

然后就可以看到一系列图,看点的变化情况了

相关推荐
Mintopia27 分钟前
OpenClaw 对软件行业产生的影响
人工智能
陈广亮1 小时前
构建具有长期记忆的 AI Agent:从设计模式到生产实践
人工智能
会写代码的柯基犬1 小时前
DeepSeek vs Kimi vs Qwen —— AI 生成俄罗斯方块代码效果横评
人工智能·llm
Mintopia2 小时前
OpenClaw 是什么?为什么节后热度如此之高?
人工智能
爱可生开源社区2 小时前
DBA 的未来?八位行业先锋的年度圆桌讨论
人工智能·dba
叁两5 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
前端付豪5 小时前
LangChain记忆:通过Memory记住上次的对话细节
人工智能·python·langchain
strayCat232555 小时前
Clawdbot 源码解读 7: 扩展机制
人工智能·开源
程序员打怪兽5 小时前
详解Visual Transformer (ViT)网络模型
深度学习