GNN 极简入门

news2025/2/3 9:07:47

文章目录

  • 图基本知识
  • GNN简介
    • GCN
  • PYG极简入门
    • Data Handling of Graphs
    • Common Benchmark Datasets
    • Mini-batches
    • Data Transforms
    • Learning Methods on Graphs

图基本知识

😸图是由节点的有穷非空集合和节点之间的集合组成,通常表示为 G = ( V , E ) G=(V, E) G=(V,E),其可分为有向图和无向图,无向图中节点之间的边没有方向,而有向图中的边是有方向的。对于图的通用符号定义中, G G G 表示一个图, V V V 为图中的节点集合, E E E 为图中的边集合,节点数量 n = ∣ V ∣ n=|V| n=V,边数量 e = ∣ E ∣ e = |E| e=E,节点 v i ∈ V v_i \in V viV,边 e i ∈ E e_i \in E eiE,单位矩阵 I n ∈ R n × n I_n \in \mathbb{R}^{n \times n} InRn×n,邻接矩阵 A ∈ R n × n A \in \mathbb{R}^{n \times n} ARn×n,关联矩阵 H ∈ R n × e H \in \mathbb{R}^{n \times e} HRn×e,度矩阵 D ∈ R n × n D \in \mathbb{R}^{n \times n} DRn×n,权重矩阵 W ∈ R n × n W \in \mathbb{R}^{n \times n} WRn×n,拉普拉斯矩阵 L ∈ R n × n L \in \mathbb{R}^{n \times n} LRn×n,特征值矩阵 Λ ∈ R n × n \Lambda \in \mathbb{R}^{n \times n} ΛRn×n,特征向量矩阵 U ∈ R n × n U \in \mathbb{R}^{n \times n} URn×n

  • 连通图:对于一个无向图,如果任意节点 v i v_i vi 都能通过一些边到达节点 v j v_j vj,则称 G G G 为连通图
  • 连通分量:无向图 G G G 的一个极大连通子图称为 G G G 的一个连通分量(或连通分支)。连通图只有一个连通分量(即其自身);非连通的无向图可能有多个连通分量
  • 强连通图:给定有向图 G G G,并且给定 G G G 中的任意两个节点 u u u v v v,如果节点 u u u v v v 互相可达,则 G G G 称为强连通图。如下面有向图就是一个强连通图
  • 弱连通图:若至少有一对节点不满足单向连通性,但去掉边的方向后从无向图的角度上看为连通图,则称为弱连通图。如下面弱连通图,节点 v 2 v_2 v2 在有向图角度上无法到达节点 v 1 v_1 v1,而在无向图的角度上,各个节点都互相可达
  • 最短路径:两个节点之间的最短路径。如下面无向图 v 1 v_1 v1 v 5 v_5 v5 的最短路径为 2,即 v 1 → v 4 → v 5 v_1 \rightarrow v_4 \rightarrow v_5 v1v4v5 v 1 → v 2 → v 5 v_1 \rightarrow v_2 \rightarrow v_5 v1v2v5
  • 图直径:图中所有所有节点之间最短路径中的最大值为图直径,如下面无向图的图直径为 2
  • 度中心性:在无向图中,可以用一个节点的度来衡量中心性,其计算公式为 D C = N d e g r e e n − 1 DC = \frac{N_{degree}}{n-1} DC=n1Ndegree。其中, N d e g r e e N_{degree} Ndegree 为节点的度(不带权的可简单理解为有几条边和该点相连),而 n n n 为节点总数量。如下面无向图中节点 v 3 v_3 v3 的度中心性为 D C = 2 5 − 1 = 0.5 DC = \frac{2}{5-1}=0.5 DC=512=0.5
  • 特征向量中心性:求邻接矩阵 A A A 的特征值 λ i \lambda_i λi 和特征向量 x i \pmb{x}_i xi,最大特征值 λ m a x \lambda_{max} λmax 对应的特征向量 x m a x \pmb{x}_{max} xmax 即为特征向量中心性的值
  • 中介中心性:图中经过某点 i i i 并且连接两点 s s s t t t 之间的最短路径数目,占 s s s t t t 之间最短路径总数的比,其公式如下:

B C = ∑ s , t ≠ i d s t ( i ) d s t BC = \sum_{s, t \ne i} \frac{d_{st}(i)}{d_{st}} BC=s,t=idstdst(i)

✍️其中, d s t d_{st} dst s s s t t t 的最短路径数量,而 d s t ( i ) d_{st}(i) dst(i) 表示从 s s s t t t 的最短路径中经过节点 i i i 的数量

  • 连接中心性(节点总数n - 1)/节点到其他节点最短路径之和。以下面无向图的节点 v 3 v_3 v3 为例, v 3 → v 1 v_3 \rightarrow v_1 v3v1 的最短路径为 1, v 3 → v 2 v_3 \rightarrow v_2 v3v2 的最短路径为 2, v 3 → v 4 v_3 \rightarrow v_4 v3v4 的最短路径为 1, v 3 → v 5 v_3 \rightarrow v_5 v3v5 的最短路径为 2,节点总数 n = 5 n=5 n=5,故连接中心性为 C C = 5 − 1 1 + 2 + 1 + 2 = 2 3 CC = \frac{5-1}{1+2+1+2} = \frac{2}{3} CC=1+2+1+251=32

在这里插入图片描述

  • 邻接矩阵:节点 v i v_i vi 和节点 v j v_j vj 之间有边则将矩阵对应位置 ( i , j ) (i, j) (i,j) 置为 1(不带权)或相应权重(带权)。以上面无向图为例,其不带权邻接矩阵如下:

A = ( v 1 v 2 v 3 v 4 v 5 v 1 0 1 1 1 0 v 2 1 0 0 0 1 v 3 1 0 0 1 0 v 4 1 0 1 0 1 v 5 0 1 0 1 0 ) A = \left( \begin{array}{c|cc} & v_1 & v_2 & v_3 & v_4 & v_5 \\ \hline v_1 & 0 & 1 & 1 & 1 & 0 \\ v_2 & 1 & 0 & 0 & 0 & 1 \\ v_3 & 1 & 0 & 0 & 1 & 0 \\ v_4 & 1 & 0 & 1 & 0 & 1 \\ v_5 & 0 & 1 & 0 & 1 & 0 \end{array}\right) A= v1v2v3v4v5v101110v210001v310010v410101v501010

  • 关联矩阵:对于有向图,若节点 v i v_i vi 在边 e j e_j ej起点则将对应位置 ( i , j ) (i, j) (i,j)1,若在边的终点则置 -1,不在边上则置 0;对于无向图,若节点在边上则置 1,否则置 0。以上面弱连通图为例,其关联矩阵如下:

H = ( e 1 e 2 e 3 e 4 v 1 1 0 0 0 v 2 0 1 − 1 0 v 3 − 1 − 1 0 1 v 4 0 0 1 − 1 ) H = \left( \begin{array}{c|cc} & e_1 & e_2 & e_3 & e_4 \\ \hline v_1 & 1 & 0 & 0 & 0 \\ v_2 & 0 & 1 & -1 & 0 \\ v_3 & -1 & -1 & 0 & 1 \\ v_4 & 0 & 0 & 1 & -1 \\ \end{array}\right) H= v1v2v3v4e11010e20110e30101e40011

  • 度矩阵:该矩阵为对角矩阵,其值为连接到该节点所有边的权重之和(权重默认为 1);若为有向图,则该矩阵可分为出度矩阵和入度矩阵。以上面无向图为例,其度矩阵如下:

D = ( 3 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 2 ) D = \begin{pmatrix} 3 & 0 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 & 0 \\ 0 & 0 & 2 & 0 & 0 \\ 0 & 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & 0 & 2 \\ \end{pmatrix} D= 3000002000002000003000002

  • 拉普拉斯矩阵:其值为对应度矩阵-邻接矩阵(有向图则需要选择出度或入度矩阵),即 L = D − A L = D - A L=DA。以上面无向图为例,其拉普拉斯矩阵:

L = D − A = ( 3 0 0 0 0 0 2 0 0 0 0 0 2 0 0 0 0 0 3 0 0 0 0 0 2 ) − ( 0 1 1 1 0 1 0 0 0 1 1 0 0 1 0 1 0 1 0 1 0 1 0 1 0 ) = ( 3 − 1 − 1 − 1 0 − 1 2 0 0 − 1 − 1 0 2 − 1 0 − 1 0 − 1 3 − 1 0 − 1 0 − 1 2 ) L = D-A = \begin{pmatrix} 3 & 0 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 & 0 \\ 0 & 0 & 2 & 0 & 0 \\ 0 & 0 & 0 & 3 & 0 \\ 0 & 0 & 0 & 0 & 2 \\ \end{pmatrix} - \begin{pmatrix} 0 & 1 & 1 & 1 & 0 \\ 1 & 0 & 0 & 0 & 1 \\ 1 & 0 & 0 & 1 & 0 \\ 1 & 0 & 1 & 0 & 1 \\ 0 & 1 & 0 & 1 & 0 \end{pmatrix} = \begin{pmatrix} 3 & -1 & -1 & -1 & 0 \\ -1 & 2 & 0 & 0 & -1 \\ -1 & 0 & 2 & -1 & 0 \\ -1 & 0 & -1 & 3 & -1 \\ 0 & -1 & 0 & -1 & 2 \end{pmatrix} L=DA= 3000002000002000003000002 0111010001100101010101010 = 3111012001102101013101012

  • 特征值矩阵:特征值构成的对角矩阵
  • 特征向量矩阵:特征向量构成的正交矩阵

GNN简介

🙀现实中越来越多的问题可以抽象成非欧氏结构数据,非欧氏数据中心节点的邻居节点数量和排列顺序不固定,不满足平移不变性,这就很难在非欧氏数据中定义卷积核。这导致现有的神经网络通常只能对常规的欧氏结构数据进行处理,传统的深度学习模型已经不能处理这种数据,从而亟需研究设计一种新的深度神经网络。而图神经网络(GNN)所处理的数据对象就是具有不规则结构的图数据,GNN 便在这种大背景下应运而生。图数据包含节点(实体)、边(关系)和整个图结构,GNN 的处理任务也主要从 Node-levelEdge-levelGraph-level 这几个角度出发。

  • Graph-level task:预测整个图的单一属性(图的标签)。例如对于用图表示的分子,我们可能想要预测分子闻起来像什么,或者它是否会与与疾病有关的受体结合;对于 MNIST 和 CIFAR 的图像分类问题,我们希望将标签与整个图像关联起来;对于文本,类似的问题是情绪分析,我们想要一次性确定整个句子的情绪

在这里插入图片描述

  • Node-level task:预测整张图中每个节点的一些属性(节点的标签)。在图像中,节点级预测问题类似于实例分割,我们试图标记图像中每个像素的类别;对于文本,类似的任务是预测句子中每个单词的词性

在这里插入图片描述

  • Edge-level task:预测边的一些属性(关系)以及存在与否(边的标签)。给定表示图像中对象的节点,我们希望预测这些节点中哪些共享一条边,或者该边的值是多少

在这里插入图片描述

😿图数据有节点、边、全局信息和连通性这四种信息,而使用神经网络解决图问题首先需要一个合适的方法对图的信息进行表示。对于节点、边和全局信息,可通过 Embedding 向量来表示,而连通性可通过最简单的邻接矩阵来表示。但使用邻接矩阵来表示连通性时,由于节点的顺序改变并不改变原始图,这将导致不同的邻接矩阵可以表示相同的图,即图和邻接矩阵不是一一对应的。此外,由于节点间并不总有关系,当图的节点有很多时,邻接矩阵可能会变得非常稀疏,这将导致计算效率很低且内存占用过高。一种更加优雅且节省内存的方法是采用邻接列表(adjacency lists),它将节点 n i n_i ni n j n_j nj 之间的边 e k e_k ek连通性描述为邻接列表第 k k k 项中的一个元组 ( i , j ) (i, j) (i,j)。如下图,第 1 条边连接节点 n 0 n_0 n0 n 1 n_1 n1,故邻接列表的第 1 项为 ( 1 , 0 ) (1, 0) (1,0)

在这里插入图片描述

✍上图中节点、边和全局使用的是标量,但实际上更多使用的是向量形式。因此,需要处理的不是大小为 [ n n o d e s n_{nodes} nnodes] 的节点张量,而是大小为 [ n n o d e s n_{nodes} nnodes, n o d e d i m node_{dim} nodedim] 的节点张量。

GCN

🎉具体参考这篇文章,讲得挺细致的了,这里就不多赘述😴

PYG极简入门

😸PyG (PyTorch Geometric)是一个建立在 PyTorch 之上的库,其可用于编写和训练图神经网络。安装的 PYG 需要与 pytorch 和 CUDA 版本对应,否则可能会出现一些错误,具体参考官方安装文档。以 Pytorch 1.12.*CUDA 11.6Windows 上以 Pip 方式安装,其命令如下:

pip install torch-scatter torch-sparse torch-cluster torch-spline-conv torch-geometric -f https://data.pyg.org/whl/torch-1.12.0+cu116.html

✍️之前安装 PYG 后出现 pytorch 的 CUDA 不可用,我这里直接重新安装对应版本的 pytorch 解决问题

Data Handling of Graphs

😸PyG 中的单个图是由 torch_geometry.data.Data 的一个实例所描述的,该实例默认包含以下属性:

  • data.x:节点特征矩阵,其形状为 [num_nodes, num_node_features]
  • data.edge_index:用于存储节点之间的边,其在 COO 格式下的形状为 [2, num_edges] 且数据类型为 torch.long
  • data.edge_attr:边特征矩阵,其形状为 [num_edges, num_edge_features]
  • data.y:训练数据标签,若 node-level 的任务则其形状为 [num_nodes, *],若为 graph-level 的任务则其形状为 [1, *]
  • data.pos:节点位置矩阵,其形状为 [num_nodes, num_dimensions]

✍️实际上,Data 对象并不限制于这些属性中,可以通过 data.face 来扩展 Data
😴以下是一个通过 PYG 构建图数据的简单例子,其包含 5 个节点(索引从 0 开始),7 条边(边的两端定义在 edge_index 中):

import torch
from torch_geometric.data import Data
from torch_geometric.utils import to_networkx
import matplotlib.pyplot as plt
import networkx as nx

# 简易可视化函数
def visualize_graph(G, color):
    plt.figure(figsize=(7, 7))
    plt.xticks([])
    plt.yticks([])
    nx.draw_networkx(G, pos=nx.spring_layout(G, seed=41), with_labels=True, node_color=color, cmap="Set2")
    plt.show()
    
edge_index = torch.tensor([[0, 1, 1, 2, 2, 3, 4],
                           [1, 2, 4, 0, 3, 4, 2]], dtype=torch.long)  # 第一行为边起点,第二行为边终点
x = torch.tensor([[0], [1], [2], [3], [4]], dtype=torch.float)        # 节点特征,这里使用一维特征
data = Data(x=x, edge_index=edge_index)                               # 构建 Data 实例
G = to_networkx(data=data)                                            # 将 Data 实例转换到 networkx.Graph
visualize_graph(G=G, color='pink')                                    # 可视化构建的图

在这里插入图片描述

✍️当 edge_index 存储方式为 [num_edges, 2] 时,需要先对其进行转置操作再使用 contiguous() 方法

Common Benchmark Datasets

😻PYG 内置了一些通用的基准数据集(如 Cora、Citeseer、Pubmed),可通过 torch_geometric.datasets 来导入相关数据集。这里以 KarateClub 数据集为例,进行一些简易操作:

from torch_geometric.datasets import KarateClub
from torch_geometric.utils import to_networkx
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np

# 简易可视化函数
def visualize_graph(G, color):
    plt.figure(figsize=(7, 7))
    plt.xticks([])
    plt.yticks([])
    nx.draw_networkx(G, pos=nx.spring_layout(G, seed=42), with_labels=False, node_color=color, cmap="Set2")
    plt.show()
    
dataset = KarateClub()
print(f'Dataset: {dataset}')                                # 数据集名称,KarateClub()
print('='*20)
print(f'Number of graphs: {len(dataset)}')                  # 图数量,1
print(f'Number of features: {dataset.num_features}')        # 点特征数量,34
print(f'Number of classes: {dataset.num_classes}')          # 数据类别数量,4

data = dataset[0]                                           # 获取 dataset 中的一个数据(图)
print(f'An undirected graph: {data.is_undirected()}')       # 是否无向图,True
print('='*30)
print(f'Num of edges: {data.num_edges}')                    # 边数量,156=78x2(因为无向图,所以乘2)
print(f'Num of nodes: {data.num_nodes}')                    # 点数量,34
print(f'Num of node features: {data.num_node_features}')    # 点特征数量,34
print(f'Shape of x: {np.shape(data.x)}')                    # 节点特征矩阵,[34, 34]
print(f'Shape of edge_index: {np.shape(data.edge_index)}')  # 边的起终点矩阵,[2, 156]
print(f'Attr of edge: {data.edge_attr}')                    # 边特征矩阵,None
print(f'Shape of y: {np.shape(data.y)}')                    # 真值,[34](对应 34 个点)
print(f'Pos of data: {data.pos}')                           # 节点位置矩阵,None

G = to_networkx(data, to_undirected=True)                   # 将 Data 实例转换到 networkx.Graph
visualize_graph(G, data.y)                                  # 可视化构建的图

在这里插入图片描述

Mini-batches

😸神经网络通常以批处理的方式进行训练,而 PyG 通过创建稀疏的对角邻接矩阵(由 edge_index 定义)并在节点维度上连接特征(X)和目标矩阵(Y)来实现 mini-batch 的并行化,这种组合允许不同数量的节点和边使用在同一个批次中。此外,PYG 有其自身的 DataLoader(torch_geometric.loader.DataLoader),这个 DataLoader 已经处理好了前面的拼接操作。

在这里插入图片描述

😻通过 PYG 的 DataLoader 可以很方便的使用 mini-batch,以下是一个数据加载的例子:

from torch_geometric.datasets import TUDataset
from torch_geometric.loader import DataLoader
from torch_scatter import scatter_mean

# 下载数据集,数据存放路径为当前路径下 data/ENZYMES 文件夹
dataset = TUDataset(root='data/ENZYMES', name='ENZYMES', use_node_attr=True)
# 加载数据集,使用的 batch size 为 32,且打乱顺序
loader = DataLoader(dataset, batch_size=32, shuffle=True)

# 获取每一个 batch
for batch in loader:
    print(batch)  # DataBatch(edge_index=[2, 4036], x=[1016, 21], y=[32], batch=[1016], ptr=[33])
    print(batch.num_graphs)                        # 32
    x = scatter_mean(batch.x, batch.batch, dim=0)  # 分别为每个图的节点维度计算平均的节点特征
    print(x.size())                                # torch.Size([32, 21])
    break                                          # 迭代一次后退出

✍️torch_geometric.data.Batch 继承自 torch_geometric.data.Data,并且多了一个 batch 属性,该属性是一个列向量,它将每个节点映射到每个 mini-batch 中的对应的图中,其形式如下:
b a t c h = [ 0 ⋯ 0 1 ⋯ n − 2 n − 1 ⋯ n − 1 ] T batch = \begin{bmatrix}0 & \cdots & 0 & 1 & \cdots & n-2 & n-1 & \cdots & n-1 \end{bmatrix}^T batch=[001n2n1n1]T

Data Transforms

😺transforms 在计算机视觉领域是一种很常见的数据增强,而 PyG 有自己的 transforms,其输出是 Data 类型,输出也是 Data 类型。可以使用 torch_geometric.transforms.Compose 封装一系列的 transforms。我们以 ShapeNet 数据集 (包含 17000 个 point clouds,每个 point 分类为 16 个类别的其中一个)为例:

import torch_geometric.transforms as T
from torch_geometric.datasets import ShapeNet

# 下载并加载数据集
dataset = ShapeNet(root='data/ShapeNet', categories=['Airplane'],
                    pre_transform=T.KNNGraph(k=6),      # 生成最近邻图
                    transform=T.RandomTranslate(0.01))  # 在一定范围内随机平移每个点
print(dataset[0])  # Data(x=[2518, 3], y=[2518], pos=[2518, 3], category=[1], edge_index=[2, 15108])

Learning Methods on Graphs

😴这里以一个简单的 GCN 模型构造和训练为例,该模型使用数据集为 Cora,加载数据集不使用 Dataset 和 DataLoader:

import torch
import torch.nn.functional as F
from torch_geometric.nn import GCNConv
from torch_geometric.datasets import Planetoid

# 下载并加载数据集
dataset = Planetoid(root='data/Planetoid', name='Cora')

# 定义 GCN 模型
class GCN(torch.nn.Module):
    def __init__(self, hidden_channels):
        super().__init__()
        torch.manual_seed(12345)
        self.conv1 = GCNConv(dataset.num_features, hidden_channels)
        self.conv2 = GCNConv(hidden_channels, dataset.num_classes)

    def forward(self, data):
        x, edge_index = data.x, data.edge_index
        x = self.conv1(x, edge_index)
        x = F.dropout(F.relu(x), p=0.5, training=self.training)
        x = self.conv2(x, edge_index)
        return x

# 模型相关配置
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')        
model = GCN(hidden_channels=16).to(device)
data = dataset[0].to(device)
criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=5e-4)

# 训练函数,返回损失值
def train():
    model.train()
    optimizer.zero_grad()
    out = model(data)
    loss = criterion(out[data.train_mask], data.y[data.train_mask])
    loss.backward()
    optimizer.step()
    return loss

# 测试函数,返回准确率
def test():
    model.eval()
    out = model(data)
    pred = out.argmax(dim=1)
    test_correct = pred[data.test_mask] == data.y[data.test_mask]
    test_acc = int(test_correct.sum()) / int(data.test_mask.sum())
    return test_acc

# 训练 200 轮
for epoch in range(1, 201):
    loss = train()
print(f'Train loss: {loss:.4f}')         # Train loss: 0.0223

test_acc = test()
print(f'Test accuracy: {test_acc:.4f}')  # Test accuracy: 0.8070

补充:A Gentle Introduction to Graph Neural Networks、图的一些基本知识:关联矩阵、拉普拉斯矩阵、图中心性【点度中心性】【 特征向量中心性】【中介中心性】【接近中心性】、图神经网络 PyTorch Geometric 入门教程

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

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

相关文章

涨知识系列:爆款短视频拍摄技巧之一,构图

拍摄技巧主要分为两个部分,一个是构图,一个是拍摄手法。这部分内容其实也是比较简单的,因为短视频毕竟不需要做到像拍电影那么专业。所以在短视频当中我们只要学会一些基本的技巧就完全够用了。更重要的是我们需要对构图和拍摄手法有一个概念…

基于KT6368A的双模蓝牙模块打印机的方案

目录 一、打印机蓝牙模块简介 目前主流的打印机,很多都还是不带蓝牙。大部分的受限于成本等等原因,都还是通过USB的方式和电脑进行通讯,从而完成打印的数据交互 因为早期蓝牙技术发展的比较缓慢,而打印机类型的产品,…

_12LeetCode代码随想录算法训练营第十二天-C++二叉树

_12LeetCode代码随想录算法训练营第十二天-C二叉树 二叉树基础知识 二叉树的种类 满二叉树 满二叉树:如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。 完全二叉树 完全二叉树的定义如下…

线段树能解决多少问题?

背景 给一个两个数组,其中一个数组是 A [1,2,3,4],另外一个数组是 B [5,6,7,8]。让你求两个数组合并后的大数组的: 最大值最小值总和 这题是不是很简单?我们直接可以很轻松地在 O(mn) 的时间解决,其中 m 和 n 分别为…

maven的java工程获取mysql数据库数据【问题及解决过程记录】

创建数据库maven,指定字符集和排序规则 UTF8MB4常用的排序规则:utf8mb4_unicode_ci、utf8mb4_general_ci、utf8mb4_bin,选用哪种方式呢?先来分析一下: 1、准确性: (1)utf8mb4_unico…

ffmpeg-时间基tbn、tbc、tbr

时间基的作用 源码来自ffmpeg5.1。 时间基在ffmpeg中是通过数据结构有理数AVRational描述的。时间基为时间戳的单位,比如时间基tbn(AVStream.time_base)0.001秒,AVPacket的pts40,则表明该AVPacket要在tbn*pts0.04秒开始显示。 /** 代码路径…

JavaScript 网页特效

一、Offset 1.1 概述 offset > 偏移量 ,可以动态的获取的元素的位置、大小等属性。 获得元素距离带有定位父元素的位置获得元素自身的大小(宽度高度) 返回的数值都不带单位 offset常用属性: 属性作用element.offsetParent返回作为该元素带有定位…

全球汽车后行业发展现状:欧洲市场保持稳健 中国产业规模增速较快

根据观研报告网发布的《2022年中国汽车后市场分析报告-市场发展格局与投资潜力研究》显示,汽车后市场(AM市场)是指汽车在销售之后维修和保养服务及其所包含的汽车零部件、汽车用品和材料的交易市场,它涵盖了消费者买车后所需要的一…

LeetCode 321 周赛

2485. 找出中枢整数 给你一个正整数 n ,找出满足下述条件的 中枢整数 x : 1 和 x 之间的所有元素之和等于 x 和 n 之间所有元素之和。 返回中枢整数 x 。如果不存在中枢整数,则返回 -1 。题目保证对于给定的输入,至多存在一个中…

STM32单片机直流电机PID速度控制正反转控制(霍尔磁铁测速)LCD1602

实践制作DIY- GC0116-直流电机PID速度控制 一、功能说明: 基于STM32单片机设计-直流电机PID速度控制 功能介绍: STM32F103C系列最小系统LCD1602直流电机磁铁霍尔传感器MX15系列驱动模块4个按键(速度减、速度加、开/关、正转/反转&#xff0…

【复习笔记】【嵌入式】嵌入式系统及其原理复习重点——篇二

嵌入式系统及其原理复习重点笔记 2 ARM处理器和指令集 ARM处理器简介 ARM架构与ARM处理器对应关系 V1版架构 该版架构只在原型机ARM1出现过,处理能力有限,其基本性能: 寻址空间:64M字节(26位)基本的数据处理指令(无乘法)字节、半字和字的…

4个封神的电脑软件,颠覆你对白嫖的认知,干货奉上

闲话少说,直上干货。 1、TinyWow TinyWow虽说是国外网站工具,但不得不承认真的无敌好用,收纳工具超200个,完全免费,无任何弹屏广告,更为良心的是,不需要注册登录,随用随走&#xff0…

如何优化大场景实时渲染?HMS Core 3D Engine这么做

在先前举办的华为开发者大会2022(HDC)上,华为通过3D数字溪村展示了自有3D引擎“HMS Core 3D Engine”(以下简称3D Engine)的强大能力。作为一款高性能、高画质、高扩展性的3D引擎,3D Engine不仅能通过实时光…

C++文件流

1、【转】string和stringstream用法总结 - 小金乌会发光-Z&M - 博客园 2、C:std::stringstream【数据类型转换、多个字符串拼接、分割字符串】_u013250861的博客-CSDN博客_c stringstream转string 3、C使用stringstream进行数据类型转换_puppylpg的…

TCP延迟应答、捎带应答、粘包问题、异常处理

TCP延迟应答、捎带应答、粘包问题、异常处理一、延迟应答二、捎带应答三、面向字节流 -- 粘包问题四、TCP中的异常处理五、补充一、延迟应答 上篇博客我们讲到TCP滑动窗口、流量控制、拥塞控制。 如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小。…

[ vulhub漏洞复现篇 ] Airflow dag中的命令注入漏洞复现 CVE-2020-11978

🍬 博主介绍 👨‍🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…

web前端-javascript-function函数的arguments对象(类数组对象,它也可以通过索引来操作数据,也可以获取长度)

arguments 对象 1. 引出 arguments 在调用 function 函数时,浏览器每次都会传递进两个隐含的参数 函数的上下文对象 this封装实参的对象 arguments 2. 说明 arguments 是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度在调用函数时&#…

ACL会议介绍 - Call for Main Conference Papers

The 61st Annual Meeting of the Association for Computational Linguistics Toronto, Canada July 9-14, 2023 网址:The 61st Annual Meeting of the Association for Computational Linguistics - ACL 2023 目录 征集主要会议文件 Submission Topics 主题轨迹…

Stm32标准库函数3——BlueTooth 蓝牙通讯测试 Stm32中继

//在使用本程序前,先将模块与手机端匹配成功,波特率38400 //串口1(A9、A10)接电脑,串口2(A2、A3)接蓝牙模块 //所有的波特率都为38400,蓝牙的供电为3.3-5v //程序功能,转…

Discrete Optimization课程笔记(4)—混合整数规划

目录​​​​​​​ 1.MIP介绍(Mixed Integer Program) Case1: Warehouse Location Case2: Knapsack Problem(Branch and Bound) 2.MIP模型(modeling) Case3: Coloring Problem(Big-M Transformation) 3.割平面法(Cutting planes) 4.多面体切割(Polyhedral Cuts) Cas…