PyTorch进阶学习笔记[长期更新]

第一章 PyTorch简介和安装

PyTorch是一个很强大的深度学习库,在学术中使用占比很大。
我这里是Mac系统的安装,相比起教程中的win/linux安装感觉还是简单不少(之前就已经安好啦),有需要指导的小伙伴可以评论。

第二章 基础知识

这里划重点!

  • 张量的创建/随机初始化
a = torch.tensor(1.0, dtype=torch.float)
d = torch.FloatTensor(2,3)
f = torch.IntTensor([1,2,3,4]) 
k = torch.rand(2, 3) 
l = torch.ones(2, 3)
m = torch.zeros(2, 3)
n = torch.arange(0, 10, 2) #arrange用于创造等差数列 interval is 2
  • 查看/修改维度
    .shape or .size()
    .view(row,column)
    .unsqeeze(1)#加一维度
    .squeeze(1)

  • tensor&numpy.array

1.array->tensor
h = torch.tensor(g) #g = np.array([[1,2,3],[4,5,6]])
i = torch.from_numpy(g)2.tensor->array
j = h.numpy()
共享内存的情况
torch.from_numpy()和torch.as_tensor()从numpy array创建得到的张量和原数据是共享内存的,张量对应的变量不是独立变量,修改numpy array会导致对应tensor的改变。
如代码例中所示,修改g改变i
  • tensor运算
o = torch.add(k,l)#o=k+l
#broadcast is two different size of  tensors adding.
print(p + q)
  • 灵活运用索引 [:]
  • 自动求导
x1 = torch.tensor(1.0, requires_grad=True)
x1.grad.data是在有requires_grad=True即要求求导数的该数字的结果。
y.backward()反向传播于梯度,不清0会累积。
x1.grad #可尝试查看导数

第三章 组成模块

  • 设计及解决学习任务
    步骤如下:
    1.数据预处理(格式统一、数据变换、划分训练集/测试集的)
    2.选择模型,损失函数,优化函数,超参(常用:batch_size,learning rate ,max_epochs,configuration of gpu)
    3.训练并计算得到表现

    -深度学习&机器学习
    1.深度学习样本多,有批batch训练。
    2.层多,需要按顺序逐层搭建。
    3.损失函数,优化器使得其更灵活
    
  • gpu配置:略

  • 数据读入:Dataset+DataLoader
    Dataset定义数据格式和变换形式,DataLoader用iterative的方式不断读入批次数据
    自定义Dataset类需要继承PyTorch自身的Dataset类。

    • 主要包含三个函数:
      init: 用于向类中传入外部参数,同时定义样本集
      getitem: 用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
      len: 用于返回数据集的样本数
    • 涉及到的API
      1.PyTorch自带的ImageFolder类的用于读取按一定结构存储的图片数据(path对应图片存放的目录,目录下包含若干子目录,每个子目录对应属于同一个类的图片),其中“data_transform”可以对图像进行一定的变换,如翻转、裁剪等操作,可自己定义。
  • 用cifar10数据集(识别普适物体的小型数据集)构建Dataset类实例:图片存放在一个文件夹,另外有一个csv文件给出了图片名称对应的标签。这种情况下需要自己来定义Dataset类
    利用ImageFolder,
    train_data = datasets.ImageFolder(root, transform=None, target_transform=None, loader=default_loader)

    • 关于ImageFolder,展开如下:(细节部分转自https://blog.csdn.net/weixin_40123108/article/details/85099449,有改动)
      root:在root指定的路径下寻找图片
      transform:对PIL Image进行的转换操作,transform的输入是使用loader读取图片的返回对象
      target_transform:对label的转换
      loader:给定路径后如何读取图片,默认读取为RGB格式的PIL Image对象
    • label是按照文件夹名顺序排序后存成字典,即{类名:类序号(从0开始)},一般来说最好直接将文件夹命名为从0开始的数字,这样会和ImageFolder实际的label一致,如果不是这种命名规范,建议看看self.class_to_idx属性以了解label和文件夹名的映射关系。
      在这里插入图片描述
from torchvision import transforms as T
import matplotlib.pyplot as plt
from torchvision.datasets import ImageFolder
# cat文件夹的图片对应label 0,dog对应1
print(dataset.class_to_idx)
# 所有图片的路径和对应的label
print(dataset.imgs)
print(dataset[0][1])# 第一维是第几张图,第二维为1返回label
print(dataset[0][0]) # 为0返回图片数据
#transform配置
normalize = T.Normalize(mean=[0.4, 0.4, 0.4], std=[0.2, 0.2, 0.2])
transform  = T.Compose([T.RandomResizedCrop(224),#即先随机采集,然后对裁剪得到的图像缩放为同一大小T.RandomHorizontalFlip(),#水平翻转T.ToTensor(),normalize,
])
dataset = ImageFolder('data1/dogcat_2/', transform=transform)
# 深度学习中图片数据一般保存成CxHxW,即通道数x图片高x图片宽
#print(dataset[0][0].size())
to_img = T.ToPILImage()
  • 另一种读入方式,自定义构建数据集
class MyDataset(Dataset):#to build dataset we needdef __init__(self, data_dir, info_csv, image_list, transform=None):"""Args:data_dir: path to image directory.info_csv: path to the csv file containing image indexeswith corresponding labels.image_list: path to the txt file contains image names to training/validation settransform: optional transform to be applied on a sample."""label_info = pd.read_csv(info_csv)image_file = open(image_list).readlines()#distinguish among read()/readline()/readlines()#link:https://zhuanlan.zhihu.com/p/26573496self.data_dir = data_dirself.image_file = image_file #custom/user-definedself.label_info = label_infoself.transform = transformdef __getitem__(self, index):#return image and label."""Args:index: the index of itemReturns:image and its labels"""image_name = self.image_file[index].strip('\n')#只要头尾包含有指定字符序列中的字符就删除,中间的删不掉,若'12'则字符串中的'21'也能删掉        raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name]#显示索引:.loc,第一个参数为 index切片,第二个为 columns列名label = raw_label.iloc[:,0]#隐式索引:.iloc(integer_location), 只能传入整数。image_name = os.path.join(self.data_dir, image_name)#path.join拼接规则https://www.jianshu.com/p/3090f7875f9bimage = Image.open(image_name).convert('RGB')if self.transform is not None:image = self.transform(image)return image, labeldef __len__(self):return len(self.image_file)
#Finishing dataset,we can use DataLoader to load batch data.
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle=False)
#batch_size:样本是按“批”读入的,batch_size就是每次读入的样本数
#num_workers:有多少个进程用于读取数据
#shuffle:是否将读入的数据打乱
#drop_last:对于样本最后一部分没有达到批次数的样本,使其不再参与训练
#PyTorch中的DataLoader的读取可以使用next和iter来完成,next(iterable[, default])
#next() 返回迭代器的下一个项目。next() 函数要和生成迭代器的iter() 函数一起使用。
#iter()函数获取这些可迭代对象的迭代器。对获取到的迭代器不断使⽤next()函数来获取下⼀条数据,调⽤了可迭代对象的 iter ⽅法.
#iterable – 可迭代对象,default – 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。images, labels = next(iter(val_loader))
print(images.shape)
plt.imshow(images[0].transpose(1,2,0))
plt.show()
  • 模型构建
    基于 Module 类的模型来完成,Module 类是 nn 模块里提供的一个模型构造类,是所有神经⽹网络模块的基类,我们可以继承它来定义我们想要的模型。 Module 类它的子类既可以是⼀个层(如PyTorch提供的 Linear 类),⼜可以是一个模型(如这里定义的 MLP 类),或者是模型的⼀个部分。
    • 继承 Module 类构造多层感知机。代码中定义的 MLP (Multilayer Perceptron)类重载了 Module 类的 init 函数和 forward 函数。它们分别用于创建模型参数和定义前向计算。前向计算也即正向传播。
      在这里插入图片描述
import torch
from torch import nnclass MLP(nn.Module):# 声明带有模型参数的层,这里声明了两个全连接层def __init__(self, **kwargs):# 调用MLP父类Block的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数super(MLP, self).__init__(**kwargs)self.hidden = nn.Linear(784, 256)#set fully connected layer#[in_features,out_features]#从输入输出的张量的shape角度来理解,相当于一个输入为[batch_size, in_features]的张量变换成了[batch_size, out_features]的输出张量。self.act = nn.ReLU()self.output = nn.Linear(256,10)# 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出def forward(self, x):o = self.act(self.hidden(x))return self.output(o)   #实例化
X = torch.rand(2,784)
net = MLP()
print(net)
net(X)

以上的 MLP 类中⽆须定义反向传播函数。系统将通过⾃动求梯度⽽自动⽣成反向传播所需的 backward 函数。
我们可以实例化 MLP 类得到模型变量 net 。下⾯的代码初始化 net 并传入输⼊数据 X 做一次前向计算。其中, net(X) 会调用 MLP 继承⾃自 Module 类的 call 函数,这个函数将调⽤用 MLP 类定义的forward 函数来完成前向计算。

#Parameter 类其实是 Tensor 的子类,如果一 个 Tensor 是 Parameter ,那么它会⾃动被添加到模型的参数列表里。所以在⾃定义含模型参数的层时,我们应该将参数定义成 Parameter ,除了直接定义成 Parameter 类外,还可以使⽤ ParameterList 和 ParameterDict 分别定义参数的列表和字典。#torch.mul()对应位相乘
#torch.mm()矩阵乘法
class MyListDense(nn.Module):def __init__(self):super(MyListDense, self).__init__()self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])self.params.append(nn.Parameter(torch.randn(4, 1)))def forward(self, x):for i in range(len(self.params)):x = torch.mm(x, self.params[i])return x
net = MyListDense()
print(net)class MyDictDense(nn.Module):def __init__(self):super(MyDictDense, self).__init__()self.params = nn.ParameterDict({'linear1': nn.Parameter(torch.randn(4, 4)),'linear2': nn.Parameter(torch.randn(4, 1))})self.params.update({'linear3': nn.Parameter(torch.randn(4, 2))}) # 新增def forward(self, x, choice='linear1'):return torch.mm(x, self.params[choice])net = MyDictDense()
print(net)
  • 卷积层
    在这里插入图片描述
#卷积运算(二维互相关)
def corr2d(X, K): h, w = K.shapeX, K = X.float(), K.float()Y = torch.zeros((X.shape[0] - h + 1, X.shape[1] - w + 1))for i in range(Y.shape[0]):for j in range(Y.shape[1]):Y[i, j] = (X[i: i + h, j: j + w] * K).sum()return Y
#Y[i, j] = (X[i: i + h, j: j + w] * K).sum() 
# 二维卷积层
class Conv2D(nn.Module):def __init__(self, kernel_size):super(Conv2D, self).__init__()self.weight = nn.Parameter(torch.randn(kernel_size))self.bias = nn.Parameter(torch.randn(1))def forward(self, x):return corr2d(x, self.weight) + self.bias #corr2d 上面的二维卷积运算
#padding
X = X.view((1, 1) + X.shape)#原shape前加两个维度
# 在⾼和宽两侧的填充数分别为2和1,将每次滑动的行数和列数称为步幅(stride)
conv2d = nn.Conv2d(..., padding=(2, 1), stride=(3, 4))
#pooling最大池化或平均池化if mode == 'max':Y[i, j] = X[i: i + p_h, j: j + p_w].max()elif mode == 'avg':Y[i, j] = X[i: i + p_h, j: j + p_w].mean()
#一个nn.Module包含各个层和一个forward(input)方法,该方法返回output
#instance:
#前馈神经网络 (feed-forward network)(LeNet)
#步骤:
#定义包含一些可学习参数(或者叫权重)的神经网络
#在输入数据集上迭代
#通过网络处理输入
#计算 loss (输出和正确答案的距离)
#将梯度反向传播给网络的参数
#更新网络的权重,一般使用一个简单的规则:weight = weight - learning_rate * gradient
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
#n包则依赖于autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output。
#backward函数会在使用autograd时自动定义,backward函数用来计算导数。def __init__(self):super(Net, self).__init__()#Net找其父类,将父类init东西给self# 输入图像channel:1;输出channel:6;5x5卷积核self.conv1 = nn.Conv2d(1, 6, 5)self.conv2 = nn.Conv2d(6, 16, 5)# an affine operation: y = Wx + bself.fc1 = nn.Linear(16 * 5 * 5, 120)self.fc2 = nn.Linear(120, 84)self.fc3 = nn.Linear(84, 10)def forward(self, x):# 2x2 Max poolingx = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))# 如果是方阵,则可以只使用一个数字进行定义x = F.max_pool2d(F.relu(self.conv2(x)), 2)x = x.view(-1, self.num_flat_features(x))#把特征拍扁x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.fc3(x)return xdef num_flat_features(self, x):#计算特征数用于拍扁size = x.size()[1:]  # 除去批处理维度的其他所有维度num_features = 1for s in size:num_features *= sreturn num_features
net = Net()
print(net)#print the net's structure.#返回可学习参数
print(net.parameters())
params = list(net.parameters())
#print(params)
print(len(params))
print(params[0].size())  # conv1的权重#to use my model
#注意:这个网络 (LeNet)的期待输入是 32x32 的张量。如果使用 MNIST 数据集来训练这个网络,要把图片大小重新调整到 32x32。
input = torch.randn(1, 1, 32, 32)
out = net(input)
print(out)
net.zero_grad()#梯度清零
out.backward(torch.randn(1, 10))#随机梯度的反向传播
#torch.nn supports mini-batches rather than only one sample.
#nn.Conv2d 接受一个4维的张量,即nSamples x nChannels x Height x Width,如果是一个单独的样本,只需要使用input.unsqueeze(0) 来添加一个“假的”批大小维度。
  • 涉及到的模块总结

    • torch.Tensor - 一个多维数组,支持诸如backward()等的自动求导操作,同时也保存了张量的梯度。
    • nn.Module- 神经网络模块。是一种方便封装参数的方式,具有将参数移动到GPU、导出、加载等功能。
    • nn.Parameter- 张量的一种,当它作为一个属性分配给一个Module时,它会被自动注册为一个参数。
    • autograd.Function - 实现了自动求导前向和反向传播的定义,每个Tensor至少创建一个Function节点,该节点连接到创建Tensor的函数并对其历史进行编码。
  • AlexNet
    请添加图片描述
    5个卷积层和3个全连接层组成的,深度总共8层。

class AlexNet(nn.Module):def __init__(self):super(AlexNet, self).__init__()self.conv = nn.Sequential(#convolution layersnn.Conv2d(1, 96, 11, 4), # in_channels, out_channels, kernel_size, stride, paddingnn.ReLU(),nn.MaxPool2d(3, 2), # kernel_size, stride# 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数nn.Conv2d(96, 256, 5, 1, 2),nn.ReLU(),nn.MaxPool2d(3, 2),# 连续3个卷积层,且使用更小的卷积窗口。除了最后的卷积层外,进一步增大了输出通道数。# 前两个卷积层后不使用池化层来减小输入的高和宽nn.Conv2d(256, 384, 3, 1, 1),nn.ReLU(),nn.Conv2d(384, 384, 3, 1, 1),nn.ReLU(),nn.Conv2d(384, 256, 3, 1, 1),nn.ReLU(),nn.MaxPool2d(3, 2))# 这里全连接层的输出个数比LeNet中的大数倍。使用丢弃层来缓解过拟合self.fc = nn.Sequential(#fully connected layersnn.Linear(256*5*5, 4096),nn.ReLU(),nn.Dropout(0.5),nn.Linear(4096, 4096),nn.ReLU(),nn.Dropout(0.5),# 输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000nn.Linear(4096, 10),)def forward(self, img):feature = self.conv(img)output = self.fc(feature.view(img.shape[0], -1))return output

在这里插入图片描述

  • 损失函数
#二分类交叉熵损失函数Cross Entropy
torch.nn.BCELoss(weight=None, size_average=None, reduce=None, reduction='mean')
#在二分类中,label是{0,1}。对于进入交叉熵函数的input为概率分布的形式。一般来说,input为sigmoid激活层的输出,或者softmax的输出。
#size_average:数据为bool,为True时,返回的loss为平均值;为False时,返回的各样本的loss之和。
#reduce:数据类型为bool,为True时,loss的返回是标量。
#(2) 默认情况下 nn.BCELoss(),reduce = True,size_average = True。
#(3) 如果reduce为False,size_average不起作用,返回向量形式的loss。
#(4) 如果reduce为True,size_average为True,返回loss的均值,即loss.mean()。
#(5) 如果reduce为True,size_average为False,返回loss的和,即loss.sum()。m = nn.Sigmoid()
loss = nn.BCELoss()
input = torch.randn(3, requires_grad=True)
target = torch.empty(3).random_(2)
output = loss(m(input), target)
output.backward()#交叉熵损失函数
torch.nn.CrossEntropyLoss(weight=None, size_average=None, ignore_index=-100, reduce=None, reduction='mean')
#ignore_index:忽略某个类的损失函数。
loss = nn.CrossEntropyLoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.empty(3, dtype=torch.long).random_(5)
output = loss(input, target)
output.backward()#L1损失函数:计算输出y和真实标签target之间的差值的绝对值。
torch.nn.L1Loss(size_average=None, reduce=None, reduction='mean')
#reduction参数决定了计算模式。有三种计算模式可选:none:逐个元素计算。 sum:所有元素求和,返回标量。 mean:加权平均,返回标量。 如果选择none,那么返回的结果是和输入元素相同尺寸的。默认计算方式是求平均。
loss = nn.L1Loss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
output.backward()#MSE损失函数:计算输出y和真实标签target之差的平方。
torch.nn.MSELoss(size_average=None, reduce=None, reduction='mean')
loss = nn.MSELoss()
input = torch.randn(3, 5, requires_grad=True)
target = torch.randn(3, 5)
output = loss(input, target)
output.backward()#平滑L1 (Smooth L1)损失函数:L1的平滑输出,其功能是减轻离群点带来的影响
torch.nn.SmoothL1Loss(size_average=None, reduce=None, reduction='mean', beta=1.0)
#过程同理,略#可视化:平滑l1与l1对比
import matplotlib.pyplot as plt
inputs = torch.linspace(-10, 10, steps=5000)
target = torch.zeros_like(inputs)loss_f_smooth = nn.SmoothL1Loss(reduction='none')
loss_smooth = loss_f_smooth(inputs, target)
loss_f_l1 = nn.L1Loss(reduction='none')
loss_l1 = loss_f_l1(inputs,target)plt.plot(inputs.numpy(), loss_smooth.numpy(), label='Smooth L1 Loss')#画图
plt.plot(inputs.numpy(), loss_l1, label='L1 loss')
plt.xlabel('x_i - y_i')
plt.ylabel('loss value')
plt.legend()#图例
plt.grid()#网格线
plt.show()#目标泊松分布的负对数似然损失
torch.nn.PoissonNLLLoss(log_input=True, full=False, size_average=None, eps=1e-08, reduce=None, reduction='mean')
#log_input:输入是否为对数形式,决定计算公式。如果log_input=False:输入数据还不是对数形式,计算中还需要对input取对数,取对数时有可能遇到input=0,这样就无法正常进行取对数运算,因此在input后加入修正项eps。其中修正项很小,它的加入并不会影响到对input对数数值的,即便有影响也可忽略不计。
#full:计算所有 loss,默认为 False。
#eps:修正项,避免 input 为 0 时,log(input) 为 nan 的情况。

Smooth L1:在这里插入图片描述
在这里插入图片描述
由图可见,smoothL1处x=0尖端更平滑

PoissonNLLLoss:
当参数log_input=True:在这里插入图片描述
当参数log_input=False:在这里插入图片描述

KLDivLoss
在这里插入图片描述

#kl散度
torch.nn.KLDivLoss(size_average=None, reduce=None, reduction='mean', log_target=False)
#功能:计算KL散度,也就是计算相对熵。用于连续分布的距离度量,并且对离散采用的连续输出空间分布进行回归通常很有用。
#reduction:计算模式,可为 none/sum/mean/batchmean。
inputs = torch.tensor([[0.5, 0.3, 0.2], [0.2, 0.3, 0.5]])
target = torch.tensor([[0.9, 0.05, 0.05], [0.1, 0.7, 0.2]], dtype=torch.float)
loss = nn.KLDivLoss()
output = loss(inputs,target)#排序损失函数MarginRankingLoss
#计算两个向量之间的相似度,用于排序任务。该方法用于计算两组数据之间的差异。
torch.nn.MarginRankingLoss(margin=0.0, size_average=None, reduce=None, reduction='mean')
#margin:边界值,x1 and x2之间的差异值
loss = nn.MarginRankingLoss()
input1 = torch.randn(3, requires_grad=True)
input2 = torch.randn(3, requires_grad=True)
target = torch.randn(3).sign()
output = loss(input1, input2, target)
output.backward()

MarginRankingLoss:
在这里插入图片描述

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

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

相关文章

【区块链安全 | 第三十八篇】合约审计之获取私有数据(二)

文章目录 前言漏洞代码代码审计攻击步骤修复/开发建议审计思路前言 在【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)中,介绍了私有数据、访问私有数据实例、Solidity 中的数据存储方式等知识,本文通过分析具体合约代码进行案例分析。 漏洞代码 // SPDX-Licens…

《微服务与事件驱动架构》读书分享

《微服务与事件驱动架构》读书分享 Building Event-Driver Microservices 英文原版由 OReilly Media, Inc. 出版,2020 作者:[加] 亚当 • 贝勒马尔 译者:温正东 作者简介: 这本书由亚当贝勒马尔(Adam Bellemare…

小刚说C语言刷题——第22讲 二维数组

昨天我们讲了一维数组,今天我们来讲二维数组。 1.定义 二维数组是指在数组名后跟两个方括号的数组。 2.语法格式 数据类型 数组名[下标][下标] 例如:int a[5][9];//表示5行9列的数组 3.访问二维数组元素 格式:数组名[行坐标][列坐标]…

Vue 大文件分片上传组件实现解析

Vue 大文件分片上传组件实现解析 一、功能概述 1.1本组件基于 Vue Element UI 实现,主要功能特点: 大文件分片上传:支持 2MB 分片切割上传实时进度显示:可视化展示每个文件上传进度智能格式校验:支持文件类型、大小…

「逻辑推理」AtCoder AT_abc401_d D - Logical Filling

前言 这次的 D 题出得很好,不仅融合了数学逻辑推理的知识,还有很多细节值得反复思考。虽然通过人数远高于 E,但是通过率甚至不到 60%,可见这些细节正是出题人的侧重点。 题目大意 给定一个长度为 N N N 的字符串 S S S&#…

腾讯后台开发 一面

一、手撕 合并升序链表 合并两个排序的链表_牛客题霸_牛客网 顺时针翻转矩阵 顺时针旋转矩阵_牛客题霸_牛客网 二、八股 1、静态变量和实例变量 public class House {public static String buildDate "2024-10-27"; // 静态变量public String color; // 实…

Unity 动画

Apply Root Motion 勾选的话就会使用动画片段自带的位移 Update Mode (动画重新计算骨骼位置转向缩放的数值): Normal : 随Update走,每次Update都计算Animate Physics :与 fixed Update() 同步&#xff0…

NDT和ICP构建点云地图 |【点云建图、Ubuntu、ROS】

### 本博客记录学习NDT,ICP构建点云地图的实验过程,参考的以下两篇博客: 无人驾驶汽车系统入门(十三)——正态分布变换(NDT)配准与无人车定位_settransformationepsilon-CSDN博客 PCL中点云配…

基于HTML + jQuery + Bootstrap 4实现(Web)地铁票价信息生成系统

地铁票价信息表生成系统 1. 需求分析 1.1 背景 地铁已经成为大多数人出行的首选,北京地铁有多条运营线路, 截至 2019 年 12 月,北京市轨道交通路网运营线路达 23 条、总里程 699.3 公里、车站 405 座。2019 年,北京地铁年乘客量达到 45.3 亿人次,日均客流为 1241.1 万人次…

EtherNet/IP 转 Modbus 协议网关

一、产品概述 1.1 产品用途 SG-EIP-MOD-210 网关可以实现将 Modbus 接口设备连接到 EtherNet/IP 网 络中。用户不需要了解具体的 Modbus 和 EtherNet/IP 协议即可实现将 Modbus 设 备挂载到 EtherNet/IP 接口的 PLC 上,并和 Modbus 设备进行数…

PostgreSQL:逻辑复制与物理复制

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

腾讯云COS与ZKmall 开源商城的存储集成方案

ZKmall 开源商城与腾讯云对象存储(COS)的集成,可通过云端资源托管、自动化数据同步、高性能存储架构实现本地存储负载降低与访问效率提升。以下是基于搜索结果的集成路径与核心优化点: 一、存储架构升级:本地与云端协同…

HTML — 浮动

浮动 HTML浮动(Float)是一种CSS布局技术,通过float: left或float: right使元素脱离常规文档流并向左/右对齐,常用于图文混排或横向排列内容。浮动元素会紧贴父容器或相邻浮动元素的边缘,但脱离文档流后可能导致父容器高…

【软件测试学习day1】软件测试概念

前言 本篇学习,测试相关基础概念、常见的开发模型测和测试模型,搞懂4个问题: 什么是需求什么是 bug什么是测试用例开发模型和测试模型 目录 1. 什么是需求 1.1 为什么要有需求 1.2 测试人员眼里的需求 1.3 如何深入了解需求 2. 测试用例…

Flutter常用组件实践

Flutter常用组件实践 1、MaterialApp 和 Center(组件居中)2、Scaffold3、Container(容器)4、BoxDecoration(装饰器)5、Column(纵向布局)及Icon(图标)6、Column/Row(横向/横向布局)+CloseButton/BackButton/IconButton(简单按钮)7、Expanded和Flexible8、Stack和Po…

刘火良FreeRTOS内核实现与应用学习之7——任务延时列表

在《刘火良FreeRTOS内核实现与应用学习之6——多优先级》的基础上:关键是添加了全局变量:xNextTaskUnblockTime ,与延时列表(xDelayedTaskList1、xDelayedTaskList2)来高效率的实现延时。 以前需要在扫描就绪列表中所…

图像预处理-插值方法

一.插值方法 当我们对图像进行缩放或旋转等操作时,需要在新的像素位置上计算出对应的像素值。 而插值算法的作用就是根据已知的像素值来推测未知位置的像素值。 1.1 最近邻插值 CV2.INTER_NEAREST 其为 warpAffine() 函数的参数 flags 的其一,表示最近…

智能配电保护:公共建筑安全的新 “防火墙”

安科瑞刘鸿鹏 摘要 随着城市建筑体量的不断增长和电气设备的广泛使用,现代建筑大楼的用电安全问题日益突出。传统配电方式面临监测盲区多、响应滞后、火灾隐患难发现等问题。为提升建筑电气系统的安全性和智能化水平,智慧用电系统应运而生。本文结合安…

如何解决DDoS攻击问题 ?—专业解决方案深度分析

本文深入解析DDoS攻击面临的挑战与解决策略,提供了一系列防御技术和实践建议,帮助企业加强其网络安全架构,有效防御DDoS攻击。从攻击的识别、防范措施到应急响应,为网络安全工作者提供了详细的操作指引。 DDoS攻击概览&#xff1a…

构建灵活的接口抽象层:支持多种后端数据存取的实战指南

构建灵活的接口抽象层:支持多种后端数据存取的实战指南 引言 在现代软件开发中,数据存取成为业务逻辑的核心组成部分。然而,由于后端数据存储方式的多样性(如关系型数据库、NoSQL数据库和文件存储),如何设计一套能够适配多种后端数据存取的接口抽象层,成为技术团队关注…