• 【Pytorch笔记】7.torch.nn (Convolution Layers)


    我们常用torch.nn来封装网络,torch.nn为我们封装好了很多神经网络中不同的层,如卷积层、池化层、归一化层等。我们会把这些层像是串成一个牛肉串一样串起来,形成网络。

    先从最简单的,都有哪些层开始学起。

    Convolution Layers - 卷积层

    torch.nn.Conv1d()

    1维卷积层。

    torch.nn.Conv1d(in_channels, 
    				out_channels, 
    				kernel_size, 
    				stride=1, 
    				padding=0, 
    				dilation=1, 
    				groups=1, 
    				bias=True, 
    				padding_mode='zeros', 
    				device=None, 
    				dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    in_channels:输入tensor的通道数;
    out_channels:输出tensor的通道数;
    kernel_size:卷积核的大小;
    stride:步长;
    padding:输入tensor的边界填充尺寸;
    dilation:卷积核之间的间距(下面这个图为dilation=2),默认为1;
    在这里插入图片描述

    groups:从输入通道到输出通道的阻塞连接数。in_channelout_channel需要能被groups整除。更具体地:
    groups=1时所有输入均与所有输出进行卷积,groups=2时该操作相当于并排设置两个卷积层,每卷积层看到一半的输入通道,产生一半的输出通道,然后将两个卷积层连接起来。groups=in_channel时输入的每个通道都和相应的卷积核进行卷积;
    bias:是否添加可学习的偏差值,True为添加,False为不添加。
    padding_mode:填充模式,有以下取值:zeros(这个是默认值)、reflectreplicatecircular

    import torch
    import torch.nn as nn
    
    m = nn.Conv1d(in_channels=16,
                  out_channels=33,
                  kernel_size=3,
                  stride=2)
    # input: 批大小为20,每个数据通道为16,size=50
    input = torch.randn(20, 16, 50)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    输出

    # output: 批大小为20,每个数据通道为33,size=24
    torch.Size([20, 33, 24])
    
    • 1
    • 2

    torch.nn.Conv2d()

    2维卷积层。

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    参数与Conv1d()基本一样,不再赘述。

    import torch
    import torch.nn as nn
    
    m = nn.Conv2d(in_channels=2,
                  out_channels=3,
                  kernel_size=3,
                  stride=2)
    input = torch.randn(20, 2, 5, 6)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出

    torch.Size([20, 3, 2, 2])
    
    • 1

    torch.nn.Conv3d()

    3维卷积层。

    torch.nn.Conv3d(in_channels, 
    			    out_channels, 
    			    kernel_size, 
    			    stride=1, 
    			    padding=0, 
    			    dilation=1, 
    			    groups=1, 
    			    bias=True, 
    			    padding_mode='zeros', 
    			    device=None, 
    			    dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    参数与Conv1d()基本一样,不再赘述。

    import torch
    import torch.nn as nn
    
    m = nn.Conv3d(in_channels=2,
                  out_channels=3,
                  kernel_size=3,
                  stride=2)
    input = torch.randn(20, 2, 4, 5, 6)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出

    torch.Size([20, 3, 1, 2, 2])
    
    • 1

    torch.nn.ConvTranspose1d()

    1维转置卷积层。

    torch.nn.ConvTranspose1d(in_channels, 
    						 out_channels, 
    						 kernel_size, 
    						 stride=1, 
    						 padding=0, 
    						 output_padding=0, 
    						 groups=1, 
    						 bias=True, 
    						 dilation=1, 
    						 padding_mode='zeros', 
    						 device=None, 
    						 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    参数与Conv1d()基本一样,不再赘述。
    唯一不同的output_padding,与padding不同的是,output_padding是输出tensor的每一个边,外面填充的层数。
    padding是输入tensor的每个边填充的层数)

    import torch
    import torch.nn as nn
    
    m = nn.ConvTranspose1d(in_channels=2,
                           out_channels=3,
                           kernel_size=3,
                           stride=1)
    input = torch.randn(20, 2, 2)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出

    torch.Size([20, 3, 4])
    
    • 1

    torch.nn.ConvTranspose2d()

    2维转置卷积层。

    torch.nn.ConvTranspose2d(in_channels, 
    						 out_channels, 
    						 kernel_size, 
    						 stride=1, 
    						 padding=0, 
    						 output_padding=0, 
    						 groups=1, 
    						 bias=True, 
    						 dilation=1, 
    						 padding_mode='zeros', 
    						 device=None, 
    						 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    参数与Conv1d()基本一样,不再赘述。

    import torch
    import torch.nn as nn
    
    m = nn.ConvTranspose2d(in_channels=2,
                           out_channels=3,
                           kernel_size=3,
                           stride=1)
    input = torch.randn(20, 2, 2, 2)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出

    torch.Size([20, 3, 4, 4])
    
    • 1

    torch.nn.ConvTranspose3d()

    3维转置卷积层。

    torch.nn.ConvTranspose3d(in_channels, 
    						 out_channels, 
    						 kernel_size, 
    						 stride=1, 
    						 padding=0, 
    						 output_padding=0, 
    						 groups=1, 
    						 bias=True, 
    						 dilation=1, 
    						 padding_mode='zeros', 
    						 device=None, 
    						 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    参数与Conv1d()基本一样,不再赘述。

    import torch
    import torch.nn as nn
    
    m = nn.ConvTranspose3d(in_channels=2,
                           out_channels=3,
                           kernel_size=3,
                           stride=1)
    input = torch.randn(20, 2, 2, 2, 2)
    output = m(input)
    print(output.size())
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出

    torch.Size([20, 3, 4, 4, 4])
    
    • 1

    torch.nn.LazyConv1d()

    1维延迟初始化卷积层,当in_channel不确定时可使用这个层。
    关于延迟初始化,大家可以参考这篇文章,我认为讲的很好:
    俱往矣… - 延迟初始化——【torch学习笔记】

    torch.nn.LazyConv1d(out_channels, 
    					kernel_size, 
    					stride=1, 
    					padding=0, 
    					dilation=1, 
    					groups=1, 
    					bias=True, 
    					padding_mode='zeros', 
    					device=None, 
    					dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    LazyConv1d没有in_channel参数
    这不代表这个层没有输入的通道,而是在调用时自动适配,并进行初始化。
    引用文章中的一段代码,改成LazyConv1d,讲述使用方法。

    import torch
    import torch.nn as nn
    
    net = nn.Sequential(
        nn.LazyConv1d(256, 2),
        nn.ReLU(),
        nn.Linear(9, 10)
    )
    print(net)
    [net[i].state_dict() for i in range(len(net))]
    
    low = torch.finfo(torch.float32).min / 10
    high = torch.finfo(torch.float32).max / 10
    X = torch.zeros([2, 20, 10], dtype=torch.float32).uniform_(low, high)
    net(X)
    print(net)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出

    Sequential(
      (0): LazyConv1d(0, 256, kernel_size=(2,), stride=(1,))
      (1): ReLU()
      (2): Linear(in_features=9, out_features=10, bias=True)
    )
    Sequential(
      (0): Conv1d(20, 256, kernel_size=(2,), stride=(1,))
      (1): ReLU()
      (2): Linear(in_features=9, out_features=10, bias=True)
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    可以看出,未进行初始化时,in_features=0。只有传入参数使用网络后才会根据输入进行初始化。

    torch.nn.LazyConv2d()

    2维延迟初始化卷积层。

    torch.nn.LazyConv2d(out_channels, 
    					kernel_size, 
    					stride=1, 
    					padding=0, 
    					dilation=1, 
    					groups=1, 
    					bias=True, 
    					padding_mode='zeros', 
    					device=None, 
    					dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    torch.nn.LazyConv3d()

    3维延迟初始化卷积层。

    torch.nn.LazyConv3d(out_channels, 
    					kernel_size, 
    					stride=1, 
    					padding=0, 
    					dilation=1, 
    					groups=1, 
    					bias=True, 
    					padding_mode='zeros', 
    					device=None, 
    					dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    torch.nn.LazyConvTranspose1d()

    1维延迟初始化转置卷积层。

    torch.nn.LazyConvTranspose1d(out_channels, 
    							 kernel_size, 
    							 stride=1, 
    							 padding=0, 
    							 output_padding=0, 
    							 groups=1, 
    							 bias=True, 
    							 dilation=1, 
    							 padding_mode='zeros', 
    							 device=None, 
    							 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    torch.nn.LazyConvTranspose2d()

    2维延迟初始化转置卷积层。

    torch.nn.LazyConvTranspose2d(out_channels, 
    							 kernel_size, 
    							 stride=1, 
    							 padding=0, 
    							 output_padding=0, 
    							 groups=1, 
    							 bias=True, 
    							 dilation=1, 
    							 padding_mode='zeros', 
    							 device=None, 
    							 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    torch.nn.LazyConvTranspose3d()

    3维延迟初始化转置卷积层。

    torch.nn.LazyConvTranspose3d(out_channels, 
    							 kernel_size, 
    							 stride=1, 
    							 padding=0, 
    							 output_padding=0, 
    							 groups=1, 
    							 bias=True, 
    							 dilation=1, 
    							 padding_mode='zeros', 
    							 device=None, 
    							 dtype=None)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    torch.nn.Unfold()

    从一个批次的输入张量中提取出滑动的局部区域块。

    torch.nn.Unfold(kernel_size, 
    				dilation=1, 
    				padding=0, 
    				stride=1)
    
    • 1
    • 2
    • 3
    • 4

    kernel_size:滑动块的大小;
    dilation:卷积核之间的间距(torch.nn.Conv1d中有图示);
    padding:输入tensor的边界填充尺寸;
    stride:滑块滑动的步长。

    这里的输入必须是4维的tensor,否则会报这样的错误:

    NotImplementedError: Input Error: Only 4D input Tensors are supported (got 2D)
    
    • 1

    示例

    import torch
    from torch import nn
    
    
    t = torch.tensor([[[[1.,  2.,  3.,  4.],
                        [5.,  6.,  7.,  8.],
                        [9.,  10., 11., 12.],
                        [13., 14., 15., 16.],]]])
    
    unfold = nn.Unfold(kernel_size=(2, 2), dilation=1, padding=0, stride=1)
    output = unfold(t)
    print(output)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    输出

    tensor([[[ 1.,  2.,  3.,  5.,  6.,  7.,  9., 10., 11.],
             [ 2.,  3.,  4.,  6.,  7.,  8., 10., 11., 12.],
             [ 5.,  6.,  7.,  9., 10., 11., 13., 14., 15.],
             [ 6.,  7.,  8., 10., 11., 12., 14., 15., 16.]]])
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    torch.nn.Fold()

    Unfold()的逆操作。当Unfold()时出现滑块有重复覆盖时会导致结果和原来不一样。因为Fold()的过程中对于同一个位置的元素进行加法处理。

    torch.nn.Fold(output_size, 
    			  kernel_size, 
    			  dilation=1, 
    			  padding=0, 
    			  stride=1)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    下面是Unfold()和Fold()结合的代码,Unfold()部分和上面代码相同。

    import torch
    from torch import nn
    
    t = torch.tensor([[[[1., 2., 3., 4.],
                      [5., 6., 7., 8.],
                      [9., 10., 11., 12.],
                      [13., 14., 15., 16.]]]])
    
    unfold = nn.Unfold(kernel_size=(2, 2), dilation=1, padding=0, stride=1)
    output = unfold(t)
    print(output)
    fold = nn.Fold(output_size=(4, 4), kernel_size=(2, 2))
    out = fold(output)
    print(out)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    输出

    tensor([[[ 1.,  2.,  3.,  5.,  6.,  7.,  9., 10., 11.],
             [ 2.,  3.,  4.,  6.,  7.,  8., 10., 11., 12.],
             [ 5.,  6.,  7.,  9., 10., 11., 13., 14., 15.],
             [ 6.,  7.,  8., 10., 11., 12., 14., 15., 16.]]])
    tensor([[[[ 1.,  4.,  6.,  4.],
              [10., 24., 28., 16.],
              [18., 40., 44., 24.],
              [13., 28., 30., 16.]]]])
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
  • 相关阅读:
    云原生系统学习[Kubernetes]——02 Pod、Deployment、Service
    springboot+基于Java的果蔬产品销售系统 毕业设计-附源码131110
    Vue极简教程,初识Vue前端框架
    C++ 围炉札记
    android学习笔记(三)
    YARN调优
    AI编程工具合集整理优缺点
    mac安装mysql,php,nginx,phpmyadmin,配置访问数据库
    Office 2021 小型企业版商用办公软件评测:提升工作效率与协作能力的专业利器
    R语言七天入门教程六:文件相关操作
  • 原文地址:https://blog.csdn.net/xhyu61/article/details/133643860