图神经网络实战(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_adjadjacency = 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)——常用图数据集

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大话设计模式之装饰模式

装饰模式(Decorator Pattern)是一种结构型设计模式,它允许向现有对象动态地添加新功能,同时又不改变其结构。装饰模式通过将对象放入包装器中来实现,在包装器中可以动态地添加功能。 在装饰模式中,通常会有…

【教程】JavaScript代码混淆及优化

摘要 本文将介绍常见的JavaScript代码混淆技术,包括字符串转十六进制、Unicode编码、Base64加密、数值加密、数组混淆、花指令、逗号表达式、控制流程平坦化和eval执行。通过对这些混淆技术的理解和应用,可以提高代码的安全性和保护知识产权。 引言 随…

(4)(4.3) Kogger Sonar

文章目录 前言 1 推荐硬件 2 配置回声探测仪模块 3 连接ArduPilot硬件 4 参数说明 前言 KOGGER 声纳(KOGGER Sonar)是一款结构紧凑、成本低廉的水下回声测深仪模块,带有 UART 接口,电源电压为 5-14v。 1 推荐硬件 CP210x USB->UART 转换器和安装…

C++第十三弹---内存管理(下)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 目录 1、operator new与operator delete函数 1.1、operator new与operator delete函数 2、new和delete的实现原理 2.1、内置类型 2.2、自定义类型 …

开源项目ChatGPT-Next-Web的容器化部署(二)-- jenkins CI构建并推送镜像

一、背景 接着上文已制作好了Dockerfile,接下来就是docker build/tag/push等一系列操作了。 不过在这之前,你还必须在jenkins等CI工具中,拉取源码,然后build构建应用。 因为本文的重点不是讲述jenkins ci工具,所以只…

亮数据——让你的IP走出去,让价值返回来

亮数据——让你的IP走出去,让价值返回来 前言跨境电商最最最大的痛点——让IP走出去超级代理服务器加速网络免费的代理管理软件亮数据解决痛点亮数据优势介绍亮数据浏览器的使用示例总结 前言 当前社会信息的价值是不可想象的,今天在亮数据中看到了个【…

Ipython与Jupyter之间的关系

IPython 和 Jupyter 之间的关系可以从它们的历史和目标中得到很好的解释。IPython(Interactive Python)最初是由 Fernando Prez 于 2001 年创建的,旨在提升 Python 的交互式计算体验。它提供了一个强大的交互式 Python shell 和一个面向高效计…

『VUE』03. 模板语法 使用js与插入html(详细图文注释)

目录 vscode终端中创建项目什么是模板语法?模板语法--js"变量"用法模板语法--插入html总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 vscode终端中创建项目 回顾一遍前面的cmd. 首先在vscode中打开一个新的空文件…

SpringAOP+自定义注解实现限制接口访问频率,利用滑动窗口思想Redis的ZSet(附带整个Demo)

目录 1.创建切面 2.创建自定义注解 3.自定义异常类 4.全局异常捕获 5.Controller层 demo的地址,自行获取《《—————————————————————————— Spring Boot整合Aop面向切面编程实现权限校验,SpringAop自定义注解自定义异常全局…

WordPress分页函数function

1、可以通过下面的代码在编辑器上添加一个分页符按钮。 2、将下面的代码添加到当前主题functions.php即可。 3、代码如下: function mce_page_break($mce_buttons) { $pos array_search(wp_more, $mce_buttons, true); if ($pos ! false) { $buttons …

全球最强开源AI大模型来了!Databricks称DBRX吊打Llama 2和GPT-3.5

美国AI初创公司Databricks公布,在语言理解、编程和数学方面,其将开源的模型DBRX的测试得分均高于GPT-3.5、Mixtral、Meta的Llama 2-70B、马斯克旗下xAI的Grok-1。作为混合专家模型,DBRX的输出token速度高Llama 2一筹。 全球最强大的开源人工智…

车载以太网AVB交换机 gptp透明时钟 5口 全千兆 SW1500

全千兆车载以太网交换机 一、产品简要分析 5端口千兆车载以太网交换机,包含4个通道的1000BASE-T1接口使用罗森博格H-MTD和泰科MATEnet双接口,1个通道1000BASE-T标准以太网(RJ45接口),可以实现车载以太网多通道交换,千兆和百兆车载…

Docker搭建LNMP环境实战(06):Docker及Docker-compose常用命令

Docker搭建LNMP环境实战(06):Docker及Docker-compose常用命令 此处列举了docker及docker-compose的常用命令,一方面可以做个了解,另一方面可以在需要的时候进行查阅。不一定要强行记忆,用多了就熟悉了。 1、…

Golang hash/crc32 库实战指南:从基础到优化

Golang hash/crc32 库实战指南:从基础到优化 引言理解CRC32hash/crc32库概览实战技巧数据校验性能优化多线程应用 错误处理与调试错误处理调试 实际案例分析结论 总结重点回顾 引言 在现代软件开发中,数据的完整性和安全性至关重要。无论是数据库存储、…

Vue-vue3

一、Vue3简介二、Vue3有那些优化性能的提升源码升级拥抱TypeScript新的特性 三、创建Vue3.0工程四、Vue3工程结构(使用cli创建的vue3)五、常用的Composition API(组合式API)setupsetup的两个注意点 ref函数reactive函数Vue3.0中的…

PCL 彩色点云RGB转灰度并显示

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 1、原理概述 不同要素之间的灰度差异较为明显。点云灰度值与RGB属性的关系为:

MySQL高阶SQL语句(二)

文章目录 MySQL高阶SQL语句(二)一、MySQL常用查询1、子查询1.1 语法1.1.1 结合select语句查询1.1.2 结合insert语句查询1.1.3 结合update语句查询1.1.4 结合delete语句查询1.1.5 在in前面添加not1.1.6 exists关键字 2、别名 二、MySQL视图1、视图介绍1.1…

《科学技术创新》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答: 问:《科学技术创新》期刊是哪个级别? 答:省级 主管单位:黑龙江省科学技术协会 主办单位:黑龙江省科普事业中心 问:《科学技术创新》期刊影响因子? 答:(2…

bugku-web-Flask_FileUpload

查看页面源码 这里提示给他一个文件,它将返回一个python运行结果给我,并且提示只能上传jpg和png文件 传递一个图片 查看源码 传递一个非图片 将源码写入新建的txt文件中 print(hello world) 将文件后缀改为jpg 上传 上传成功 查看源码 得到运行结果 我…

展示大屏-24小时天气预报

一、项目说明 展示大屏显示未来一周天气和24小时天气详情。 二、技术工具 1.语言&框架:java、springboot 2.UI界面:jQuery、HTML、CSS、 VUE 3.开发工具:IntelliJ IDEA、Eclipse 三、实现步骤 后端步骤 1.调取免费或收费的API接口。 …