- 1. 构建基本的神经网络
- 1.1 定义自己的神经网络
- 1.1.1 nn.Module类
- 1.1.2 例子测试
- 2 torch.nn库以及nn与nn.functional的区别
- 3. 卷积层Convolution Layers
- 3.1 卷积层CONV2D
- 3.1.1 torch.nn.functional.conv2d
- 3.1.2 torch.nn.Conv2d
- 3.1.3 stride,padding,dilation 参数
- 3.1.4 in_channels 、out_channels参数与卷积计算
- 3.1.5 python 代码例子
- 3.1.5.1 上边的例子复现代码
- 3.1.5.2 CIFAR10数据集合的一个例子
- 4. 池化层Convolution Layers
- 4.1 Max Pooling 最大池化层
- 4.1.1 torch.nn.functional.max_pool2d
- 4.1.2 torch.nn.MaxPool2d
- 4.1.3 ceil_mode参数
- 4.1.4 python代码例子
- 4.1.4.1 上边的例子复现代码
- 4.1.4.2 nn.MaxPool2d例子
结合前边的内容学习:
Pytorch 学习第【1】天
Pytorch 学习第【2】天
Pytorch 学习第【3】天
Pytorch 学习第【4】天
神经网络由对数据进行 *** 作的层/模块组成。torch.nn命名空间提供了构建自己的神经网络所需的所有构建模块。PyTorch中的每个模块都子类化了nn.Module。一个神经网络本身就是一个由其他模块(层)组成的模块。这种嵌套结构允许轻松构建和管理复杂的架构。
我们通过子类化 nn.Module 来定义我们的神经网络,并在 init 中初始化神经网络层。每个 nn.Module 子类都在 forward 方法中实现了对输入数据的 *** 作。
【PS:简单来说就是需要定义一个类需继承 nn.Module,nn.Module是神经网络的基本骨架,接下来就来了解nn.Moudle】
nn.Module是所有神经网络模块的基类。所以自己定义的神经网络需要继承nn.Module。
文档给出的例子:
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module): #这里对nn.Module进行了继承
def __init__(self): #初始化函数
super().__init__() #这里是对父类进行初始化
self.conv1 = nn.Conv2d(1, 20, 5) #自己定义 *** 作1
self.conv2 = nn.Conv2d(20, 20, 5) #自己定义 *** 作2
def forward(self, x): #
x = F.relu(self.conv1(x)) # x进行卷积、然后进行非线性处理
return F.relu(self.conv2(x)) # 进行卷积、然后进行非线性处理,然后返回
【PS:其中的forword函数,输入x,输出处理后的x】
1.1.2 例子测试import torch
from torch import nn
# myExample创建一个简单的神经网络
class myExample(nn.Module):
def __init__(self):
super().__init__()
def forward(self,input):
output = input * 2
return output
example = myExample()
# 输入值为2
x = torch.tensor(2)
output = example(x)
print(output)
输出结果
tensor(4)
进程已结束,退出代码0
2 torch.nn库以及nn与nn.functional的区别
(1) tocrch.nn库:
torch.nn是专门为神经网络设计的模块化接口
nn构建于autograd之上,可以用来定义和运行神经网络
nn.Parameter
nn.Linear&nn.conv2d等等
nn.functional
nn.Module
nn.Sequential
(2)nn.functional
包含torch.nn库中所有函数,包含大量loss和activation function
两者的区别:
- nn.functional.xxx是函数接口,而nn.Xxx是nn.functional.xxx的类封装,并且nn.Xxx都继承于一个共同祖先nn.Module。
- nn.Xxx除了具有nn.functional.xxx功能之外,内部附带了nn.Module相关的属性和方法,例如train(),
eval(),load_state_dict, state_dict等。 - 两者的调用方式不同。nn.Xxx需要先实例化并传入参数,然后以函数调用的方式调用实例化的对象并传入输入数据。nn.functional.xxx同时传入输入数据和weight,
bias等其他参数 。 - nn.Xxx继承于nn.Module, 能够很好的与nn.Sequential结合使用,
而nn.functional.xxx无法与nn.Sequential结合使用 - nn.Xxx不需要你自己定义和管理weight;而nn.functional.xxx需要你自己定义weight,每次调用的时候都需要手动传入weight,不利于代码复用。
说明参考来源
卷积 *** 作的目的是提取图像的特征。根据不同的卷积核、不同的计算方式,会得到不同的特征提取图。
【PS:为了更好的理解,先上图片:】
(1)卷积核:类似轮廓图
[[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]]
(2)卷积核: 类似浮雕
[[-2, 1, 0],
[-1, 1, -1],
[0, 1, 2]]
(2)卷积核:类似反相
[[1, 0, 1],
[0, -5, 0],
[1, 0, 1]]
演示的代码如下:
import torch
from torch import nn
from torchvision import transforms
from PIL import Image
import torch.nn.functional as F
to_pil_image = transforms.ToPILImage()
transform = transforms.Compose([
transforms.ToTensor()
])
class example(nn.Module):
def __init__(self):
super().__init__()
# 自定义卷积核
kernel = [[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]]
# kernel = [[-2, 1, 0],
# [-1, 1, -1],
# [0, 1, 2]]
# kernel = [[1, 0, 1],
# [0, -5, 0],
# [1, 0, 1]]
# 转成FloatTensor格式。并且增加2个维度
kernel = torch.FloatTensor(kernel).unsqueeze(0).unsqueeze(0)
# print(kernel.shape)
# self.weight = nn.Parameter(data=kernel, requires_grad=False)
self.kernel= kernel
def forward(self, x):
x1 = x[:, 0]
x2 = x[:, 1]
x3 = x[:, 2]
x1 = F.conv2d(x1.unsqueeze(1), self.kernel, padding=1)
x2 = F.conv2d(x2.unsqueeze(1), self.kernel, padding=1)
x3 = F.conv2d(x3.unsqueeze(1), self.kernel, padding=1)
x = torch.cat([x1, x2, x3], dim=1)
return x
jiuchong = example() # 创建实例
img_PIL = Image.open("horse.jpg") # 读取图片
img_tensor=transform(img_PIL) # PIL to tensor
print(img_tensor.shape) # 查看形状
input = torch.reshape(img_tensor, (1, 3, 4256, 2832)) #根据要求进行改变形状
output = jiuchong(input) # 进行相应 *** 作并输出
# print(output.shape)
output = output.squeeze(0) # 减少一个维度
# print(output.shape)
img = to_pil_image(output) # tensor to PIL
img.save("horse(1).jpg") # 保存图片
3.1 卷积层CONV2D
3.1.1 torch.nn.functional.conv2d
先介绍下:TORCH.NN.FUNCTIONAL.CONV2D
是对一个由多个输入平面组成的输入图像进行二维卷积。同时该 *** 作符支持TensorFloat32。
参数:
torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor
解析:
input :形状为(minibatch,in_channels,iH,iW)的输入张量。【PS:可以知道需要的是四维的,(批次大小,通道数,高度,宽度)】
weight : 形状的过滤器(out_channels ,in_channels / groups ,kH, kW) ;(卷积核的个数,每个卷积核的通道数,每个卷积核的高,每个卷积核的宽)。
bias :代表每一个channel的bias,是一个维数等于out_channels的tensor。【通常
选择为true,就是卷积的卷积的结果是否加减上一个常数】
stride是一个数或者一个二元组(SH,SW),代表纵向和横向的步长
padding是一个数或者一个二元组(PH,PW ),代表纵向和横向的填充值
dilation是一个数,代表卷积核内部每个元素之间间隔元素的数目(不常用,默认为0,可以不用管,如果想详细了解,请参考:https://www.cnblogs.com/wanghui-garcia/p/10775367.html)
groups是一个数,代表分组卷积时分的组数,特别的当groups = in_channel时,就是在做逐层卷积(depth-wise conv)
groups作用:对input中的每个样例数据,将通道分为groups等份,即每个样例数据被分成了groups个大小为(in_chanmnelgroups, iA, iw)的子数据。对于这每个子数据来说,卷积核的大小为(in_channelgroups, k , kW)。这一整个样例数据的计算结果为各个子数据的卷积结果拼接所得。
3.1.2 torch.nn.Conv2d对一个由多个输入平面组成的输入信号进行二维卷积。
参数:
torch.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)
解析:
in_channels (int) - 输入图像中的通道数【例如彩色图像一般就3个通道】
out_channels (int) - 由卷积产生的通道数
kernel_size (int or tuple) - 卷积核的大小
stride (int or tuple, optional) - 卷积的跨度。默认值:1
padding (int, tuple or str, optional) - 在输入的四边都加上padding。默认值:0
padding_mode (string, optional) - ‘zeros’, ‘reflect’, ‘replicate’ or ‘circular’. 默认值:‘零’。【就是padding时用什么填充】
dilation (int or tuple, optional) - 核心元素之间的间距。默认值:1
groups (int, optional) - 从输入通道到输出通道的阻塞连接的数量。默认值:1
bias (bool, optional) - 如果为真,给输出增加一个可学习的偏置。默认值。真【通常
选择为true,就是卷积的卷积的结果是否加减上一个常数】
【PS:蓝色对应着输入,阴影对应卷积核,绿色对应输出】
例1:stride=1,paddding=0, 一个特征图尺寸为44的输入,使用33的卷积核。
例2:stride=1,paddding=1, 一个特征图尺寸为55的输入,使用33的卷积核。
例3:stride=2,paddding=0, 一个特征图尺寸为55的输入,使用33的卷积核。
例4:stride=2,paddding=1, 一个特征图尺寸为55的输入,使用33的卷积核。
例5:stride=1,paddding=0,dilation = 2 一个特征图尺寸为66的输入,使用33的卷积核。
例1:
例2:
卷积计算部分过程:
(1)第1步计算
(2)第2步计算
…
(9)第9步计算
import torch
import torch.nn.functional as F
a = torch.arange(1, 26)
inputs = a.view(5, 5)
print(inputs)
kernel = torch.tensor([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
inputs = torch.reshape(inputs,(1,1,5,5))
kernel = torch.reshape(kernel,(1,1,3,3))
outputs = F.conv2d(inputs,kernel,stride=1,padding=0,dilation=1)
print(outputs)
输出结果:
tensor([[ 1, 2, 3, 4, 5],
[ 6, 7, 8, 9, 10],
[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25]])
tensor([[[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]]]])
进程已结束,退出代码0
3.1.5.2 CIFAR10数据集合的一个例子
import torch
from torch.utils.tensorboard import SummaryWriter
import torchvision
from torch.utils.data import DataLoader
from torch import nn
dataset = torchvision.datasets.CIFAR10("./dataset", train=False, transform=torchvision.transforms.ToTensor(),
download=True)
dataloader = DataLoader(dataset, batch_size=64)
class example(nn.Module):
def __init__(self):
super(example, self).__init__()
self.conv2 = nn.Conv2d(in_channels=3, out_channels=6, kernel_size=3, stride=1, padding=0, dilation=1)
def forward(self, x):
x = self.conv2(x)
return x
jiuchong = example()
writer = SummaryWriter("./logs")
step = 0
for data in dataloader:
imgs, targets = data
outputs = jiuchong(imgs)
print(imgs.shape)
print(outputs.shape)
writer.add_images("input", imgs, step)
outputs = torch.reshape(outputs, (-1, 3, 30, 30))
writer.add_images("output", outputs, step)
step = step + 1
输出结果:
池化层被用来减少特征图的尺寸。因此,它减少了需要学习的参数数量和网络中执行的计算量。池化层总结了由卷积层生成的特征图的某个区域中存在的特征。因此,进一步的 *** 作是在总结的特征上进行的,而不是由卷积层产生的精确定位的特征。这使得该模型对输入图像中的特征位置的变化更加稳健。
4.1 Max Pooling 最大池化层最大池化是一种池化 *** 作,从过滤器所覆盖的特征图区域中选择最大的元素。因此,最大集合层后的输出将是一个包含前一个特征图中最突出特征的特征图。
4.1.1 torch.nn.functional.max_pool2d参数:
torch.nn.functional.max_pool2d(input, kernel_size, stride=None, padding=0, dilation=1, ceil_mode=False, return_indices=False)
解析:
input - 输入张量(minibatch,in_channels,iH,iW),
kernel_size - 池化区域的大小。可以是一个单一的数字或一个元组(kH, kW)
stride - 池化 *** 作的跨度。可以是单个数字或一个元组(sH, sW)。默认值:kernel_size
padding - 隐含的负无穷大的padding要加在两边,必须>= 0并且<= kernel_size / 2。
dilation - 滑动窗口内元素之间的跨度,必须>0。
ceil_mode - 如果为真,将使用ceil而不是floor来计算输出形状。这可以确保输入张量中的每个元素都被滑动窗口所覆盖。
return_indices - 如果为真,将返回argmax和最大值。对以后的 torch.nn.functional.max_unpool2d 有用。
【PS:这就不一详细说了,与卷积层的参数相似。需要注意:stride的默认值是 kernel_size。并且ceil_mode:如果为True时,会使用向上取整代替默认的向下取整 *** 作来计算输出的形状.后边会举个例子】
4.1.2 torch.nn.MaxPool2d参数:
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
解析:
kernel_size - 窗口的大小,取其最大值
stride - 窗口的跨度。默认值是kernel_size
padding - 隐含的零填充,在两边添加。
dilation - 一个控制窗口中元素的跨度的参数
return_indices - 如果为真,将与输出一起返回最大索引。对以后的 torch.nn.MaxUnpool2d 有用。
ceil_mode - 如果为真,将使用ceil而不是floor来计算输出形状。
4.1.3 ceil_mode参数(1) ceil_mode = False
(2) ceil_mode = True
(1)ceil_mode=False
import torch
import torch.nn.functional as F
a = torch.arange(1, 26,dtype=torch.float32)
inputs = a.view(5, 5)
print(inputs)
inputs = torch.reshape(inputs,(1,1,5,5))
outputs =F.max_pool2d(inputs,3,ceil_mode=False)
print(outputs)
输出结果:
tensor([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.],
[11., 12., 13., 14., 15.],
[16., 17., 18., 19., 20.],
[21., 22., 23., 24., 25.]])
tensor([[[[13.]]]])
进程已结束,退出代码0
(2)ceil_mode=True
输出结果
tensor([[ 1., 2., 3., 4., 5.],
[ 6., 7., 8., 9., 10.],
[11., 12., 13., 14., 15.],
[16., 17., 18., 19., 20.],
[21., 22., 23., 24., 25.]])
tensor([[[[13., 15.],
[23., 25.]]]])
进程已结束,退出代码0
4.1.4.2 nn.MaxPool2d例子
【PS:效果与上相同】
import torch
from torch import nn
class example(nn.Module):
def __init__(self):
super(example, self).__init__()
self.maxPool = nn.MaxPool2d(3, ceil_mode=False)
def forward(self, x):
x = self.maxPool(x)
return x
jiuchong = example()
a = torch.arange(1, 26, dtype=torch.float32)
inputs = a.view(5, 5)
print(inputs)
inputs = torch.reshape(inputs, (1, 1, 5, 5), )
outputs = jiuchong(inputs)
print(outputs)
【今天就简单的介绍了卷积层和池化层的一些简单例子,对部分常用参数进行详细的介绍。如果您觉得文章对您有帮助,可以点击【点赞】!短短的路走走停停,这图画的自己都佩服哈哈!】
本文作者:九重!
本文链接:https://blog.csdn.net/weixin_43798572/article/details/124385802
关于博主:评论和私信会在第一时间回复。或者直接私信我。
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【点赞】【收藏】一下。您的鼓励是博主的最大动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)