卷积函数
注:
函数语法、参数介绍、shape、变量、Example,均转自 PyTorch 中文手册。
说实话 PyTorch 中文手册 对于参数in_channels
和out_channels
的讲解还是不够详细。
所以我参考了另一篇博客 【PyTorch学习笔记】17:2D卷积,nn.Conv2d和F.conv2d 来讲解这两个参数的意义。
函数语法:
- 一维
class torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
- 二维
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
- 三维
class torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
关于卷积层函数各参数的含义,详见Convolution arithmetic ,其动态图演示很形象。
参数介绍:
- in_channels(
int
) – 输入信号的通道 - out_channels(
int
) – 卷积产生的通道 - kerner_size(
int
ortuple
) - 卷积核的尺寸 - stride(
int
ortuple
,optional
) - 卷积步长 - padding (
int
ortuple
,optional
)- 输入的每一条边补充0的层数 - dilation(
int
ortuple
,optional
) – 卷积核元素之间的间距 - groups(
int
,optional
) – 从输入通道到输出通道的阻塞连接数 - bias(
bool
,optional
) - 如果bias=True,添加偏置
shape:
- 一维卷积层:
输入: (N,Cin,Lin)
输出: (N,Cout,Lout)
输入输出的计算方式 - 二维卷积层:
输入: (N,C_in,H_in,W_in)
输出: (N,C_out,H_out,W_out)
输入输出的计算方式 - 三维卷积层
输入: (N,C_in,D_in,H_in,W_in)
输出: (N,C_out,D_out,H_out,W_out)
输入输出的计算方式
变量
- weight(
tensor
) - 卷积的权重,大小是(out_channels
,in_channels
,kernel_size
) - bias(
tensor
) - 卷积的偏置系数,大小是(out_channel
)
Example:
一维卷积层
m = nn.Conv1d(16, 33, 3, stride=2)
input = autograd.Variable(torch.randn(20, 16, 50))
output = m(input)
二维卷积层
# With square kernels and equal stride
m = nn.Conv2d(16, 33, 3, stride=2)
# non-square kernels and unequal stride and with padding
m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))
# non-square kernels and unequal stride and with padding and dilation
m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
input = autograd.Variable(torch.randn(20, 16, 50, 100))
output = m(input)
三维卷积层
# With square kernels and equal stride
m = nn.Conv3d(16, 33, 3, stride=2)
# non-square kernels and unequal stride and with padding
m = nn.Conv3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(4, 2, 0))
input = autograd.Variable(torch.randn(20, 16, 10, 50, 100))
output = m(input)
参数in_channels
和 out_channels
的意义(参考文首博客):
以nn.Conv2d()
为例(因为Conv2d
用来处理图像问题,而且nn.
的使用频率大于F.
)
in_channels
指输入图像的通道数。
如灰度图像的in_channels
为 1;RGB图像的in_channels
为 3(忽略alpha通道)。
out_channels
直观理解是输入图像经过该卷积层之后的输出通道数。往深里说是“这个卷积核将输入图像从多少个通道 映射 到多少个通道上”。
而这个输出通道数,其实就是卷积核的种类数(一种卷积核对应一个输出通道)。
对于卷积核的种类数的种类数,在后面的示例中会有更直观的体现。
再单独把计算输出维度(非通道)的公式拿出来(默认步长stride
= 1)
- 不加padding:out_size = in_size - kernel_size + 1
- 加padding:out_size = in_size + 2*padding - kernel_size + 1
当步长stride
为 2 时,把步长stride
为 1 时的out_size
除 2 即可。
基本用法的示例:
import torch
from torch import nn
"""2维的卷积层,用于图片的卷积"""
# 输入图像的通道数=1(灰度图像),卷积核的种类数=3
# 卷积核的shape是3乘3的,扫描步长为1,不加padding
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=0)
"""要输入的原始图像"""
# 样本数=1,通道数=1,图像的shape是28乘28的
x = torch.rand(1, 1, 28, 28)
"""使用上面定义的卷积层layer和输入x,完成一次卷积的前向运算"""
out = layer.forward(x)
# 得到的还是1张图片,因为用了3种kernel所以输出的通道数变成3了
# 因为没加padding,原来28乘28的图像在3乘3卷积下得到的边长是28-3+1=26
print(out.shape) # torch.Size([1, 3, 26, 26])
"""添加padding看看"""
# 这次使用padding为1.所以原始图像上下左右都加了一层0
layer = nn.Conv2d(1, 3, kernel_size=3, stride=1, padding=1)
print(layer.forward(x).shape) # torch.Size([1, 3, 28, 28])
"""步长设置为2看看"""
# stride设置为2,也就是每次移动2格子(向上或者向右)
layer = nn.Conv2d(1, 3, kernel_size=3, stride=2, padding=1)
# 相当于每次跳1个像素地扫描,输出的Feature Map直接小了一半
print(layer.forward(x).shape) # torch.Size([1, 3, 14, 14])
"""实际使用时,应该这样用!"""
out = layer(x)
print(out.shape) # torch.Size([1, 3, 14, 14])
运行结果:
torch.Size([1, 3, 26, 26])
torch.Size([1, 3, 28, 28])
torch.Size([1, 3, 14, 14])
torch.Size([1, 3, 14, 14])
查看卷积层信息:
print(layer.weight)
print(layer.bias)
tensor([[[[ 0.1277, -0.1672, 0.1102],
[ 0.3176, 0.0236, 0.2537],
[ 0.0737, 0.0904, 0.0261]]],
[[[ 0.0349, -0.2042, 0.1766],
[-0.0938, -0.0470, 0.2011],
[-0.2460, 0.0876, 0.3124]]],
[[[-0.2361, -0.0971, -0.1031],
[-0.0756, -0.3073, 0.3227],
[-0.1951, -0.2395, -0.0769]]]], requires_grad=True)
Parameter containing:
tensor([ 0.0790, -0.3261, 0.0697], requires_grad=True)
解卷积函数(可近似视为)
- 一维
class torch.nn.ConvTranspose1d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
- 二维
class torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
- 三维
torch.nn.ConvTranspose3d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
一维的解卷积操作、二维的转置卷积操作(transposed convolution operator
,注意改视作操作可视作解卷积操作,但并不是真正的解卷积操作) 该模块可以看作是Conv1d
、Conv2d
、相对于其输入的梯度,有时(但不正确地)被称为解卷积操作。
三维的转置卷积操作(transposed convolution operator
,注意改视作操作可视作解卷积操作,但并不是真正的解卷积操作) 转置卷积操作将每个输入值和一个可学习权重的卷积核相乘,输出所有输入通道的求和。
该模块可以看作是Conv3d
相对于其输入的梯度,有时(但不正确地)被称为解卷积操作。
注意
由于内核的大小,输入的最后的一些列的数据可能会丢失。因为输入和输出不是完全的互相关。因此,用户可以进行适当的填充(padding操作)。
参数
- in_channels(
int
) – 输入信号的通道数 - out_channels(
int
) – 卷积产生的通道 - kernel_size(
int
ortuple
) - 卷积核的大小 - stride(
int
ortuple
,optional
) - 卷积步长 - padding(
int
ortuple
,optional
) - 输入的每一条边补充0的层数 - output_padding(
int
ortuple
,optional
) - 输出的每一条边补充0的层数 - dilation(
int
ortuple
,optional
) – 卷积核元素之间的间距 - groups(
int
,optional
) – 从输入通道到输出通道的阻塞连接数 - bias(
bool
,optional
) - 如果bias=True,添加偏置
shape:
- 一维解卷积
输入: (N,C_in,L_in)
输出: (N,C_out,L_out) - 二维转置卷积
输入: (N,C_in,H_in,W_in)
输出: (N,C_out,H_out,W_out)
- 三维转置卷积
输入: (N,C_in,H_in,W_in)
输出: (N,C_out,H_out,W_out)
变量:
- weight(
tensor
) - 卷积的权重,大小是(in_channels
,in_channels
,kernel_size
) - bias(
tensor
) - 卷积的偏置系数,大小是(out_channel
)
Example:
二维
# With square kernels and equal stride
m = nn.ConvTranspose2d(16, 33, 3, stride=2)
# non-square kernels and unequal stride and with padding
m = nn.ConvTranspose2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))
input = autograd.Variable(torch.randn(20, 16, 50, 100))
output = m(input)
# exact output size can be also specified as an argument
input = autograd.Variable(torch.randn(1, 16, 12, 12))
downsample = nn.Conv2d(16, 16, 3, stride=2, padding=1)
upsample = nn.ConvTranspose2d(16, 16, 3, stride=2, padding=1)
h = downsample(input)
h.size()
# torch.Size([1, 16, 6, 6])
output = upsample(h, output_size=input.size())
output.size()
# torch.Size([1, 16, 12, 12])
三维
# With square kernels and equal stride
m = nn.ConvTranspose3d(16, 33, 3, stride=2)
# non-square kernels and unequal stride and with padding
m = nn.Conv3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(0, 4, 2))
input = autograd.Variable(torch.randn(20, 16, 10, 50, 100))
output = m(input)