图神经网络

本文介绍了图神经网络的基本原理,包括节点嵌入和图嵌入的概念,以及GNNs的工作流程。接着详细讲解了图卷积网络(GCN)的特性、参数共享和泛化能力,并给出了Cora数据集上的GCN模型实现示例。此外,还讨论了图注意力网络(GAT)如何通过注意力机制改进节点关系的学习。最后,简要介绍了图自编码器(GAE)在无监督学习中的应用,用于学习图的隐藏表示。
摘要由CSDN通过智能技术生成

目录

图神经网络原理

图神经网络分类

1、图卷积网络(GCN)

2、图注意力网络(GAT)

3、图自编码器(GAE)


图神经网络原理

       图神经网络(Graph Neural Networks,GNNs)是一种用于处理图结构数据的机器学习模型。与传统的神经网络模型适用于处理向量或矩阵数据不同,GNNs专门用于建模和学习图数据中的关系和结构。

       GNNs的原理基于节点嵌入(node embedding)和图嵌入(graph embedding)。节点嵌入是指将每个节点映射到低维向量空间,以便模型能够捕捉节点之间的关系。图嵌入则是将整个图映射到一个低维向量表示,用于对整个图进行全局的特征提取。

下面是一个简单的GNN模型的原理和工作流程:

1. 初始化节点嵌入:对每个节点进行初始化,将其表示为向量形式。

2. 信息传递:GNN通过迭代的方式将节点的信息进行传递和聚合。在每个迭代步骤中,每个节点会考虑其自身的特征以及邻居节点的特征,并更新自身的嵌入表示。这样,节点可以逐渐获取和整合周围节点的信息。

3. 聚合邻居信息:在信息传递的过程中,节点会聚合邻居节点的信息。常用的聚合方式包括求和、平均、最大等。聚合后的邻居信息会被结合到节点的嵌入表示中。

4. 更新节点表示:节点通过考虑自身的特征和聚合后的邻居信息,更新自身的嵌入表示。更新可以通过神经网络层、图卷积等方式进行。

5. 重复迭代:上述信息传递和节点更新的过程可以进行多次迭代,直到达到预定义的迭代次数或收敛条件。

6. 图嵌入:最后,可以对整个图进行汇总,得到表示整个图的向量表示。这个向量表示可以用于进行图级别的任务,如图分类、图生成等。

        需要注意的是,不同的GNN模型可能有不同的具体实现细节和变体,如图卷积网络(Graph Convolutional Networks,GCNs)、GraphSAGE、GAT(Graph Attention Networks)等。这些模型在信息传递、节点更新和图嵌入等方面可能有所差异,但整体思想基本类似。通过学习图数据中的节点之间的关系和结构,GNNs能够有效地进行图分析和图学习任务。

图神经网络分类

1、图卷积网络(GCN)

图卷积网络(Graph Convolutional Networks,GCNs)有以下优点:

1. 局部和全局信息融合:GCNs通过邻居聚合和节点表示更新的过程,能够有效地融合节点的局部和全局信息。节点的表示可以逐步地通过邻居节点的信息进行传播和更新,从而捕捉图数据中的结构和关系。

2. 参数共享和计算效率:GCNs的参数共享机制使得模型可以在整个图的不同部分共享参数,从而减少参数量和计算复杂度。这使得GCNs能够高效地处理大规模的图数据。

3. 泛化能力:GCNs具有良好的泛化能力,能够处理不同规模、结构和特征的图数据。GCNs的表示学习过程可以逐步融合节点的邻居信息,从而使得节点的表示更具有表征能力。

我们将使用Cora数据集来说明实现GCNs的过程。假设你已经下载了Cora数据集,可以通过以下代码加载和准备数据:

import torch
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures

# 加载Cora数据集
dataset = Planetoid(root='/path/to/cora', name='Cora', transform=NormalizeFeatures())

# 划分数据集为训练集、验证集和测试集
data = dataset[0]
data.train_mask = data.val_mask = data.test_mask = data.y = None
data = dataset[0]
data.train_mask = torch.zeros(data.num_nodes, dtype=torch.bool)
data.train_mask[:200] = 1
data.val_mask = torch.zeros(data.num_nodes, dtype=torch.bool)
data.val_mask[200:500] = 1
data.test_mask = torch.zeros(data.num_nodes, dtype=torch.bool)
data.test_mask[500:] = 1

接下来,我们可以定义GCN模型。以下是一个简单的两层GCN模型的实现:

import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.nn import GCNConv

class GCN(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(GCN, self).__init__()
        self.conv1 = GCNConv(input_dim, hidden_dim)
        self.conv2 = GCNConv(hidden_dim, output_dim)
        
    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index)
        x = F.relu(x)
        x = F.dropout(x, training=self.training)
        x = self.conv2(x, edge_index)
        return F.log_softmax(x, dim=1)

然后,我们可以训练和评估模型:

import torch.optim as optim
from torch_geometric.data import DataLoader

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = GCN(input_dim=dataset.num_features, hidden_dim=16, output_dim=dataset.num_classes).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.01)
criterion = nn.NLLLoss()

train_loader = DataLoader([data], batch_size=1, shuffle=True)
val_loader = DataLoader([data], batch_size=1, shuffle=False)
test_loader = DataLoader([data], batch_size=1, shuffle=False)

def train():
    model.train()
    for data in train_loader:
        data = data.to(device)
        optimizer.zero_grad()
        output = model(data.x, data.edge_index)
        loss = criterion(output[data.train_mask], data.y[data.train_mask])
        loss.backward()
        optimizer.step()

def evaluate(loader):
    model.eval()
    correct = 0
    for data in loader:
        data = data.to(device)
        with torch.no_grad():
            output = model(data.x, data.edge_index)
            pred = output.argmax(dim=1)
            correct += pred.eq(data.y).sum().item()
    return correct / len(loader.dataset)

for epoch in range(200):
    train()
    train_acc = evaluate(train_loader)
    val_acc = evaluate(val_loader)
    print(f'Epoch: {epoch+1}, Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f}')

test_acc = evaluate(test_loader)
print(f'Test Acc: {test_acc:.4f}')

2、图注意力网络(GAT)

图注意力网络(Graph Attention Networks,GAT)是一种图神经网络模型,通过引入注意力机制来对图数据进行建模。相比于传统的图卷积网络(GCN),GAT能够动态地学习节点之间的重要性权重,从而更好地捕捉节点之间的关系。

我们将使用Cora数据集来说明实现GAT的过程。假设你已经下载了Cora数据集,可以通过以下代码加载和准备数据:

import torch
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures

# 加载Cora数据集
dataset = Planetoid(root='/path/to/cora', name='Cora', transform=NormalizeFeatures())

# 划分数据集为训练集、验证集和测试集
data = dataset[0]
data.train_mask = data.val_mask = data.test_mask = None
data.train_mask[:200] = True
data.val_mask[200:500] = True
data.test_mask[500:] = True

接下来,我们可以定义GAT模型。以下是一个简单的两层GAT模型的实现:

import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.nn import GATConv

class GAT(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim, num_heads):
        super(GAT, self).__init__()
        self.conv1 = GATConv(input_dim, hidden_dim, heads=num_heads)
        self.conv2 = GATConv(hidden_dim * num_heads, output_dim, concat=False)
        
    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index)
        x = F.elu(x)
        x = self.conv2(x, edge_index)
        return F.log_softmax(x, dim=1)

然后,我们可以训练和评估模型:

import torch.optim as optim
from torch_geometric.data import DataLoader

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = GAT(input_dim=dataset.num_features, hidden_dim=8, output_dim=dataset.num_classes, num_heads=8).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.005)
criterion = nn.NLLLoss()

train_loader = DataLoader([data], batch_size=1, shuffle=True)
val_loader = DataLoader([data], batch_size=1, shuffle=False)
test_loader = DataLoader([data], batch_size=1, shuffle=False)

def train():
    model.train()
    for data in train_loader:
        data = data.to(device)
        optimizer.zero_grad()
        output = model(data.x, data.edge_index)
        loss = criterion(output[data.train_mask], data.y[data.train_mask])
        loss.backward()
        optimizer.step()

def evaluate(loader):
    model.eval()
    correct = 0
    for data in loader:
        data = data.to(device)
        with torch.no_grad():
            output = model(data.x, data.edge_index)
            pred = output.argmax(dim=1)
            correct += pred.eq(data.y).sum().item()
    return correct / len(loader.dataset)

for epoch in range(200):
    train()
    train_acc = evaluate(train_loader)
    val_acc = evaluate(val_loader)
    print(f'Epoch: {epoch+1}, Train Acc: {train_acc:.4f}, Val Acc: {val_acc:.4f}')

test_acc = evaluate(test_loader)
print(f'Test Acc: {test_acc:.4f}')

3、图自编码器(GAE)

图自编码器(Graph Autoencoder)是一种用于图数据的无监督学习模型,用于学习图结构中的隐藏表示。图自编码器通常由编码器和解码器两部分组成,旨在将图数据压缩到低维空间中,并尽可能地还原原始图数据。

我们将使用Cora数据集来说明实现图自编码器的过程。假设你已经下载了Cora数据集,可以通过以下代码加载和准备数据:

import torch
from torch_geometric.datasets import Planetoid
from torch_geometric.transforms import NormalizeFeatures

# 加载Cora数据集
dataset = Planetoid(root='/path/to/cora', name='Cora', transform=NormalizeFeatures())

# 获取图数据
data = dataset[0]

接下来,我们可以定义图自编码器模型。以下是一个简单的图自编码器模型的实现:

import torch.nn as nn
import torch.nn.functional as F
from torch_geometric.nn import GCNConv

class GraphAutoencoder(nn.Module):
    def __init__(self, input_dim, hidden_dim):
        super(GraphAutoencoder, self).__init__()
        self.encoder = GCNConv(input_dim, hidden_dim)
        self.decoder = GCNConv(hidden_dim, input_dim)
        
    def forward(self, x, edge_index):
        z = self.encoder(x, edge_index)
        x_hat = self.decoder(z, edge_index)
        return z, x_hat

然后,我们可以训练模型:

import torch.optim as optim
from torch_geometric.data import DataLoader

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

model = GraphAutoencoder(input_dim=dataset.num_features, hidden_dim=16).to(device)
optimizer = optim.Adam(model.parameters(), lr=0.01)
criterion = nn.MSELoss()

data = data.to(device)

def train():
    model.train()
    optimizer.zero_grad()
    z, x_hat = model(data.x, data.edge_index)
    loss = criterion(x_hat, data.x)
    loss.backward()
    optimizer.step()

def evaluate():
    model.eval()
    with torch.no_grad():
        z, x_hat = model(data.x, data.edge_index)
        loss = criterion(x_hat, data.x)
    return loss.item()

for epoch in range(200):
    train()
    loss = evaluate()
    print(f'Epoch: {epoch+1}, Loss: {loss:.4f}')

在训练过程中,模型通过将输入图数据压缩为低维表示z,然后再使用解码器将低维表示还原为原始图数据。训练过程中的损失函数为均方差损失,用于衡量重构的图数据与原始图数据之间的差异。

# GPF ## 一、GPF(Graph Processing Flow):利用神经网络处理问题的一般化流程 1、节点预表示:利用NE框架,直接获得全每个节点的Embedding; 2、正负样本采样:(1)单节点样本;(2)节点对样本; 3、抽取封闭子:可做类化处理,建立一种通用数据结构; 4、子特征融合:预表示、节点特征、全局特征、边特征; 5、网络配置:可以是输入、输出的网络;也可以是输入,分类/聚类结果输出的网络; 6、训练和测试; ## 二、主要文件: 1、graph.py:读入数据; 2、embeddings.py:预表示学习; 3、sample.py:采样; 4、subgraphs.py/s2vGraph.py:抽取子; 5、batchgraph.py:子特征融合; 6、classifier.py:网络配置; 7、parameters.py/until.py:参数配置/帮助文件; ## 三、使用 1、在parameters.py中配置相关参数(可默认); 2、在example/文件夹中运行相应的案例文件--包括链接预测、节点状态预测; 以链接预测为例: ### 1、导入配置参数 ```from parameters import parser, cmd_embed, cmd_opt``` ### 2、参数转换 ``` args = parser.parse_args() args.cuda = not args.noCuda and torch.cuda.is_available() torch.manual_seed(args.seed) if args.cuda: torch.cuda.manual_seed(args.seed) if args.hop != 'auto': args.hop = int(args.hop) if args.maxNodesPerHop is not None: args.maxNodesPerHop = int(args.maxNodesPerHop) ``` ### 3、读取数据 ``` g = graph.Graph() g.read_edgelist(filename=args.dataName, weighted=args.weighted, directed=args.directed) g.read_node_status(filename=args.labelName) ``` ### 4、获取全节点的Embedding ``` embed_args = cmd_embed.parse_args() embeddings = embeddings.learn_embeddings(g, embed_args) node_information = embeddings #print node_information ``` ### 5、正负节点采样 ``` train, train_status, test, test_status = sample.sample_single(g, args.testRatio, max_train_num=args.maxTrainNum) ``` ### 6、抽取节点对的封闭子 ``` net = until.nxG_to_mat(g) #print net train_graphs, test_graphs, max_n_label = subgraphs.singleSubgraphs(net, train, train_status, test, test_status, args.hop, args.maxNodesPerHop, node_information) print('# train: %d, # test: %d' % (len(train_graphs), len(test_graphs))) ``` ### 7、加载网络模型,并在classifier中配置相关参数 ``` cmd_args = cmd_opt.parse_args() cmd_args.feat_dim = max_n_label + 1 cmd_args.attr_dim = node_information.shape[1] cmd_args.latent_dim = [int(x) for x in cmd_args.latent_dim.split('-')] if len(cmd_args.latent_dim) == 1: cmd_args.latent_dim = cmd_args.latent_dim[0] model = classifier.Classifier(cmd_args) optimizer = optim.Adam(model.parameters(), lr=args.learningRate) ``` ### 8、训练和测试 ``` train_idxes = list(range(len(train_graphs))) best_loss = None for epoch in range(args.num_epochs): random.shuffle(train_idxes) model.train() avg_loss = loop_dataset(train_graphs, model, train_idxes, cmd_args.batch_size, optimizer=optimizer) print('\033[92maverage training of epoch %d: loss %.5f acc %.5f auc %.5f\033[0m' % (epoch, avg_loss[0], avg_loss[1], avg_loss[2])) model.eval() test_loss = loop_dataset(test_graphs, model, list(range(len(test_graphs))), cmd_args.batch_size) print('\033[93maverage test of epoch %d: loss %.5f acc %.5f auc %.5f\033[0m' % (epoch, test_loss[0], test_loss[1], test_loss[2])) ``` ### 9、运行结果 ``` average test of epoch 0: loss 0.62392 acc 0.71462 auc 0.72314 loss: 0.51711 acc: 0.80000: 100%|███████████████████████████████████| 76/76 [00:07<00:00, 10.09batch/s] average training of epoch 1: loss 0.54414 acc 0.76895 auc 0.77751 loss: 0.37699 acc: 0.79167: 100%|█████████████████████████████████████| 9/9 [00:00<00:00, 34.07batch/s] average test of epoch 1: loss 0.51981 acc 0.78538 auc 0.79709 loss: 0.43700 acc: 0.84000: 100%|███████████████████████████████████| 76/76 [00:07<00:00, 9.64batch/s] average training of epoch 2: loss 0.49896 acc 0.79184 auc 0.82246 loss: 0.63594 acc: 0.66667: 100%|█████████████████████████████████████| 9/9 [00:00<00:00, 28.62batch/s] average test of epoch 2: loss 0.48979 acc 0.79481 auc 0.83416 loss: 0.57502 acc: 0.76000: 100%|███████████████████████████████████| 76/76 [00:07<00:00, 9.70batch/s] average training of epoch 3: loss 0.50005 acc 0.77447 auc 0.79622 loss: 0.38903 acc: 0.75000: 100%|█████████████████████████████████████| 9/9 [00:00<00:00, 34.03batch/s] average test of epoch 3: loss 0.41463 acc 0.81132 auc 0.86523 loss: 0.54336 acc: 0.76000: 100%|███████████████████████████████████| 76/76 [00:07<00:00, 9.57batch/s] average training of epoch 4: loss 0.44815 acc 0.81711 auc 0.84530 loss: 0.44784 acc: 0.70833: 100%|█████████████████████████████████████| 9/9 [00:00<00:00, 28.62batch/s] average test of epoch 4: loss 0.48319 acc 0.81368 auc 0.84454 loss: 0.36999 acc: 0.88000: 100%|███████████████████████████████████| 76/76 [00:07<00:00, 10.17batch/s] average training of epoch 5: loss 0.39647 acc 0.84184 auc 0.89236 loss: 0.15548 acc: 0.95833: 100%|█████████████████████████████████████| 9/9 [00:00<00:00, 28.62batch/s] average test of epoch 5: loss 0.30881 acc 0.89623 auc 0.95132 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值