pytorch汇总(二)

简介: pytorch汇总(二)

transforms的使用

简短介绍

2.png

先来看看其内部架构:

2.png2.png



ToTensor类

ToTensor:意思是把一个PIL类型和numpy类型转变为tensor

2.png


代码练习

from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
# python的用法:tensor数据类型
# 通过transforms.toTensor去看两个问题
# 问题1:transforms该如何使用?
# 问题2:为什么需要tensor的数据类型?
# 绝对路径     D:\python基础语法视频课程\learn_pytorch\data\train\ants_image\0013035.jpg
# 相对路径     data/train/ants_image/0013035.jpg
img_path = "data/train/ants_image/0013035.jpg"
img = Image.open(img_path)
writer = SummaryWriter("logs")
# 下面演示transforms的使用
tensor_trans = transforms.ToTensor()
# 这里其实默认调用的就是ToTensor类中的__call__方法,也可以写成tensor_ing = tensor_trans.__call__(img)
# 这里的tensor_img就是tensor类型,原因是tensor_trans调用了__call__方法
# 而__call__方法就是将PIL类型或者是numpy类型的图片转变为tensor类型
tensor_img = tensor_trans(img)
writer.add_image("tensor_img", tensor_img)
writer.close()

示意图:

2.png


__call__方法介绍

2.png

__call__方法有点像我们的__init__方法,即创建对象传参便自动调用一样


Compose类

简短介绍

可以看到Compose类就是将所有的transforms进行一个拼接

2.png

源码给了我们一个案例:

2.png2.png



下面将在介绍Resize方法的时候进行Compose()的代码演示


ToPILImage类

其是将tensor类型和numpy类型转成PIL类型

2.png


Normalize类

2.png

注意我们归一化必须是一个tensor数据类型,然后归一化的计算公式如下:


output[channel] = (input[channel] - mean[channel]) / std[channel]


归一化操作代码:


from PIL import Image
from torch.utils.tensorboard import SummaryWriter
from torchvision import transforms
img_path = "image/90179376_abc234e5f4.jpg"
# 此时的img是PIL类型
writer = SummaryWriter("logs")
img = Image.open(img_path)
# ToTensor的使用
trans_tensor = transforms.ToTensor()
# 此时的img_tensor是tensor类型
img_tensor = trans_tensor(img)
# 此处打印看下img_tensor是几个信道的,结果为[3, 512, 768],是三个信道
print(img_tensor.shape)
# 下面演示Normalize的使用
# 注意Normalize方法中的参数是一个是均值,一个是标准差
# 又因为我们的图像是三个信道的,所以我们的标准差和均值都要提供三个值,此时我们都设置为0.5
# 先打印归一化前的第0层第0行第0列的像素进行输出
print(img_tensor[0][0][0])
trans_norm = transforms.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])
# trans_norm中只能传入tensor类型数据
img_norm = trans_norm(img_tensor)
# 输出归一化后的第0层第0行第0列的像素
print(img_norm[0][0][0])
# 此处add_image中传入的图片类型是tensor类型
writer.add_image("Normalize",img_norm)
writer.close()

可以看到我们所给的均值为0.5,标准差为0.5,根据如下公式:


output[channel] = (input[channel] - mean[channel]) / std[channel]


我们来算下:

假设此时我们的input图片的像素值的范围在【0,1】之内,

然后此时根据公式可得:


output = (input-0.5)/0.5 = 2 * input - 1
最终的output的值范围为【-1,1】


下面给出归一化前后图像对比:

2.png


Resize类

resize类的作用就是将给定的图片重新给定大小

2.png

这里的意思如果我们的Resize方法的参数中给定了高度和宽度的话,那么将会按照给定的参数进行输出


代码示例

Resize方法的第一种用法

from PIL import Image
from torchvision import transforms
img_path = "image/90179376_abc234e5f4.jpg"
# 此时的img是PIL类型
img = Image.open(img_path)
# ToTensor的使用
trans_tensor = transforms.ToTensor()
# 此时的img_tensor是tensor类型
img_tensor = trans_tensor(img)
# Resize的使用
# 注意Resize中输入的图片类型是PIL类型
# 此处我们先打印一下发现原来的图片大小为(500,332)
print(img.size)
# resize的第一种用法,输入的是两个值,代表高度和宽度
trans_resize = transforms.Resize((512, 512))
img_resize = trans_resize(img)
# 输出结果为<PIL.Image.Image image mode=RGB size=512x512 at 0x1E2C65073D0>
# 我们会发现经过Resize方法处理过后的图片类型仍为PIL,然后大小变为了512×512
print(img_resize)

Resize方法的第二种用法 (并附加使用Compose方法)

from PIL import Image
from torchvision import transforms
img_path = "image/90179376_abc234e5f4.jpg"
# 此时的img是PIL类型
img = Image.open(img_path)
# ToTensor的使用
trans_tensor = transforms.ToTensor()
# 此时的img_tensor是tensor类型
img_tensor = trans_tensor(img)
# Resize的使用
# 注意Resize中输入的图片类型是PIL类型
# 此处我们先打印一下发现原来的图片大小为(500,332)
print(img.size)
# resize的第二种用法,使用compose方法进行拼接
# 这里我们只给定了一个值,意为不指定高和宽,是进行等比例的缩放
trans_resize = transforms.Resize(512)
# PIL------>PIL------->tensor
# 这里其实就是trans_resize将一个PIL类型的图片调整为指定尺寸,但是最终的输出结果依然为PIL
# 然后输出的PIL格式的图片又作为trans_tensor的输入值,因为trans_tensor是将PIL格式的图片转为tensor格式
# 所以最终trans_compose就是可以将PIL类型的图片转变为tensor类型
trans_compose = transforms.Compose([trans_resize, trans_tensor])
# img_resize最终为tensor类型
img_resize = trans_compose(img)

compose这个函数的作用是可以把transforms类中的任意方法组合起来放到列表里,并且按照从前往后的顺序依次执行这些方法,前面方法的结果作为下一个方法的输入

compose组合了两个方法:Resize将输入的PIL格式的img图片转化为指定尺寸,转化后的图片类型依然为PIL类型,trans_tensor将改变了尺寸的img(还是PIL格式)的图片转换为tensor格式的图片。


总结

要多注意函数的输入输出,输入的话一般transforms的源码中会给,但是输出就未必了,如果想要知道输出的变量的类型的话可以使用type方法,即type(变量名)即可.


torchvision中数据集的使用

首先我们就拿torchvision中的CIFAR10数据集进行导入

import torchvision
"""
train_set是我们的训练数据集,所以train我们设置为true,
创建一个名为datasets的文件夹,把我们下载的数据保存进去
train后面默认的值为true
因为我们自己没有准备数据集,要从网上的torchvision中去下载我们的数据集,所以此处的download为true
"""
train_set = torchvision.datasets.CIFAR10(root="./datasets", train=True, download=True)
# test_set为测试数据集,所以train为false
test_set = torchvision.datasets.CIFAR10(root="./datasets", train=False, download=True)

导入之后先打印一下数据集的第一个看看是啥:

print(test_set[0])

结果为:

(<PIL.Image.Image image mode=RGB size=32x32 at 0x1E5198374F0>, 3)

前面的部分为图片,后面的3为target,至于这个target是什么我们来打断点看下:

2.png


img, target = test_set[0]
print(img)
print(target)


所以此时我们可以这么写代码:

img, target = test_set[0]
print(img)
print(target)

打印的结果跟上面一样,说明此时数据集的第一个是一个cat的图片

,所以说明我们拿img可以直接拿到图片


如果想展示这个图片的话使用image.show()方法即可:

image.show()

因为CIFAR10数据集中默认的图片类型为PIL,所以我们也可以使用transforms将我们的类型转变为tensor数据类型,并且在tensorboard中进行展示,来看代码:

import torchvision
from torch.utils.tensorboard import SummaryWriter
# 因为CIFAR10这个数据集当中的所有数据的类型都为PIL类型,所以我们需要使用transforms将其转变为tensor类型
dataset_transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor()
])
"""
train_set是我们的训练数据集,所以train我们设置为true,
创建一个名为datasets的文件夹,把我们下载的数据保存进去
train后面默认的值为true
因为我们自己没有准备数据集,要从网上的torchvision中去下载我们的数据集,所以此处的download为true
transform=dataset_transform意为将我们数据集中的图片类型从PIL类型转变为tensor类型
"""
train_set = torchvision.datasets.CIFAR10(root="./datasets", train=True, transform=dataset_transform, download=True)
# test_set为测试数据集,所以train为false
test_set = torchvision.datasets.CIFAR10(root="./datasets", train=False, transform=dataset_transform, download=True)
writer = SummaryWriter("logs")
# 这里是我们想显示测试数据集的前十张图片
for i in range(10):
    img, target = test_set[i]
    writer.add_image("test_set", img, i)
writer.close()

Dataload

之前我们说过Datasset就是告诉我们数据集在哪,以及第一张和第二张数据是什么,包括告诉我们数据集中有多少数据,我们只需要将Dataset实例化放到我们的Dataload中即可


那么到底什么是Dataloader呢?

Dataloader就是将我们Dataset中的数据加载到我们的神经网络当中去,然后Dataloader将从Dataset中取数据,至于怎么取如何取将在Dataloader中进行一个参数的设置来决定的


下面来看下官网中的描述:

首先来看的就是我们在Dataloader中的参数的设置:

dataset (Dataset) – dataset from which to load the data.
batch_size (int, optional) – how many samples per batch to load (default: 1).
shuffle (bool, optional) – set to True to have the data reshuffled at every epoch (default: False).
sampler (Sampler or Iterable, optional) – defines the strategy to draw samples from the dataset. Can be any Iterable with __len__ implemented. If specified, shuffle must not be specified.
batch_sampler (Sampler or Iterable, optional) – like sampler, but returns a batch of indices at a time. Mutually exclusive with batch_size, shuffle, sampler, and drop_last.
num_workers (int, optional) – how many subprocesses to use for data loading. 0 means that the data will be loaded in the main process. (default: 0)
collate_fn (callable, optional) – merges a list of samples to form a mini-batch of Tensor(s). Used when using batched loading from a map-style dataset.
pin_memory (bool, optional) – If True, the data loader will copy Tensors into CUDA pinned memory before returning them. If your data elements are a custom type, or your collate_fn returns a batch that is a custom type, see the example below.
drop_last (bool, optional) – set to True to drop the last incomplete batch, if the dataset size is not divisible by the batch size. If False and the size of dataset is not divisible by the batch size, then the last batch will be smaller. (default: False)
timeout (numeric, optional) – if positive, the timeout value for collecting a batch from workers. Should always be non-negative. (default: 0)
worker_init_fn (callable, optional) – If not None, this will be called on each worker subprocess with the worker id (an int in [0, num_workers - 1]) as input, after seeding and before data loading. (default: None)
generator (torch.Generator, optional) – If not None, this RNG will be used by RandomSampler to generate random indexes and multiprocessing to generate base_seed for workers. (default: None)
prefetch_factor (int, optional, keyword-only arg) – Number of samples loaded in advance by each worker. 2 means there will be a total of 2 * num_workers samples prefetched across all workers. (default: 2)
persistent_workers (bool, optional) – If True, the data loader will not shutdown the worker processes after a dataset has been consumed once. This allows to maintain the workers Dataset instances alive. (default: False)

我们拿打牌进行举例

batch_size就是我们从dataset中的牌的数据集中抽取多少张牌的意思


shuffle代表我们牌每次抽取完都要进行洗牌,其是为了判断两次牌的顺序是否一样,设置为true代表不一样,设置为false代表一样,默认为false

一般我们都设置为true,再通俗点讲就是取batch是否随机取, true就代表要随机抓取


num_workers 参与工作的线程数,即加载数据的时候采用单进程还是多进程,默认值为0即采用主进程进行加载,但是在windows可能会出现问题


drop_last 对最后不足batchsize的数据的处理方法,打个比方现在有100张牌,然后每次抽取3张,100对3取余等于33,最后的余数为1,我们的drop_last 就是看这个1我们是要还是不要,如果drop_last 为true,代表我们不要这个1,只需要99张牌即可,如果为false,就代表最终我们拿完99张牌后还需要把最后余下来的那张牌拿到手


代码示例

import torchvision
# 准备的测试数据集
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
test_data = torchvision.datasets.CIFAR10("./datasets", train=False, transform=torchvision.transforms.ToTensor())
# batch_size等于64相当于从dataset中随机每次取64个数据集
test_loader = DataLoader(dataset=test_data, batch_size=64, shuffle=True, num_workers=0, drop_last=True)
# 测试数据集中第一张图片及target,因为CIFAR10数据集中的__getItem__方法的返回值是img和target
img, target = test_data[0]
# 打印结果为torch.Size([3, 32, 32]),说明第一张图片是一个三通道的,高度32,宽32的
print(img.shape)
# 其target为3
print(target)
writer = SummaryWriter("dataloader")
# epoch代表轮数,可取0和1,这里是为了验证shuffle的
# shuffle为true时,第0轮的图片顺序跟第1轮的图片顺序不一样
for epoch in range(2):
    # 设置全局步长step = 0
    step = 0
    # 遍历dataloader从dataset所取到的数据
    for data in test_loader:
        imgs, targets = data
        writer.add_images("Epoch: {}".format(epoch), imgs, step)
        # 步长每次都加1,这样可以观察到每走一步我们的dataloader所取的图片有哪些
        step = step + 1
writer.close()

注意事项:

1:关于shuffle:

2.png


神经网络的基本骨架nn-module

2.png

在基本上所有的神经网络中,我们都必须要继承nn.Module这个类,官网中也给我了我们详细的介绍:其是所有类的一个基类,也就是父类

2.png

官网给的代码模板如下:


import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)
        self.conv2 = nn.Conv2d(20, 20, 5)
    def forward(self, x):
        x = F.relu(self.conv1(x))
        return F.relu(self.conv2(x))

意思就是所有的类都要继承我们的nn.module类,然后要定义两个方法:一个是__init__方法,一个是forward方法,在__init__方法中,我们必须要显示的调用父类的init方法,即super().__init__()这句话是必须写的,底下的卷积操作我们可以自己定义操作,


forward顾名思义为前向传播,即我们给定一个输入,经过神经网络中的forward函数处理后,最终有了一个output的输出

总结:__init__方法内部定义我们卷积的方法,forward方法内部定义执行卷积方法的操作

2.png

其中forward函数中的这段代码解释如下:

x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))

2.png

conv1就是卷积操作,然后relu就是非线性操作


代码示例

import torch
from torch import nn
class Tudui(nn.Module):
    def __init__(self):
        super().__init__()
    def forward(self, input):
        output = input + 1
        return output
tudui = Tudui()
# 给定一个输入
x = torch.tensor(1.0)
# 把输入x放到神经网络当中
output = tudui(x)
# 最终的输出结果为tensor(2.)
print(output)

卷积操作

还是先来看pytorch官网的描述吧:

这里我们首先介绍torch.nn.functional下的con2d,其实后面我们用的更多的是torch.nn

一般图像都是2D的,选这个点进去

2.png

然后来看官网给的一些参数:

2.png


input就是我们输入的图片,其对我们输入的图片是有尺寸要求的,即需要有batch,通道数,高度,宽度等

weight就是权重,即为一个卷积核,其尺寸要求是要有一个输出,groups一般取1,然后高和宽

bias即为偏差

stride就是卷积核的步径

来看一个卷积操作的举例,我们的输入是一个5×5的一图像,最终我们经过卷积核后的卷积输出如下图所示,步长为1,最终的结果如下所示:

对于参数的一个要求在这里:

2.png

可以看到这里对于input参数和output参数的要求

2.png


下面我们将根据上面的图来进行一个简单的编码:

首先来看一段代码:

import torch
# 定义我们的输入,注意转成了tensor数据类型
input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]])
# 此处定义我们的卷积核
kernel = torch.tensor([[1, 2, 1],
                       [0, 1, 0],
                       [2, 1, 0]])
print(input.shape)
print(kernel.shape)

输出结果为:

torch.Size([5, 5])
torch.Size([3, 3])

这里可以看到并不符合我们最终的一个要求,原因是input和weight不但要求参数有高和宽,还有别的,但是这里并没有,所以我们需要reshape方法来重新指定,下面来看代码:


代码示例

import torch
import torch.nn.functional as F
# 定义我们的输入,注意转成了tensor数据类型
input = torch.tensor([[1, 2, 0, 3, 1],
                      [0, 1, 2, 3, 1],
                      [1, 2, 1, 0, 0],
                      [5, 2, 3, 1, 1],
                      [2, 1, 0, 1, 1]])
# 此处定义我们的卷积核
kernel = torch.tensor([[1, 2, 1],
                       [0, 1, 0],
                       [2, 1, 0]])
"""
这里我们需要重新reshape一下input和卷积核的数据,满足我们卷积的一个输入
"""
input = torch.reshape(input, (1, 1, 5, 5))
kernel = torch.reshape(kernel, (1, 1, 3, 3))
#打印结果为torch.Size([1, 1, 5, 5])
print(input.shape)
#torch.Size([1, 1, 3, 3])
print(kernel.shape)
# 利用conv2d进行卷积操作,这里我们放入了三个形参,stride表示步长为1
output = F.conv2d(input, kernel, stride=1)
# 最终的输出结果为tensor([[[[10, 12, 12],
#                          [18, 16, 16],
#                           [13,  9,  3]]]])
print(output)
# 此时步长为2
output2 = F.conv2d(input, kernel, stride=2)
# 最终的输出结果为tensor([[[[10, 12],
#                       [13,  3]]]])
print(output2)
# 此时的步长为1,padding就是会在我们输入的图像两边进行一个填充
output3 = F.conv2d(input, kernel, stride=1, padding=1)
# 最终的输出结果为tensor([[[[ 1,  3,  4, 10,  8],
#                          [ 5, 10, 12, 12,  6],
#                            [ 7, 18, 16, 16,  8],
#                              [11, 13,  9,  3,  4],
#                                [14, 13,  9,  7,  4]]]])
print(output3)

注意事项:最后我们设置了一个padding = 1,意为在我们输入的图像两边进行一个填充,我们画了一个示意图便于理解

2.png


神经网络----卷积层

下面来看torch.nn中的conv2d,一般我们用这个多一点

先来看看里面有什么参数吧:


CLASStorch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’, device=None, dtype=None)

2.png



in_channels:代表我们输入图片的通道数,一般彩色照片都是三个通达

out_channels:代表我们输出时候的通道数

kernel_size:卷积核的大小,如果值为3代表的就是3✖3的一个卷积核

stride:代表我们的步长

padding:意为在我们输入的图像两边进行一个填充

这五个是比较

dilation:就是卷积核之间的元素相差的距离

groups:一般都会一直设置为1

padding_model就是我们padding选择padding填充的时候按照什么模式进行一个填充,一般我们选择zeros进行一个填充

bias一般设置为true


接下来让我们对in_channels和out_channels做一个解释:先来看一张图:

2.png

这张图的意思就是in_channel的通道数为1,即输入的照片是5×5的,即一张图片,所以通道数为1,然后假设此时我们设置out_channel也就是我们输出的通道数为1的话,此时就只需要一个卷积核,而当out_channel等于2的时候,意味着我们就需要两个卷积核,最终也会得到两个输出值,如上图所示:


欧克那现在我们来看下代码把:


代码示例

import torch
import torchvision
from torch import nn
from torch.nn import Conv2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("datasets", train=False, transform=torchvision.transforms.ToTensor(),
                                       download=True)
# dataloader从我们的dataset中取数据,batch_size为一次取64张图片
dataloader = DataLoader(dataset, batch_size=64)
# 定义我们的卷积神经网络
class Tudui(nn.Module):
    def __init__(self):
        # 必须有的步骤,第一部需要先继承我们父类的__init__方法
        super(Tudui, self).__init__()
        # 输入通道因为是彩色图片,所以in_channels值为3,输出通道的大小我们指定out_channels为6,stride为步长等于1,
        self.conv1 = Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0)
    # 定义我们神经网络的输入x
    def forward(self, x):
        # 然后让我们的输入结果x进行一个卷积操作后得到一个输出结果x
        x = self.conv1(x)
        return x
# 初始化我们的网络
tudui = Tudui()
writer = SummaryWriter("logs")
# 定义我们的初始步长为0
step = 0
# 获取我们dataloader中的数据
for data in dataloader:
    # 获取每一条数据的imgs和targets
    imgs, targets = data
    # 然后将我们的图片放入到我们的神经网络内部,经过forward方法进行一些卷积的操作
    # 这也更加验证了dataloader的作用就是将数据送到神经网络当中去
    output = tudui(imgs)
    # 输出结果为torch.Size([64, 3, 32, 32]),64是DataLoader中的batch_size,可以看到此时的图片的通道为3
    print(imgs.shape)
    # 输出结果为torch.Size([64, 6, 30, 30]),64是DataLoader中的batch_size,经过卷积后的通道变为了6
    print(output.shape)
    # 使用tensorboard进行更直观的显示
    writer.add_images("input", imgs, step)
    """
    注意我们output的某个输出结果为[64, 6, 30, 30],说明其最终经过卷积后的图片的通道为6
    但是使用add——images方法的时候我们的通道只能是3,所以此处我们需要使用不那么严谨的方法
    即使用torch.reshape方法来修改output,将其通道修改为3,但是batch_size我们并不知道
    所以我们设置其为-1,这样他会根据其他的值自己计算
    并且还有一个问题要注意的就是我们图像原本大小为32×32,经过卷积后变成了30✖30
    如果经过卷积后我们的图片大小想要保持不变的话,仍需要对原图片进行我们的填充,使用padding
    """
    output = torch.reshape(output, (-1, 3, 30, 30))
    writer.add_images("output", output, step)
    step = step + 1

最后的效果图如下所示:

2.png


神经网络–最大池化的使用

一般我们使用的都是nn.MaxPool12d

2.png2.png2.png




kernel_size是用于取最大值的一个窗口,设置为3就是33的窗口,给定数组就是对应数组的大小

stride就是步长,其默认值为kernel_size的大小,之前再卷积层的时候其默认大小为1,注意这里的区别

padding与之前一样

dilation:就是卷积核之间的元素相差的距离

2.png

return_indices一般用不到

ceil_mode设置为true和false比较有讲究,默认情况为false我们来看:

2.png

在我们最大池中,假设此时有一个33的一个最大值窗口,那么最终我们的步长也就是3,然后第一个最大值窗口选出来的数字为2

2.png

然后走三步:

2.png

发现此时没有3*3=9个元素了,那么此时ceil_mode的作用就出来啦,假设此时这是为true的话,最终我们选择的时候就要再这六个元素中找最大值,此时找到的最大值为3,假设为false,就不能找

然后继续往下:

2.png

假设ceil_mode此时为true的话,最终我们选择的时候就要再这六个元素中找最大值,找到的最大值为5,假设为false,就不能找

继续往下找

2.png

假设ceil_mode此时为true的话,最终我们选择的时候就要再这六个元素中找最大值,找到的最大值为1,假设为false,就不能找


所以最终的结果是这样的:

2.png

注意事项:池化操作是不改变我们的的图像大小的通道大小的

2.png


注意这里池化的时候我们给定的输入依然是(N,C,H,W)类型

代码示例

import torch
import torchvision
from torch import nn
from torch.nn import MaxPool2d
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("datasets", train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        # 再初始化方法中定义我们的池化操作
        self.maxpool1 = MaxPool2d(kernel_size=3, ceil_mode=False)
    def forward(self, input):
        # forward当中执行我们的池化操作
        output = self.maxpool1(input)
        return output
# 初始化我们的网络
tudui = Tudui()
writer = SummaryWriter("logs_maxpool")
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, step)
    # 这里不同于卷积操作,池化的话最终的通道大小依然为之前的大小,所以不需要reshape操作
    # 传参的时候默认调用我们的forward方法
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step = step + 1
writer.close()

在tensorboard中的效果:

2.png


神经网络–非线性激活

2.png

这里我们讲的就是我们的Relu函数以及我们Sigmoid函数

2.png


代码示例

import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
dataset = torchvision.datasets.CIFAR10("datasets", train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=64)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.relu1 = ReLU()
        self.sigmoid1 = Sigmoid()
    def forward(self, input):
        output = self.sigmoid1(input)
        return output
tudui = Tudui()
writer = SummaryWriter("logs_relu")
step = 0
for data in dataloader:
    imgs, targets = data
    writer.add_images("input", imgs, global_step=step)
    output = tudui(imgs)
    writer.add_images("output", output, step)
    step += 1
writer.close()

结果展示

2.png

相关文章
|
7月前
|
机器学习/深度学习 分布式计算 PyTorch
Tensorflow、Pytorch、
Tensorflow、Pytorch、Horovod、Spark、JupyterLab、TF-Serving、Triton等。 是什么,怎么用,推荐demo
132 40
|
3月前
|
机器学习/深度学习 自然语言处理 算法
|
3月前
|
机器学习/深度学习 数据采集 PyTorch
PyTorch
【9月更文挑战第30天】
30 1
|
4月前
|
存储 机器学习/深度学习 并行计算
Pytorch NCHW/NHWC 的理解
Pytorch NCHW/NHWC 的理解
133 1
|
4月前
|
机器学习/深度学习 PyTorch 算法框架/工具
PyTorch提升脚印
PyTorch提升脚印
22 3
|
4月前
|
机器学习/深度学习 PyTorch TensorFlow
TensorFlow和PyTorch的实际应用比较
TensorFlow和PyTorch的实际应用比较
|
机器学习/深度学习 人工智能 PyTorch
什么是Pytorch?
什么是Pytorch?
157 0
|
机器学习/深度学习 人工智能 并行计算
【PyTorch】Pytorch基础第0章
【PyTorch】Pytorch基础第0章
79 0
|
机器学习/深度学习 编解码 算法
使用PolyGen和PyTorch生成3D模型
使用PolyGen和PyTorch生成3D模型
140 0
使用PolyGen和PyTorch生成3D模型
|
存储 PyTorch 算法框架/工具
pytorch汇总(一)
pytorch汇总(一)
318 0
pytorch汇总(一)