2024/7/7周报

文章目录

  • 摘要
  • Abstract
  • 文献阅读
    • 题目
    • 问题
    • 本文贡献
    • 问题描述
    • 图神经网络
    • Framework
    • 实验
      • 数据集
      • 实验结果
  • 深度学习
    • MAGNN模型相关代码
    • GNN
    • 为什么要用GNN?
    • GNN面临挑战
  • 总结

摘要

本周阅读了一篇用于多变量时间序列预测的多尺度自适应图神经网络的文章,多变量时间序列(MTS)预测在智能应用的自动化和最优化中发挥着重要作用。这是一项具有挑战性的任务。本文提出了一种多尺度自适应图神经网络(MAGNN)来解决上述问题。MAGNN利用多尺度金字塔网络在不同的时间尺度上保持潜在的时间依赖关系。作者还开发了一个基于尺度的融合模块,有效地促进了不同时间尺度上的协作,并自动捕捉贡献的时间模式的重要性。在六个真实数据集上的实验表明,MAGNN在各种设置下的性能都优于最先进的方法。

Abstract

This week,an article on multi-scale adaptive graph neural network for multivariable time series prediction is readed. Multivariable time series (MTS) prediction plays an important role in the automation and optimization of intelligent applications. This is a challenging task. In this paper, a multi-scale adaptive graph neural network (MAGNN) is proposed to solve the above problems. MAGNN uses multi-scale pyramid network to maintain potential time dependence on different time scales. The author also developed a scale-based fusion module, which effectively promoted the cooperation on different time scales and automatically captured the importance of the contribution time pattern. Experiments on six real data sets show that the performance of MAGNN is better than the most advanced methods in various settings.

文献阅读

题目

Multi-Scale Adaptive Graph Neural Network for Multivariate Time Series Forecasting

问题

1)传统的方法,如向量自回归(VAR)、时间正则化矩阵分解(TRMF)、向量自回归滑动平均(VARMA)和高斯过程(GP),往往依赖于严格的平稳假设,无法捕捉变量之间的非线性相关性。
2)注意机制和基于记忆的网络模型侧重于时间相关性的建模,将MTS的输入处理为向量,并假设单个变量的预测值受所有其他变量的影响,这在实际应用中是不合理的,也是很难满足的。例如,一条街道的TrafficflOWS很大程度上受到邻近街道的影响,而来自远处街道的影响相对较小。
3)现有的GNN模型只考虑了单个时间尺度上的时间依赖关系,这可能不能正确地反映许多现实世界场景中的变化。已有的工作学习共享邻接矩阵来表示丰富的变量间依赖关系,这使得模型偏向于学习一种突出的共享时态模式。

本文贡献

1)提出MAGNN,它学习一种既能综合反映多尺度时态模式又能反映特定尺度变量间依赖关系的时态表示。
2)设计了一个自适应图学习模块,用于探索不同时间尺度下丰富和隐含的变量间依赖关系,以及一个基于尺度的融合模块,用于促进这些特定尺度的时间表示之间的协作,并自动捕获贡献的时间模式的重要性。
3)在六个真实世界的MTS基准数据集上进行广泛的实验。实验结果表明,该方法的性能优于目前最先进的方法。

问题描述

本文主要研究MTS预测。在形式上,给定一个输入的时间序列数据在这里插入图片描述,其中在这里插入图片描述表示时间步t的值,N是变量维度,在这里插入图片描述表示第t个时间步的第i个变量的值,MTS预测的目的是预测未来在时间步t+h的值在这里插入图片描述,其中h表示需要预测的未来时间步数。这个问题可以表述为:在这里插入图片描述。式中F为映射函数,θ表示所有可学习的参数。

然后,存在如下几种关于MTS预测的定义:

定义1:MTS数据用图结构表示。图被定义为G=(V,E),其中V表示节点集,|V|=N,E是边集。假设在这里插入图片描述,将第i个变量视为第i个节点在这里插入图片描述在这里插入图片描述的值是的特征,每条边在这里插入图片描述的都表明vi和vj之间存在变量间的依赖关系。

定义2:加权邻接矩阵。图的加权邻接矩阵在这里插入图片描述是一种用于存储边权重的数学表示方法,其中如果在这里插入图片描述在这里插入图片描述;如果在这里插入图片描述在这里插入图片描述。对于没有任何先验知识的纯MTS数据,需要学习多图的加权邻接矩阵来表示丰富且隐式的变量间依赖关系。据此,MTS预测公式可修改为:在这里插入图片描述。其中在这里插入图片描述表示能被GNN用于MTS预测的图集。

图神经网络

论文方法中应用的图卷积操作定义如下:
在这里插入图片描述
其中G=(V,E,A)是一个带加权邻接矩阵的图,x是节点的表示,σ是一个激活函数,θ是可学习的参数矩阵,A\hat{}=I_{n}+A是具有自连接的邻接矩阵,D\hat{}A\hat{}的对角度矩阵,在这里插入图片描述。通过将图卷积操作多层堆叠,可以聚合多阶的邻居信息。

多尺度GNN,又称分层GNN,通常在细粒度图的基础上分层构建粗粒度图。MAGNN关注时间维度的尺度,与一般的多尺度GNN非常不同,后者主要关注空间维度的尺度。MAGNN引入了一个多尺度金字塔网络,将原始时间序列转换为从较小尺度到较大尺度的特征表示,在该网络上,它学习每个尺度下具有相同大小的特定尺度图,并对每个图使用公式在这里插入图片描述定义的基本GNN。

Framework

下图说明了MAGNN的框架,它包括四个主要部分:a)多尺度金字塔网络,用于在不同的时间尺度上保持底层的时间层次;b)自适应图学习模块,用于自动推断变量间的依赖关系;c)多尺度时间图神经网络,用于捕获各种尺度特定的时间模式;d)尺度级融合模块,用于有效地促进跨不同时间尺度的协作。
在这里插入图片描述
MAGNN框架的4个主要部分组成具体作用如下:(a)两个并行的卷积神经网络和每层的逐点相加将特征表示从较小尺度分层变换到较大尺度;(b)自适应图学习模块将节点嵌入和尺度嵌入作为输入,并输出特定尺度的邻接矩阵;©将每个尺度特定的特征表示和邻接矩阵输入到时序图神经网络(TGNN)中,以获得尺度特定的表示。(d)加权融合特定尺度表示以捕获贡献的时间模式。最终的多尺度表示被送入包括两个卷积神经网络的输出模块以获得预测值。

实验

数据集

为了评估MAGNN的性能,在六个公共基准数据集上进行了实验:太阳能、交通、电力、汇率、纳斯达克和METR-LA。表一汇总了数据集的统计数据,6个公共基准数据集的详细情况如下:
太阳能:此数据集包含从国家可再生能源实验室收集的太阳能,2007年从阿拉巴马州的137个光伏发电厂每10分钟采样一次。
交通:此数据集包含加州交通部的道路使用率(在0到1之间),这些数据是从2015年到2016年旧金山湾区的862个传感器每小时汇总的。
用电量:此数据集包含UCI机器学习存储库的用电量,从2012年到2014年每小时汇总321个客户端的用电量。R汇率:该数据集包含八个国家的汇率,从1990年到2016年每天都进行抽样。
Nasdaq:这个数据集包含82家公司的股票价格,从2016年7月到2016年12月每分钟抽样一次。
METR-LA:此数据集包含洛杉矶县的平均车速,这些车速是从2012年3月至2012年6月高速公路上的207个环路探测器收集的5分钟数据。
将六个数据集按时间顺序分为训练集(60%)、验证集(20%)和测试集(20%)。
在这里插入图片描述
输入窗口大小T设置为168。学习率设置为0.001。使用ADAM优化器,所有可训练的参数都可以通过反向传播进行优化。对于所有数据集,尺度数为4。多尺度金字塔网络中的CNN的核大小从金字塔网络的第一层到最后一层分别设置为1×7、1×6和1×3,所有CNN的步长设置为2。作者分别设置地平线h={3,6,12,24},对于Nasdaq数据集,预测范围被设置为3到24分钟,对于METR-LA数据集,从15到120分钟,对于太阳能数据集,从30到240分钟,对于交通和电力数据集,从3到24小时,对于汇率数据集,从3到24天。预测范围越大,预测就越难。

实验结果

六个数据集上所有方法的结果总结如下表(按RSE表示):
在这里插入图片描述
在六个真实数据集上的实验表明,MAGNN在各种设置下的性能都优于最先进的方法。

深度学习

MAGNN模型相关代码

from layer import *
# from AGCRN import *
import torchclass magnn(nn.Module):def __init__(self, gcn_depth, num_nodes, device, dropout=0.3, subgraph_size=20, node_dim=40, conv_channels=32, gnn_channels=32, scale_channels=16, end_channels=128, seq_length=12, in_dim=1, out_dim=12, layers=3, propalpha=0.05, tanhalpha=3, single_step=True):super(magnn, self).__init__()self.num_nodes = num_nodesself.dropout = dropoutself.device = deviceself.single_step = single_stepself.filter_convs = nn.ModuleList()self.gate_convs = nn.ModuleList()self.scale_convs = nn.ModuleList()self.gconv1 = nn.ModuleList()self.gconv2 = nn.ModuleList()self.norm = nn.ModuleList()self.seq_length = seq_lengthself.layer_num = layersself.gc = graph_constructor(num_nodes, subgraph_size, node_dim, self.layer_num, device)if self.single_step:self.kernel_set = [7, 6, 3, 2]else:self.kernel_set = [3, 2, 2]self.scale_id = torch.autograd.Variable(torch.randn(self.layer_num, device=self.device), requires_grad=True)# self.scale_id = torch.arange(self.layer_num).to(device)self.lin1 = nn.Linear(self.layer_num, self.layer_num) self.idx = torch.arange(self.num_nodes).to(device)self.scale_idx = torch.arange(self.num_nodes).to(device)self.scale0 = nn.Conv2d(in_channels=in_dim, out_channels=scale_channels, kernel_size=(1, self.seq_length), bias=True)self.multi_scale_block = multi_scale_block(in_dim, conv_channels, self.num_nodes, self.seq_length, self.layer_num, self.kernel_set)# self.agcrn = nn.ModuleList()length_set = []length_set.append(self.seq_length-self.kernel_set[0]+1)for i in range(1, self.layer_num):length_set.append( int( (length_set[i-1]-self.kernel_set[i])/2 ) )for i in range(self.layer_num):"""RNN based model"""# self.agcrn.append(AGCRN(num_nodes=self.num_nodes, input_dim=conv_channels, hidden_dim=scale_channels, num_layers=1) )self.gconv1.append(mixprop(conv_channels, gnn_channels, gcn_depth, dropout, propalpha))self.gconv2.append(mixprop(conv_channels, gnn_channels, gcn_depth, dropout, propalpha))self.scale_convs.append(nn.Conv2d(in_channels=conv_channels,out_channels=scale_channels,kernel_size=(1, length_set[i])))self.gated_fusion = gated_fusion(scale_channels, self.layer_num)# self.output = linear(self.layer_num*self.hidden_dim, out_dim)self.end_conv_1 = nn.Conv2d(in_channels=scale_channels,out_channels=end_channels,kernel_size=(1,1),bias=True)self.end_conv_2 = nn.Conv2d(in_channels=end_channels,out_channels=out_dim,kernel_size=(1,1),bias=True)def forward(self, input, idx=None):seq_len = input.size(3)assert seq_len==self.seq_length, 'input sequence length not equal to preset sequence length'scale = self.multi_scale_block(input, self.idx)# self.scale_weight = self.lin1(self.scale_id)self.scale_set = [1, 0.8, 0.6, 0.5]adj_matrix = self.gc(self.idx, self.scale_idx, self.scale_set)outputs = self.scale0(F.dropout(input, self.dropout, training=self.training))out = []out.append(outputs)for i in range(self.layer_num):"""RNN-based model"""# output = self.agcrn[i](scale[i].permute(0, 3, 2, 1), adj_matrix) # B T N D# output = output.permute(0, 3, 2, 1)output = self.gconv1[i](scale[i], adj_matrix[i])+self.gconv2[i](scale[i], adj_matrix[i].transpose(1,0))scale_specific_output = self.scale_convs[i](output)out.append(scale_specific_output)# concatenate# outputs = outputs + scale_specific_output# mean-pooling    # outputs = torch.mean(torch.stack(out), dim=0)out0 = torch.cat(out, dim=1)out1 = torch.stack(out, dim = 1)if self.single_step:outputs = self.gated_fusion(out0, out1)x = F.relu(outputs)x = F.relu(self.end_conv_1(x))x = self.end_conv_2(x)return x, adj_matrix

网络层定义如下:

from __future__ import division
import torch
import torch.nn as nn
from torch.nn import init
import numbers
import torch.nn.functional as F
import numpy as npclass nconv(nn.Module):def __init__(self):super(nconv,self).__init__()def forward(self,x, A):x = torch.einsum('ncvl,vw->ncwl',(x,A))return x.contiguous()class dy_nconv(nn.Module):def __init__(self):super(dy_nconv,self).__init__()def forward(self,x, A):x = torch.einsum('ncvl,nvwl->ncwl',(x,A))return x.contiguous()class linear(nn.Module):def __init__(self,c_in,c_out,bias=True):super(linear,self).__init__()self.mlp = torch.nn.Conv2d(c_in, c_out, kernel_size=(1, 1), padding=(0,0), stride=(1,1), bias=bias)def forward(self,x):return self.mlp(x)class layer_block(nn.Module):def __init__(self, c_in, c_out, k_size):super(layer_block, self).__init__()self.conv_output = nn.Conv2d(c_in, c_out, kernel_size=(1, 1), stride=(1, 2))self.conv_output1 = nn.Conv2d(c_in, c_out, kernel_size=(1, k_size), stride=(1, 1), padding=(0, int( (k_size-1)/2 ) ) )self.output = nn.MaxPool2d(kernel_size=(1,3), stride=(1,2), padding=(0,1))self.conv_output1 = nn.Conv2d(c_in, c_out, kernel_size=(1, k_size), stride=(1, 1) )self.output = nn.MaxPool2d(kernel_size=(1,3), stride=(1,2))self.relu = nn.ReLU()def forward(self, input):conv_output = self.conv_output(input) # shape (B, D, N, T)conv_output1 = self.conv_output1(input)output = self.output(conv_output1)return self.relu( output+conv_output[...,-output.shape[3]:] )# return self.relu( conv_output )class multi_scale_block(nn.Module):def __init__(self, c_in, c_out, num_nodes, seq_length, layer_num, kernel_set, layer_norm_affline=True):super(multi_scale_block, self).__init__()self.seq_length = seq_lengthself.layer_num = layer_numself.norm = nn.ModuleList()self.scale = nn.ModuleList()for i in range(self.layer_num):self.norm.append(nn.BatchNorm2d(c_out, affine=False))#     # self.norm.append(LayerNorm((c_out, num_nodes, int(self.seq_length/2**i)),elementwise_affine=layer_norm_affline))#     self.norm.append(LayerNorm((c_out, num_nodes, length_set[i]),elementwise_affine=layer_norm_affline))self.start_conv = nn.Conv2d(c_in, c_out, kernel_size=(1, 1), stride=(1, 1))self.scale.append(nn.Conv2d(c_out, c_out, kernel_size=(1, kernel_set[0]), stride=(1, 1)))for i in range(1, self.layer_num):self.scale.append(layer_block(c_out, c_out, kernel_set[i]))def forward(self, input, idx): # input shape: B D N Tself.idx = idxscale = []scale_temp = inputscale_temp = self.start_conv(scale_temp)# scale.append(scale_temp)for i in range(self.layer_num):scale_temp = self.scale[i](scale_temp)# scale_temp = self.norm[i](scale_temp)# scale_temp = self.norm[i](scale_temp, self.idx)# scale.append(scale_temp[...,-self.k:])scale.append(scale_temp)return scaleclass top_down_path(nn.Module):def __init__(self, c_in, c_out_1, c_out_2, c_out_3, c_out_4):super(top_down_path, self).__init__()self.down1 = nn.Conv2d(c_in, c_out_1, kernel_size=(1, 1), stride=(1, 1))self.down2 = nn.Conv2d(c_out_1, c_out_2, kernel_size=(1, 7), stride=(1, 2), padding=(0, 2))self.down3 = nn.Conv2d(c_out_2, c_out_3, kernel_size=(1, 6), stride=(1, 2))self.down4 = nn.Conv2d(c_out_3, c_out_4, kernel_size=(1, 3), stride=(1, 2))self.up3 = nn.ConvTranspose2d(c_out_4, c_out_3, kernel_size=(1,3), stride=(1,2))# self.up3 = nn.MaxUnpool2d()self.up2 = nn.ConvTranspose2d(c_out_3, c_out_2, kernel_size=(1,6), stride=(1,2), output_padding=(0,1))self.up1 = nn.ConvTranspose2d(c_out_2, c_out_1, kernel_size=(1,7), stride=(1,2))def forward(self, input):down_1 = self.down1(input)down_2 = self.down2(down_1)down_3 = self.down3(down_2)down_4 = self.down4(down_3)up_3 = self.up3(down_4)output_3 = down_3 + up_3up_2 = self.up2(output_3)output_2 = down_2 + up_2up_1 = self.up3(output_2)output_1 = down_1[:,:,:,1:] + up_1return down_4, output_3, output_2, output_1class gated_fusion(nn.Module):def __init__(self, skip_channels, layer_num, ratio=1):super(gated_fusion, self).__init__()# self.reduce = torch.mean(x,dim=2,keepdim=True)self.dense1 = nn.Linear(in_features=skip_channels*(layer_num+1), out_features=(layer_num+1)*ratio, bias=False)self.dense2 = nn.Linear(in_features=(layer_num+1)*ratio, out_features=(layer_num+1), bias=False)def forward(self, input1, input2):se = torch.mean(input1, dim=2, keepdim=False)se = torch.squeeze(se)se = F.relu(self.dense1(se))se = F.sigmoid(self.dense2(se))se = torch.unsqueeze(se, -1)se = torch.unsqueeze(se, -1)se = torch.unsqueeze(se, -1)x = torch.mul(input2, se)x = torch.mean(x, dim=1, keepdim=False)return xclass prop(nn.Module):def __init__(self,c_in,c_out,gdep,dropout,alpha):super(prop, self).__init__()self.nconv = nconv()self.mlp = linear(c_in,c_out)self.gdep = gdepself.dropout = dropoutself.alpha = alphadef forward(self,x,adj):adj = adj + torch.eye(adj.size(0)).to(x.device)d = adj.sum(1)h = xdv = da = adj / dv.view(-1, 1)for i in range(self.gdep):h = self.alpha*x + (1-self.alpha)*self.nconv(h,a)ho = self.mlp(h)return hoclass mixprop(nn.Module):def __init__(self,c_in,c_out,gdep,dropout,alpha):super(mixprop, self).__init__()self.nconv = nconv()self.mlp = linear((gdep+1)*c_in,c_out)self.gdep = gdepself.dropout = dropoutself.alpha = alphadef forward(self,x,adj):adj = adj + torch.eye(adj.size(0)).to(x.device)d = adj.sum(1)h = xout = [h]a = adj / d.view(-1, 1)for i in range(self.gdep):h = self.alpha*x + (1-self.alpha)*self.nconv(h,a)out.append(h)ho = torch.cat(out,dim=1)ho = self.mlp(ho)return hoclass graph_constructor(nn.Module):def __init__(self, nnodes, k, dim, layer_num, device, alpha=3):super(graph_constructor, self).__init__()self.nnodes = nnodesself.layers = layer_numself.emb1 = nn.Embedding(nnodes, dim)self.emb2 = nn.Embedding(nnodes, dim)self.lin1 = nn.ModuleList()self.lin2 = nn.ModuleList()for i in range(layer_num):self.lin1.append(nn.Linear(dim,dim))self.lin2.append(nn.Linear(dim,dim))self.device = deviceself.k = kself.dim = dimself.alpha = alphadef forward(self, idx, scale_idx, scale_set):nodevec1 = self.emb1(idx)nodevec2 = self.emb2(idx)adj_set = []for i in range(self.layers):nodevec1 = torch.tanh(self.alpha*self.lin1[i](nodevec1*scale_set[i]))nodevec2 = torch.tanh(self.alpha*self.lin2[i](nodevec2*scale_set[i]))a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))adj0 = F.relu(torch.tanh(self.alpha*a))mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device)mask.fill_(float('0'))s1,t1 = adj0.topk(self.k,1)mask.scatter_(1,t1,s1.fill_(1))# print(mask)adj = adj0*maskadj_set.append(adj)return adj_setclass graph_constructor_full(nn.Module):def __init__(self, nnodes, k, dim, layer_num, device, alpha=3):super(graph_constructor_full, self).__init__()self.nnodes = nnodesself.layers = layer_numself.emb1 = nn.Embedding(nnodes, dim)self.emb2 = nn.Embedding(nnodes, dim)self.lin1 = nn.ModuleList()self.lin2 = nn.ModuleList()for i in range(self.layers):self.lin1.append(nn.Linear(dim,dim))self.lin2.append(nn.Linear(dim,dim))self.device = deviceself.k = kself.dim = dimself.alpha = alphaself.static_feat = static_featdef forward(self, idx, scale_idx, scale_set):nodevec1 = self.emb1(idx)nodevec2 = self.emb2(idx)adj_set = []for i in range(self.layers):nodevec1 = torch.tanh(self.alpha*self.lin1[i](nodevec1*scale_set[i]))nodevec2 = torch.tanh(self.alpha*self.lin2[i](nodevec2*scale_set[i]))a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))adj0 = F.relu(torch.tanh(self.alpha*a))adj_set.append(adj0)return adj_setclass graph_constructor_one(nn.Module):def __init__(self, nnodes, k, dim, layer_num, device, alpha=3, static_feat=None):super(graph_constructor_one, self).__init__()self.nnodes = nnodesself.layers = layer_numself.emb1 = nn.Embedding(nnodes, dim)self.emb2 = nn.Embedding(nnodes, dim)self.lin1 = nn.ModuleList()self.lin2 = nn.ModuleList()self.lin1 = nn.Linear(dim,dim)self.lin2 = nn.Linear(dim,dim)self.device = deviceself.k = kself.dim = dimself.alpha = alphaself.static_feat = static_featdef forward(self, idx, scale_idx, scale_set):nodevec1 = self.emb1(idx)nodevec2 = self.emb2(idx)adj_set = []nodevec1 = torch.tanh(self.alpha*self.lin1(nodevec1))nodevec2 = torch.tanh(self.alpha*self.lin2(nodevec2))a = torch.mm(nodevec1, nodevec2.transpose(1,0))-torch.mm(nodevec2, nodevec1.transpose(1,0))adj0 = F.relu(torch.tanh(self.alpha*a))mask = torch.zeros(idx.size(0), idx.size(0)).to(self.device)mask.fill_(float('0'))s1,t1 = adj0.topk(self.k,1)mask.scatter_(1,t1,s1.fill_(1))adj = adj0*maskreturn adj

GNN

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在使用图的时候可以简单的将其划分为下面几步:

1.给定一个图,首先将节点转化为递归单元,将边转化为前馈神经网络;
2.对所有节点执行n次邻域聚合(消息传递)。
3.对所有节点的嵌入向量求和得到图表示H。
4.将H传递到更高的层中,或者使用它来表示图形的独特属性。

为什么要用GNN?

GNN与CNN、RNN的比较,为什么不用CNN或RNN,而用GNN?

GNN 是一种专门为图结构数据设计的神经网络。它可以处理不规则的拓扑结构,并且可以捕捉节点之间的复杂关系。GNN可以通过消息传递和聚合机制来处理不同大小和结构的图数据。由于其适应性和灵活性,GNN 在许多领域,如社交网络分析、化学分子识别和推荐系统等,取得了显著的成功。

选择 GNN 而不是 CNN 或 RNN 的主要原因是数据结构和任务类型。当处理图结构数据或需要捕捉复杂的节点关系时,GNNs是更合适的选择。然而,在处理网格结构数据(如图像)或序列数据(如文本)时,CNN和 RNN可能是更好的选择。

GNN简单来说就是Graph + Nerual Networks,关键问题就是将图的结构和图中每个节点和边的特征转化为一般的神经网络的输入(张量)。

GNN面临挑战

目前,GNN面临的挑战主要包括:1)如何有效处理大规模图数据;2)如何增强GNN的表达能力,以捕捉更为复杂的图结构;3)如何解决图数据中的不确定性和噪声问题。

总结

下周将继续学习GNN的一些相关数学知识,从理论上进一步理解GNN。

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

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

相关文章

Vulkan 学习(1)---- Vulkan 基本概念和发展历史

目录 Vulkan及其演化史Vulkan 基本概念基本术语 Vulkan 的原理Vulkan应用程序Vulkan的编程模型硬件初始化窗口展示表面资源设置流水线设置描述符和描述符缓冲池基于SPIR-V的着色器流水线管理指令的记录队列的提交 Vulkan及其演化史 目前主流的图形渲染API有OpenGL、OpenGL ES、…

ROS——多个海龟追踪一个海龟实验

目标 通过键盘控制一个海龟(领航龟)的移动,其余生成的海龟通过监听实现追踪定期获取领航龟和其余龟的坐标信息,通过广播告知其余龟,进行相应移动其余龟负责监听 疑惑点(已解决) int main(int…

【感谢告知】本账号内容调整,聚焦于Google账号和产品的使用经验和问题案例分析

亲爱的各位朋友: 感谢您对本账号的关注和支持! 基于对朋友们需求的分析和个人兴趣的转变,该账号从今天将对内容做一些调整,有原来的内容改为Google(谷歌)账号和产品的使用经验,以及相关问题的…

判断是否为完全二叉树

目录 分析 分析 1.完全二叉树的概念:对于深度为K的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。 2.思路:可以采…

Redis源码整体结构

一 前言 Redis源码研究为什么先介绍整体结构呢?其实也很简单,作为程序员的,要想对一个项目有快速的认知,对项目整体目录结构有一个清晰认识,有助于我们更好的了解这个系统。 二 目录结构 Redis源码download到本地之后,对应结构如下: 从上面的截图可以看出,Redis源码一…

pdf怎么转换成图片格式文件,pdf文档怎么转换成图片格式

在数字化时代,pdf文件转换成图片格式是一种常见的操作,无论是在工作还是日常生活中,我们总会遇到需要将pdf文件转换为图片的需求。这可能是因为图片格式更易于分享、展示或编辑。那么,如何高效地将pdf转换成图片呢?本文…

C++初学者指南-4.诊断---未定义行为检测器

C初学者指南-4.诊断—未定义行为检测器 未定义行为检测器(UBSAN) 适用编译器:clang,g在运行时检测许多类型的未定义行为 解引用空指针从未对齐的指针读取整数溢出被0除 … 在代码中加入额外的指令:在调试构建中增加运行时约25% 示例:有符号整形溢出 …

RabbitMq - Java客户端基础【简单案例 +Work模型】

目录 1、前置知识 1.1、AMQP怎么理解 1.2、Spring AMQP是什么 1.3、为什么要了解Spring-AMQP? 2、使用Spring-AMQP实现一个发消息案例 3、Work模型 问题: 优化: 小结:Work模型的使用: 1、前置知识 1.1、AMQP怎…

【论文阅读】-- Visual Traffic Jam Analysis Based on Trajectory Data

基于轨迹数据的可视化交通拥堵分析 摘要1 引言2 相关工作2.1 交通事件检测2.2 交通可视化2.3 传播图可视化 3 概述3.1 设计要求3.2 输入数据说明3.3 交通拥堵数据模型3.4 工作流程 4 预处理4.1 路网处理4.2 GPS数据清理4.3 地图匹配4.4 道路速度计算4.5 交通拥堵检测4.6 传播图…

2024世界人工智能大会,神仙打架

B站:啥都会一点的研究生公众号:啥都会一点的研究生 AI圈最近又发生了啥新鲜事? 该栏目以周更频率总结国内外前沿AI动态,感兴趣的可以点击订阅合集以及时收到最新推送 B站首秀世界人工智能大会,展示自研AI技术与AIGC…

生成式人工智能如何改变软件开发:助手还是取代者?

生成式人工智能如何改变软件开发:助手还是取代者? 生成式人工智能(AIGC)正在引领软件开发领域的技术变革。从代码生成、错误检测到自动化测试,AI工具在提高开发效率的同时,也引发了对开发者职业前景的讨论…

【shell编程小项目】

目录 一、项目拓扑二、要求三、shell编程 一、项目拓扑 二、要求 环境准备: 准备两个虚拟机,按照环境配置好对应的 IP 地址和对应的主机名和 SSH 密钥登录在 workstation.exam.com 节点实现如下需求: 1、编写 Shell 脚本,要求代码…

【web APIs】快速上手Day04(Dom节点)

目录 Web APIs - 第4天日期对象实例化方法案例-页面显示时间时间的另外一个写法 时间戳三种方式获取时间戳案例-毕业倒计时效果 节点操作DOM节点查找节点父节点查找案例-关闭广告子节点查找兄弟关系查找 增加节点创建节点追加节点案例-学成在线案例渲染克隆节点 删除节点 M端事…

ESP32 步进电机精准控制:打造高精度 DIY 写字机器人,实现流畅书写体验

摘要: 想让你的 ESP32 不再仅仅是控制灯光的工具吗? 本文将带你使用 ESP32 开发板、步进电机和简单的机械结构打造一个能够自动写字的机器人。我们将深入浅出地讲解硬件连接、软件代码以及控制逻辑,并提供完整的项目代码和电路图,即使是 Ardu…

在mac下 Vue2和Vue3并存 全局Vue2环境创建Vue3新项目(Vue cli2和Vue cli4)

全局安装vue2 npm install vue-cli -g自行在任意位置创建一个文件夹vue3,局部安装vue3,注意不要带-g npm install vue/cli安装完成后,进入目录,修改vue为vue3 找到vue3/node-moudles/.bin/vue,把vue改成vue3。 对环境变量进行配置…

码垛机:物流自动化的关键设备

在数字化浪潮席卷全球的今天,物流行业正迎来前所未有的变革。其中,码垛机作为物流自动化的关键设备,正在逐步改变着传统仓库的运营模式,引领着物流自动化的新篇章。 一、码垛机:物流自动化的得力助手 码垛机是一种能够…

【手写数据库内核组件】0201 哈希表hashtable的实战演练,多种非加密算法,hash桶的冲突处理,查找插入删除操作的代码实现

hash表原理与实战 ​专栏内容: postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 文章目录 hash表…

从资金管理的角度 谈谈伦敦金投资技巧

刚进入伦敦金市场的时候,笔者认为技术分析是很重要的,所以将学习伦敦金投资技巧的精力全部投入到技术分析的学习中。经过一系列交易的亏损,笔者才发现,其实交易管理才是最重要的。如果管理得好,30%的胜率,投…

Python28-7.5 降维算法之t-分布邻域嵌入t-SNE

t-分布邻域嵌入(t-distributed Stochastic Neighbor Embedding,t-SNE)是一种用于数据降维和可视化的机器学习算法,尤其适用于高维数据的降维。t-SNE通过将高维数据嵌入到低维空间(通常是二维或三维)中&…

CC工具箱使用指南:【相交占比分析】

一、简介 需求场景如下,有【待分析地块】和【面积占比参考】2个图层。2个图层之间存在空间上的重叠。工具的目的是为了分析出【待分析地块】的每1个图斑中,和【面积占比参考】相交的面积,以及和总面积的占比。 举一个应用场景为例&#xff0…