pytorch 保存模型+加载模型+修改部分层+冻结部分层+删除部分层

2023-05-16

pytorch的一些细节操作

本文以普通的CNN为例

1. 实验用的模型

在这里插入图片描述
参考博客。

2. 模型代码

原始代码分成两个部分:
第一个是写CNN模型框架的py文件,cnn.py
第二个是主文件,用于下载数据和模型超参数等。work.py

cnn.py文件如下:

from torch import nn

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 25, kernel_size=3),
            nn.BatchNorm2d(25),
            nn.ReLU(inplace=True)
        )

        self.layer2 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        self.layer3 = nn.Sequential(
            nn.Conv2d(25, 50, kernel_size=3),
            nn.BatchNorm2d(50),
            nn.ReLU(inplace=True)
        )

        self.layer4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2)
        )

        self.fc = nn.Sequential(
            nn.Linear(50 * 5 * 5, 1024),
            nn.ReLU(inplace=True),
            nn.Linear(1024, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 10)
        )

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

work文件如下:

import torch
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms

import cnn

# 定义一些超参数
batch_size = 64
learning_rate = 0.02
num_epoches = 20

# 数据预处理。transforms.ToTensor()将图片转换成PyTorch中处理的对象Tensor,并且进行标准化(数据在0~1之间)
# transforms.Normalize()做归一化。它进行了减均值,再除以标准差。两个参数分别是均值和标准差
# transforms.Compose()函数则是将各种预处理的操作组合到了一起
data_tf = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize([0.5], [0.5])])

# 数据集的下载器
train_dataset = datasets.MNIST(
    root='./data', train=True, transform=data_tf, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 选择模型
model = cnn.CNN()
# model = net.Activation_Net(28 * 28, 300, 100, 10)
# model = net.Batch_Net(28 * 28, 300, 100, 10)
if torch.cuda.is_available():
    model = model.cuda()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate)

# 训练模型
epoch = 0
for data in train_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()
    else:
        img = Variable(img)
        label = Variable(label)
    out = model(img)
    loss = criterion(out, label)
    print_loss = loss.data.item()

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    epoch+=1
    if epoch%50 == 0:
        print('epoch: {}, loss: {:.4}'.format(epoch, loss.data.item()))

# 模型评估
model.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()

    out = model(img)
    loss = criterion(out, label)
    eval_loss += loss.data.item()*label.size(0)
    _, pred = torch.max(out, 1)
    num_correct = (pred == label).sum()
    eval_acc += num_correct.item()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(test_dataset)),
    eval_acc / (len(test_dataset))
))

这是初始代码,可以直接运行。

3. 保存模型和加载模型

保存文件有两种方式:
第一种是直接保存模型的所有文件。
第二种是保存模型的参数,这种方法是官方推荐的,因为不占内存。(推荐)

3.1 保存和加载整个模型

声明,我们的例子里面用到了一个词,就是model这个单词,其实这个名字是根据我们自己定义的模型的名字来的。比如我们上面work这个文件中有

# 选择模型
model = cnn.CNN()

这个model就是我们的模型的名字,我们可以随便定义这个名字
保存模型

torch.save(model, PATH)

例如在我们的这个例子里面:

torch.save(model,'CNN_all.pth')

加载模型

model = torch.load(PATH)
model.eval()

例子

model = torch.load('CNN_all.pth')

声明:后面的这个CNN_all.pth也是可以随意命名的

3.2 保存和加载模型的参数- state_dict

保存模型

#保存模型的参数
torch.save(model.state_dict(),'CNN_Origi.pth')

加载模型

model.load_state_dict(torch.load('CNN_Origi.pth'))

4. 增加部分层和删掉部分层

我们在加载模型的时候,一定要先加载模型结构,在加载参数。
在这里我们以官方推荐的方法为例,因为这样更容易调整模型的结构。

首先声明一下,我们在对模型进行微调的时候,很多同学想删除最后面的部分层,其实这并不是删除,只是我们需要重新写一个层,然后把后面的这个层替换掉。

举个例子,我们现在需要复现某个文章中的实验,
在这里插入图片描述
比如这个实验,GAP表示全局平局池化,shuffle表示把全局平均池化的每个1*1的feature map的顺序打乱。
我为了验证他们这个思想的正确性做了两组实验,第一种是直接把右边的PermuteNet直接写出来,然后训练。
第二种思想是先在上面的普通CNN上做预训练,然后替换掉最后的全连接层fc,然后在换成GAP和shuffle。

首先把我们的代码弄上来
这个是直接训练的代码,也就是右边那部分。其中的Shufflechnalles是我自己写的层,本来在pytorch中有nn.Shufflechnalle()这个函数 ,但是这个函数式刚加进来的,所以这个版本的pytorch有bug,没法对nn.Shufflechnalle()层求梯度。

cnn1.py


import torch
from torch import nn

class Shufflechnalles(nn.Module):
    '''打乱层的特征映射'''
    def __init__(self, **kwargs):
        super(Shufflechnalles, self).__init__(**kwargs)
    def forward(self, x, groups=2):
        bs, chnls, h, w = x.data.size()
        #if chnls % groups:
            #return x
        chnls_per_group = int(chnls / groups)
        x = x.view(bs, groups, chnls_per_group, h, w)
        x = torch.transpose(x, 1, 2).contiguous()
        x = x.view(bs, -1, h, w)
        return x
        

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        #输入图像1x28x28
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 25, kernel_size=3),
            nn.BatchNorm2d(25),
            nn.ReLU(inplace=True)
        )
        #输出:25x26x26
        self.layer2 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2)
        )
        #输出:25x13x13

        self.layer3 = nn.Sequential(
            nn.Conv2d(25, 50, kernel_size=3),
            nn.BatchNorm2d(50),
            nn.ReLU(inplace=True)
        )
        #输出:50x3x3

        self.layer4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2),
            Shufflechnalles(),
            nn.AdaptiveAvgPool2d((1,1))
        )
        #输出:50x5x5

        self.layer5 = nn.Sequential(
            #nn.AdaptiveAvgPool2d(10),
            nn.Linear(50 * 1 * 1,1024),
            nn.ReLU(inplace=True),
            nn.Linear(1024, 128),
            nn.ReLU(inplace=True),
            nn.Linear(128, 10)
        )


    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        #x = self.layer5(x)
        x = x.view(x.size(0), -1)
        #将第卷积的输出拉伸为一行,相当于tensorflow中的fleetn
        x = self.layer5(x)
        return x

大家直接在下面的work1.py里面做训练就可以了

import torch
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import cnn1
import torchvision
# 定义一些超参数
batch_size = 10
learning_rate = 0.01
num_epoches = 70

# 数据预处理。transforms.ToTensor()将图片转换成PyTorch中处理的对象Tensor,并且进行标准化(数据在0~1之间)
# transforms.Normalize()做归一化。它进行了减均值,再除以标准差。两个参数分别是均值和标准差
# transforms.Compose()函数则是将各种预处理的操作组合到了一起
data_tf = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize([0.5], [0.5])])

# 数据集的下载器
train_dataset = datasets.MNIST(
    root='./data', train=True, transform=data_tf, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

# 选择模型
model = cnn1.CNN()
# model = net.Activation_Net(28 * 28, 300, 100, 10)
# model = net.Batch_Net(28 * 28, 300, 100, 10)
if torch.cuda.is_available():
    model = model.cuda()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=learning_rate)

# 训练模型
epoch = 0
for data in train_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()
    else:
        img = Variable(img)
        label = Variable(label)
    out = model(img)
    loss = criterion(out, label)
    print_loss = loss.data.item()

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    epoch+=1
    if epoch%50 == 0:
        print('epoch: {}, loss: {:.4}'.format(epoch, loss.data.item()))

#保存模型的参数
torch.save(model.state_dict(),'CNN_Origi.pth')
torch.save(model,'CNN_all.pth')

# 模型评估
model.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()

    out = model(img)
    loss = criterion(out, label)
    eval_loss += loss.data.item()*label.size(0)
    _, pred = torch.max(out, 1)
    num_correct = (pred == label).sum()
    eval_acc += num_correct.item()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(test_dataset)),
    eval_acc / (len(test_dataset))
))

4.1 修改部分层

现在我们想在前面提到的cnn.py训练好的模型上做改动,也就是冻结layer4之前的层,然后增加GAP和shuffle两个部分。
同时删除最后的fc层。

我们首先上代码

from collections import OrderedDict
import torch
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
import CNN_shu
import torchvision


#自定义的特征维度洗牌层
class Shufflechnalles(nn.Module):
    '''打乱层的特征映射'''
    def __init__(self, **kwargs):
        super(Shufflechnalles, self).__init__(**kwargs)
    def forward(self, x, groups=2):
        bs, chnls, h, w = x.data.size()
        #if chnls % groups:
            #return x
        chnls_per_group = int(chnls / groups)
        x = x.view(bs, groups, chnls_per_group, h, w)
        x = torch.transpose(x, 1, 2).contiguous()
        x = x.view(bs, -1, h, w)
        return x

# 定义一些超参数
batch_size = 10
learning_rate = 0.01
num_epoches = 70

# 数据预处理。transforms.ToTensor()将图片转换成PyTorch中处理的对象Tensor,并且进行标准化(数据在0~1之间)
# transforms.Normalize()做归一化。它进行了减均值,再除以标准差。两个参数分别是均值和标准差
# transforms.Compose()函数则是将各种预处理的操作组合到了一起
data_tf = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize([0.5], [0.5])])

# 数据集的下载器
train_dataset = datasets.MNIST(
    root='./data', train=True, transform=data_tf, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

#下载模型
CNN_shuffmodel = cnn.CNN()
#下载模型参数
CNN_shuffmodel.load_state_dict(torch.load('CNN_Origi.pth'))
#修改模型结构
#在第四层增加一个shuffle层和一个全局平局池化
CNN_shuffmodel.layer4.add_module('add_shuffle',Shufflechnalles())
CNN_shuffmodel.layer4.add_module('add_AGP',nn.AdaptiveAvgPool2d((1,1)))
#替换最后一个层

# 写一个需要添加的层
classifier = nn.Sequential(OrderedDict([('fc1', nn.Linear(50 * 1 * 1, 10))]))
#替换
CNN_shuffmodel.fc = classifier
print(CNN_shuffmodel)

if torch.cuda.is_available():
    CNN_shuffmodel = CNN_shuffmodel.cuda()

# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(CNN_shuffmodel.parameters(), lr=learning_rate)

# 训练模型
epoch = 0
for data in train_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()
    else:
        img = Variable(img)
        label = Variable(label)
    out = CNN_shuffmodel(img)
    loss = criterion(out, label)
    print_loss = loss.data.item()

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    epoch+=1
    if epoch%50 == 0:
        print('epoch: {}, loss: {:.4}'.format(epoch, loss.data.item()))

#保存模型的参数
#torch.save(CNN_shuffmodel.state_dict(),'CNN_train_shuff.pth')

# 模型评估
CNN_shuffmodel.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()

    out = CNN_shuffmodel(img)
    loss = criterion(out, label)
    eval_loss += loss.data.item()*label.size(0)
    _, pred = torch.max(out, 1)
    num_correct = (pred == label).sum()
    eval_acc += num_correct.item()
print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(test_dataset)),
    eval_acc / (len(test_dataset))
))

我们首先看一下原始CNN的结构
![在这里插入图片描述](https://img-blog.csdnimg.cn/e1a19c75acd34c2cb2173dbf57e4d0f7.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA6ZSu55uY6L6555qE54Of54Gw,size_17,color_FFFFFF,t_70,g_se,x_16

看一下核心修改部分

#下载模型
CNN_shuffmodel = cnn.CNN()
#下载模型参数
CNN_shuffmodel.load_state_dict(torch.load('CNN_Origi.pth'))
#修改模型结构
#在第四层增加一个shuffle层和一个全局平局池化
CNN_shuffmodel.layer4.add_module('add_shuffle',Shufflechnalles())
CNN_shuffmodel.layer4.add_module('add_AGP',nn.AdaptiveAvgPool2d((1,1)))
#替换最后一个层

# 写一个需要添加的层
classifier = nn.Sequential(OrderedDict([('fc1', nn.Linear(50 * 1 * 1, 10))]))
#替换
CNN_shuffmodel.fc = classifier
print(CNN_shuffmodel)

首先,第一个就是关于下载模型的,我们可以用load的方式下载模型,也可以自己把这个模型的结构文件下载下来直接通过import的方式调用。
然后是加载模型参数
加载模型参数这一块我需要提一下,我以前以为加载模型参数是在修改好模型结构之后再加载的。然后我发现一直报错。后来我把加载模型参数调整到修改模型参数之前,然后就没有报错,正常训练了。
原始的CNN结构
在这里插入图片描述

再看看修改好的模型机构
在这里插入图片描述

5. 关于添加模型层

对比上面两个模型结构图
我们看layer4这个
原始的layer4只有一个maxpooling层。然后后面就接一些全连接层和softmax分类。
我们在想把gap和shuffle天加到llayer4,然后把fc层替换成一个线性分类层。
首先是添加,分为在模型内添加和在模型后面添加,这个部分可以参考这个教学视屏。从第15分钟以后开始看,就知道到如何添加模型了。

这个是在模型的layer4中添加模块,你看我门指定了layer4这个层

#在第四层增加一个shuffle层和一个全局平局池化
CNN_shuffmodel.layer4.add_module('add_shuffle',Shufflechnalles())
CNN_shuffmodel.layer4.add_module('add_AGP',nn.AdaptiveAvgPool2d((1,1)))

我们可以直接在模型最后添加一个新的层
#在最后一层层增加一个shuffle层和一个全局平局池化

CNN_shuffmodeladd_module('add_shuffle',Shufflechnalles())
CNN_shuffmodel.add_module('add_AGP',nn.AdaptiveAvgPool2d((1,1)))

直接这样就行了。

6. 关于替换部分层

#替换最后一个层
# 写一个需要替换的层,替换后的新层交fc1
classifier = nn.Sequential(OrderedDict([('fc1', nn.Linear(50 * 1 * 1, 10))]))
#然后替换一下就可以了
CNN_shuffmodel.fc = classifier

7. 关于删除部分层

其实删除模型层就是替换模型部分层,我们只需要写一个空层替换局可以了,
如下:

#删除最后一个层,或者说删除任意一个层
# 写一个空的层
classifier = nn.Sequential()
#然后替换一下就可以了
CNN_shuffmodel.fc = classifier

删除层就是这么简单。

8. 关于冻结部分层

我们现在只想训练最后的fc1层,然后就有了下面的

#3.冻结部分层
#将满足条件的参数的 requires_grad 属性设置为False
for name, value in model_conv.named_parameters():
    if (name != 'fc.weight') and (name != 'fc.bias'):
        value.requires_grad = True
#修改优化器
optimizer = optim.Adam(filter(lambda p: p.requires_grad, CNN_shuffmodel.parameters()), lr=learning_rate)     

从上面看,我们指定只训练 最后一层的权值和偏置
所以代码的意思是,如果名字不是fc.weight和fc.bias就不训练。

filter() 函数用于过滤序列,过滤掉不符合条件的元素,返回一个迭代器对象,如果要转换为列表,可以使用 list() 来转换。

该接收两个参数,第一个为函数,第二个为序列,序列的每个元素作为参数传递给函数进行判,然后返回 True 或 False,最后将返回 True 的元素放到新列表中。

filter()函数将requires_grad = True的参数传入优化器进行反向传播,requires_grad = False的则被过滤掉。

说实话,上面这种方法我用的时候报错了,至今还没解决,于是我想出来了一个新的方法
也就是追层修改

for para in CNN_shuffmodel.layer1.parameters():
    para.requires_grad = False
for para in CNN_shuffmodel.layer2.parameters():
    para.requires_grad = False
for para in CNN_shuffmodel.layer3.parameters():
    para.requires_grad = False
for para in CNN_shuffmodel.layer4.parameters():
    para.requires_grad = False   
#最后还是需要调整优化器
optimizer = optim.Adam(filter(lambda p: p.requires_grad, CNN_shuffmodel.parameters()), lr=learning_rate)  
    

这个方法在我的实验中没有报错

9. 关于add_module()模块的用法

这个模块算法pytorch的一个比较进阶的用法了,用法是主要是调用backbone时候会用到。
add_module()可以快速地替换特定结构可以不用修改过多的代码。
add_module的功能为Module添加一个子module,对应名字为name。使用方式如下:

add_module(name, module)

其中name为子模块的名字,使用这个名字可以访问特定的子module。module为我们自定义的子module。

一般情况下子module都是在A.init(self)中定义的,比如A中一个卷积子模块self.conv1 = torch.nn.Conv2d(…)。此时,这个卷积模块在A的名字其实是’conv1’。

对比之下,add_module()函数就可以在A.init(self)以外定义A的子模块。如定义同样的卷积子模块,可以通过A.add_module(‘conv1’, torch.nn.Conv2d(…))。
例如:

9.1 一般用法

import torch

class Net3(torch.nn.Module):
  def __init__(self):
    super(Net3, self).__init__()
    self.conv=torch.nn.Sequential()
    self.conv.add_module("conv1",torch.nn.Conv2d(3, 32, 3, 1, 1))
    self.conv.add_module("relu1",torch.nn.ReLU())
    self.conv.add_module("pool1",torch.nn.MaxPool2d(2))
    self.dense = torch.nn.Sequential()
    self.dense.add_module("dense1",torch.nn.Linear(32 * 3 * 3, 128))
    self.dense.add_module("relu2",torch.nn.ReLU())
    self.dense.add_module("dense2",torch.nn.Linear(128, 10))
 
  def forward(self, x):
    conv_out = self.conv1(x)
    res = conv_out.view(conv_out.size(0), -1)
    out = self.dense(res)
    return out
 
model3 = Net3()
print(model3)

输出结果

Net3(
  (conv): Sequential(
    (conv1): Conv2d(3, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (relu1): ReLU()
    (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (dense): Sequential(
    (dense1): Linear(in_features=288, out_features=128, bias=True)
    (relu2): ReLU()
    (dense2): Linear(in_features=128, out_features=10, bias=True)
  )
)

9.2 更高级的用法

class Policy(nn.Module):
    def __init__(self, input_size, output_size, hidden_sizes=(),nonlinearity=F.relu, init_std=0.1, min_std=1e-6):

        super(Policy, self).__init__()
        self.input_size = input_size
        self.output_size = output_size
        self.hidden_sizes = hidden_sizes
        self.nonlinearity = nonlinearity
        self.min_log_std = math.log(min_std)
        self.num_layers = len(hidden_sizes) + 1

        self.is_disc_action = False

        layer_sizes = (input_size,) + hidden_sizes
        for i in range(1, self.num_layers):
            self.add_module('layer{0}'.format(i),
                            nn.Linear(layer_sizes[i - 1], layer_sizes[i]))
        self.mu = nn.Linear(layer_sizes[-1], output_size)

        self.sigma = nn.Parameter(torch.Tensor(output_size))
        self.sigma.data.fill_(math.log(init_std))
        self.apply(_weight_init)

    def forward(self, input, params=None):
        if params is None:
            params = OrderedDict(self.named_parameters())
        output = input
        for i in range(1, self.num_layers):
            output = F.linear(output,
                              weight=params['layer{0}.weight'.format(i)],
                              bias=params['layer{0}.bias'.format(i)])
            output = self.nonlinearity(output)
        mu = F.linear(output, weight=params['mu.weight'],
                      bias=params['mu.bias'])
        scale = torch.exp(torch.clamp(params['sigma'], min=self.min_log_std))
        #print(mu.data, scale.data)

        return Normal(loc=mu, scale=scale)

主要是自动命名每一层的名字

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

pytorch 保存模型+加载模型+修改部分层+冻结部分层+删除部分层 的相关文章

  • 机器学习中神经网络,支持向量机以及贝叶斯分类器总结

    第五章神经网络 5 1神经元模型 神经网络中最基本的成分是神经元模型 xff0c 即 简单单元 在 M P神经元模型 中 xff0c 神经元接受收到来自n个其他神经元传递过来的输入信号 xff0c 这些输入信号经过带权重的连接进行传递 xf
  • 机器学习中的降维与度量学习(reduce dimension and metric learning)

    降维与度量学习 k近邻学习 k近邻 k Nearest Neighbor 简称kNN 学习是一种监督学习方法 其工作机制为 xff1a 在样本中 xff0c 根据距离度量找出训练集中临近的k个样本 xff0c 基于这k个样本进行预测 一般
  • Warning: Invalid argument “/map“ passed to canTransform argument target_frame in tf2 frame_ids···

    Warning Invalid argument map passed to canTransform argument target frame in tf2 frame ids cannot start with a like at l
  • CAN为什么会发送失败

    CAN总线调试过程中出现报文发送失败 xff0c 很多工程师都对此只知其一不知其二 xff0c 这里就CAN报文发送失败的问题我们来做一次探讨 在了解CAN报文为什么会发送失败之前我们先看看一条正确的CAN报文到底应该是怎么样的 xff0c
  • git分支和tag

    分支管理 查看当前分支 git branch创建分支 git branch git branch index one切换分支 git checkout lt 分支名称 xff0c 主分支是master gt git checkout ind
  • TT无人机扩展模块库分析(default.ino)补篇2

    这个简单 请对照 因为源码在这里出现了和手柄相关的源码 设置tof传感器的超时时间 xff08 500 xff09 什么单位 xff1f 没有搜索到 xff0c 我用SI了 搜索到了 有很多函数 定位位置 在这里 找到了 xff0c 为什么
  • TCP建立连接的过程

    TCP是面向连接的 可靠的 基于字节流的传输层协议 xff0c 是TCP IP协议中最重要的协议之一了 我们都知道TCP通过三次握手建立连接 xff0c 那么每一次握手的作用 为什么要三次握手 如果某次握手丢包会发生什么呢 xff1f 文章
  • CANanlystII 基于linux的二次开发实践

    1 USBCAN分析仪国内现状 这是目前国内市场上的USBCAN分析仪现状 2 创芯科技产品 创芯科技的这个红色盒子是我比较下来综合性价比最高的 同时支持windows和linux的设备只要320元左右 你既可以用可视化界面发送 接收报文
  • AXI DMA总结、内核axidmatest.c测试程序分析、SG mode

    AXI DMA 概述 xff1a XILINX提供的AXI DMA支持Scatter Gather mode和Direct Register mode 数据位宽支持32 64 128 256 512 1024bits xff0c strea
  • ZYNQ 平台 AD9361实现网络通信的一种方案+网卡驱动分析及实现

    声明 xff1a 文中若有不合理的地方 xff0c 欢迎讨论学习及指正 xff0c 本文仅仅涉及软件部分的代码 xff0c 不阐述逻辑代码的实现 功能 xff1a 通过AD9361芯片实现无线组网 xff0c 能实现视频 文件 音频等传输
  • MTD分析

    概述 xff1a 本文对mtd的整个结构进行了分析 xff0c 分析得并非很深入 xff0c 但可以了解大体框架和目录结构 xff0c 另外本文会对源码文件进行分析 xff0c 大致描述其作用 xff0c 针对本文的内容中 xff0c 如有
  • CAN总线详解(转)

    1 简介 CAN是控制器局域网络 Controller Area Network CAN 的简称 xff0c 是一种能够实现分布式实时控制的串行通信网络 优点 xff1a 传输速度最高到1Mbps xff0c 通信距离最远到10km xff
  • Linux Socket CAN——驱动开发(转)

    Linux Socket CAN驱动开发 一 CAN总线协议 CAN是Controller Area Network 控制器局域网 的缩写 CAN通信协议在1986年由德国电气商博世公司所开发 xff0c 主要面向汽车的通信系统 现已是IS
  • Joint state with name: “base_l_wheel_joint” was received but not found in URDF

    ROS melodic下运行出现 WARN xff1a Joint state with name base l wheel joint was received but not found in URDF 原因是在robot描述文件URD
  • 已解决 vmware 虚拟机安装后没有虚拟网卡问题

    我用的方法是重装vmware xff0c 使用的是win10的系统 之前安装网ubuntu以后 xff0c 发现主机并没有虚拟网卡 xff0c 也百度了各种方法 xff0c 然而并没有什么用 xff0c 也问了很多人 xff0c 他们也提供
  • rk3399下pwm驱动

    现在记录一下rk3399下pwm的驱动编写 xff0c 下面是内核pwm的API xff0c 从开源论坛复制 xff08 firefly的开源论坛里面的Wiki教程 xff09 1 在要使用 PWM 控制的设备驱动文件中包含以下头文件 xf
  • rk3399下spi驱动

    SPI 使用 Note xff1a 本文从firefly wiki截取 SPI是一种高速的 xff0c 全双工 xff0c 同步串行通信接口 xff0c 用于连接微控制器 传感器 存储设备等 Firefly RK3399 开发板提供了 SP
  • rk3399 u-boot修改开机logo以及开机动画和开机视频

    首先分析了一下uboot启动流程中的一部分代码 xff0c 如下 第一部分 xff1a 开机logo xff08 下面代码分析排版有点乱 xff0c 可以忽略 xff09 1 board late init rk33xx c board r
  • VMware 虚拟网卡防火墙问题

    看了很多人遇到过一段时间会自己删除虚拟网卡的问题 xff0c 这里做一个补充 xff0c 关于防火墙问题 xff0c 如下 这里点进去 点击更改设置 xff08 先找到下图这一项 xff09 最后记得保存更改 xff0c 关于VMware的
  • postman汉化包下载

    postman汉化包 https github com hlmd Postman cn releases postman官网下载地址 Download Postman Get Started for Free

随机推荐

  • 一帧数据接收方法

    最近在做485数据通讯 xff0c 遇到一些通讯问题 xff0c 特意去查找资料 xff0c 一帧数据接收有三种方法 xff0c 现分享如下 xff1a 第一种方法 xff1a 根据帧头和帧尾进行校验 xff0c 串口发送2字节例如 xff
  • 如何使用RTKLIB进行RTK定位(一)

    今天从这个demo xff0c 教给大家如何使用RTKLIB进行RTK定位 xff0c 包括配置文件 数据等 xff1b RTKLIB源码和exe下载地址 xff1a RTKLIB An Open Source Program Packag
  • C++ “::” 作用域符 双冒号

    一 是作用域符 xff0c 是运算符中等级最高的 xff0c 它分为三种 1 global scope 全局作用域符 xff09 xff0c 用法 xff08 name 2 class scope 类作用域符 xff09 xff0c 用法
  • OpenMv测距(Apriltag)

    利用OpenMv测离Apriltag的距离 xff08 其他色块啥的算法都差不多 xff0c 主要是Apriltag精确一些 xff09 span class token comment 本次利用OpenMv单目测距Apriltag离摄像头
  • CMake Error at /usr/lib/x86_64-linux-gnu/cmake/Qt5Core/Qt5CoreConfig.cmake:27 (message)

    CMake Error at usr lib x86 64 linux gnu cmake Qt5Core Qt5CoreConfig cmake 27 message 在catkin make的时候 xff0c 如果提示 so文件报错 x
  • Deep-Sort多目标追踪算法代码解析

    Deep SORT是多目标跟踪 Multi Object Tracking 中常用到的一种算法 xff0c 是一个Detection Based Tracking的方法 这个算法工业界关注度非常高 xff0c 在知乎上有很多文章都是使用了D
  • 红黑树的查找时间复杂度O(logn)

    红黑树查找时间复杂度 如果二叉排序树是平衡的 xff0c 则n个节点的二叉排序树的高度为Log2n 43 1 其查找效率为O Log2n xff0c 近似于折半查找 如果二叉排序树完全不平衡 xff0c 则其深度可达到n xff0c 查找效
  • Ubuntu16.04环境下STM32和ROS间的串口通信

    目录 前言介绍 lt 1 gt 最终协议的样子 lt 2 gt 本方案提供的API实现的功能 原理 lt 1 gt 简要叙述 lt 2 gt 这里是如何使用共用体的 xff1f 前期准备 lt 1 gt 确保硬件连接 lt 2 gt 查看串
  • C++版本OpenCv教程(三十五 )Laplacian算子

    上述的边缘检测算子都具有方向性 xff0c 因此需要分别求取X方向的边缘和Y方向的边缘 xff0c 之后将两个方向的边缘综合得到图像的整体边缘 Laplacian算子具有各方向同性的特点 xff0c 能够对任意方向的边缘进行提取 xff0c
  • 【从零开始学深度学习编译器】五,TVM Relay以及Pass简介

    TVM Relay以及Pass简介 0x0 介绍0x2 Relay介绍0x2 1 使用Relay建立一个计算图0x2 2 Module xff1a 支持多个函数 xff08 Graphs xff09 0x2 3 Let Binding an
  • 模型量化的原理与实践 —基于YOLOv5实践目标检测的PTQ与QAT量化

    这里写自定义目录标题 一 量化基础知识 1 1 Tops是什么意思 1 2 什么是定点数 1 3 定点数转换 1 4 什么是量化 1 5 定点计算 1 5 1 定点计算 误差计算 1 5 2 定点计算 内存对比 1 5 3 定点计算 速度对
  • TensorRT INT8量化说明文档

    TensorRT developer guide intro quantization 7 Working with INT8 7 1 Introduction to Quantization 7 1 1 Quantization Work
  • YOLO-NAS讲解

    Meet YOLO NAS New YOLO Object Detection Model Beats YOLOv6 amp YOLOv8 代码链接 What is YOLO NAS What does the NAS in YOLO NA
  • Windows下jupyter notebook的安装和使用

    1 安装 xff1a xff08 1 xff09 首先打开Windows命令终端 xff1a 输入命令 xff1a pip install jupyter notebook 慢慢等待安装完成就可以了 我的是已经是安装完成了 在命令行窗口中输
  • 无人驾驶模型预测控制carSIM和MATLAB联合仿真

    本例参照龚建伟的 无人驾驶车辆模型预测控制 书中第四章节 1 carSIM软件介绍 carSIM是由美国MSC公司开发的车辆动力学仿真软件 xff0c 它可以方便灵活地定义实验环境和试验过程 xff0c 准确预测和仿真汽车的操纵稳定性 动力
  • Ubuntu之间通过有线网sftp传输文件

    两台Ubuntu设备之间有线网直连 xff0c 通过sftp传输文件 xff1a 打开有线连接 xff0c 配置ipv4 xff0c 可参考下图 xff1a 两台Ubuntu设备使用同一个网关 xff0c 但是地址ip必须不同 xff0c
  • 虚拟机VMware15中安装Ubuntu18.04步骤

    先安装虚拟机VMware15 xff1a 下载地址 xff1a Windows 10 64位下载链接 xff1a pan baidu com s 1Q9MVsEzVVoeOb99lQ1tsVQ 提取码 xff1a dggh Windows
  • 机械手基础知识(2)之机械手的正运动学和逆运动学问题

    开篇总结 xff1a 机械手运动学是机器人控制中的重要研究内容 xff0c 得知机械手各关节变量的大小 xff0c 可以计算出机械手末端的位姿 xff0c 这个过程叫做机械手的正向运动学 xff1b 获得机械手末端在笛卡尔空间中的位姿 xf
  • 一看就懂的LSTM+Attention,此处用softmax求概率

    1 序言 首先 xff0c 我是看这两篇文章的 但是 xff0c 他们一个写的很笼统 xff0c 一个是根据Encoder Decoder和Query key value 第二个讲的太深奥了 xff0c 绕来绕去 xff0c 看了两天才知道
  • pytorch 保存模型+加载模型+修改部分层+冻结部分层+删除部分层

    pytorch的一些细节操作 本文以普通的CNN为例 1 实验用的模型 参考博客 2 模型代码 原始代码分成两个部分 xff1a 第一个是写CNN模型框架的py文件 xff0c cnn py 第二个是主文件 xff0c 用于下载数据和模型超