图神经网络实战(7)——图卷积网络(Graph Convolutional Network, GCN)详解与实现
图神经网络实战(7)——图卷积网络详解与实现
- 0. 前言
- 1. 图卷积层
- 2. 比较 GCN 和 GNN
- 2.1 数据集分析
- 2.2 实现 GCN 架构
- 小结
- 系列链接
0. 前言
图卷积网络 (Graph Convolutional Network
, GCN
) 架构由 Kipf
和 Welling
于 2017
年提出,其理念是创建一种适用于图的高效卷积神经网络 (Convolutional Neural Networks, CNN)。更准确地说,它是图信号处理中图卷积操作的近似,由于其易用性,GCN
已成为最受欢迎的图神经网络 (Graph Neural Networks, GNN) 之一,是处理图数据时创建基线模型的首选架构。
在本节中,我们将讨论 Vanilla GNN 架构的局限性,这有助于我们理解 GCN
的核心思想。并详细介绍 GCN
的工作原理,解释为什么 GCN
比 Vanilla GNN
性能更好,通过使用 PyTorch Geometric
在 Cora 和 Facebook Page-Page 数据集上实现 GCN
来验证其性能。
1. 图卷积层
与表格或图像数据不同,图数据中节点的邻居数量并不总是相同。例如,在下图中,节点 1
有 3
个邻居,而节点 2
只有 1
个:
但是,观察图神经网络 (Graph Neural Networks, GNN) 层就会发现,邻居数量的差异并不会导致计算的复杂化。GNN
层由一个简单的求和公式组成,没有任何归一化系数,计算节点 i i i 的嵌入方法如下:
h i = ∑ j ∈ N i x j W T h_i=\sum_{j\in \mathcal N_i}x_jW^T hi=j∈Ni∑xjWT
假设节点 1
有 1,000
个邻居,而节点 2
只有 1
个邻居,那么 h 1 h_1 h1 嵌入的值将远远大于 h 2 h_2 h2 嵌入的值。这样便会出现一个问题,当我们要对这些嵌入进行比较时,如果它们的值相差过大,如何进行有意义的比较?
一个简单的解决方案是将嵌入除以邻居数量,用 deg ( A ) \deg(A) deg(A) 表示节点的度,因此 GNN
层公式可以更新为:
h i = 1 deg ( i ) ∑ j ∈ N i x j W T h_i=\frac 1{\deg(i)}\sum_{j\in \mathcal N_i}x_jW^T hi=deg(i)1j∈Ni∑xjWT
那么如何将其转化为矩阵乘法呢?首先回顾普通 GNN
层的计算公式:
H = A ~ T X W T H=\tilde A^TXW^T H=A~TXWT
其中, A ~ = A + I \tilde A=A+I A~=A+I。公式中缺少的是一个能为我们提供归一化系数 1 deg ( A ) \frac 1 {\deg(A)} deg(A)1 的矩阵,可以利用度矩阵 D D D 来计算每个节点的邻居数量。上示图像中的图的度矩阵如下:
D = [ 3 0 0 0 0 1 0 0 0 0 2 0 0 0 0 2 ] D=\left[\begin{array}{c} 3 & 0 & 0 & 0\\ 0 & 1 & 0 & 0\\ 0 & 0 & 2 & 0\\ 0 & 0 & 0 & 2\\ \end{array}\right] D= 3000010000200002
使用 NumPy
表示以上矩阵:
import numpy as npD = np.array([[3, 0, 0, 0],[0, 1, 0, 0],[0, 0, 2, 0],[0, 0, 0, 2]
])
根据定义, D D D 给出了每个节点的度 deg ( i ) \deg(i) deg(i) 。因此,根据度矩阵的逆矩阵 D − 1 D^{-1} D−1 可以直接得到归一化系数 1 deg ( A ) \frac 1 {\deg(A)} deg(A)1:
可以使用 numpy.linalg.inv()
函数计算矩阵的逆:
print(np.linalg.inv(D))
'''输出如下
[[0.33333333 0. 0. 0. ][0. 1. 0. 0. ][0. 0. 0.5 0. ][0. 0. 0. 0.5 ]]
'''
为了更加精确,在图中添加了自循环,用 A ~ = A + I \tilde A=A+I A~=A+I 表示。同样,我们也需要在度矩阵中加入自循环,即 D ~ = D + I \tilde D= D+I D~=D+I ,因此最终所需的矩阵为 D ~ − 1 = ( D + I ) − 1 \tilde D^{-1} = (D+I)^{-1} D~−1=(D+I)−1:
在 NumPy
中,可以使用函数 numpy.identity(n)
快速创建指定维度 n
的单位矩阵 I I I:
print(np.linalg.inv(D + np.identity(4)))
'''输出如下
[[0.25 0. 0. 0. ][0. 0.5 0. 0. ][0. 0. 0.33333333 0. ][0. 0. 0. 0.33333333]]
'''
得到归一化系数矩阵后,有两种应用方式:
- D ~ − 1 A ~ X W T \tilde D^{-1}\tilde AXW^T D~−1A~XWT 会对每一行特征进行归一化处理。
- A ~ D ~ − 1 X W T \tilde A \tilde D^{-1}XW^T A~D~−1XWT 会对每一列特征进行归一化处理。
接下来,通过计算 D ~ − 1 A ~ \tilde D^{-1}\tilde A D~−1A~ 和 A ~ D ~ − 1 \tilde A \tilde D^{-1} A~D~−1 进行验证:
D ~ − 1 A ~ = [ 1 4 0 0 0 0 1 2 0 0 0 0 1 3 0 0 0 0 1 3 ] ⋅ [ 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 ] = [ 1 4 1 4 1 4 1 4 1 2 1 2 0 0 1 3 0 1 3 1 3 1 3 0 1 3 1 3 ] A ~ D ~ − 1 = [ 1 1 1 1 1 1 0 0 1 0 1 1 1 0 1 1 ] ⋅ [ 1 4 0 0 0 0 1 2 0 0 0 0 1 3 0 0 0 0 1 3 ] = [ 1 4 1 2 1 3 1 3 1 4 1 2 0 0 1 4 0 1 3 1 3 1 4 0 1 3 1 3 ] \tilde D^{-1}\tilde A=\left[\begin{array}{c} \frac 14 & 0 & 0 & 0\\ 0 & \frac 12 & 0 & 0\\ 0 & 0 & \frac 13 & 0\\ 0 & 0 & 0 & \frac 13\\ \end{array}\right] \cdot \left[\begin{array}{c} 1 & 1 & 1 & 1\\ 1 & 1 & 0 & 0\\ 1 & 0 & 1 & 1\\ 1 & 0 & 1 &1\\ \end{array}\right]=\left[\begin{array}{c} \frac 14 & \frac 14 & \frac 14 & \frac 14\\ \frac 12 & \frac 12 & 0 & 0\\ \frac 13 & 0 & \frac 13 & \frac 13\\ \frac 13 & 0 & \frac 13 & \frac 13\\ \end{array}\right]\\ \tilde A \tilde D^{-1}=\left[\begin{array}{c} 1 & 1 & 1 & 1\\ 1 & 1 & 0 & 0\\ 1 & 0 & 1 & 1\\ 1 & 0 & 1 &1\\ \end{array}\right] \cdot \left[\begin{array}{c} \frac 14 & 0 & 0 & 0\\ 0 & \frac 12 & 0 & 0\\ 0 & 0 & \frac 13 & 0\\ 0 & 0 & 0 & \frac 13\\ \end{array}\right]=\left[\begin{array}{c} \frac 14 & \frac 12 & \frac 13 & \frac 13\\ \frac 14 & \frac 12 & 0 & 0\\ \frac 14 & 0 & \frac 13 & \frac 13\\ \frac 14 & 0 & \frac 13 & \frac 13\\ \end{array}\right] D~−1A~= 41000021000031000031 ⋅ 1111110010111011 = 4121313141210041031314103131 A~D~−1= 1111110010111011 ⋅ 41000021000031000031 = 4141414121210031031313103131
在第一种情况下,每一行的和都等于 1
;在第二种情况下,每一列的和都等于 1
。矩阵乘法可以使用 numpy.matmul()
函数执行,或使用 Python
内置的矩阵乘法运算符 @
。定义邻接矩阵并使用 @
操作符计算矩阵乘法:
A = np.array([[1, 1, 1, 1],[1, 1, 0, 0],[1, 0, 1, 1],[1, 0, 1, 1]
])
print(np.linalg.inv(D + np.identity(4)) @ A)
print('------------------------------')
print(A @ np.linalg.inv(D + np.identity(4)))
'''输出如下
[[0.25 0.25 0.25 0.25 ][0.5 0.5 0. 0. ][0.33333333 0. 0.33333333 0.33333333][0.33333333 0. 0.33333333 0.33333333]]
------------------------------
[[0.25 0.5 0.33333333 0.33333333][0.25 0.5 0. 0. ][0.25 0. 0.33333333 0.33333333][0.25 0. 0.33333333 0.33333333]]
'''
得到的结果与手动计算的矩阵乘法相同。那么,在实践中我们应该使用哪种应用方式?第一种方案似乎看起来合理,因为它能很好地对相邻节点特征进行归一化处理。
但 Kipf
和 Welling
提出,具有多个邻居的节点的特征很容易传播,而与之相反,孤立节点的特征不容易传播。在 GCN
论文中,作者提出了一种混合归一化方法来平衡这种影响。在实践中,使用以下公式为邻居较少的节点分配更高的权重:
H = D ~ − 1 2 A ~ T D ~ − 1 2 X W T H=\tilde D^{-\frac 12}\tilde A^T\tilde D^{-\frac 12}XW^T H=D~−21A~TD~−21XWT
就单个嵌入而言,上式可以写为:
h i = ∑ j ∈ N i 1 deg ( i ) deg ( j ) x j W T h_i=\sum_{j\in \mathcal N_i}\frac 1{\sqrt {\deg(i)}\sqrt {\deg(j)}}x_jW^T hi=j∈Ni∑deg(i)deg(j)1xjWT
这就是实现原始图卷积层的数学公式。与普通的 GNN
层一样,我们可以通过堆叠图卷积层创建 GCN
。接下来,使用 PyTorch Geometric
实现一个 GCN
模型,并验证其性能是否优于原始图神经网络模型。
2. 比较 GCN 和 GNN
我们已经证明了 vanilla GNN 性能优于 Node2Vec 模型,接下来,我们将其与 GCN
进行比较,比较它们在 Cora 和 Facebook Page-Page 数据集上的表现。
与普通 GNN
相比,GCN
的主要特点是通过考虑节点度来权衡其特征。在构建模型之前,我们首先计算这两个数据集中的节点度,这与 GCN
的性能直接相关。
根据我们对 GCN
架构的了解,可以猜测当节点度差异较大时,它的性能会更好。如果每个节点都有相同数量的邻居,那么无论使用哪种归一化方式,架构之间都是等价的: deg ( i ) deg ( i ) = deg ( i ) \sqrt {\deg(i)} \sqrt {\deg(i)}= \deg (i) deg(i)deg(i)=deg(i)。
2.1 数据集分析
(1) 从 PyTorch Geometric
中导入 Planetoid
类,为了可视化节点度,同时导入两个附加类( degree
用于获取每个节点的邻居数,Counter
用于计算每个度数的节点数)和 matplotlib
库:
import torch
from torch_geometric.datasets import Planetoid
from torch_geometric.utils import degree
from collections import Counter
import matplotlib.pyplot as plt
(2) 导入 Cora
数据集,并将图存储在 data
中:
dataset = Planetoid(root=".", name="Cora")
data = dataset[0]
(3) 计算图中每个节点的邻居数:
degrees = degree(data.edge_index[0]).numpy()
(4) 为了生成更自然的可视化效果,统计具有相同度的节点数量:
numbers = Counter(degrees)
(5) 使用条形图来绘制统计结果:
fig, ax = plt.subplots()
ax.set_xlabel('Node degree')
ax.set_ylabel('Number of nodes')
plt.bar(numbers.keys(), numbers.values())
plt.show()
从上图中可以看出,图中的度分布近似指数分布,从 1
个邻居( 485
个节点)到 168
个邻居( 1
个节点)不等,这种不平衡的数据集正是归一化处理的用武之地。
(6) 在 Facebook Page-Page
数据集上重复同样的过程:
from torch_geometric.datasets import FacebookPagePage# Import dataset from PyTorch Geometric
dataset = FacebookPagePage(root=".")
data = dataset[0]# Create masks
data.train_mask = range(18000)
data.val_mask = range(18001, 20000)
data.test_mask = range(20001, 22470)# Get list of degrees for each node
degrees = degree(data.edge_index[0]).numpy()# Count the number of nodes for each degree
numbers = Counter(degrees)# Bar plot
fig, ax = plt.subplots()
ax.set_xlabel('Node degree')
ax.set_ylabel('Number of nodes')
plt.bar(numbers.keys(), numbers.values())
plt.show()
Facebook Page-Page
数据集的图的节点度分布看起来更加失衡,邻居数量从 1
到 709
不等。出于同样的原因,Facebook Page-Page
数据集也是应用 GCN
的合适实例。
2.2 实现 GCN 架构
我们可以从零开始实现 GCN
层,但这里我们无需再从头造轮子,PyTorch Geometric
已经内置了 GCN
层,首先在 Cora
数据集上实现 GCN
架构。
(1) 从 PyTorch Geometric
中导入 GCN
层,并导入 PyTorch
:
import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConvdataset = Planetoid(root=".", name="Cora")
data = dataset[0]
(2) 创建函数 accuracy()
计算模型准确率:
def accuracy(y_pred, y_true):"""Calculate accuracy."""return torch.sum(y_pred == y_true) / len(y_true)
(3) 创建 GCN
类,其中 __init__()
函数接受三个参数作为输入:输入维度 dim_in
、隐藏维度 dim_h
和输出维度 dim_out
:
class GCN(torch.nn.Module):"""Graph Convolutional Network"""def __init__(self, dim_in, dim_h, dim_out):super().__init__()self.gcn1 = GCNConv(dim_in, dim_h)self.gcn2 = GCNConv(dim_h, dim_out)
(4) forward()
方法使用两个 GCN
层,并对分类结果应用 log_softmax
函数:
def forward(self, x, edge_index):h = self.gcn1(x, edge_index)h = torch.relu(h)h = self.gcn2(h, edge_index)return F.log_softmax(h, dim=1)
(5) fit()
方法与 Vanilla GNN
相同,为了更好的比较,使用具有相同参数的 Adam
优化器,其中学习率 lr
为 0.1
,L2
正则化 weight_decay
为 0.0005
:
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, data.edge_index)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}%')
(6) 编写 test()
方法:
@torch.no_grad()def test(self, data):self.eval()out = self(data.x, data.edge_index)acc = accuracy(out.argmax(dim=1)[data.test_mask], data.y[data.test_mask])return acc
(7) 实例化模型并训练 100
个 epoch
:
# Create the Vanilla GNN model
gcn = GCN(dataset.num_features, 16, dataset.num_classes)
print(gcn)# Train
gcn.fit(data, epochs=100)
训练过程中的输出结果如下:
(8) 最后,在测试集上对模型进行评估:
acc = gcn.test(data)
print(f'\nGCN test accuracy: {acc*100:.2f}%\n')# GCN test accuracy: 80.30%
重复此实验 100
次,模型的平均准确率为 80.26%(±0.59%)
,明显 vanilla GNN
模型的平均准确率 74.99%(±1.60%)
。
(9) 将同样的模型应用于 Facebook Page-Page
数据集,其平均准确率可以达到 91.78%(±0.31%)
,同样比 vanilla GNN
的结果( 84.91%(±1.88%)
)高出很多:
# Load Facebook Page-Page
dataset = FacebookPagePage(root=".")
data = dataset[0]
data.train_mask = range(18000)
data.val_mask = range(18001, 20000)
data.test_mask = range(20001, 22470)# Train GCN
gcn = GCN(dataset.num_features, 16, dataset.num_classes)
print(gcn)
gcn.fit(data, epochs=100)
acc = gcn.test(data)
print(f'\nGCN test accuracy: {acc*100:.2f}%\n')
下表总结了不同模型在不同数据集上的准确率和标准差:
MLP | GNN | GCN | |
---|---|---|---|
Cora | 53.47%(±1.95%) | 74.99%(±1.60%) | 80.26%(±0.59%) |
75.22%(±0.39%) | 84.91%(±1.88%) | 91.78%(±0.31%) |
我们可以将这些性能提升归因于这两个数据集中节点度的分布的不平衡性。通过对特征进行归一化处理,并考虑中心节点及其邻居的数量,GCN
的灵活性得到了极大的提升,可以很好地处理各种类型的图。但节点分类远不是 GCN
的唯一应用,在之后的学习中,我们将看到 GCN
模型的更多新颖应用。
小结
在本节中,我们改进了 vanilla GNN
层,使其能够正确归一化节点特征,这一改进引入了图卷积网络 (Graph Convolutional Network
, GCN
) 层和混合归一化。在 Cora
和 Facebook Page-Page
数据集上,我们对比了 GCN
架构与 Node2Vec
和 vanilla GNN
之间的性能差异。由于采用了归一化处理,GCN
在这两个数据集中都具有较高的准确率。
系列链接
图神经网络实战(1)——图神经网络(Graph Neural Networks, GNN)基础
图神经网络实战(2)——图论基础
图神经网络实战(3)——基于DeepWalk创建节点表示
图神经网络实战(4)——基于Node2Vec改进嵌入质量
图神经网络实战(5)——常用图数据集
图神经网络实战(6)——使用PyTorch构建图神经网络
相关文章:
图神经网络实战(7)——图卷积网络(Graph Convolutional Network, GCN)详解与实现
图神经网络实战(7)——图卷积网络详解与实现 0. 前言1. 图卷积层2. 比较 GCN 和 GNN2.1 数据集分析2.2 实现 GCN 架构 小结系列链接 0. 前言 图卷积网络 (Graph Convolutional Network, GCN) 架构由 Kipf 和 Welling 于 2017 年提出,其理念是…...
大话设计模式之外观模式
外观模式(Facade Pattern)是一种软件设计模式,旨在提供一个简单的接口,隐藏系统复杂性,使得客户端能够更容易地使用系统。这种模式属于结构型模式,它通过为多个子系统提供一个统一的接口,简化了…...
CAD Plant3D 2024 下载地址及安装教程
CAD Plant3D是一款专业的三维工厂设计软件,用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一,专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能,帮助…...
Intellij IDEA / Android studio 可持续开发笔记
Intellij 的Java/安卓工具链有着一种不可持续性,这种不可持续性体现在多个方面。 首先是不可持续运行。IDEA 使用时间越长,内存占用越大,从不主动释放。运行时间越长,日志越多,从不主动清理。 然后是不完整的开源&am…...
c++----list模拟实现
目录 1. list的基本介绍 2. list的基本使用 2.1 list的构造 用法示例 2.2 list迭代器 用法示例 2.3. list容量(capacity)与访问(access) 用法示例 2.4 list modifiers 用法示例 2.5 list的迭代器失效 3.list的模拟实现 3.1…...
FastAPI+React全栈开发15 让我们构建一个展示API
Chapter03 Getting Started with FastAPI 15 Let’s Build a showcase API FastAPIReact全栈开发15 让我们构建一个展示API REST APIs are all about cycles of HTTP requests and responses, it is the engine that powers the web and is implemented in every web framew…...
list(链表)容器(二)
一、list 插入和删除 函数原型: push_back(elem);//在容器尾部加入一个元素 pop_back();//删除容器中最后一个元素 push_front(elem);//在容器开头插入一个元素 pop_front();//从容器开头移除第一个元素 insert(pos,elem);//在pos位置插elem元素的拷贝,…...
世优科技上榜2024年度《中国虚拟数字人影响力指数报告》
日前,第三期《中国虚拟数字人影响力指数报告》在中国网络视听大会上正式发布。本期《报告》由中国传媒大学媒体融合与传播国家重点实验室(以下简称“国重实验室”)、中国传媒大学数字人研究院编制,中国网络视听协会、人民日报智慧…...
【调试方法】C代码中dump中间数据的方法
一,简介 本文主要介绍,如何在C语言代码中将音频流数据进行写入文件,方便调试定位问题: 二,函数实现 按int8_t写入 #include <stdio.h>int32_t write_int8_t_data(int8_t *name, int8_t *buffer, int32_t dat…...
【BUG】vue中@change时间传值丢失问题
项目场景: 在修改项目bug时,发现后端响应到前端的值,通过change事件调用方法,在方法中拿到值时,有部分数据丢失。 问题描述 后端传到前端的值为:字符串类型的"00000089",change调用…...
Linux提权!!!
上一篇文章讲了Windows的提权,那么这篇文章就来讲一下Linux的提权 1.SUID提权 suid权限 作用:让普通用户临时拥有该文件的属主的执行权限,suid权限只能应用在二进制可执行文件(命令)上,而且suid权限只能设置…...
Android Studio学习7——常用控件view
Android控件 双击shift键——>搜索想要找的文件 Ctrlshift回车——>补全“;”号 CtrlX——>删除一行,只需把鼠标放在那一行 windows自带字体...
Springboot3 集成knife4j(swagger)
knife4j是为Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui,取名kni4j是希望它能像一把匕首一样小巧,轻量,并且功能强悍! 官网地址: Knife4j 集Swagger2及OpenAPI3为一体的增强解决方案. | Knife4j 本文以Springboot3版本集成kn…...
深信服:借助观测云实现全链路可观测性
导读 深信服科技股份有限公司 简称「深信服」( Sangfor Technologies Inc. ),是一家领先的网络安全和云计算解决方案提供商,致力于为全球客户提供高效、智能、安全的网络和云服务。随着公司业务的不断扩展,也面临着监…...
详解Qt中使用线程
详解Qt中使用线程 Qt中的线程相关知识涵盖了线程创建、管理、通信以及线程安全等方面。下面将详细讲解这些知识点,并提供对应的示例代码。 线程创建与管理 QThread类 Qt通过QThread类来创建和管理线程。要创建一个新的工作线程,通常有两种方法&#…...
在.Net6中用gdal实现第一个功能
目录 一、创建.NET6的控制台应用程序 二、加载Gdal插件 三、编写程序 一、创建.NET6的控制台应用程序 二、加载Gdal插件 Gdal的资源可以经过NuGet包引入。右键单击项目名称,然后选择 "Manage NuGet Packages"(管理 NuGet 包)。N…...
采用大语言模型进行查询重写——Query Rewriting via Large Language Models
文章:Query Rewriting via Large Language Models,https://arxiv.org/abs/2403.09060 摘要 查询重写是在将查询传递给查询优化器之前处理编写不良的查询的最有效技术之一。 手动重写不可扩展,因为它容易出错并且需要深厚的专业知识。 类似地…...
使用Vue实现CSS过渡和动画
01-初识动画和过渡 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>使用vue实现css过渡和动画&l…...
一家购物商场的数据运营挑战
✅作者简介:《数据运营:数据分析模型撬动新零售实战》作者、《数据实践之美》作者、数据科技公司创始人、多次参加国家级大数据行业标准研讨及制定、高端企培合作讲师。 🌸公众号:风姑娘的数字视角,免费分享数据应用相…...
React Native框架开发APP,安装免费的图标库(react-native-vector-icons)并使用详解
一、安装图标库 要使用免费的图标库,你可以使用 React Native Vector Icons 库。 首先,确保你已经安装了 react-native-vector-icons: npm install --save react-native-vector-iconsnpm install --save-dev types/react-native-vector-ic…...
idea端口占用
报错:Verify the connector‘s configuration, identify and stop any process that‘s listening on port XXXX 翻译: 原因: 解决: 一、重启大法 二、手动关闭 启动spring项目是控制台报错,详细信息如下ÿ…...
MQ消息队列详解以及MQ重复消费问题
MQ消息队列详解以及MQ重复消费问题 1、解耦2、异步调用3、流量削峰4、MQ重复消费问题,以及怎么解决?4.1、重复消费产生4.2、解决方法: https://blog.csdn.net/qq_44240587/article/details/104630567 核心的就是:解耦、异步、削锋…...
系统IO函数接口
目录 前言 一. man手册 1.1 man手册如何查询 1.2 man手册基础 二.系统IO函数接口 三.open打开文件夹 3.1 例1 open打开文件 3.2 open打开文件代码 3.3 例2 创建文件 四.write写文件 4.1 write写文件 五. read读文件 5.1 read读文件与偏移 5.2 偏移细节 5.3 read读文件代码 六.复…...
06 监听器
文章目录 SessionAttListenerDemo.javaSessionListenerDemo.javaProductController.java SessionAttListenerDemo.java package com.aistart.listener;import javax.servlet.ServletContext; import javax.servlet.annotation.WebListener; import javax.servlet.http.HttpSess…...
C语言第三十九弹---预处理(上)
✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】 预处理 1、预定义符号 2、#define定义常量 3、#define定义宏 4、带有副作用的宏参数 5、宏替换的规则 6、宏和函数的对比 总结 在C语言中,预处…...
计算机视觉无人驾驶技术:入门指南
I. 引言: 计算机视觉无人驾驶技术是一种基于计算机视觉和机器学习技术的自动化驾驶技术。它可以通过搭载各种传感器和摄像机,让车辆自主感知周围环境,实现尽可能自动化的驾驶操作。 这种技术具有重要性和优势,包括: …...
Golang和Java对比
其实我是Javaer转的Golang,我谈谈自己对Java和Golang的体会 我先讲讲我认为Golang的优点 1、Golang是一门新语言,相比于Java,他的生态要小很多,优点很明显,自由度高,学习成本低,能快速拉起一个…...
2024.2.29力扣每日一题——统计可能的树根数目
2024.2.29 题目来源我的题解方法一 深度搜索(暴力) 超时方法二 树形动态规划 题目来源 力扣每日一题;题序:2581 我的题解 方法一 深度搜索(暴力) 超时 以每个节点node为跟进行深度搜索,并在搜…...
同一个主机配置多个SSH key
使用git时,我们可能一个git客户端使用多个git服务器,比如github,自建gitlab,gitee,为了防止提交混乱,所以需要一一对应生成公私钥。 第一步: 使用ssh-keygen生成多对密钥对,比如&…...
SAP系统财务模块简介:实现财务管理的卓越之道
作为全球领先的企业管理软件提供商,SAP公司开发了一系列强大而全面的财务模块,帮助企业实现财务管理的高效运作与优化。SAP系统的财务模块涵盖了财务核算、成本管理、资金管理、资产会计等多个方面,为企业提供了完整的财务管理解决方案。本文…...
做网站怎么加水平线/网络推广公司排名
金三银四找工作旺季,又来给大家送干货了。关于Python后端工程师你了解多少,下面告诉你如何面试Python后端工程师? 文章目录一、Python后端技术栈1.1 Python语言基础1.2 Python框架1.3 数据库1.4 Web1.5 系统二、关于面试自我介绍2.1 面试流程…...
网页一键建站/连接友谊
2015 年,因为工作岗位的变动,开始负责给集团招聘一些技术人员,出于对公司的负责,也为了更好的胜任技术经理的职位,在面试的这件事上,我做了大量的“功课”,首先我研究了几乎所有大厂的面试题&am…...
如何查看网站点击量/查询网站流量的网址
1.触发器 这是一个非常简单直接的解决方案,我们只需要将DTS引擎驻留在比如windows服务中,该引擎通过数据库的触发器事件获取源表数据更新的所有情况,即增量,然后相应的更新目的表。然而,由谁来创建触发器了…...
做外贸独立网站必须要有备案么/青岛网页搜索排名提升
乔治拿来一组等长的木棒,将它们随机地砍断,使得每一节木棍的长度都不超过50个长度单位。 然后他又想把这些木棍恢复到为裁截前的状态,但忘记了初始时有多少木棒以及木棒的初始长度。 请你设计一个程序,帮助乔治计算木棒的可能最…...
学做网站需要多长时间/公司网站建设
如何让报表中的Table按自己的需要来分页?例如,每20行就强制分页。 方法: 1. 在Table中添加一个分组,分组表达式为 (RowNumber("Table1") - 1) / 20 2. 去掉分组组头 3. 在分组属性中选择checkbox "在结尾处分页…...
网站如何做关键词优化/杭州网站优化推荐
remote-control 可以让用户通过外部接口控制应用程序音乐, 官方建议的做法是在View显示的时候接收remote-control事件 [c-sharp] view plaincopy - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [[UIApplication sharedApplication…...