图卷积神经网络GCN系列二:节点分类(含示例及代码)
图上的机器学习任务通常有三种类型:整图分类、节点分类和链接预测。本篇博客要实现的例子是节点分类,具体来说是用GCN对Cora数据集里的样本进行分类。
Cora数据集介绍:
Cora数据集由许多机器学习领域的paper构成,这些paper被分为7个类别:
- Case_Based
- Genetic_Algorithms
- Neural_Networks
- Probabilistic_Methods
- Reinforcement_Learning
- Rule_Learning
- Theory
在该数据集中,每一篇论文至少引用了该数据集里面另外一篇论文或者被另外一篇论文所引用,数据集总共有2708篇papers。
在消除停词以及除去文档频率小于10的词汇,最终词汇表中有1433个词汇,所以特征是1433维。0和1描述的是每个单词在paper中是否存在。
把每一篇论文作为一个节点,根据论文之间的引用关系可以构建一个graph,包含2708个节点。0~139为训练节点数据,140~539为验证节点数据,1708~2707为测试节点数据。
代码:(摘自https://github.com/rexrex9/gnn/blob/main/gcn.py。讲解视频https://www.bilibili.com/video/BV1W5411N78Y?from=search&seid=6220646189261474464&spm_id_from=333.337.0.0)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | import torch import torch.nn as nn import torch.nn.functional as F from dgl.nn.pytorch import GraphConv from dgl.data import CoraGraphDataset class GCN( nn.Module ): def __init__( self , g, #DGL的图对象 in_feats, #输入特征的维度 n_hidden, #隐层的特征维度 n_classes, #类别数 n_layers, #网络层数 activation, #激活函数 dropout #dropout系数 ): super ( GCN, self ).__init__() self .g = g self .layers = nn.ModuleList() # 输入层 self .layers.append( GraphConv( in_feats, n_hidden, activation = activation )) # 隐层 for i in range (n_layers - 1 ): self .layers.append(GraphConv(n_hidden, n_hidden, activation = activation )) # 输出层 self .layers.append( GraphConv( n_hidden, n_classes ) ) self .dropout = nn.Dropout(p = dropout) def forward( self , features ): h = features for i, layer in enumerate ( self .layers ): if i ! = 0 : h = self .dropout( h ) h = layer( self .g, h ) return h def evaluate(model, features, labels, mask): model. eval () with torch.no_grad(): logits = model(features) logits = logits[mask] labels = labels[mask] _, indices = torch. max (logits, dim = 1 ) correct = torch. sum (indices = = labels) return correct.item() * 1.0 / len (labels) def train(n_epochs = 100 , lr = 1e - 2 , weight_decay = 5e - 4 , n_hidden = 16 , n_layers = 1 , activation = F.relu , dropout = 0.5 ): data = CoraGraphDataset() g = data[ 0 ] # 图的所有信息,包含2078个节点,每个节点1433维,所有节点可分为7类。10556条边。 features = g.ndata[ 'feat' ] labels = g.ndata[ 'label' ] train_mask = g.ndata[ 'train_mask' ] # 0~139为训练节点 val_mask = g.ndata[ 'val_mask' ] # 140~539为验证节点 test_mask = g.ndata[ 'test_mask' ] # 1708-2707为测试节点 in_feats = features.shape[ 1 ] n_classes = data.num_classes model = GCN(g, in_feats, n_hidden, n_classes, n_layers, activation, dropout) loss_fcn = torch.nn.CrossEntropyLoss() optimizer = torch.optim.Adam( model.parameters(), lr = lr, weight_decay = weight_decay) best_val_acc = 0 for epoch in range ( n_epochs ): model.train() logits = model( features ) loss = loss_fcn( logits[ train_mask ], labels[ train_mask ] ) optimizer.zero_grad() loss.backward() optimizer.step() acc = evaluate(model, features, labels, val_mask) print ( "Epoch {} | Loss {:.4f} | Accuracy {:.4f} " . format (epoch, loss.item(), acc )) if acc > best_val_acc: best_val_acc = acc torch.save(model.state_dict(), 'models/best_model.pth' ) model.load_state_dict(torch.load( "models/best_model.pth" )) acc = evaluate(model, features, labels, test_mask) print ( "Test accuracy {:.2%}" . format (acc)) if __name__ = = '__main__' : train() |
运行结果:
......
分类:
Deep Learning
, Graph
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通