GCN(二)GCN模型介绍

本文介绍了如何使用PyTorch实现GCN模型,详细步骤包括初始化模型、构建两层GraphConvolution层、前向传播过程,以及在Cora数据集上进行训练,展示了GCN用于节点分类的实际操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一节介绍了处理cora数据集,以及返回的结果:

  • features:论文的属性特征,维度2708×14332708 \times 14332708×1433,并且做了归一化,即每一篇论文属性值的和为1.
  • labels:每一篇论文对应的分类编号:0-6
  • adj:邻接矩阵,维度2708×27082708 \times 27082708×2708
  • idx_train:0-139
  • idx_val:200-499
  • idx_test:500-1499

这一节介绍GCN的模型。

GCN 模型

model:

import torch.nn as nn
import torch.nn.functional as F
from pygcn.layers import GraphConvolution


class GCN(nn.Module):
    def __init__(self, nfeat, nhid, nclass, dropout):
        super(GCN, self).__init__()

        self.gc1 = GraphConvolution(nfeat, nhid)  # 构建第一层 GCN
        self.gc2 = GraphConvolution(nhid, nclass)  # 构建第二层 GCN
        self.dropout = dropout

    def forward(self, x, adj):
        x = F.relu(self.gc1(x, adj))
        x = F.dropout(x, self.dropout, training=self.training)
        x = self.gc2(x, adj)
        return F.log_softmax(x, dim=1)

layers:

import math

import torch

from torch.nn.parameter import Parameter
from torch.nn.modules.module import Module


class GraphConvolution(Module):
    """
    Simple GCN layer, similar to https://arxiv.org/abs/1609.02907
    """

    def __init__(self, in_features, out_features, bias=True):
        super(GraphConvolution, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.weight = Parameter(torch.FloatTensor(in_features, out_features))  # input_features, out_features
        if bias:
            self.bias = Parameter(torch.FloatTensor(out_features))
        else:
            self.register_parameter('bias', None)
        self.reset_parameters()

    def reset_parameters(self):
        stdv = 1. / math.sqrt(self.weight.size(1))
        self.weight.data.uniform_(-stdv, stdv)  # 随机化参数
        if self.bias is not None:
            self.bias.data.uniform_(-stdv, stdv)

    def forward(self, input, adj):
        support = torch.mm(input, self.weight)  # GraphConvolution forward。input*weight
        output = torch.spmm(adj, support)  # 稀疏矩阵的相乘,和mm一样的效果
        if self.bias is not None:
            return output + self.bias
        else:
            return output

    def __repr__(self):
        return self.__class__.__name__ + ' (' \
               + str(self.in_features) + ' -> ' \
               + str(self.out_features) + ')'

初始化模型

调用模型:

model = GCN(nfeat=features.shape[1],
            nhid=args.hidden,
            nclass=labels.max().item() + 1,
            dropout=args.dropout)

具体参数:

model = GCN(nfeat=1433,
            nhid=16,
            nclass=7,
            dropout=0.5)

初始化模型两层GCN:

self.gc1 = GraphConvolution(nfeat=1433, nhid=16)  # 构建第一层 GCN
self.gc2 = GraphConvolution(nhid=16, nclass=7)  # 构建第二层 GCN
self.dropout = 0.5

初始化具体layer:
第一层:gc1

def __init__(self, in_features, out_features, bias=True):
    super(GraphConvolution, self).__init__()
    self.in_features = 1433
    self.out_features = 16
    self.weight = Parameter(torch.FloatTensor(1433, 16))  # input_features, out_features
	self.bias = Parameter(torch.FloatTensor(16))
    self.reset_parameters() # 初始化w和b

参数www的维度:W1433×16W_{1433 \times 16}W1433×16
参数bbb的维度:b1×16b_{1 \times 16}b1×16
第二层:gc2

def __init__(self, in_features, out_features, bias=True):
    super(GraphConvolution, self).__init__()
    self.in_features = 16
    self.out_features = 7
    self.weight = Parameter(torch.FloatTensor(16, 7))  # input_features, out_features
	self.bias = Parameter(torch.FloatTensor(7))
    self.reset_parameters() # 初始化w和b

参数www的维度:W1433×16W_{1433 \times 16}W1433×16
参数bbb的维度: b1×7b_{1 \times 7}b1×7

forward执行模型

  1. 首先执行model:
def forward(self, x, adj):
    x = F.relu(self.gc1(x, adj))
    x = F.dropout(x, self.dropout, training=self.training)
    x = self.gc2(x, adj)
    return F.log_softmax(x, dim=1)
  1. 执行self.gc1(x, adj)x表示输入特征,维度2708×14332708 \times 14332708×1433adj表示邻接矩阵,维度2708×27082708 \times 27082708×2708

  2. 执行GCN layer gc1层,

        support = torch.mm(input, self.weight)  # GraphConvolution forward。input*weight
        output = torch.spmm(adj, support)

计算output,output2708×16=adj2708×2708×input2708×1433×W1433×16output_{2708 \times 16} = adj_{2708 \times 2708} \times input_{2708 \times 1433} \times W_{1433 \times 16}output2708×16=adj2708×2708×input2708×1433×W1433×16,然后返回output=output2708×16+bias1×16output = output_{2708 \times 16} + bias_{1 \times 16}output=output2708×16+bias1×16

output[0]=
tensor([ 0.0201, -0.0242,  0.0608,  0.0272,  0.0133,  0.0085,  0.0084, -0.0265,
         0.0149, -0.0100,  0.0077,  0.0029,  0.0145, -0.0181, -0.0021, -0.0183],
       grad_fn=<SelectBackward>)
self.bias=
Parameter containing:
tensor([-0.2232, -0.0295, -0.1387,  0.2170, -0.1749, -0.1551,  0.1056, -0.1860,
        -0.0666, -0.1327,  0.0212,  0.1587,  0.2496, -0.0154, -0.1683,  0.0151],
       requires_grad=True)
(output + self.bias)[0]=
tensor([-0.2030, -0.0537, -0.0779,  0.2442, -0.1616, -0.1466,  0.1140, -0.2125,
        -0.0516, -0.1427,  0.0289,  0.1615,  0.2641, -0.0336, -0.1704, -0.0032],
       grad_fn=<SelectBackward>)
  1. 使用ReluReluRelu激活函数,
x = F.relu(self.gc1(x, adj))
x[0]=
tensor([0.0000, 0.0000, 0.0000, 0.2442, 0.0000, 0.0000, 0.1140, 0.0000, 0.0000,
       0.0000, 0.0289, 0.1615, 0.2641, 0.0000, 0.0000, 0.0000],
      grad_fn=<SelectBackward>)
  1. 在training阶段,使用dropoutdropoutdropout, 执行x=x1−0.5x=\frac{x}{1-0.5}x=10.5x,并以0.5的概率去除:
x = F.dropout(x, self.dropout, training=self.training)
x[0]=
tensor([0.0000, 0.0000, 0.0000, 0.4884, 0.0000, 0.0000, 0.2280, 0.0000, 0.0000,
        0.0000, 0.0000, 0.3230, 0.5282, 0.0000, 0.0000, 0.0000],
       grad_fn=<SelectBackward>)
  1. 执行第二层 gc2
        support = torch.mm(input, self.weight)  # GraphConvolution forward。input*weight
        output = torch.spmm(adj, support)

计算output,output2708×7=adj2708×2708×input2708×16×W16×7output_{2708 \times 7} = adj_{2708 \times 2708} \times input_{2708 \times 16} \times W_{16 \times 7}output2708×7=adj2708×2708×input2708×16×W16×7,然后返回output=output2708×7+bias1×7output = output_{2708 \times 7} + bias_{1 \times 7}output=output2708×7+bias1×7

output[0]=
tensor([-0.1928,  0.1723,  0.1689, -0.0516,  0.0387, -0.0276, -0.1027],
       grad_fn=<SelectBackward>)
  1. 将返回结果x,直接吐给F.log_softmax(x,dim=1)F.log\_softmax(x, dim=1)F.log_softmax(x,dim=1)dim=1dim=1dim=1表示对7维度进行log_softmax
x[0]=
tensor([-2.1474, -1.7823, -1.7856, -2.0062, -1.9158, -1.9822, -2.0573],
       grad_fn=<SelectBackward>)
  1. 将output与label进行计算loss 与 acc_train
    loss=tensor(1.9186, grad_fn=<NllLossBackward>) acc_train=tensor(0.1357, dtype=torch.float64)
  2. 最后进行反向传播,更新梯度W和b
  3. 完成一次train的过程
### GCN(图卷积网络)模型的实现方法与代码示例 #### 背景介绍 图卷积网络(Graph Convolutional Network, GCN)是一种专门用于处理图结构数据的深度学习模型。它能够通过对节点及其邻居的信息进行聚合和更新,从而有效地捕捉图中的拓扑结构特性[^1]。 #### 数据准备 在使用GCN之前,通常需要准备好两个主要的数据组件: 1. **邻接矩阵 (Adjacency Matrix)**:表示图中节点之间的连接关系。如果存在边,则对应的矩阵位置为1;否则为0。 2. **特征矩阵 (Feature Matrix)**:每个节点的初始特征向量组成的矩阵。 对于实际应用,还需要定义标签集以及划分训练集、验证集和测试集。 --- #### 实现步骤概述 以下是基于PyTorch Geometric库的一个简单GCN实现流程: 1. 安装必要的依赖项: ```bash pip install torch torchvision torchaudio dgl torch_geometric ``` 2. 导入所需模块并加载数据: ```python import torch from torch_geometric.datasets import Planetoid from torch_geometric.nn import GCNConv dataset = Planetoid(root='/tmp/Cora', name='Cora') # 使用Cora数据集作为示例 data = dataset[0] ``` 3. 构建GCN模型架构: ```python class GCN(torch.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 = torch.relu(x) x = self.conv2(x, edge_index) return torch.log_softmax(x, dim=1) model = GCN(dataset.num_node_features, 16, dataset.num_classes) optimizer = torch.optim.Adam(model.parameters(), lr=0.01) criterion = torch.nn.NLLLoss() ``` 4. 训练过程: ```python def train(): model.train() optimizer.zero_grad() # 清除梯度 out = model(data.x, data.edge_index) # 前向传播 loss = criterion(out[data.train_mask], data.y[data.train_mask]) # 计算损失 loss.backward() # 反向传播 optimizer.step() # 更新参数 return loss.item() for epoch in range(200): # 进行200轮训练 loss = train() if epoch % 10 == 0: print(f'Epoch {epoch}, Loss: {loss:.4f}') ``` 5. 测试性能: ```python def test(mask): model.eval() with torch.no_grad(): pred = model(data.x, data.edge_index).argmax(dim=1) correct = (pred[mask] == data.y[mask]).sum().item() acc = correct / mask.sum().item() return acc val_acc = test(data.val_mask) test_acc = test(data.test_mask) print(f'Validation Accuracy: {val_acc:.4f}') print(f'Test Accuracy: {test_acc:.4f}') ``` --- #### 关键点解析 - **聚合操作**:GCN的核心在于如何通过聚合邻居节点信息来更新当前节点的特征[^2]。 - **层数设置**:一般来说,3~5层即可满足大多数任务需求,过多的层次可能导致过拟合或计算资源浪费[^2]。 - **优化器选择**:Adam优化器因其良好的收敛性和稳定性,在许多实验中被广泛采用。 --- #### 示例应用场景 假设有一个社交网络分析场景,目标是对用户进行社区划分或者兴趣推荐。可以将用户的交互行为抽象成一张无向图,其中顶点代表用户,边则反映他们的互动频率。接着按照上述方法搭建GCN模型,并利用历史记录完成监督学习任务。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值