首页 > 其他分享 >十五、PyTorch常用工具模块

十五、PyTorch常用工具模块

时间:2024-10-30 11:12:09浏览次数:1  
标签:__ img 常用工具 self batch dataset PyTorch 模块 data

  在训练神经网络过程中,需要用到很多工具,其中最重要的三部分是:数据、可视化和GPU加速。本章主要介绍Pytorch在这几方面的工具模块,合理使用这些工具能够极大地提高编码效率。

1.1 数据处理

  在解决深度学习问题的过程中,往往需要花费大量的精力去处理数据,包括图像、文本、语音或其它二进制数据等。数据的处理对训练神经网络来说十分重要,良好的数据处理不仅会加速模型训练,更会提高模型效果。考虑到这点,PyTorch提供了几个高效便捷的工具,以便使用者进行数据处理或增强等操作,同时可通过并行化加速数据加载。

1.1.1 数据加载

  在PyTorch中,数据加载可通过自定义的数据集对象。数据集对象被抽象为Dataset类,实现自定义的数据集需要继承Dataset,并实现两个Python方法:

  • __getitem__:返回一条数据,或一个样本。obj[index]等价于obj.__getitem__(index)
  • __len__:返回样本的数量。len(obj)等价于obj.__len__()

  这里我们以Kaggle经典挑战赛"Dogs vs. Cat"的数据为例,来详细讲解如何处理数据。"Dogs vs. Cats"是一个分类问题,判断一张图片是狗还是猫,其所有图片都存放在一个文件夹下,根据文件名的前缀判断是狗还是猫。

# 这条命令用于关闭终端输出中的颜色显示,使输出变成无色的纯文本显示。
%env LS_COLORS = None 
# 以无颜色的方式查看 data/dogcat/ 目录的结构,会以 ASCII 字符显示,不会出现颜色
!tree --charset ascii  data/dogcat/

# 结果
env: LS_COLORS=None
data/dogcat/
|-- cat.12484.jpg
|-- cat.12485.jpg
|-- cat.12486.jpg
|-- cat.12487.jpg
|-- dog.12496.jpg
|-- dog.12497.jpg
|-- dog.12498.jpg
`-- dog.12499.jpg

0 directories, 8 files
import torch as t
from torch.utils import data
import os
from PIL import Image
import numpy as np

class DogCat(data.Dataset):
    def __init__(self, root):
        imgs  = os.listdir(root)
        # 这里不实际加载图片,只是指定路径,当调用__getitem__时才会真正读图片
        # 将文件夹路径 root 和每一个文件名 img 连接起来,生成文件的完整路径。
        self.imgs = [os.path.join(root, img) for img in imgs]

    def __getitem__(self, index):
        img_path = self.imgs[index]
        # 将路径按斜杠 '/' 分割成各个部分,生成一个列表。取列表的最后一个元素,即文件名部分。
        # 判断文件名中是否包含 'dog',若包含则标签 label 设为 1(表示狗),否则为0(猫)
        label = 1 if 'dog' in img_path.split('/')[-1] else 0
        # 使用 PIL 库打开图片文件,将其加载为 PIL Image 对象
        pil_img = Image.open(img_path)
        # 将 PIL Image 对象转换为 numpy 数组
        array = np.asarray(pil_img)
        # 将 numpy 数组转换为 PyTorch 张量
        data = t.from_numpy(array)
        return data, label

    def __len__(self):
        return len(self.imgs)

dataset = DogCat('./data/dogcat')
# 使用 __getitem__ 方法获取数据集中的第一张图片及其标签
img, label = dataset[0] # 相当于调用dataset.__grtitem__(0)
for img, label in dataset:
    print(img.size(), img.float().mean(), label)

# 结果
torch.Size([375, 499, 3]) tensor(116.8187) 1
torch.Size([499, 379, 3]) tensor(171.8088) 0
torch.Size([236, 289, 3]) tensor(130.3022) 0
torch.Size([377, 499, 3]) tensor(151.7141) 1
torch.Size([374, 499, 3]) tensor(115.5157) 0

  通过上面的代码,我们学习了如何自定义自己的数据集,并可以依次获取。但这里返回的数据不适合实际使用,因其具有如下两方面问题:

  • 返回样本的形状不一,因每张图片的大小不一样,这对于需要取batch训练的神经网络来说很不友好
  • 返回样本的数值较大,未归一化至[-1, 1]

  针对上述问题,PyTorch提供了torchvision。它是一个视觉工具包,提供了很多视觉图像处理的工具,其中transforms模块提供了对PIL Image对象和Tensor对象的常用操作。

对PIL Image的操作包括:

  • Scale:调整图片尺寸,长宽比保持不变
  • CenterCropRandomCropRandomResizedCrop: 裁剪图片
  • Pad:填充
  • ToTensor:将PIL Image对象转成Tensor,会自动将[0, 255]归一化至[0, 1]

对Tensor的操作包括:

  • Normalize:标准化,即减均值,除以标准差
  • ToPILImage:将Tensor转为PIL Image对象

  如果要对图片进行多个操作,可通过Compose函数将这些操作拼接起来,类似于nn.Sequential。注意,这些操作定义后是以函数的形式存在,真正使用时需调用它的__call__方法,这点类似于nn.Module。例如要将图片调整为224×224,首先应构建这个操作trans = Resize((224, 224)),然后调用trans(img)。下面我们就用transforms的这些操作来优化上面实现的dataset。

import os
from PIL import  Image
import numpy as np
from torchvision import transforms as T

transform = T.Compose([
    T.Resize(224), # 缩放图片(Image),保持长宽比不变,最短边为224像素
    T.CenterCrop(224), # 从图片中间切出224*224的图片
    T.ToTensor(), # 将图片(Image)转成Tensor,归一化至[0, 1]
    T.Normalize(mean=[.5, .5, .5], std=[.5, .5, .5]) # 标准化至[-1, 1],规定均值和标准差
])

class DogCat(data.Dataset):
    def __init__(self, root, transforms=None):
        imgs = os.listdir(root)
        self.imgs = [os.path.join(root, img) for img in imgs]
        self.transforms=transforms
        
    def __getitem__(self, index):
        img_path = self.imgs[index]
        label = 0 if 'dog' in img_path.split('/')[-1] else 1
        data = Image.open(img_path)
        if self.transforms:
            data = self.transforms(data)
        return data, label
    
    def __len__(self):
        return len(self.imgs)

dataset = DogCat('./data/dogcat/', transforms=transform)
img, label = dataset[0]
for img, label in dataset:
    print(img.size(), label)

   除了上述操作之外,transforms还可通过Lambda封装自定义的转换策略。例如想对PIL Image进行随机旋转,则可写成这样trans=T.Lambda(lambda img: img.rotate(random()*360))

  torchvision已经预先实现了常用的Dataset,包括前面使用过的CIFAR-10,以及ImageNet、COCO、MNIST、LSUN等数据集,可通过诸如torchvision.datasets.CIFAR10来调用。在这里介绍一个会经常使用到的Dataset——ImageFolder,它的实现和上述的DogCat很相似。ImageFolder假设所有的文件按文件夹保存,每个文件夹下存储同一个类别的图片,文件夹名为类名,其构造函数如下:

ImageFolder(root, transform=None, target_transform=None, loader=default_loader)

它主要有四个参数:

  • root:在root指定的路径下寻找图片
  • transform:对PIL Image进行的转换操作,transform的输入是使用loader读取图片的返回对象
  • target_transform:对label的转换
  • loader:给定路径后如何读取图片,默认读取为RGB格式的PIL Image对象

  label是按照文件夹名顺序排序后存成字典,即{类名:类序号(从0开始)},一般来说最好直接将文件夹命名为从0开始的数字,这样会和ImageFolder实际的label一致,如果不是这种命名规范,建议看看self.class_to_idx属性以了解label和文件夹名的映射关系。

!tree --charset ASCII  data/dogcat_2/
data/dogcat_2/
|-- cat
|   |-- cat.12484.jpg
|   |-- cat.12485.jpg
|   |-- cat.12486.jpg
|   `-- cat.12487.jpg
`-- dog
    |-- dog.12496.jpg
    |-- dog.12497.jpg
    |-- dog.12498.jpg
    `-- dog.12499.jpg

2 directories, 8 files

from torchvision.datasets import ImageFolder
dataset = ImageFolder('data/dogcat_2/')
# cat文件夹的图片对应label 0,dog对应1
dataset.class_to_idx
# {'cat': 0, 'dog': 1}
# 所有图片的路径和对应的label
dataset.imgs

[('data/dogcat_2/cat/cat.12484.jpg', 0),
 ('data/dogcat_2/cat/cat.12485.jpg', 0),
 ('data/dogcat_2/dog/dog.12498.jpg', 1),
 ('data/dogcat_2/dog/dog.12499.jpg', 1)]

# 没有任何的transform,所以返回的还是PIL Image对象
dataset[0][1] # 第一维是第几张图,第二维为1返回label
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('data/dogcat_2/', transform=transform)
# 深度学习中图片数据一般保存成CxHxW,即通道数x图片高x图片宽
dataset[0][0].size()
# torch.Size([3, 224, 224])

# 张量格式的图像转换为PIL图像格式
to_img = T.ToPILImage()
# 0.2和0.4是标准差和均值的近似,将转换后的图像处理,这样就可以用于显示
to_img(dataset[0][0]*0.2+0.4)

  Dataset只负责数据的抽象,一次调用__getitem__只返回一个样本。前面提到过,在训练神经网络时,最好是对一个batch的数据进行操作,同时还需要对数据进行shuffle和并行加速等。对此,PyTorch提供了DataLoader帮助我们实现这些功能。

DataLoader的函数定义如下: DataLoader(dataset, batch_size=1, shuffle=False, sampler=None, num_workers=0, collate_fn=default_collate, pin_memory=False, drop_last=False)

  • dataset:加载的数据集(Dataset对象)
  • batch_size:batch size
  • shuffle::是否将数据打乱
  • sampler: 样本抽样,后续会详细介绍
  • num_workers:使用多进程加载的进程数,0代表不使用多进程
  • collate_fn: 如何将多个样本数据拼接成一个batch,一般使用默认的拼接方式即可
  • pin_memory:是否将数据保存在pin memory区,pin memory中的数据转到GPU会快一些
  • drop_last:dataset中的数据个数可能不是batch_size的整数倍,drop_last为True会将多出来不足一个batch的数据丢弃
from torch.utils.data import DataLoader

dataloader = DataLoader(dataset, batch_size=3, shuffle=True, num_workers=0, drop_last=False)
# 将 dataloader 转换为一个迭代器,使其可以逐批获取数据。每次访问后自动指向下一个元素
dataiter = iter(dataloader)
# 从 dataiter 迭代器中获取下一个批次的数据。
imgs, labels = next(dataiter)
imgs.size() # batch_size, channel, height, width

# torch.Size([3, 3, 224, 224])

  dataloader是一个可迭代的对象,意味着我们可以像使用迭代器一样使用它,例如:

for batch_datas, batch_labels in dataloader:
    train()

  或

dataiter = iter(dataloader)
batch_datas, batch_labesl = next(dataiter)

   在数据处理中,有时会出现某个样本无法读取等问题,比如某张图片损坏。这时在__getitem__函数中将出现异常,此时最好的解决方案即是将出错的样本剔除。如果实在是遇到这种情况无法处理,则可以返回None对象,然后在Dataloader中实现自定义的collate_fn,将空对象过滤掉。但要注意,在这种情况下dataloader返回的batch数目会少于batch_size。

class NewDogCat(DogCat): # 继承前面实现的DogCat数据集
    def __getitem__(self, index):
        try:
            # 调用父类的获取函数,即 DogCat.__getitem__(self, index)
            return super(NewDogCat,self).__getitem__(index)
        except:
            return None, None

from torch.utils.data.dataloader import default_collate # 导入默认的拼接方式
def my_collate_fn(batch):
    '''
    batch中每个元素形如(data, label)
    '''
    # 过滤掉批次数据 batch 中第一个元素为 None 的样本,只保留第一个元素不为 None 的样本。
    batch = list(filter(lambda x:x[0] is not None, batch))
    # 如果 batch 为空,则直接返回一个空的张量
    if len(batch) == 0: return t.Tensor()
    return default_collate(batch) # 用默认方式拼接过滤后的batch数据

dataset = NewDogCat('data/dogcat_wrong/', transforms=transform)
dataset[5]
# 结果
(tensor([[[ 3.0000,  3.0000,  3.0000,  ...,  2.5490,  2.6471,  2.7059],
          [ 3.0000,  3.0000,  3.0000,  ...,  2.5686,  2.6471,  2.7059],
          [ 2.9804,  3.0000,  3.0000,  ...,  2.5686,  2.6471,  2.6863],
          ...,
          [-0.9020, -0.8627, -0.8235,  ...,  0.0392,  0.2745,  0.4314],
          [-0.9216, -0.8824, -0.8235,  ...,  0.0588,  0.2745,  0.4314],
          [-0.9412, -0.9020, -0.8431,  ...,  0.0980,  0.3137,  0.4510]],
 
         [[ 3.0000,  2.9608,  2.8824,  ...,  2.5294,  2.6275,  2.6863],
          [ 3.0000,  2.9804,  2.9216,  ...,  2.5098,  2.6275,  2.6863],
          [ 3.0000,  2.9804,  2.9608,  ...,  2.5098,  2.6078,  2.6667],
          ...,
dataloader = DataLoader(dataset, 2, collate_fn=my_collate_fn, num_workers=1,shuffle=True)
for batch_datas, batch_labels in dataloader:
    print(batch_datas.size(),batch_labels.size())
    
# 结果
torch.Size([2, 3, 224, 224]) torch.Size([2])
torch.Size([1, 3, 224, 224]) torch.Size([1])
torch.Size([2, 3, 224, 224]) torch.Size([2])
torch.Size([2, 3, 224, 224]) torch.Size([2])
torch.Size([1, 3, 224, 224]) torch.Size([1])

  来看一下上述batch_size的大小。其中第2个的batch_size为1,这是因为有一张图片损坏,导致其无法正常返回。而最后1个的batch_size也为1,这是因为共有9张(包括损坏的文件)图片,无法整除2(batch_size),因此最后一个batch的数据会少于batch_szie,可通过指定drop_last=True来丢弃最后一个不足batch_size的batch。

  对于诸如样本损坏或数据集加载异常等情况,还可以通过其它方式解决。例如但凡遇到异常情况,就随机取一张图片代替:

class NewDogCat(DogCat):
    def __getitem__(self, index):
        try:
            return super(NewDogCat, self).__getitem__(index)
        except:
            new_index = random.randint(0, len(self)-1)
            return self[new_index]

  相比较丢弃异常图片而言,这种做法会更好一些,因为它能保证每个batch的数目仍是batch_size。但在大多数情况下,最好的方式还是对数据进行彻底清洗。

  DataLoader封装了Python的标准库multiprocessing,使其能够实现多进程加速。在此提几点关于Dataset和DataLoader使用方面的建议:

  1. 高负载的操作放在__getitem__中,如加载图片等。
  2. dataset中应尽量只包含只读对象,避免修改任何可变对象,利用多线程进行操作

  以下是一个不好的例子:

class BadDataset(Dataset):
    def __init__(self):
        self.datas = range(100)
        self.num = 0 # 取数据的次数
    def __getitem__(self, index):
        self.num += 1
        return self.datas[index]

  在 Dataset 中使用 Transforms 是线程安全的,因为只在每次数据加载时应用变换,不会更改原始数据,也不会在线程之间共享。

  使用Python multiprocessing库的另一个问题是,在使用多进程时,如果主程序异常终止(比如用Ctrl+C强行退出),相应的数据加载进程可能无法正常退出。这时你可能会发现程序已经退出了,但GPU显存和内存依旧被占用着,或通过topps aux依旧能够看到已经退出的程序,这时就需要手动强行杀掉进程。建议使用如下命令:

ps x | grep <cmdline> | awk '{print $1}' | xargs kill
pgrep -u root|xargs kill -9 # 杀掉所有进程,注意检查是否有其他进程在运行
  • ps x:获取当前用户的所有进程
  • grep <cmdline>:找到已经停止的PyTorch程序的进程,例如你是通过python train.py启动的,那你就需要写grep 'python train.py'
  • awk '{print $1}':获取进程的pid
  • xargs kill:杀掉进程,根据需要可能要写成xargs kill -9强制杀掉进程

   PyTorch中还单独提供了一个sampler模块,用来对数据进行采样。常用的有随机采样器:RandomSampler,当dataloader的shuffle参数为True时,系统会自动调用这个采样器,实现打乱数据。默认的是采用SequentialSampler,它会按顺序一个一个进行采样。这里介绍另外一个很有用的采样方法: WeightedRandomSampler,它会根据每个样本的权重选取数据,在样本比例不均衡的问题中,可用它来进行重采样。

  构建WeightedRandomSampler时需提供两个参数:每个样本的权重weights、共选取的样本总数num_samples,以及一个可选参数replacement。权重越大的样本被选中的概率越大,待选取的样本数目一般小于全部的样本数目。replacement用于指定是否可以重复选取某一个样本,默认为True,即允许在一个epoch中重复采样某一个数据。如果设为False,则当某一类的样本被全部选取完,但其样本数目仍未达到num_samples时,sampler将不会再从该类中选择数据,此时可能导致weights参数失效。

dataset = DogCat('data/dogcat/', transforms=transform)

# 狗的图片被取出的概率是猫的概率的两倍
# 两类图片被取出的概率与weights的绝对大小无关,只和比值有关
weights = [2 if label == 1 else 1 for data, label in dataset]
weights
# [1, 2, 2, 1, 2, 1, 1, 2]

from torch.utils.data.sampler import  WeightedRandomSampler
sampler = WeightedRandomSampler(weights,\
                                num_samples=9,\
                                replacement=True)
dataloader = DataLoader(dataset,
                        batch_size=3,
                        sampler=sampler)
for datas, labels in dataloader:
    print(labels.tolist())

[1, 0, 1]
[0, 0, 1]
[1, 0, 1]

  可见猫狗样本比例约为1:2,另外一共只有8个样本,但是却返回了9个,说明肯定有被重复返回的,这就是replacement参数的作用,下面将replacement设为False试试。

sampler = WeightedRandomSampler(weights, 8, replacement=False)
dataloader = DataLoader(dataset, batch_size=4, sampler=sampler)
for datas, labels in dataloader:
    print(labels.tolist())
    
[0, 1, 1, 1]
[1, 0, 0, 0]

  在这种情况下,num_samples等于dataset的样本总数,为了不重复选取,sampler会将每个样本都返回,这样就失去weight参数的意义了。

  从上面的例子可见sampler在样本采样中的作用:如果指定了sampler,shuffle将不再生效,并且sampler.num_samples会覆盖dataset的实际大小,即一个epoch返回的图片总数取决于sampler.num_samples

1.2 计算机视觉工具包:torchvision

  torchvision主要包含三部分:

    • models:提供深度学习中各种经典网络的网络结构以及预训练好的模型,包括AlexNet、VGG系列、ResNet系列、Inception系列等。
    • datasets: 提供常用的数据集加载,设计上都是继承torhc.utils.data.Dataset,主要包括MNISTCIFAR10/100ImageNetCOCO等。
    • transforms:提供常用的数据预处理操作,主要包括对Tensor以及PIL Image对象的操作。
from torchvision import models
from torch import nn
# 加载预训练好的模型,如果不存在会进行下载
# 预训练好的模型保存在 ~/.torch/models/下面
resnet34 = models.squeezenet1_1(pretrained=True, num_classes=1000)

# 修改最后的全连接层为10分类问题(默认是ImageNet上的1000分类)
resnet34.fc=nn.Linear(512, 10)

from torchvision import datasets
# 指定数据集路径为data,如果数据集不存在则进行下载
# 通过train=False获取测试集
dataset = datasets.MNIST('data/', download=True, train=False, transform=transform)

  Transforms中涵盖了大部分对Tensor和PIL Image的常用处理,这些已在上文提到,这里就不再详细介绍。需要注意的是转换分为两步,第一步:构建转换操作,例如transf = transforms.Normalize(mean=x, std=y),第二步:执行转换操作,例如output = transf(input)。另外还可将多个处理操作用Compose拼接起来,形成一个处理转换流程。

  torchvision还提供了两个常用的函数。一个是make_grid,它能将多张图片拼接成一个网格中;另一个是save_img,它能将Tensor保存成图片。

dataloader = DataLoader(dataset, shuffle=True, batch_size=16)
from torchvision.utils import make_grid, save_image
dataiter = iter(dataloader)
img = make_grid(next(dataiter)[0], 4) # 拼成4*4网格图片,且会转成3通道
to_img(img)

save_image(img, 'a.png')
Image.open('a.png')

1.3 可视化工具

  在训练神经网络时,我们希望能更直观地了解训练情况,包括损失曲线、输入图片、输出图片、卷积核的参数分布等信息。这些信息能帮助我们更好地监督网络的训练过程,并为参数优化提供方向和依据。最简单的办法就是打印输出,但其只能打印数值信息,不够直观,同时无法查看分布、图片、声音等。在本节,我们将介绍两个深度学习中常用的可视化工具:Tensorboard和Visdom

1.4 使用GPU加速:cuda

  这部分内容在前面介绍Tensor、Module时大都提到过,这里将做一个总结,并深入介绍相关应用。

  在PyTorch中以下数据结构分为CPU和GPU两个版本:

    • Tensor
    • nn.Module(包括常用的layer、loss function,以及容器Sequential等)

  它们都带有一个.cuda方法,调用此方法即可将其转为对应的GPU对象。注意,tensor.cuda会返回一个新对象,这个新对象的数据已转移至GPU,而之前的tensor还在原来的设备上(CPU)。而module.cuda则会将所有的数据都迁移至GPU,并返回自己。所以module = module.cuda()module.cuda()所起的作用一致。

  另外这里需要专门提一下,大部分的损失函数也都属于nn.Moudle,但在使用GPU时,很多时候我们都忘记使用它的.cuda方法,这在大多数情况下不会报错,因为损失函数本身没有可学习的参数(learnable parameters)。但在某些情况下会出现问题,为了保险起见同时也为了代码更规范,应记得调用criterion.cuda。下面举例说明。

# 交叉熵损失函数,带权重
criterion = t.nn.CrossEntropyLoss(weight=t.Tensor([1, 3]))
input = t.randn(4, 2).cuda()
target = t.Tensor([1, 0, 0, 1]).long().cuda()

# 下面这行会报错,因weight未被转移至GPU
# loss = criterion(input, target)

# 这行则不会报错
criterion.cuda()
loss = criterion(input, target)

criterion._buffers
# 结果
OrderedDict([('weight', 
               1
               3
              [torch.cuda.FloatTensor of size 2 (GPU 0)])])

   而除了调用对象的.cuda方法之外,还可以使用torch.cuda.device,来指定默认使用哪一块GPU,或使用torch.set_default_tensor_type使程序默认使用GPU,不需要手动调用cuda。

# 如果未指定使用哪块GPU,默认使用GPU 0
x = t.cuda.FloatTensor(2, 3)
# x.get_device() == 0
y = t.FloatTensor(2, 3).cuda()
# y.get_device() == 0

# 指定默认使用GPU 1
with t.cuda.device(1):    
    # 在GPU 1上构建tensor
    a = t.cuda.FloatTensor(2, 3)

    # 将tensor转移至GPU 1
    b = t.FloatTensor(2, 3).cuda()
    c = a + b
    z = x + y

    # 手动指定使用GPU 0
    d = t.randn(2, 3).cuda(0)
t.set_default_tensor_type('torch.cuda.FloatTensor') # 指定默认tensor的类型为GPU上的FloatTensor
a = t.ones(2, 3)
a.is_cuda # ture

 

标签:__,img,常用工具,self,batch,dataset,PyTorch,模块,data
From: https://www.cnblogs.com/pgl6/p/18514831

相关文章

  • D51【python 接口自动化学习】- python基础之模块与标准库
    day51模块的导入学习日期:20241028学习目标:模块与标准库--66模块的导入:如何使用其他人编写好的代码功能?学习笔记模块的作用导入模块的方法#导入模块#方式一importos#获取当前的位置print(os.getcwd())#方式二fromosimportgetcwd#获取当前的位置pr......
  • 基于深度学习+pytorch+Flask+SpringBoot+Vue+MySQL的水果识别系统
    目录前言1.登陆注册2.水果识别3.识别记录4.用户管理5.个人中心6.模型训练7.模型测试源码获取前言本系统是一个完整的基于深度学习+pytorch+Flask+SpringBoot+Vue+MySQL的水果识别系统。包括LeNet、AlexNet、VGG、GoogLeNet、ResNet、MobileNetV2网络模型。可以直接......
  • 基于深度学习+pytorch+Flask+SpringBoot+Vue+MySQL的动物识别系统
    目录前言1.登陆注册2.动物识别3.识别记录4.用户管理5.个人中心6.模型训练7.模型测试源码获取前言本系统是一个完整的基于深度学习+pytorch+Flask+SpringBoot+Vue+MySQL的动物识别系统。包括LeNet、AlexNet、VGG、GoogLeNet、ResNet、MobileNetV2网络模型。可以直接......
  • YOLO11改进 | 卷积模块 | 无卷积步长用于低分辨率图像和小物体的新 CNN 模块SPD-Conv
    秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转......
  • Python小白学习教程从入门到入坑------第十八课 异常模块与包【下】(语法基础)
    一、内置全局变量__name__在Python中,有一些内置的全局变量和特殊变量,它们是由Python解释器预定义的,可以在代码的任何地方直接使用。这些变量通常用于提供关于当前解释器状态的信息,或者用于控制解释器的行为在Python中,__name__是一个内置的特殊变量,也被称为“魔法变量”或“......
  • Maven如何只打包项目某个模块及其依赖模块?
    一、背景在SpringCloud微服务框架下,会存在多个模块。当我们需要对其中某一个服务打包的时候,需要将该服务依赖的模块一起打包更新,如果项目比较小的话我们可以直接将项目中的所有模块进行cleaninstall即可。但是当项目运行一段时间后,项目中的代码量会变得很多,每个模块的打包......
  • STM32+致远电子Dport模块的Ethercat从站开发
    环境准备硬件环境1.Dport-stm32评估板2.stlink3.千兆网线4.安装有twincat3的上位机电脑(带千兆网口) 软件环境1.TC31-FULL-Setup.3.1.4024.53.exe2.mdk5开发环境3.SSCTool.exe4.stm32cubemx 例程资料1.致远电子官网 开发流程1.底层硬件EPC103-DP系统框图,......
  • NGINX 1.20.1版安装stream模块
    NGINX于1.9.0版本开始支持stream模块来代理tcp连接。在Centos操作系统若前期以YUM方式安装了nginx,后期想要添加stream模块。1.首先需要检查nginx版本是否支持这一特性,若已支持可直接安装模块,否则重装。2.其次按照如下步骤(部分步骤仅做参考,未必需要执行)2.1安装CentOS的epel-releas......
  • Allegro 16.6 布局时,模块如何进行复用
    模块复用:在原理图中有多个模块相似时,在PCB里面把这些模块处理为相同的布局,就可以使用模块复用功能。上图演示:1.在菜单栏打开PlacementEdit2.框选需要的模块,在某个器件上鼠标右键选择placereplicatecreate,再单击鼠标右键,选择done,单击鼠标左键,会弹出另存为对话框。 ......
  • Pytorch学习--神经网络--非线性激活
    一、用法torch.nn.ReLU图像处理中的应用:在图像处理任务中,ReLU激活函数能够增强特征提取的能力,使网络更好地捕捉图像的细节和边缘。这是因为ReLU对大部分负数响应为零,能在一定程度上减少网络计算量,并对特征层起到稀疏化的效果,避免信息的过度平滑。torch.nn.Sigmoid......