60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记

2023-05-16

诸神缄默不语-个人CSDN博文目录

本笔记是我学习 Deep Learning with PyTorch: A 60 Minute Blitz 这一PyTorch官方教程后的学习笔记。
该教程在官网上更新过,因此未来还可能继续更新。以后的读者所见的版本可能与我学的不同。
以下将按照教程中的顺序撰写笔记:

  1. Tensor(张量)。
  2. torch.autograd(自动求导包)。
  3. Neural Networks(神经网络)。
  4. Training a Classifier(图片分类任务示例)。
  5. 可选学习:Data Parallelism(数据并行)。

并最后整理教程中建议的衍生学习材料作为第6部分。

本文中不详细介绍代码相关的内容。对函数的解释建议翻阅PyTorch文档,也可参考我写的 PyTorch Python API详解大全(持续更新ing…)_诸神缄默不语的博客-CSDN博客 一文。

文中所使用的notebook文件下载并修改自原教程。
每一节都可以点击该图标下载notebook文件:
在这里插入图片描述

由于原教程notebook文件中部分Markdown内容显示有问题,因此我将我下载的notebook文件上传到了GitHub公开项目 PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial: 60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)相关文件(除数据平行部分,该部分直接上传了py后缀的代码脚本文件),这些notebook文件中的Markdown部分已经修改为了可以正常显示的形式(我是使用VSCode打开notebook文件,因此仅限于保证在VSCode中打开可以正常显示),并添加了一些我个人的学习笔记,可供参考。源代码与教程顺序的对应关系见后文。
此外在该项目中还放了一个原教程中置于colab的notebook文件。详情见下文。

原教程的notebook文件基本就是网页内容本身。有条件的读者也可以直接从原教程网页跳转到colab运行代码,点击教程每页上方这个图标即可:在这里插入图片描述
以后如果有缘可能会撰写colab使用方面的笔记。

建议读者提前学过线性代数和神经网络常识,会用 numpy,已经安装好 torch 和 torchvision 包

文章目录

  • 1. Tensor
  • 2. Autograd
  • 3. Neural Networks
  • 4. CIFAR10 (Example: Image Classification)
    • Step1:下载并规范化数据集
    • Step2:定义一个卷积神经网络
    • Step3:定义损失函数和优化器
    • Step4:训练神经网络
    • Step5:测试神经网络
    • 在GPU上训练
  • 5. 多GPU数据并行训练
  • 6. 衍生学习资料
  • 7. 其他正文及脚注未提及的参考资料

在教程首页有一个YouTube链接的视频,这只是一个两分钟的简介,没有干货,如果没有条件使用YouTube的读者也不用刻意去看。

1. Tensor

教程notebook:https://github.com/PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial/blob/master/tensor_tutorial.ipynb

  1. 什么是Tensor?
    torch中的Tensor是一种数据结构,其实在使用上与Python的list、numpy的array、ndarray等数据结构比较类似,可以当成一个多维数组来用。
    在数学上对张量这一专业名词有特定的定义,但是反正大概理解成一个多维数组就够用了。
  2. 如何生成Tensor?
    torch包中提供了一系列直接生成Tensor的函数,如 zeros()ones()rand() 等。
    此外,可以用 tensor(data) 函数直接将某一表示数组的数据(接受listnumpy.ndarray等格式)转换为Tensor。
    也可以通过 from_numpy(data) 函数将numpy.ndarray格式的数据转换为Tensor。
    还可以生成一个与其他Tensor具有相同dtype和device等属性的Tensor,使用torch的 ones_like(data)rand_like(data) 等函数,或Tensor的 new_ones() 等函数。
  3. Tensor的属性:shape(返回torch.Size格式)(也可以用size()函数),dtype,device(可见PyTorch Python API详解大全(持续更新ing…)_诸神缄默不语的博客-CSDN博客第0节的相关介绍)
  4. Tensor可以进行的操作:类似numpy的API;改变原数据的原地操作在函数后面加_就可以(一般不建议这么操作)
    1. 索引
    2. 切片
    3. join:cat(tensors)stack(tensors)
    4. 加法:add()+
    5. 乘法:对元素层面的乘法mul()*,矩阵乘法matmul()@
    6. resize
      1. reshape()view()(建议使用reshape(),因为仅使用view()可能会造成Tensor不contiguous的问题,可参考PyTorch Python API详解大全(持续更新ing…)_诸神缄默不语的博客-CSDN博客一文脚注3的介绍)
      2. squeeze()去掉长度为1的维度
      3. unsqueeze()增加一个维度(长度为1)
      4. transpose()转置2个维度
  5. Tensor.numpy()可以将Tensor转换为numpy数据。反向的操作见上面序号2部分。
    注意这两方向的转换的数据对象都是占用同一储存空间,修改后变化也会体现在另一对象上。
  6. item()函数返回仅有一个元素的Tensor的该元素值。

2. Autograd

教程notebook:https://github.com/PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial/blob/master/autograd_tutorial.ipynb

  1. torch.autograd是PyTorch提供的自动求导包,非常好用,可以不用自己算神经网络偏导了。
  2. 神经网络构成、常识部分这里就不再详细介绍了,总之大概就是:
    1. 神经网络由权重、偏置等参数决定的函数构成,这些参数在PyTorch中都储存在Tensor里
    2. 神经网络的训练包括前向传播反向传播两部分,前向传播就是用函数计算预测值,反向传播就是通过这一预测值产生的error/loss来更新参数(通过梯度下降的方式)
      对反向传播算法的介绍,教程中提供了3b1b的视频作为参考。原链接是YouTube视频,不方便的读者可以看B站上面的:【官方双语】深度学习之反向传播算法 上/下 Part 3 ver 0.9 beta  下篇:反向传播的微积分原理
      (对上一视频所属的3B1B深度学习视频系列,我也撰写了学习笔记,可参考:3B1B深度学习系列视频学习笔记_诸神缄默不语的博客-CSDN博客 )
  3. 神经网络的一轮训练:
    1. 前向传播:prediction = model(data)
    2. 反向传播
      1. 计算loss
      2. loss.backward()(autograd会在这一步计算参数的梯度,存在相应参数Tensor的grad属性中)
      3. 更新参数
        1. 加载optimizer(通过torch.optim)
        2. optimizer.step()对参数使用梯度下降的方法进行更新(梯度来源自参数的grad属性)

本节以下内容都属于原理部分,可以直接跳过

  1. autograd实现细节:一个示例
    1. 将Tensor的requires_grad属性设置为True,可以追踪autograd在其上每一步的操作
    2. 示例中,提供了两个requires_grad为True的Tensor(含两个元素的向量)a和b,设其损失函数 Q = 3 a 3 − b 2 Q = 3a^3 - b^2 Q=3a3b2
    3. 注意:对Q计算梯度时,需要在backward()函数中添加gradient参数,这个gradient是和当前Tensor形状相同的Tensor,包含当前Tensor的梯度,比如示例中使用的是: d Q d Q = 1 \frac{dQ}{dQ} = 1 dQdQ=1(因为Q是向量而非标量,参考backward()的文档。为了避免这个问题也可以直接将Q转化为标量然后使用backward()方法,如Q.sum().backward()
    4. 计算梯度:
      external_grad = torch.tensor([1., 1.])
      Q.backward(gradient=external_grad)
    5. 现在Q相对于a和b的梯度向量就分别储存在了a.grad和b.grad中,可以直接查看
  2. 教程中提供了aotugrad矢量分析方面的解释,我没看懂,以后学了矢量分析看懂了再说。
  3. autograd的计算图
    1. autograd维护一个由Function对象组成的DAG中的所有数据和操作。这个DAG是以输入向量为叶,输出向量为根。autograd从根溯叶计算梯度
    2. 在前向传播时,autograd同时干两件事:计算输出向量,维护DAG中操作的gradient function
    3. 反向传播以根节点调用backward()方法作为开始,autograd做以下三件事:用数据的grad_fn属性计算梯度,将梯度分别加总累积到各Tensor的grad属性中,根据链式法则传播到叶节点
    4. 如图,前序号4部分示例 Q = 3 a 3 − b 2 Q = 3a^3 - b^2 Q=3a3b2的DAG(箭头是前向传播的方向,节点是前向传播过程中每个操作的backward functions,蓝色的叶节点是a和b)
      figure
    5. 注意:PyTorch中的DAG是动态的,每次调用backward()方法都重新填出一个DAG
  4. 将Tensor的requires_grad属性设置为False,可以将其排除在DAG之外,autograd就不会计算它的梯度。
    在神经网络中,这种不需要计算梯度的参数叫frozen parameters。可以冻结不需要知道梯度的参数(节省计算资源),也可以在微调预训练模型时使用(此时往往冻结绝大多数参数,仅调整classifier layer参数,以在新标签上做预测)。
    类似功能也可以用上下文管理器torch.no_grad()实现。

3. Neural Networks

教程notebook:https://github.com/PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial/blob/master/neural_networks_tutorial.ipynb

  1. 神经网络可以通过torch.nn包搭建(torch.nn包里预定义的层调用了torch.nn.functional包的函数)
  2. nn.Module包含了网络层
  3. forward(input)方法返回输出结果
  4. 示例:简单前馈神经网络convnet
    figure
  5. 典型的神经网络训练流程:(从下一序号开始对每一部分进行详细介绍)
    1. 定义具有可训练参数(或权重)的神经网络
    2. 用数据集进行多次迭代
      1. 前向传播
      2. 计算loss
      3. 计算梯度
      4. 使用梯度下降法更新参数
  6. 定义网络
    只需要定义forward()方法,backward()方法会自动定义(因为用了autograd)。在forward()方法中可以进行任何Tensor操作。
    本部分代码定义了一个卷积→池化→卷积→池化→仿射变换→仿射变换→仿射变换的叠叠乐网络。
    (这个网络我有一点没搞懂,就是仿射变换前一步,既然已知数据维度是16*6*6,为什么还要用num_flat_features()这个方法算一遍啊……?)
import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        #Conv2d是在输入信号(由几个平面图像构成)上应用2维卷积
        # 1 input image channel, 6 output channels, 3x3 square convolution kernel
        self.conv1 = nn.Conv2d(1, 6, 3)
        self.conv2 = nn.Conv2d(6, 16, 3)
        # an affine operation: y = Wx + b
        #affine仿射的
        self.fc1 = nn.Linear(16 * 6 * 6, 120)
        #16是conv2的输出通道数,6*6是图像维度
        #(32*32的原图,经conv1卷后是6*30*30,经池化后是6*15*15,经conv2卷后是16*13*13,经池化后是16*6*6)
        #经过网络层后的维度数计算方式都可以看网络的类的文档来查到
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square, you can specify with a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))
        #将x转化为元素不变,尺寸为[-1,self.num_flat_features(x)]的Tensor
        #-1的维度具体是多少,是根据另一维度计算出来的
        #由于另一维度是x全部特征的长度,所以这一步就是把x从三维张量拉成一维向量
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
    #计算得到x的特征总数(就是把各维度乘起来)
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

net = Net()
print(net)

输出:

Net(
  (conv1): Conv2d(1, 6, kernel_size=(3, 3), stride=(1, 1))
  (conv2): Conv2d(6, 16, kernel_size=(3, 3), stride=(1, 1))
  (fc1): Linear(in_features=576, out_features=120, bias=True)
  (fc2): Linear(in_features=120, out_features=84, bias=True)
  (fc3): Linear(in_features=84, out_features=10, bias=True)
)

模型的可学习参数存储在net.parameters()中。这个方法的返回值是一个迭代器,包含了模型及其所有子模型的参数

  1. 前向传播out = net(input)
  2. 反向传播:先将参数梯度缓冲池清零(否则梯度会累加),再反向传播(此处使用一个随机矩阵)
    net.zero_grad()1
    out.backward(torch.randn(1, 10))
    如果有计算出损失函数,上一行代码应为:loss.backward()
  3. 注意:torch.nn只支持mini-batch,所以如果只有一个输入数据的话,可以用input.unsqueeze(0)方法创造一个伪batch维度
  4. 损失函数
    torch.nn包中定义的损失函数文档:https://pytorch.org/docs/nn.html#loss-functions
    以MSELoss为例:
    criterion = nn.MSELoss()
    loss = criterion(output, target)

对如此得到的loss,其grad_fn组成的DAG为:
在这里插入图片描述
所以,调用loss.backward()后,所有张量的梯度都会得到更新
直观举例:

print(loss.grad_fn)  # MSELoss
print(loss.grad_fn.next_functions[0][0])  # Linear
print(loss.grad_fn.next_functions[0][0].next_functions[0][0])  # ReLU

输出:

<MseLossBackward object at 0x0000015F84F7E388>
<AddmmBackward object at 0x0000015FFFF98E48>
<AccumulateGrad object at 0x0000015F84F7E388>

  1. 更新网络中的权重step()
    使用torch.optim中的优化器(lr入参是学习率,这个学习率也可以通过torch.optim.lr_scheduler包实现learning rate scheduling操作2
import torch.optim as optim

# create your optimizer
optimizer = optim.SGD(net.parameters(), lr=0.01)

# in your training loop:
optimizer.zero_grad()   #原因见前
output = net(input)
loss = criterion(output, target)
loss.backward()
optimizer.step()    # Does the update

4. CIFAR10 (Example: Image Classification)

教程notebook:https://github.com/PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial/blob/master/cifar10_tutorial.ipynb

  1. 各种形式的数据都可以通过Python标准库转换为numpy数组格式,然后再转换为Tensor格式
    1. 图像:Pillow, OpenCV
    2. 音频:scipy and librosa
    3. 文本:raw Python or Cython based loading, or NLTK and SpaCy
  2. 对计算机视觉任务,PyTorch有专门的包torchvision,可以直接通过torchvision.datasetstorch.utils.data.DataLoader下载Imagenet, CIFAR10, MNIST等常用数据集并对其进行数据转换
  3. 在本教程中使用的是CIFAR10。图片是3通道,大小为32*32。标签为图像类别(共10类)

Step1:下载并规范化数据集

通过torch.utils.data.DataLoader加载torchvision.datasets中的数据集,返回迭代器
使用torchvision.transforms包进行规范化

Step2:定义一个卷积神经网络

这个神经网络和第3部分神经网络里的模型相似,只是将数据维度做了修改。
这里的数据特征尺寸在网络层之间的变化是 3 ∗ 32 ∗ 32 → ( c o n v 1 ) 6 ∗ 28 ∗ 28 → ( p o o l ) 6 ∗ 14 ∗ 14 → ( c o n v 2 ) 16 ∗ 10 ∗ 10 → ( p o o l ) 16 ∗ 5 ∗ 5 → ( f c 1 ) 120 → ( f c 2 ) 84 → ( f c 3 ) 10 3*32*32\xrightarrow{(conv1)}6*28*28\xrightarrow{(pool)}6*14*14\xrightarrow{(conv2)}16*10*10\xrightarrow{(pool)}16*5*5\xrightarrow{(fc1)}120\xrightarrow{(fc2)}84\xrightarrow{(fc3)}10 33232(conv1) 62828(pool) 61414(conv2) 161010(pool) 1655(fc1) 120(fc2) 84(fc3) 10

import torch.nn as nn
import torch.nn.functional as F


class Net(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.pool = nn.MaxPool2d(2, 2)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = self.pool(F.relu(self.conv1(x)))
        x = self.pool(F.relu(self.conv2(x)))
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x


net = Net()

Step3:定义损失函数和优化器

import torch.optim as optim

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)

Step4:训练神经网络

for epoch in range(2):  # loop over the dataset multiple times

    running_loss = 0.0
    for i, data in enumerate(trainloader, 0):
        # get the inputs; data is a list of [inputs, labels]
        inputs, labels = data

        # zero the parameter gradients
        optimizer.zero_grad()

        # forward + backward + optimize
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        # print statistics
        running_loss += loss.item()  
        #loss.item()文档:https://pytorch.org/docs/stable/tensors.html?highlight=item#torch.Tensor.item
        #Returns the value of this tensor as a standard Python number.
        if i % 2000 == 1999:    # print every 2000 mini-batches
            print('[%d, %5d] loss: %.3f' %
                  (epoch + 1, i + 1, running_loss / 2000))
            running_loss = 0.0

print('Finished Training')

将模型保存到本地:

PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)

对模型存取的更多细节详见:SERIALIZATION SEMANTICS

Step5:测试神经网络

加载模型文件:

net = Net()
net.load_state_dict(torch.load(PATH))

用测试集输出向量中最大的元素代表的类作为输出

correct = 0
total = 0
with torch.no_grad():
    for data in testloader:
        images, labels = data
        outputs = net(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print('Accuracy of the network on the 10000 test images: %d %%' % (
    100 * correct / total))

在GPU上训练

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

net.to(device)
inputs, labels = data[0].to(device), data[1].to(device)  #把每一步的输入数据和目标数据也转到GPU上

注意,直接调用 my_tensor.to(device) 将返回一个在GPU上的 my_tensor 的副本而不是直接重写 my_tensor,因此在后续训练的过程中需要将其赋予一个新Tensor,然后用新Tensor来训练。

5. 多GPU数据并行训练

原教程:DATA PARALLELISM

代码:Note-of-PyTorch-60-Minutes-Tutorial/dp.py at master · PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial

这个教程主要讲如何使用 DataParallel 这个类(简称DP)。文档:DataParallel — PyTorch 1.10 documentation
PyTorch常用的另一个多卡训练的类是 DistributedDataParallel(简称DDP。文档:DistributedDataParallel — PyTorch 1.10.0 documentation)。那个类怎么用我还没搞懂,我就先把这个 DataParallel 搞懂了来写一写……

核心代码:

model = nn.DataParallel(model)

在单卡上写好的model直接调用这个类,然后别的都跟单卡形式下的一样就可以了。程序会自动把数据拆分放到所有已知的GPU上来运行。
看我在GitHub上写的代码,数据是直接从第一维拆开平均放到各个GPU上,相当于每个GPU放 batch_size/卡数 个样本。

设置已知的GPU,可以在运行代码的 python 加上 CUDA_VISIBLE_DEVICES 参数,举例:

CUDA_VISIBLE_DEVICES=0,1,2,3 python example.py

注意如果要使用nohup的话,这个参数要加在nohup的还前面,举例:

CUDA_VISIBLE_DEVICES=0,1,2,3 nohup python -u example.py >> nohup_output.log 2>&1 &

如果不设置则默认为所有GPU。

对GPU数量的计数可以使用 torch.cuda.device_count() 代码。

原理我还没怎么搞懂,但是据说直接用 DataParallel 不太好,有各卡空间不均衡之类的问题,建议使用 DistributedDataParallel。我学会那个类的使用方法以后大约也会写篇笔记博文的。

其他多卡运行PyTorch模型的资料可参考:

  1. PyTorch分布式训练简介
  2. Distributed communication package - torch.distributed — PyTorch 1.10.0 documentation

6. 衍生学习资料

  1. 微调torchvision模型教程
  2. autograd具体机制
  3. 逆向自动求导法应用实例 colab版 由于众所周知的有些读者可能无法登入colab,因此我也下载了原notebook文件放在了GitHub公开项目上供便捷下载,网址:https://github.com/PolarisRisingWar/Note-of-PyTorch-60-Minutes-Tutorial/blob/master/Simple_Grad.ipynb
  4. 训练神经网络玩视频游戏 REINFORCEMENT LEARNING (DQN) TUTORIAL
  5. 在ImageNet数据集上训练ResNet ImageNet training in PyTorch
  6. 用GAN生成人脸 Deep Convolution Generative Adversarial Networks
  7. 用Recurrent LSTM networks训练一个词级别的语言模型 Word-level language modeling RNN
  8. 更多PyTorch应用示例
  9. 更多PyTorch教程
  10. 在论坛上讨论PyTorch
  11. 在Slack上与其他PyTorch学习者交流

7. 其他正文及脚注未提及的参考资料

  1. pytorch tutorial : A 60 Minute Blitz_Gitabytes的博客-CSDN博客:这一篇在原教程的基础上还有所衍生,比如讲了个用torch.optim.lr_scheduler.ExponentialLR的代码例子。
  2. torch.nn.Module.zero_grad()的使用_敲代码的小风的博客-CSDN博客_torch zero_grad:这一篇用代码演示了一下PyTorch的梯度积累和清零的过程。
  3. optimizer.zero_grad()和net.zero_grad()_前进ing_嘟嘟的博客-CSDN博客

  1. 注意这个zero_grad()方法在此处是用在了net(一个网络(nn.Module子类)实例)上,后文的zero_grad()方法则是用在了optimizer(优化器)上。
    前者的文档见https://pytorch.org/docs/stable/generated/torch.nn.Module.html#torch.nn.Module.zero_grad,是将其所有参数梯度清零。
    后者的文档见https://pytorch.org/docs/stable/optim.html#torch.optim.Optimizer.zero_grad,是将优化器上所有参数梯度清零。
    注意到我们往优化器中传的就是这个网络的所有参数:optimizer = optim.SGD(net.parameters(), lr=0.01),所以我觉得这两种写法应该是一样的(因为model.parameters()返回一个Tensor的迭代器,Tensor作为一个可变object应该是直接传入引用,所以应该一样)。但是我还没有试验过,如果有闲情逸致的话可以试试。
    另,如果有frozen parameters,或者优化器只优化一部分模型中的参数,可能不等价。这一部分我也还没有试验过。
    此外参考为什么要使用 zero_grad()?_马鹏森的博客-CSDN博客_net.zero_grad()一文,还可以实现对特定Variable梯度清零:Variable.grad.data.zero_() ↩︎

  2. 这个东西我会在写李宏毅机器学习笔记的时候细讲的。 ↩︎

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记 的相关文章

  • MFC学习笔记(二)处理命令行选项

    目标 让应用程序处理这里所见的命令行标志 gt XXX exe c d 策略 一个MFC应用程序可以用CCommandLineInfo类的成员函数ParseParam 处理一些标准标 志 要添加我们自己的标志 xff0c 而仍然能够支持另外
  • C++ expection异常类、捕获所有异常(C++ primer,P639)

    expection类 头文件 lt expection gt stdexcept类 C 43 43 primer plus xff0c P632 包含以下异常 xff1a domain errorinvalid argumentlength
  • 5.1 运输层协议

    运输层协议 运输层的复用与常见端口常用端口 UDP协议特点UDP帧格式 TCP协议特点socket套接字可靠传输工作原理TCP帧首部重要字段 TCP可靠传输以字节为单位的滑动窗口选择超时重传时间选择确认SACK xff08 未经常使用P22
  • Linux上VScode + cmake + gcc开发环境搭建

    VScode 43 cmake 43 gcc 下载 安装vscode安装插件cmake文件结构vscode修改json文件编译 调试的过程 下载 安装 span class token comment cmake gcc 安装都很简单 sp
  • 软件测试面试04:实战项目介绍

    4 1 简单介绍下最近做过的项目 根据自己的项目整理完成 xff0c 要点 xff1a 1 xff09 项目背景 业务 需求 核心业务的流程 2 xff09 项目架构 xff0c B S还是C 5 xff0c 数据库用的什么 中间件用的什么
  • 一张图搞定SDF的概念

    本文仅代表个人理解 xff0c 谬误之处请指正 SDF Signed Distance Field 译为有向距离场 xff0c 有向 距离 场 这三个词非常精确的描述了 sdf 究竟是个什么东西 GPU Gems 3 中是这么描述 sdf
  • Ubuntu Windows双系统切换最简方法!!!

    安装完Ubuntu windows双系统后的第一个问题 xff1a 该怎么在两个系统间快速自由切换呢 xff1f 本文给出两种无需命令行的实用易上手方式 一 什么 xff0c 你要快快快快速切换 xff1f 这里直接给出答案 xff0c F
  • C++primer(第五版)习题答案

    前两章习题较简单 xff0c 这里就不作整理了 xff0c 直接从第三章开始 持续更新 xff1a Chapter 3 Strings Vectors and Arrays Exercise 3 1 part 1 include lt io
  • PX4源码地址和wiki

    源码 https github com 987419640 Firmware wiki https dev px4 io v1 9 0 zh concept architecture html
  • 视觉十四讲:第七讲_2D-2D:对极几何估计姿态

    1 对极几何 从2张图片中 得到若干个配对好的2d特征点 就可以运用对极几何来恢复出两帧之间的运动 设P的空间坐标为 P 61 X Y Z T 两个像素点 p 1 p 2 的像素坐标为 s 1 p 1 61 KP s 2 p 2 61 K
  • VINS_FUSION入门系列---GPS与VIO融合

    参考的博客 https blog csdn net subiluo article details 105429471 http www luyixian cn news show 313718 aspx state 状态量 位姿 速度 b
  • 几种常用加壳软件图文详解

    为了保护自己的软件不轻易被他人 借鉴 xff0c 有必要对软件进行一些加密保护 xff0c 而这方面目前己有成熟的专业加密软件可选择 但不要太依赖壳的保护 xff0c 大多数壳是可以被攻破的 xff0c 还是在自身保护上下些功夫 加密软件比
  • debian添加source源后update出现GPG错误

    错误如下 xff1a W GPG error http mirrors 163 com debian buster updates InRelease The following signatures couldn 39 t be veri
  • windows clang 编译Qt

    准备 xff1a qt everywhere src 5 15 0 zip jom 1 1 3 zip LLVM 10 0 0 win64 exe VS2019 xff1a 需要安装win10 SDK xff0c 也有自带的clang xf
  • docker 最新Dockerfile命令手册

    Dockerfile Reference Docker can build images automatically by reading the instructions from a Dockerfile A Dockerfile is
  • 单片机移植 - RTOS总结 -uC/OS-II ; FreeRTOS的区别

    RTOS总结 uC OS II FreeRTOS的区别 实时操作 xff08 RTOS xff09 系统有很多种 xff0c 分别为 Clinux C OS II eCos FreeRTOS mbed OS RTX Vxworks QNX
  • CentOs Stream脚本安装单机版Kubernetes并配置Calico和NFS

    随着Kubernetes和CentOs的不断升级 xff0c 在安装Kubernetes时 xff0c 网上其他的一些参考资料可能会遇到一些问题 本文以脚本方式列出了所有步骤 xff0c 这些步骤对于一台纯净的CentOs Stream服务
  • java基础必备丨阿里云kubernetes集群部署

    1 创建的前提 开通资源编排服务ROS 因为阿里云的k8s集群依赖于ROS的资源编排 xff0c 所以 xff0c 要先开通ROS才可以创建k8s集群开通弹性伸缩服务ESS开通访问控制服务RAM 2 创建说明 每个账号创建的云资源是由于配额
  • 从头开始写STM32F103C8T6驱动库(四)——编写延时函数,详解Systick

    系列文章目录 Github开源地址 从头开始写STM32F103C8T6驱动库 xff08 一 xff09 STM32CubeMX创建并调整工程结构 从头开始写STM32F103C8T6驱动库 xff08 二 xff09 编写系统初始化程序
  • 【ROS】在 Ubuntu 20.04 安装 ROS 的详细教程

    ROS安装指南 目录 ROS安装指南 前言 一 配置Linux清华镜像源1 1 介绍1 2 开始配置 二 安装ROS2 1 ROS的介绍2 1 开始安装 xff1a 配置公钥2 2 系统更新2 3 安装ROS 三 配置ROS3 1 初始化r

随机推荐

  • 京东业务增长10倍背后的敏捷开发秘籍【案例+分析】

    需求又要改 xff1f 项目上线时间又提前了 xff1f 老板还嫌增长不够 xff1f 团队都开始灰心丧气了 xff1f 来看看京东内部是如何解决这些让人焦头烂额的棘手问题 1 两次失败之后成功支持双11活动 京东每年两次大的的促销活动中都
  • 串口调试助手源程序

    目次 xff1a 1 建立项目 2 在项目中插入MSComm控件 3 利用ClassWizard定义CMSComm类控制变量 4 在对话框中添加控件 5 添加串口事件消息处理函数OnComm 6 打开和设置串口参数 7 发送数据 8 发送十
  • 【统计计算之非均匀分布随机数的生成】

    在学习统计计算这门课中 xff0c 学习到了非常多的算法 xff0c 个人觉得非常有趣 xff0c 希望可以和大家总结分享一下 持续更新中 我们用的课本 xff1a 统计计算 李东风 非均匀分布随机数 1 变换法 变换法主要分为两种 xff
  • Ubuntu 18.04在 VMware中启动时一直停留在Starting Update UTMP about System Runlevel Changes

    环境 Ubuntu 18 04 安装在VMware中 问题 启动时一直停留在Starting Update UTMP about System Runlevel Changes 解决思路 由于本人的虚拟机磁盘空间所剩无几 xff0c 怀疑是
  • linux零碎知识点

    源码包安装的 Apache 默认伪用户 xff1a daemonTCP IP是一个工业标准而非国际标准TCP IP可以用于同一主机上不同进程之间的通信Linux 由 Kernel Shelll 应用程序 组成网络协议三要素 xff1a 语义
  • 算法小知识

    一个数如果恰好等于它的因子之和 xff0c 这个数就称为 完数 例如6 61 1 xff0b 2 xff0b 3 xff0c 再如8的因子和是7 xff08 即1 43 2 43 4 xff09 xff0c 8不是完数回文数是指正序 xff
  • 启动 tomcat ,一直停在com.alibaba.druid.pool.DruidDataSource:init

    启动 tomcat 一直停在com alibaba druid pool DruidDataSource init clean一下就可以了
  • Win10 触摸屏 快捷键操作

    Win10 触摸板 快捷键操作 在 Windows 10 笔记本电脑的触摸板上试用这些手势 xff1a 快捷键 选择项目 xff1a 点击触摸板右键单击效果 xff1a 两根手指点击一次应用滚动 xff1a 将两个手指放在触摸板上 xff0
  • JCE cannot authenticate the provider BC

    JCE cannot authenticate the provider BC 解决办法 xff1a 修改 JAVA HOME jre lib security java security 文件 添加如下内容 security provid
  • Docker命令之:load命令

    作用 xff1a Load span class hljs operator an span image span class hljs built in from span span class hljs operator a span
  • Docker命令之: tag命令

    作用 xff1a span class hljs operator span class hljs keyword Create span a tag TARGET IMAGE that refers span class hljs key
  • installshield中增加BDE组件

    在C Program Files Common Files Borland Shared BDE下面有一个bdeinst cab xff0c 把它解压开后有一个bdeinst dll xff0c 把他打包到你的安装程序 xff0c 然后选择
  • intellij idea 合并分支到主分支,主分支代码同步到某一分支

    将gith或者Gitee上的项目clone到本地 git span class hljs keyword clone span https span class hljs comment xxxx span 打开intellij idea
  • springboot项目 intellij idea 找不到或者无法加载主类

    试了很多种网上的方法 xff0c 例如清除缓存 xff0c 指定module path 重启等都没有起作用 最后发现是 project structure project settings project project compiler
  • Vivado综合running时间太长

    cancel后查看log日志 xff0c 出现警告warnning PID not specified xff0c 解决办法 xff1a 新建一个工程 xff0c 导入原工程源文件 xff0c 重新进行综合 xff0c 就可以了
  • 使用putty和ssh登录时进不去

    我的是win10系统 初步理解ssh是一个协议 xff0c putty是一个使用这个协议连接本地电脑和远程服务器的开源软件 我知道连接ssh有两种方式 xff1a 第一种 xff1a 电脑左下角搜索界面输入 terminal 打开命令行cm
  • 联想win10安全模式进入以及退出

    进入安全模式的办法 xff1a 1 按住shift再点击重启 疑难解答 可进入带命令提示符的安全模式 进去后仅命令行一个窗口 xff0c 关闭后会出现黑屏 xff0c 仅有一个光标 2 桌面运行win 43 r 勾选安全引导 可直接进入安全
  • Linux网络编程之tcpdump抓包分析TCP三次握手过程

    使用TCP协议进行网络通讯时 xff0c 通信的两端首先需要建立起一条连接链路 xff0c 当然这并不表示使用UDP通信不需要 连接链路 xff0c 这里说的连接链路指的是通信协议范畴的东东 xff0c 并不是物理介质或者电磁波信号 xff
  • inceptionv3迁移学习 训练+测试

    迁移学习在实际应用中的意义非常大 xff0c 它可以将之前已学过的知识 xff08 模型参数 xff09 迁移到一项新的任务上 xff0c 使学习效率大大的提高 我们知道 xff0c 要训练一个复杂的深度学习模型 xff0c 成本是十分巨大
  • 60分钟闪击速成PyTorch(Deep Learning with PyTorch: A 60 Minute Blitz)学习笔记

    诸神缄默不语 个人CSDN博文目录 本笔记是我学习 Deep Learning with PyTorch A 60 Minute Blitz 这一PyTorch官方教程后的学习笔记 该教程在官网上更新过 xff0c 因此未来还可能继续更新