图神经网络实战(6)——使用PyTorch构建图神经网络

图神经网络实战(6)——使用PyTorch构建图神经网络

    • 0. 前言
    • 1. 传统机器学习与人工智能
    • 2. 人工神经网络基础
      • 2.1 人工神经网络组成
      • 2.2 神经网络的训练
    • 3. 图神经网络
    • 4. 使用香草神经网络执行节点分类
      • 4.1 数据集构建
      • 4.2 模型构建
      • 4.3 模型训练
    • 5. 实现香草图神经网络执行节点分类
      • 5.1 图神经网络基本原理
      • 5.2 实现香草图神经网络
    • 小结
    • 系列链接

0. 前言

图数据集通常比简单的连接集合更加丰富,因为节点和边可以具有表示分数、颜色、单词等特征。包含这些额外信息在输入数据中对于生成最佳嵌入至关重要。由于节点和边的特征与非图数据集具有相似的结构,这意味着经典技术如神经网络可以应用于这些数据。在本节中,我们将使用 Cora 和 Facebook Page-Page 数据集,首先将它们视为表格数据集,观察香草神经网络 (vanilla neural networks) 在节点特征上的表现如何。然后,尝试在神经网络中加入拓扑信息,实现图神经网络 (Graph Neural Networks, GNN) 架构:一个同时考虑节点特征和边的简单模型。最后,我们将比较两种架构的性能。

1. 传统机器学习与人工智能

传统应用程序中,系统是通过使用程序员编写的复杂算法来实现智能化的。例如,假设我们希望识别照片中是否包含狗。在传统的机器学习 (Machine Learning, ML) 中,需要机器学习研究人员首先确定需要从图像中提取的特征,然后提取这些特征并将它们作为输入传递给复杂算法,算法解析给定特征以判断图像中是否包含狗:

传统机器学习

然而,如果要为多种类别图像分类手动提取特征,其数量可能是指数级的,因此,传统方法在受限环境中效果很好(例如,识别证件照片),而在不受限制的环境中效果不佳,因为每张图像之间都有较大差异。
我们可以将相同的思想扩展到其他领域,例如文本或结构化数据。过去,如果希望通过编程来解决现实世界的任务,就必须了解有关输入数据的所有内容并编写尽可能多的规则来涵盖所有场景,并且不能保证所有新场景都会遵循已有规则。
而神经网络内含了特征提取的过程,并将这些特征用于分类/回归,几乎不需要手动特征工程,只需要标记数据(例如,哪些图片是狗,哪些图片不是狗)和神经网络架构,不需要手动提出规则来对图像进行分类,这减轻了传统机器学习技术强加给程序员的大部分负担。
训练神经网络需要提供大量样本数据。例如,在前面的例子中,我们需要为模型提供大量的狗和非狗图片,以便它学习特征。神经网络用于分类任务的流程如下,其训练与测试是端到端 (end-to-end) 的:

神经网络训练

2. 人工神经网络基础

2.1 人工神经网络组成

ANN 是张量(权重, weights )和数学运算的集合,其排列方式近似于松散的人脑神经元排列。可以将其视为一种数学函数,它将一个或多个张量作为输入并预测相应输出(一个或多个张量)。将输入连接到输出的操作方式称为神经网络的架构,我们可以根据不同的任务构建不同架构,即基于问题是包含结构化数据还是非结构化(图像,文本,语音)数据,这些数据就是输入和输出张量的列表。ANN 由以下部分组成:

  • 输入层:将自变量作为输入
  • 隐藏(中间)层:连接输入和输出层,在输入数据之上执行转换;此外,隐藏层利用节点单元(下图中的圆圈)将其输入值修改为更高/更低维的值;通过修改中间节点的激活函数可以实现复杂表示函数
  • 输出层:输入变量产生的值

综上,神经网络的典型结构如下:

神经网络架构
输出层中节点的数量(上图中的圆圈)取决于实际任务以及我们是在尝试预测连续变量还是分类变量。如果输出是连续变量,则输出有一个节点。如果输出是具有 m 个可能类别的分类,则输出层中将有 m 个节点。接下来,我们深入介绍节点/神经元的工作原理,神经元按如下方式转换其输入:

神经元

其中, x 1 x_1 x1 x 2 x_2 x2,…, x n x_n xn 是输入变量, w 0 w_0 w0 是偏置项(类似于线性/逻辑回归中的偏差); w 1 w_1 w1 w 2 w_2 w2,…, w n w_n wn 是赋予每个输入变量的权重,输出值 a a a 计算如下:

a = f ( w 0 + ∑ w i N w i x i ) a=f(w_0+\sum _{w_i} ^N w_ix_i) a=f(w0+wiNwixi)

可以看到, a a a 是权重和输入对的乘积之和,之后使用一个附加函数 f ( w 0 + ∑ w i N w i x i ) f(w_0+\sum _{w_i} ^N w_ix_i) f(w0+wiNwixi),函数 f f f 是在乘积之和之上应用的非线性激活函数,用于在输入和它们相应的权重值的总和上引入非线性,可以通过使用多个隐藏层实现更强的非线性能力。
整体而言,神经网络是节点的集合,其中每个节点都有一个可调整的浮点值(权重),并且节点间相互连接,返回由网络架构决定的输出。网络由三个主要部分组成:输入层、隐藏层和输出层。我们可以使用多层 (n) 隐藏层,深度学习通常表示具有多个隐藏层的神经网络。通常,当神经网络需要学习具有复杂上下文或上下文不明显的任务(例如图像识别)时,就必须具有更多隐藏层。

2.2 神经网络的训练

训练神经网络实际上就是通过重复两个关键步骤来调整神经网络中的权重:前向传播和反向传播。

  1. 在前向传播 (feedforward propagation) 中,我们将一组权重应用于输入数据,将其传递给隐藏层,对隐藏层计算后的输出使用非线性激活,通过若干个隐藏层后,将最后一个隐藏层的输出与另一组权重相乘,就可以得到输出层的结果。对于第一次正向传播,权重的值将随机初始化
  2. 在反向传播 (backpropagation) 中,尝试通过测量输出的误差,然后相应地调整权重以降低误差。神经网络重复正向传播和反向传播以预测输出,直到获得令误差较小的权重为止

3. 图神经网络

图神经网络 (Graph Neural NetworkGNN) 是一种专门用于处理图数据的深度学习模型。传统的神经网络主要用于处理向量或序列数据,而图神经网络则可以有效地处理非结构化的图形数据,如社交网络、推荐系统中的用户-物品关系、生物信息学中的蛋白质相互作用网络等。
图神经网络通过学习节点之间的连接模式和拓扑结构来捕捉图数据中的信息传播和相互作用。它通过将每个节点及其邻居节点的特征进行聚合和更新,从而实现对整个图的表示学习。在图神经网络中,通常会定义节点表示 (node embedding) 和边表示 (edge embedding),以便更好地表示节点之间的关系和特征。
图神经网络的基本原理是通过多层神经网络结构来逐步传播和更新节点的特征信息,从而实现对整个图的全局信息的学习和表示。这种方式可以帮助图神经网络在保留局部结构信息的同时,也考虑了全局图的拓扑结构和特征之间的关系,从而提高了对图数据的建模能力。
图神经网络已经在许多领域得到广泛应用,包括社交网络分析、推荐系统、生物信息学、知识图谱等。它为处理复杂的非结构化数据提供了一种强大的工具,有助于挖掘数据中的潜在模式和关联,从而推动了深度学习在图数据分析领域的发展和应用。

4. 使用香草神经网络执行节点分类

与 Zachary’s Karate Club 数据集相比,Cora 和 Facebook Page-Page 数据集包含了额外信息——节点特征,提供了图中节点的额外信息,例如用户的年龄、性别或兴趣爱好等。在香草神经网络( vanilla neural networks, 也称为多层感知器, multilayer perceptron )中,嵌入会直接用于模型,以执行节点分类等下游任务。

4.1 数据集构建

在本节中,我们将节点特征视为常规的表格数据集,并在这个数据集上训练一个简单的神经网络来对节点进行分类。需要注意的是,这种架构没有考虑到网络的拓扑结构。以 Cora 数据集为例,通过创建数据对象可以轻松访问节点特征的表格数据集。
首先,通过合并 data.x (包含节点特征)和 data.y (包含七个类别中每个节点的类别标签),将该对象转换为普通的 pandas DataFrame

import pandas as pd
df_x = pd.DataFrame(data.x.numpy())
df_x['label'] = pd.DataFrame(data.y)
print(df_x)

得到的数据集如下所示:

        0    1    2    3    4    5  ...  1428  1429  1430  1431  1432  label
0     0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3
1     0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      4
2     0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      4
3     0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      0
4     0.0  0.0  0.0  1.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3
...   ...  ...  ...  ...  ...  ...  ...   ...   ...   ...   ...   ...    ...
2703  0.0  0.0  0.0  0.0  0.0  1.0  ...   0.0   0.0   0.0   0.0   0.0      3
2704  0.0  0.0  1.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3
2705  0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3
2706  0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3
2707  0.0  0.0  0.0  0.0  0.0  0.0  ...   0.0   0.0   0.0   0.0   0.0      3

[2708 rows x 1434 columns]

这是一个包含数据和标签的经典数据集,据此,我们可以构建一个简单的多层感知器 (Multilayer Perceptron, MLP),用 data.y 提供的标签对 data.x 进行训练。
创建 MLP 类,包含以下四个方法:

  • __init__() 用于初始化实例
  • forward() 用于执行前向传播
  • fit() 用于执行反向传播训练模型
  • test() 用于评估模型

在训练模型之前,我们必须定义模型评价指标。多分类问题有多种评价指标,包括准确率 (accuracy)、F1 分数 (F1 score)、ROC AUC ( Area Under the Receiver Operating Characteristic Curve) 等。在本节中,我们采用准确率作为评价指标,即正确预测的百分比。虽然这并不是多分类模型的最佳评价指标,但它更容易理解,我们也可以使用其他指标来代替它:

def accuracy(y_pred, y_true):
    """Calculate accuracy."""
    return torch.sum(y_pred == y_true) / len(y_true)

4.2 模型构建

接下来,我们使用 PyTorch 构建 MPL 模型。

(1)PyTorch 中导入所需的函数和类:

import torch
from torch.nn import Linear
import torch.nn.functional as F

(2) 创建一个名为 MLP 的新类,它继承自 torch.nn.Module

class MLP(torch.nn.Module):

(3) __init__() 方法有三个参数 (dim_indim_hdim_out),分别表示输入层、隐藏层和输出层的神经元数量,在 __init__() 方法中还需要定义两个线性层:

    def __init__(self, dim_in, dim_h, dim_out):
        super().__init__()
        self.linear1 = Linear(dim_in, dim_h)
        self.linear2 = Linear(dim_h, dim_out)

(4) forward() 方法用于执行前向传递。输入通过 ReLU (Rectified Linear Unit) 激活函数馈送到第一个线性层,之后计算结果传递到第二个线性层。最后,返回分类结果的 log_softmax 值:

    def forward(self, x):
        x = self.linear1(x)
        x = torch.relu(x)
        x = self.linear2(x)
        return F.log_softmax(x, dim=1)

(5) fit() 方法用于模型训练。首先,初始化一个损失函数和一个优化器用于训练过程:

    def fit(self, data, epochs):
        criterion = torch.nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(self.parameters(),
                                          lr=0.01,
                                          weight_decay=5e-4)

(6) 循环训练 MPL 模型,在损失函数之上使用 accuracy() 函数:

        self.train()
        for epoch in range(epochs+1):
            optimizer.zero_grad()
            out = self(data.x)
            loss = criterion(out[data.train_mask], data.y[data.train_mask])
            acc = accuracy(out[data.train_mask].argmax(dim=1),
                          data.y[data.train_mask])
            loss.backward()
            optimizer.step()

(7) 在同一个循环中,每 20epoch 打印一次训练数据和测试数据的损失和准确率:

            if(epoch % 20 == 0):
                val_loss = criterion(out[data.val_mask], data.y[data.val_mask])
                val_acc = accuracy(out[data.val_mask].argmax(dim=1),
                                  data.y[data.val_mask])
                print(f'Epoch {epoch:>3} | Train Loss: {loss:.3f} | Train Acc:'
                      f' {acc*100:>5.2f}% | Val Loss: {val_loss:.2f} | '
                      f'Val Acc: {val_acc*100:.2f}%')

(8) test() 方法用于在测试集上对模型进行评估,并返回模型准确率:

    @torch.no_grad()      
    def test(self, data):
        self.eval()
        out = self(data.x)
        acc = accuracy(out.argmax(dim=1)[data.test_mask], data.y[data.test_mask])
        return acc

4.3 模型训练

对于不同数据集需要单独训练模型,由于我们想要分别在 CoraFacebook Page-Page 数据集上执行节点分类任务,因此需要一个专门用于 Cora 的模型,和一个专门用于 Facebook Page-Page 的模型。首先,在 Cora 上训练 MLP 模型。

(1) 创建一个 MLP 模型并打印模型简要信息,以检查模型构建是否正确:

mlp = MLP(dataset.num_features, 16, dataset.num_classes)
print(mlp)

输出结果如下所示:

MLP(
  (linear1): Linear(in_features=1433, out_features=16, bias=True)
  (linear2): Linear(in_features=16, out_features=7, bias=True)
)

(2) 可以看到,我们得到了正确的特征数量,接下来,对这个模型进行 100epoch 训练:

mlp.fit(data, epochs=100)

在训练循环中打印的指标变化情况如下所示:

Epoch   0 | Train Loss: 1.953 | Train Acc: 13.57% | Val Loss: 1.97 | Val Acc: 16.00%
Epoch  20 | Train Loss: 0.081 | Train Acc: 100.00% | Val Loss: 1.49 | Val Acc: 50.20%
Epoch  40 | Train Loss: 0.009 | Train Acc: 100.00% | Val Loss: 1.63 | Val Acc: 50.20%
Epoch  60 | Train Loss: 0.006 | Train Acc: 100.00% | Val Loss: 1.62 | Val Acc: 48.80%
Epoch  80 | Train Loss: 0.007 | Train Acc: 100.00% | Val Loss: 1.49 | Val Acc: 51.00%
Epoch 100 | Train Loss: 0.008 | Train Acc: 100.00% | Val Loss: 1.42 | Val Acc: 51.20%

(3) 最后,评估评估的准确率:

acc = mlp.test(data)
print(f'\nMLP test accuracy: {acc*100:.2f}%')

在测试数据上,模型准确率如下所示:

MLP test accuracy: 52.40%

(4)Facebook Page-Page 数据集重复同样的过程,输出结果如下:

Epoch   0 | Train Loss: 1.400 | Train Acc: 26.00% | Val Loss: 1.41 | Val Acc: 25.86%
Epoch  20 | Train Loss: 0.651 | Train Acc: 74.33% | Val Loss: 0.66 | Val Acc: 73.89%
Epoch  40 | Train Loss: 0.575 | Train Acc: 77.14% | Val Loss: 0.62 | Val Acc: 75.49%
Epoch  60 | Train Loss: 0.547 | Train Acc: 78.07% | Val Loss: 0.60 | Val Acc: 75.79%
Epoch  80 | Train Loss: 0.531 | Train Acc: 78.83% | Val Loss: 0.60 | Val Acc: 75.54%
Epoch 100 | Train Loss: 0.517 | Train Acc: 79.52% | Val Loss: 0.59 | Val Acc: 75.69%

MLP test accuracy: 74.89%

尽管这两个数据集在某些方面非常相似,但可以看到,使用相同的模型训练后的模型准确率却大相径庭。接下来,我们将同时考虑图数据的节点特征和拓扑结构构建香草图神经网络 (Vanilla Graph Neural Network, Vanilla GNN)。

5. 实现香草图神经网络执行节点分类

5.1 图神经网络基本原理

在介绍图神经网络 (Graph Neural Network, GNN) 架构前,尝试从零开始构建 GNN 模型以了解 GNN 的核心思想。首先,我们回顾简单线性层的定义。
一个香草神经网络层对应于一个线性变换关系 h A = x A W T h_A=x_AW^T hAxAWT,其中 x A x_A xA 是节点 A A A 的输入向量, W W W 是网络层的权重矩阵。在 PyTorch 中,可以使用 torch.mm() 函数或 nn.Linear 类来实现上述变换,而后者还可以添加偏置等其他参数。
对于图数据集,输入向量是节点特征,这意味着节点之间是完全独立的,因此 MPL 模型还不足以很好地理解图,与图像中的像素一样,节点的上下文对于理解节点至关重要。在图像中,我们只有在观察一组像素而不是单个像素时,才能够识别出边缘、模式等,同样,要了解一个节点,就需要查看它的邻居。
使用 N A \mathcal N_A NA 表示节点 A A A 的邻居集,则图线性层 (Graph Linear Layer) 可以表示为:
h A = ∑ i ∈ N A x i W T h_A=\sum_{i\in \mathcal N_A} x_iW^T hA=iNAxiWT
也可以对上述公式进行简单的变换。例如,可以为中心节点设置一个权重矩阵 W 1 W_1 W1,为邻居设置另一个权重矩阵 W 2 W_2 W2。需要注意的是,我们不能为每个邻居设置一个权重矩阵,因为邻居节点数量会因节点不同而变化。
在神经网络中,为了高效的计算,不能将上述等式应用于每个节点,而应使用矩阵乘法。例如,线性层的方程可以改写为 H = X W T H=XW^T H=XWT,其中 X X X 是输入矩阵。
CoraFacebook Page-Page 数据集中,邻接矩阵 A A A 包含图中每个节点之间的连接。将输入矩阵与邻接矩阵相乘,就能直接求出邻居节点的特征。可以在邻接矩阵中加入自循环,这样中心节点的特征也会被考虑在内。更新后的邻接矩阵可以表示为 A ~ = A + I \tilde A=A+I A~=A+I,图线性层可以重写如下:
H = A ~ T X W T H=\tilde A^TXW^T H=A~TXWT

5.2 实现香草图神经网络

PyTorch 中实现上述图线性层并进行测试,然后,将它作为常规网络层来构建一个香草图神经网络 (Vanilla Graph Neural Network, Vanilla GNN)。

(1) 首先,创建一个新类 VanillaGNNLayer,继承自 torch.nn.Module 类:

class VanillaGNNLayer(torch.nn.Module):

(2)VanillaGNNLayer 的初始化需要两个参数,dim_indim_out,分别表示输入和输出的特征数,在 __init__() 方法中初始化一个无偏置线性变换:

    def __init__(self, dim_in, dim_out):
        super().__init__()
        self.linear = Linear(dim_in, dim_out, bias=False)

(3)forward() 方法中执行两个操作,首先执行线性变换,然后与邻接矩阵 A ~ \tilde A A~ 相乘:

    def forward(self, x, adjacency):
        x = self.linear(x)
        x = torch.sparse.mm(adjacency, x)
        return x

(4) 在创建 vanilla GNN 之前,还需要将数据集中的边索引 (data.edge_index) 以坐标格式转换为邻接矩阵,此外,还需要加入自循环;否则,中心节点的特征将不会被它们自己的嵌入所考虑。使用 to_den_adj()torch.eye() 函数能够快速实现上述操作:

from torch_geometric.utils import to_dense_adj

adjacency = to_dense_adj(data.edge_index)[0]
adjacency += torch.eye(len(adjacency))
print(adjacency)

输出邻接矩阵如下所示:

tensor([[1., 0., 0.,  ..., 0., 0., 0.],
        [0., 1., 1.,  ..., 0., 0., 0.],
        [0., 1., 1.,  ..., 0., 0., 0.],
        ...,
        [0., 0., 0.,  ..., 1., 0., 0.],
        [0., 0., 0.,  ..., 0., 1., 1.],
        [0., 0., 0.,  ..., 0., 1., 1.]])

但由于它是一个稀疏矩阵,因此在这个张量中大部分元素 0,节点之间存在连接时元素为 1。有了图线性层和邻接矩阵后, 我们就可以用与实现 MLP 类似的方法实现 vanilla GNN

(5) 创建一个包含两个图线性层的新类:

class VanillaGNN(torch.nn.Module):
    """Vanilla Graph Neural Network"""
    def __init__(self, dim_in, dim_h, dim_out):
        super().__init__()
        self.gnn1 = VanillaGNNLayer(dim_in, dim_h)
        self.gnn2 = VanillaGNNLayer(dim_h, dim_out)

(6) 图神经网络层会将之前计算的邻接矩阵作为额外输入:

    def forward(self, x, adjacency):
        h = self.gnn1(x, adjacency)
        h = torch.relu(h)
        h = self.gnn2(h, adjacency)
        return F.log_softmax(h, dim=1)

(7) fit()test() 方法与 MLP 模型完全相同:

    def fit(self, data, epochs):
        criterion = torch.nn.CrossEntropyLoss()
        optimizer = torch.optim.Adam(self.parameters(),
                                      lr=0.01,
                                      weight_decay=5e-4)

        self.train()
        for epoch in range(epochs+1):
            optimizer.zero_grad()
            out = self(data.x, adjacency)
            loss = criterion(out[data.train_mask], data.y[data.train_mask])
            acc = accuracy(out[data.train_mask].argmax(dim=1),
                          data.y[data.train_mask])
            loss.backward()
            optimizer.step()

            if(epoch % 20 == 0):
                val_loss = criterion(out[data.val_mask], data.y[data.val_mask])
                val_acc = accuracy(out[data.val_mask].argmax(dim=1),
                                  data.y[data.val_mask])
                print(f'Epoch {epoch:>3} | Train Loss: {loss:.3f} | Train Acc:'
                      f' {acc*100:>5.2f}% | Val Loss: {val_loss:.2f} | '
                      f'Val Acc: {val_acc*100:.2f}%')

    @torch.no_grad()
    def test(self, data):
        self.eval()
        out = self(data.x, adjacency)
        acc = accuracy(out.argmax(dim=1)[data.test_mask], data.y[data.test_mask])
        return acc

(8) 创建、训练并评估模型:

gnn = VanillaGNN(dataset.num_features, 16, dataset.num_classes)
print(gnn)
# Train
gnn.fit(data, epochs=100)
# Test
acc = gnn.test(data)
print(f'\nGNN test accuracy: {acc*100:.2f}%')

输出结果如下所示:

VanillaGNN(
  (gnn1): VanillaGNNLayer(
    (linear): Linear(in_features=1433, out_features=16, bias=False)
  )
  (gnn2): VanillaGNNLayer(
    (linear): Linear(in_features=16, out_features=7, bias=False)
  )
)
Epoch   0 | Train Loss: 2.626 | Train Acc: 16.43% | Val Loss: 2.56 | Val Acc: 7.40%
Epoch  20 | Train Loss: 0.274 | Train Acc: 95.71% | Val Loss: 1.22 | Val Acc: 67.60%
Epoch  40 | Train Loss: 0.046 | Train Acc: 100.00% | Val Loss: 1.40 | Val Acc: 74.60%
Epoch  60 | Train Loss: 0.015 | Train Acc: 100.00% | Val Loss: 1.60 | Val Acc: 74.00%
Epoch  80 | Train Loss: 0.008 | Train Acc: 100.00% | Val Loss: 1.65 | Val Acc: 73.40%
Epoch 100 | Train Loss: 0.005 | Train Acc: 100.00% | Val Loss: 1.68 | Val Acc: 72.00%

GNN test accuracy: 74.40%

Facebook Page-Page 数据集重复相同的训练过程。为了获得具有可比性的结果,我们在每个数据集上对每个模型重复了 100 次相同的实验,实验结果如下表所示:

MLPGNN
Cora53.52%(±1.79%)75.01%(±1.53%)
Facebook75.22%(±0.51%)85.01%(±1.55%)

可以看到,MLPCora 上的准确率较低,在 Facebook Page-Page 数据集上的表现较好,但在这两种情况下 MLP 的性能均被 vanilla GNN 所超越。这些结果表明了在节点特征中包含拓扑信息的重要性,由于 GNN 不使用表格数据集训练,而是考虑了每个节点的整个邻域,因此准确率提高了 10~20%

小结

在本节中,我们了解了 Vanilla 神经网络和图神经网络 (Graph Neural Network, GNN)之间的差异,利用了一些简单的线性代数知识构建了香草图神经网络 (Vanilla Graph Neural Network, Vanilla GNN) 架构,同时使用了两个不同的图数据集,以便比较两种不同的架构。最后,使用 PyTorch 中实现了两种架构,并评估了它们的性能。结果表明,在这两个数据集上,即使是最简单的 Vanilla GNN 也完全优于 MLP

系列链接

图神经网络实战(1)——图神经网络(Graph Neural Networks, GNN)基础
图神经网络实战(2)——图论基础
图神经网络实战(3)——基于DeepWalk创建节点表示
图神经网络实战(4)——基于Node2Vec改进嵌入质量
图神经网络实战(5)——常用图数据集

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/494934.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

聚观早报 | 比亚迪2023年营收;vivo X Fold3系列发布

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 3月28日消息 比亚迪2023年营收 vivo X Fold3系列发布 现代汽车拟投入68万亿韩元 华为P70系列最新渲染图 苹果A1…

Art Gallery Vol.2

Art Gallery Vol.2为您的游戏、VR项目和模拟器提供了一个很好的解决方案,图片库。 一个充满雕塑和框架的现代艺术画廊。它包括11件雕塑、14幅画作。适合收藏展览或画作展示。 所有画作都是独立的纹理,非常适合ArchViz、VR或任何类型的AAA游戏。 下载:​​Unity资源商店链接…

[linux] AttributeError: module ‘transformer_engine‘ has no attribute ‘pytorch‘

[BUG] AttributeError: module transformer_engine has no attribute pytorch Issue #696 NVIDIA/Megatron-LM GitHub 其中这个答案并没有解决我的问题&#xff1a; import flash_attn_2_cuda as flash_attn_cuda Traceback (most recent call last): File "<stdi…

国产数据库中统计信息自动更新机制

数据库中统计信息描述的数据库中表和索引的大小数以及数据分布状况&#xff0c;统计信息的准确性对优化器选择执行计划时具有重要的参考意义。本文简要整理了下传统数据库和国产数据库中统计信息的自动更新机制&#xff0c;以加深了解。 1、数据库统计信息介绍 优化器是数据库…

【系统架构师】-第13章-层次式架构设计

层次式体系结构设计是将系统组成一个层次结构&#xff0c;每一层 为上层服务 &#xff0c;并作为下层客户。 在一些层次系统中&#xff0c;除了一些精心挑选的输出函数外&#xff0c; 内部的层接口只对相邻的层可见 。 连接件通过决定层间如何交互的协议来定义&#xff0c;拓扑…

优化体验课转化流程:提升转化率,实现教育品牌增长

随着在线教育市场的竞争日益激烈&#xff0c;体验课转化流程成为影响教育机构发展的关键环节之一。本文将深入探讨如何优化体验课转化流程&#xff0c;提升转化率&#xff0c;实现教育品牌的可持续增长。 ### 什么是体验课转化流程&#xff1f; 体验课转化流程是指教育机构通…

windows安全中心设置@WindowsDefender@windows安全中心常用开关

文章目录 abstractwindows defender相关服务&#x1f47a; 停用windows Defender临时关闭实时防护使用软件工具关闭defender control(慎用)dismdControl 其他方法使其他杀毒软件注册表修改 保护历史恢复被认为是有病毒的文件添加信任目录,文件,文件类型或进程 abstract window…

Stable Diffusion XL之使用Stable Diffusion XL训练自己的AI绘画模型

文章目录 一 SDXL训练基本步骤二 从0到1上手使用Stable Diffusion XL训练自己的AI绘画模型2.1 配置训练环境与训练文件2.2 SDXL训练数据集制作(1) 数据筛选与清洗(2) 使用BLIP自动标注caption(3) 使用Waifu Diffusion 1.4自动标注tag(4) 补充标注特殊tag(5) 训练数据预处理(标注…

Sublime for Mac 使用插件Terminus

1. 快捷键打开命令面板 commandshiftp2. 选择 Package Control: Install Package&#xff0c;然后会出现安装包的列表 3. 在安装终端插件前&#xff0c;我们先装个汉化包&#xff0c;ChineseLocallization&#xff0c;安装完重启 4. 输入 terminus&#xff0c;选择第一个&am…

面试题:Java虚拟机JVM的组成

1. 基础概念 JVM是什么 Java Virtual Machine Java程序的运行环境&#xff08;java二进制字节码的运行环境&#xff09; 好处&#xff1a; 一次编写&#xff0c;到处运行 自动内存管理&#xff0c;垃圾回收机制 JVM由哪些部分组成&#xff0c;运行流程是什么&#xff1f; …

DoCAN配置

DoCAN涉及模块 CanTrcv -> Can -> CanIf -> CanTp -> PduR -> Dcm DCM DcmDslProtocolRow DcmDslProtocolID: DCM_UDS_ON_CAN DslProtocolSIDTable DcmDslMainConnection Rx 物理寻址/功能寻址 PDUR PduRBswModules-Dcm

spring安全框架之Shiro

Shiro 一、现存问题 1.1 现存问题 认证&#xff08;登录&#xff09;&#xff1a;认证操作流程都差不多&#xff0c;但是每次都需要手动的基于业务代码去实现&#xff0c;很麻烦&#xff01; 授权&#xff1a;如果权限控制粒度比较粗&#xff0c;可以自身去实现&#xff0c…

【论文阅读】Faster Neural Networks Straight from JPEG

Faster Neural Networks Straight from JPEG 论文链接&#xff1a;Faster Neural Networks Straight from JPEG (neurips.cc) 作者&#xff1a;Lionel Gueguen&#xff0c;Alex Sergeev&#xff0c;Ben Kadlec&#xff0c;Rosanne Liu&#xff0c;Jason Yosinski 机构&#…

数据结构与算法 单链表的基本运算

一、实验内容 编写一个程序实现&#xff0c;实现单链表的各种基本运算&#xff08;假设单链表的元素类型为char&#xff09;&#xff0c;并以此为基础设计一个程序完成下列功能&#xff1a; 初始化单链表&#xff1b;采用尾插法依次插入元素a&#xff0c;b&#xff0c;c&…

GitHub Copilot如何订阅使用

1.Copilot是什么 Copilot是由Github和OpenAI联合开发的一个基于人工智能大模型的代码写作工具。 我们都知道Github是世界上拥有开源项目及代码最多的一个平台&#xff0c;有了这么一个得天独厚的资源&#xff0c;Github联合OpenAI喂出了Copilot。经过不断地更新迭代&#xff…

GNU Radio之OFDM Carrier Allocator底层C++实现

文章目录 前言一、OFDM Carrier Allocator 简介二、底层 C 实现1、make 函数2、ofdm_carrier_allocator_cvc_impl 函数3、calculate_output_stream_length 函数4、work 函数5、~ofdm_carrier_allocator_cvc_impl 函数 三、OFDM 数据格式 前言 OFDM Carrier Allocator 是 OFDM …

Spring Boot项目启动过程中为什么日志打印没有显示完整包名呢?

一、前言 不知道大家注意过没有&#xff0c;在Spring Boot项目启动过程中日志打印并没有显示完整的报名&#xff0c;而是显示一些o.a.c&#xff0c;o.s.web形式的包名&#xff0c;如下图&#xff1a; 这是为什么呢&#xff1f; 二、原理 首先&#xff0c;我们先看一下Spring…

ArrayList和LinkedList有什么区别?

ArrayList和LinkedList的区别 ArrayList 和 LinkedList 是 Java 中常用的两种集合类&#xff0c;它们都实现了 List 接口&#xff0c;但在内部实现和性能上有一些区别。 内部实现&#xff1a; ArrayList 使用数组实现&#xff0c;它的元素在内存中是连续存储的&#xff0c;每…

软件部署资源计算工具:精确评估资源需求

软件部署资源计算工具&#xff1a;精确评估资源需求 在当今快速发展的信息技术时代&#xff0c;软件部署已成为企业运营不可或缺的一部分。然而&#xff0c;一个常见的挑战是如何精确评估软件部署所需的资源。资源评估不仅关系到软件的性能和稳定性&#xff0c;还直接影响到成…

Spring Boot:Web开发之三大组件的整合

Spring Boot 前言Spring Boot 整合 ServletSpring Boot 整合 FilterSpring Boot 整合 Listener 前言 在 Web 开发中&#xff0c;Servlet 、Filter 和 Listener 是 Java Web 应用中的三大组件。Servlet 是 Java 代码&#xff0c;通过 Java 的 API 动态的向客户端输出内容。Filt…