1. torch.Storage
一个 torch.Storage 是一个单一数据类型的连续一维数组。每个 torch.Tensor 都有一个对应的、相同数据类型的存储。
- byte():将此存储转为byte类型
- char():将此存储转为char类型
- clone():返回此存储的一个副本
- cpu():如果当前此存储不在 CPU 上,则返回一个它的 CPU 副本
- cuda(device=None, async=False):返回此对象在 CUDA 内存中的一个副本。如果此对象已在 CUDA 内存中且在正确的设备上,那么不会执行复制操作,直接返回原对象。
参数:
(1)device (int) - 目标 GPU 的 id。默认值是当前设备。
(2)async (bool) -如果值为 True,且源在锁定内存中,则副本相对于宿主是异步的。否则此参数不起效果。 - double():将此存储转为 double 类型
- float():将此存储转为 float 类型
- half():将此存储转为 half 类型
- int():将此存储转为 int 类型
- long():将此存储转为 long 类型
- short():将此存储转为 short 类型
- tolist():返回一个包含此存储中元素的列表
- type(new_type=None, async=False):将此对象转为指定类型。如果已经是正确类型,不会执行复制操作,直接返回原对象。参数:
(1)new_type (type or string) -需要转成的类型
(2)async (bool) -如果值为 True,且源在锁定内存中,则副本相对于宿主是异步的。否则此参数不起效果。
2.torch.nn
class torch.nn.Parameter()
:
Variable 的一种,常被用于模块参数(module parameter)。Parameters 是 Variable 的子类。 Paramenters 和 Modules 一起使用的时候会有一些特殊的属性,即:当Paramenters 赋值给 Module 的属性的时候,他会自动的被加到 Module 的 参数列表中(即:会出现在 parameters() 迭代器中)。将 Varibale 赋值给 Module 属性则不会有这样的影响。 这样做的原因是:我们有时候会需要缓存一些临时的状态(state), 比如:模型中 RNN 的最后一个隐状态。如果没有Parameter 这个类的话,那么这些临时变量也会注册成为模型变量。Variable 与 Parameter 的另一个不同之处在于, Parameter 不能被 volatile(即:无法设置 volatile=True)而且默认 requires_grad=True。 Variable 默认 requires_grad=False。class torch.nn.Module
:所有网络的基类。你的模型也应该继承这个类
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5)# submodule: Conv2d
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
通过上面方式赋值的 submodule 会被注册。当调用 .cuda() 的时候,submodule 的参数也会转换为 cuda Tensor。
add_module(name, module)
:将一个 child module 添加到当前 modle。 被添加的 module 可以通过 name 属性来获取。
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.add_module("conv", nn.Conv2d(10, 20, 4))
#self.conv = nn.Conv2d(10, 20, 4) 和上面这个增加 module 的方式等价
model = Model()
print(model.conv)
# Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
print(model.children())
- children():返回当前模型 子模块的迭代器。
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.add_module("conv", nn.Conv2d(10, 20, 4))
self.add_module("conv1", nn.Conv2d(20 ,10, 4))
model = Model()
for sub_module in model.children():
print(sub_module)
# Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
# Conv2d(20, 10, kernel_size=(4, 4), stride=(1, 1))
- cpu(device_id=None):将所有的模型参数(parameters)和 buffers 复制到 CPU
- cuda(device_id=None):将所有的模型参数(parameters)和 buffers 赋值 GPU
- eval():将模型设置成 evaluation 模式,仅仅当模型中有 Dropout 和 BatchNorm 是才会有影响。
- float():将 parameters 和 buffers 的数据类型转换成 float。
- forward(* input):定义了每次执行的 计算步骤。 在所有的子类中都需要重写这个函数。
- half():将 parameters 和 buffers 的数据类型转换成 half。
- load_state_dict(state_dict):将 state_dict 中的 parameters 和 buffers 复制到此 module 和它的子类中。 state_dict 中的 key 必须和 model.state_dict()返回的 key 一致。 NOTE:用来加载模型参数。
- modules():返回一个包含 当前模型 所有模块的迭代器。
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.add_module("conv", nn.Conv2d(10, 20, 4))
self.add_module("conv1", nn.Conv2d(20 ,10, 4))
model = Model()
for module in model.modules():
print(module)
# Model(
# (conv): Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
# (conv1): Conv2d(20, 10, kernel_size=(4, 4), stride=(1, 1))
# )
# Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
# Conv2d(20, 10, kernel_size=(4, 4), stride=(1, 1))
可以看出, modules()返回的 iterator 不止包含 子模块。这是和 children()的不同。NOTE: 重复的模块只被返回一次(children()也是)。 在下面的例子中, submodule 只会被返回一次:
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
submodule = nn.Conv2d(10, 20, 4)
self.add_module("conv", submodule )
self.add_module("conv1", submodule )
model = Model()
for module in model.modules():
print(module)
# Model(
# (conv): Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
# (conv1): Conv2d(20, 10, kernel_size=(4, 4), stride=(1, 1))
# )
# Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
- named_children():返回 包含 模型当前子模块 的 模块名字和模块本身的迭代器。
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
submodule = nn.Conv2d(10, 20, 4)
self.add_module("conv", submodule )
self.add_module("conv1", submodule )
model = Model()
for name, module in model.named_children():
if name in ["conv"]:
print(module)
# Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
注意:重复的模块只被返回一次(children()也是)。
- parameters(memo=None):返回一个 包含模型所有参数 的迭代器。一般用来当作 optimizer 的参数。
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.add_module("conv", nn.Conv2d(10, 20, 4))
self.add_module("conv1", nn.Conv2d(20 ,10, 4))
model = Model()
for param in model.parameters():
print(type(param.data), param.size())
# <class 'torch.Tensor'> torch.Size([20, 10, 4, 4])
# <class 'torch.Tensor'> torch.Size([20])
# <class 'torch.Tensor'> torch.Size([10, 20, 4, 4])
# <class 'torch.Tensor'> torch.Size([10])
- register_backward_hook(hook):
在 module 上注册一个 bachward hook。每次计算 module 的 inputs 的梯度的时候,这个 hook 会被调用。 hook 应该拥有下面的 signature。hook(module, grad_input, grad_output) -> Variable or None如果 module 有多个输入输出的话,那么 grad_input grad_output 将会是个 tuple。 hook 不应该修改它的arguments,但是它可以选择性的返回关于输入的梯度,这个返回的梯度在后续的计算中会替代grad_input。这个函数返回一个句柄(handle)。它有一个方法 handle.remove(),可以用这个方法将 hook 从 module移除。 - register_buffer(name, tensor):给 module 添加一个 persistent buffer。persistent buffer 通常被用在这么一种情况:我们需要保存一个状态,但是这个状态不能看作成为模型参数。 例如: , BatchNorm’s running_mean 不是一个 parameter, 但是它也是需要保存的状态之一。Buffers 可以通过注册时候的 name 获取。
NOTE:我们可以用 buffer 保存移动平均
self.register_buffer('running_mean', torch.zeros(num_features))
- register_forward_hook(hook):在 module 上注册一个 forward hook。 每次调用forward()计算输出的时候,这个 hook 就会被调用。它应该拥有以下签名:
hook(module, input, output) -> None
,hook 不 应 该 修 改 input 和 output 的 值 。 这 个 函 数 返 回 一 个 句 柄 (handle) 。 它 有 一 个 方 法 handle.remove(),可以用这个方法将 hook 从 module 移除。 - register_parameter(name, param):向 module 添加 parameter。parameter 可以通过注册时候的 name 获取。
- state_dict(destination=None, prefix=’’):返回一个字典,保存着module的所有状态。parameters和persistent buffers都会包含在字典中,字典的key就是parameter和buffer的names。
import torch
import torch.nn as nn
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv2 = nn.Linear(1,2)
self.vari = torch.rand([1])
self.par = torch.rand([1])
self.register_buffer("buffer", torch.randn([2,3]))
model = Model()
print(model.state_dict().keys())
# odict_keys(['buffer', 'conv2.weight', 'conv2.bias'])
train(mode=True)
:将 module 设置为 training mode。仅仅当模型中有 Dropout 和 BatchNorm 是才会有影响。zero_grad()
:将 module 中的所有模型参数的梯度设置为 0.class torch.nn.Sequential(* args)
:一个时序容器。 Modules 会以他们传入的顺序被添加到容器中。当然,也可以传入一个 OrderedDict。为了更容易的理解如何使用 Sequential, 下面给出了一个例子:
import torch
import torch.nn as nn
from collections import OrderedDict
model1 = nn.Sequential(nn.Conv2d(1, 20, 5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU())
model2 = nn.Sequential(OrderedDict([
("conv1",nn.Conv2d(1, 20, 5)),
("relu1",nn.ReLU()),
("conv2",nn.Conv2d(20, 64, 5)),
("relu2",nn.ReLU())
]))
print(model1.state_dict().keys())
print(model2.state_dict().keys())
# odict_keys(['0.weight', '0.bias', '2.weight', '2.bias'])
# odict_keys(['conv1.weight', 'conv1.bias', 'conv2.weight', 'conv2.bias'])
class torch.nn.ModuleList(modules=None)
:将 submodules 保存在一个 list 中。ModuleList 可以像一般的 Python list 一样被索引。而且 ModuleList 中包含的 modules 已经被正确的注册,对所有的 module method 可见。
import torch
from torch import nn
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.linears = nn.ModuleList([nn.Linear(10, 10) for i in range(10)])
def forward(self, x):
for i, l in enumerate(self.linears):
x = self.linears[i//2](x) + l(x)
return x
model1 = MyModule()
print(model1.state_dict().keys())
# odict_keys(['linears.0.weight', 'linears.0.bias', 'linears.1.weight',
# 'linears.1.bias', 'linears.2.weight', 'linears.2.bias', 'linears.3.weight',
# 'linears.3.bias', 'linears.4.weight', 'linears.4.bias', 'linears.5.weight',
# 'linears.5.bias', 'linears.6.weight', 'linears.6.bias', 'linears.7.weight',
# 'linears.7.bias', 'linears.8.weight', 'linears.8.bias', 'linears.9.weight',
# 'linears.9.bias'])
class torch.nn.ParameterList(parameters=None)
:ParameterList 可以像一般的 Python list 一样被索引。而且 ParameterList 中包含的 parameters 已经被正确的注册,对所有的 module method 可见。
class MyModule(nn.Module):
def __init__(self):
super(MyModule, self).__init__()
self.params = nn.ParameterList([nn.Parameter(torch.randn(10, 10)) for i in range(10)])
def forward(self, x):
# ParameterList can act as an iterable, or be indexed using ints
for i, p in enumerate(self.params):
x = self.params[i // 2].mm(x) + p.mm(x)
return x
有像python一样的append和extend方法。
3.卷积层
class torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
:一维卷积层,输入的尺度是 ( N , C i n , L ) (N, C_{in},L) (N,Cin,L),输出尺度 ( N , C o u t , L o u t ) ( N,C_{out},L_{out}) (N,Cout,Lout)的计算方式:
o u t ( N i , C o u t j ) = b i a s ( C o u t j ) + ∑ k = 0 C i n − 1 w e i g h t ( C o u t j , k ) ⨂ i n p u t ( N i , k ) out(N_i, C_{out_j})=bias(C {out_j})+\sum^{C{in}-1}_{k=0}weight(C{out_j},k)\bigotimes input(N_i,k) out(Ni,Coutj)=bias(Coutj)+k=0∑Cin−1weight(Coutj,k)⨂input(Ni,k)
主要参数:
(1)dilation:用于控制kernel的核点之间的距离,参考这里
(2)groups:控制输入和输出之间的连接, group=1,输出是所有的输入的卷积; group=2,此时相当于有并排的两个卷积层,每个卷积层计算输入通道的一半,并且产生的输出是输出通道的一半,随后将这两个输出连接起来。
假设输入尺度: ( N , C i n , L i n ) (N, C_{in},L_{in}) (N,Cin,Lin),输出尺度 ( N , C o u t , L o u t ) (N, C_{out},L_{out}) (N,Cout,Lout),输入输出的计算方式: L o u t = f l o o r ( ( L i n + 2 p a d d i n g − d i l a t i o n ( k e r n e r l _ s i z e − 1 ) − 1 ) / s t r i d e + 1 ) L_{out}=floor((L_{in}+2padding-dilation(kernerl\_size-1)-1)/stride+1) Lout=floor((Lin+2padding−dilation(kernerl_size−1)−1)/stride+1)
import torch
import torch.nn as nn
m = nn.Conv1d(16, 33, 3, stride=2)
input = torch.randn(20, 16, 50)
output = m(input)
print(output.shape)
# torch.Size([20, 33, 24])
class torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
:
参数 kernel_size, stride,padding, dilation 也可以是一个 int 的数据,此时卷积 height 和 width 值相同;也可以是一个 tuple 数组, tuple 的第一维度表示 height 的数值, tuple 的第二维度表示 width 的数值。如果 bias=True,添加偏置。
假设输入尺度: ( N , C i n , H i n , W i n ) (N, C_{in},H_{in},W_{in}) (N,Cin,Hin,Win),输出尺度 ( N , C o u t , H o u t , W o u t ) (N, C_{out},H_{out},W_{out}) (N,Cout,Hout,Wout),输入输出的计算方式:
H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ( k e r n e r l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 0 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] ( k e r n e r l _ s i z e [ 1 ] − 1 ) − 1 ) / s t r i d e [ 1 ] + 1 ) H_{out}=floor((H_{in}+2padding[0]-dilation[0](kernerl\_size[0]-1)-1)/stride[0]+1)\\W_{out}=floor((W_{in}+2padding[1]-dilation[1](kernerl\_size[1]-1)-1)/stride[1]+1) Hout=floor((Hin+2padding[0]−dilation[0](kernerl_size[0]−1)−1)/stride[0]+1)Wout=floor((Win+2padding[1]−dilation[1](kernerl_size[1]−1)−1)/stride[1]+1)
import torch
import torch.nn as nn
m = nn.Conv2d(16, 33, 3, stride=2)
input = torch.randn(20, 16, 50, 100)
output = m(input)
print(output.shape)
# torch.Size([20, 33, 24, 49])
class torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
:
三维卷积层, 输入的尺度是 ( N , C i n , D , H , W ) (N, C_{in},D,H,W) (N,Cin,D,H,W),输出尺度 ( N , C o u t , D o u t , H o u t , W o u t ) ( N,C_{out},D_{out},H_{out},W_{out}) (N,Cout,Dout,Hout,Wout)
D o u t = f l o o r ( ( D i n + 2 p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ( k e r n e r l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 0 ] + 1 ) H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 1 ] − d i l a t i o n [ 2 ] ( k e r n e r l _ s i z e [ 1 ] − 1 ) − 1 ) / s t r i d e [ 1 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 2 ] − d i l a t i o n [ 2 ] ( k e r n e r l _ s i z e [ 2 ] − 1 ) − 1 ) / s t r i d e [ 2 ] + 1 ) D_{out}=floor((D_{in}+2padding[0]-dilation[0](kernerl\_size[0]-1)-1)/stride[0]+1) \\H_{out}=floor((H_{in}+2padding[1]-dilation[2](kernerl\_size[1]-1)-1)/stride[1]+1)\\W_{out}=floor((W_{in}+2padding[2]-dilation[2](kernerl\_size[2]-1)-1)/stride[2]+1) Dout=floor((Din+2padding[0]−dilation[0](kernerl_size[0]−1)−1)/stride[0]+1)Hout=floor((Hin+2padding[1]−dilation[2](kernerl_size[1]−1)−1)/stride[1]+1)Wout=floor((Win+2padding[2]−dilation[2](kernerl_size[2]−1)−1)/stride[2]+1)
参数 kernel_size, stride, padding, dilation 可以是一个 int 的数据 - 卷积 height 和 width 值相同,也可以是一个有三个 int 数据的 tuple 数组, tuple 的第一维度表示 depth 的数值, tuple 的第二维度表示height 的数值, tuple 的第三维度表示 width 的数值
import torch
import torch.nn as nn
m1 = nn.Conv3d(16, 33, 3, stride=2)
m2 = nn.Conv3d(16, 33, (3, 5, 2), stride=(2,1,1), padding=(4, 2, 0))
input = torch.randn(20, 16, 10, 50, 100)
output1 = m1(input)
print(output1.shape)
# torch.Size([20, 33, 4, 24, 49])
output2 = m2(input)
print(output2.shape)
# torch.Size([20, 33, 8, 50, 99])
torch.nn.ConvTranspose1d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
:由于内核的大小,输入的最后的一些列的数据可能会丢失。用户可以进行适当的填充(padding 操作)。
重要参数:
(1):padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
(2):output_padding(int or tuple, optional) - 输出的每一条边补充 0 的层数
输入尺寸: ( N , C i n , L i n ) (N,C_{in},L_{in}) (N,Cin,Lin)
输出尺寸: ( N , C o u t , L o u t ) (N,C_{out},L_{out}) (N,Cout,Lout)
L o u t = ( L i n − 1 ) s t r i d e − 2 p a d d i n g + k e r n e l _ s i z e + o u t p u t _ p a d d i n g L_{out}=(L_{in}-1)stride-2padding+kernel\_size+output\_padding Lout=(Lin−1)stride−2padding+kernel_size+output_padding
import torch
import torch.nn as nn
m = nn.ConvTranspose1d(16, 33, 3, stride=2, padding=1, output_padding=1)
input = torch.randn(20, 16, 100)
output = m(input)
print(output.shape)
# torch.Size([20, 33, 200])
torch.nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
:2 维的转置卷积操作,由于内核的大小,输入的最后的一些列的数据可能会丢失。用户可以进行适当的填充(padding 操作)。
重要参数:
(1):padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
(2):output_padding(int or tuple, optional) - 输出的每一条边补充 0 的层数
输入尺寸:
(
N
,
C
_
i
n
,
H
_
i
n
,
W
_
i
n
)
(N,C\_in,H\_in, W\_in)
(N,C_in,H_in,W_in)
输出尺寸:
(
N
,
C
_
o
u
t
,
H
_
o
u
t
,
W
_
o
u
t
)
(N,C\_out,H\_out,W\_out)
(N,C_out,H_out,W_out)
H
o
u
t
=
(
H
i
n
−
1
)
s
t
r
i
d
e
[
0
]
−
2
p
a
d
d
i
n
g
[
0
]
+
k
e
r
n
e
l
_
s
i
z
e
[
0
]
+
o
u
t
p
u
t
_
p
a
d
d
i
n
g
[
0
]
W
o
u
t
=
(
W
i
n
−
1
)
s
t
r
i
d
e
[
1
]
−
2
p
a
d
d
i
n
g
[
1
]
+
k
e
r
n
e
l
_
s
i
z
e
[
1
]
+
o
u
t
p
u
t
_
p
a
d
d
i
n
g
[
1
]
H_{out}=(H_{in}-1)stride[0]-2padding[0]+kernel\_size[0]+output\_padding[0]\\W_{out}=(W_{in}-1)stride[1]-2padding[1]+kernel\_size[1]+output\_padding[1]
Hout=(Hin−1)stride[0]−2padding[0]+kernel_size[0]+output_padding[0]Wout=(Win−1)stride[1]−2padding[1]+kernel_size[1]+output_padding[1]
import torch
import torch.nn as nn
m1 = nn.ConvTranspose2d(16, 33, 3, stride=2)
m2 = nn.ConvTranspose2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2))
input = torch.randn(20, 16, 50, 100)
output1 = m1(input)
output2 = m2(input)
print(output1.shape)
# torch.Size([20, 33, 101, 201])
print(output2.shape)
# torch.Size([20, 33, 93, 100])
input = 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)
down = downsample(input)
print(down.shape)
# torch.Size([1, 16, 6, 6])
up = upsample(down, output_size=input.size())
print(up.shape)
# torch.Size([1, 16, 12, 12])
torch.nn.ConvTranspose3d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
:3 维的转置卷积操作
由于内核的大小,输入的最后的一些列的数据可能会丢失。用户可以进行适当的填充(padding 操作)。
重要参数:
(1):padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
(2):output_padding(int or tuple, optional) - 输出的每一条边补充 0 的层数
输入: ( N , C i n , D i n , H i n , W i n ) (N,C_{in},D_{in},H_{in},W_{in}) (N,Cin,Din,Hin,Win)
输出: ( N , C o u t , D o u t , H o u t , W o u t ) (N,C_{out},D_{out},H_{out},W_{out}) (N,Cout,Dout,Hout,Wout)
D o u t = ( D i n − 1 ) s t r i d e [ 0 ] − 2 p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] + o u t p u t _ p a d d i n g [ 0 ] H o u t = ( H i n − 1 ) s t r i d e [ 1 ] − 2 p a d d i n g [ 1 ] + k e r n e l _ s i z e [ 1 ] + o u t p u t _ p a d d i n g [ 0 ] W o u t = ( W i n − 1 ) s t r i d e [ 2 ] − 2 p a d d i n g [ 2 ] + k e r n e l _ s i z e [ 2 ] + o u t p u t _ p a d d i n g [ 2 ] D_{out}=(D_{in}-1)stride[0]-2padding[0]+kernel\_size[0]+output\_padding[0]\\H_{out}=(H_{in}-1)stride[1]-2padding[1]+kernel\_size[1]+output\_padding[0]\\W_{out}=(W_{in}-1)stride[2]-2padding[2]+kernel\_size[2]+output\_padding[2] Dout=(Din−1)stride[0]−2padding[0]+kernel_size[0]+output_padding[0]Hout=(Hin−1)stride[1]−2padding[1]+kernel_size[1]+output_padding[0]Wout=(Win−1)stride[2]−2padding[2]+kernel_size[2]+output_padding[2]
import torch
import torch.nn as nn
m1 = nn.ConvTranspose3d(16, 33, 3, stride=2)
m2 = nn.ConvTranspose3d(16, 33, (3, 5, 2), stride=(2, 1, 1), padding=(0, 4, 2))
input = torch.randn(20, 16, 10, 50, 100)
output1 = m1(input)
output2 = m2(input)
print(output1.shape)
# torch.Size([20, 33, 21, 101, 201])
print(output2.shape)
# torch.Size([20, 33, 21, 46, 97])
torch.nn.MaxPool1d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
:对于输入信号的输入通道,提供 1 维最大池化(max pooling)操作。
输入: ( N , C i n , L i n ) (N,C_{in},L_{in}) (N,Cin,Lin)
输出: ( N , C o u t , L o u t ) (N,C_{out},L_{out}) (N,Cout,Lout)
L o u t = f l o o r ( ( L i n + 2 p a d d i n g − d i l a t i o n ( k e r n e l _ s i z e − 1 ) − 1 ) / s t r i d e + 1 ) L_{out}=floor((L_{in} + 2padding - dilation(kernel\_size - 1) - 1)/stride + 1) Lout=floor((Lin+2padding−dilation(kernel_size−1)−1)/stride+1)
import torch
import torch.nn as nn
m = nn.MaxPool1d(3, stride=2)
input = torch.randn(20, 16, 50)
output1 = m(input)
print(output.shape)
# torch.Size([20, 33, 200])
torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
:对于输入信号的输入通道,提供 2 维最大池化(max pooling)操作
输入: ( N , C i n , H i n , W i n ) (N,C_{in},H_{in},W_{in}) (N,Cin,Hin,Win)
输出: ( N , C o u t , H o u t , W o u t ) (N,C_{out},H_{out},W_{out}) (N,Cout,Hout,Wout)
H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ( k e r n e l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 0 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] ( k e r n e l _ s i z e [ 1 ] − 1 ) − 1 ) / s t r i d e [ 1 ] + 1 ) H_{out}=floor((H_{in} + 2padding[0] - dilation[0](kernel\_size[0] - 1) - 1)/stride[0] + 1)\\W_{out}=floor((W_{in} + 2padding[1] - dilation[1](kernel\_size[1] - 1) - 1)/stride[1] + 1) Hout=floor((Hin+2padding[0]−dilation[0](kernel_size[0]−1)−1)/stride[0]+1)Wout=floor((Win+2padding[1]−dilation[1](kernel_size[1]−1)−1)/stride[1]+1)
import torch
import torch.nn as nn
m1 = nn.MaxPool2d(3, stride=2)
m2 = nn.MaxPool2d((3,2), stride=(2,1))
input = torch.randn(20, 16, 50, 32)
output1 = m1(input)
output2 = m2(input)
print(output1.shape)
# torch.Size([20, 16, 24, 15])
print(output2.shape)
# torch.Size([20, 16, 24, 31])
torch.nn.MaxPool3d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
:对于输入信号的输入通道,提供 3 维最大池化(max pooling)操作
输入: ( N , C i n , D i n , H i n , W i n ) (N,C_{in},D_{in},H_{in},W_{in}) (N,Cin,Din,Hin,Win)
输出: ( N , C o u t , D o u t , H o u t , W o u t ) (N,C_{out},D_{out},H_{out},W_{out}) (N,Cout,Dout,Hout,Wout)
D o u t = f l o o r ( ( D i n + 2 p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ( k e r n e l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 0 ] + 1 ) H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] ( k e r n e l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 1 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 2 ] − d i l a t i o n [ 2 ] ( k e r n e l _ s i z e [ 2 ] − 1 ) − 1 ) / s t r i d e [ 2 ] + 1 ) D_{out}=floor((D_{in} + 2padding[0] - dilation[0](kernel\_size[0] - 1) - 1)/stride[0] + 1)\\H_{out}=floor((H_{in} + 2padding[1] - dilation[1](kernel\_size[0] - 1) - 1)/stride[1] + 1)\\W_{out}=floor((W_{in} + 2padding[2] - dilation[2](kernel\_size[2] - 1) - 1)/stride[2] + 1) Dout=floor((Din+2padding[0]−dilation[0](kernel_size[0]−1)−1)/stride[0]+1)Hout=floor((Hin+2padding[1]−dilation[1](kernel_size[0]−1)−1)/stride[1]+1)Wout=floor((Win+2padding[2]−dilation[2](kernel_size[2]−1)−1)/stride[2]+1)
import torch
import torch.nn as nn
m1 = nn.MaxPool3d(3, stride=2)
m2 = nn.MaxPool3d((3,2,2), stride=(2,1,2))
input = torch.randn(20, 16, 50, 44, 31)
output1 = m1(input)
output2 = m2(input)
print(output1.shape)
# torch.Size([20, 16, 24, 21, 15])
print(output2.shape)
# torch.Size([20, 16, 24, 43, 15])
torch.nn.MaxUnpool1d(kernel_size, stride=None, padding=0)
:MaxUnpool1d 输入 MaxPool1d 的输出,包括最大值的索引。MaxPool1d 可以将多个输入大小映射到相同的输出大小。
重要参数:
(1)kernel_size(int or tuple) - max pooling 的窗口大小
(2)stride(int or tuple, optional) - max pooling 的窗口移动的步长。默认值是 kernel_size
(3)padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
输入:
1)input:需要转换的 tensor
2)indices: Maxpool1d 的索引号
3)output_size:一个指定输出大小的 torch.Size
输入尺寸: ( N , C , H i n ) (N,C,H_{in}) (N,C,Hin)
输出尺寸: ( N , C , H o u t ) (N,C,H_{out}) (N,C,Hout)
H o u t = ( H i n − 1 ) s t r i d e [ 0 ] − 2 p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] H_{out}=(H_{in}-1)stride[0]-2padding[0]+kernel\_size[0] Hout=(Hin−1)stride[0]−2padding[0]+kernel_size[0]
import torch
import torch.nn as nn
pool = nn.MaxPool1d(2, stride=2, return_indices=True)
unpool = nn.MaxUnpool1d(2, stride=2)
input = torch.Tensor([[[1, 2, 3, 4, 5, 6, 7, 8]]])
output, indices = pool(input)
print(output, indices)
# tensor([[[2., 4., 6., 8.]]]) tensor([[[1, 3, 5, 7]]])
print(unpool(output, indices))
# tensor([[[0., 2., 0., 4., 0., 6., 0., 8.]]])
torch.nn.MaxUnpool2d(kernel_size, stride=None, padding=0)
:Maxpool2d 的逆过程,不过并不是完全的逆过程,因为在 maxpool2d 的过程中,一些最大值的已经丢失。 MaxUnpool2d 的输入是 MaxPool2d 的输出,包括最大值的索引。
重要参数:
(1)kernel_size(int or tuple) - max pooling 的窗口大小
(2)stride(int or tuple, optional) - max pooling 的窗口移动的步长。默认值是 kernel_size
(3)padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
输入:
1)input:需要转换的 tensor
2)indices: Maxpool2d 的索引号
3)output_size:一个指定输出大小的 torch.Size
输入尺寸: ( N , C , H i n , W i n ) (N,C,H_{in},W_{in}) (N,C,Hin,Win)
输出尺寸: ( N , C , H o u t , W o u t ) (N,C,H_{out},W_{out}) (N,C,Hout,Wout)
H o u t = ( H i n − 1 ) s t r i d e [ 0 ] − 2 p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] W o u t = ( W i n − 1 ) s t r i d e [ 1 ] − 2 p a d d i n g [ 1 ] + k e r n e l _ s i z e [ 1 ] H_{out}=(H_{in}-1)stride[0]-2padding[0]+kernel\_size[0]\\W_{out}=(W_{in}-1)stride[1]-2padding[1]+kernel\_size[1] Hout=(Hin−1)stride[0]−2padding[0]+kernel_size[0]Wout=(Win−1)stride[1]−2padding[1]+kernel_size[1]
import torch
import torch.nn as nn
pool = nn.MaxPool2d(2, stride=2, return_indices=True)
unpool = nn.MaxUnpool2d(2, stride=2)
input = torch.Tensor([[[[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]]]])
output, indices = pool(input)
print(output, indices)
# tensor([[[[ 6., 8.],[14., 16.]]]])
# tensor([[[[ 5, 7],[13, 15]]]])
print(unpool(output, indices))
# tensor([[[[ 0., 0., 0., 0.],
# [ 0., 6., 0., 8.],
# [ 0., 0., 0., 0.],
# [ 0., 14., 0., 16.]]]])
torch.nn.MaxUnpool3d(kernel_size, stride=None, padding=0)
:Maxpool3d 的逆过程,不过并不是完全的逆过程,因为在 maxpool3d 的过程中,一些最大值的已经丢失。 MaxUnpool3d 的输入就是 MaxPool3d 的输出,包括最大值的索引。
重要参数:
(1)kernel_size(int or tuple) - max pooling 的窗口大小
(2)stride(int or tuple, optional) - max pooling 的窗口移动的步长。默认值是 kernel_size
(3)padding(int or tuple, optional) - 输入的每一条边补充 0 的层数
输入:
1)input:需要转换的 tensor
2)indices: Maxpool3d 的索引号
3)output_size:一个指定输出大小的 torch.Size
输入尺寸: ( N , C , D i n , H i n , W i n ) (N,C,D_{in},H_{in},W_{in}) (N,C,Din,Hin,Win)
输出尺寸: ( N , C , D o u t , H o u t , W o u t ) (N,C,D_{out},H_{out},W_{out}) (N,C,Dout,Hout,Wout)
D o u t = ( D i n − 1 ) s t r i d e [ 0 ] − 2 p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 0 ] H o u t = ( H i n − 1 ) s t r i d e [ 1 ] − 2 p a d d i n g [ 0 ] + k e r n e l _ s i z e [ 1 ] W o u t = ( W i n − 1 ) s t r i d e [ 2 ] − 2 p a d d i n g [ 2 ] + k e r n e l _ s i z e [ 2 ] D_{out}=(D_{in}-1)stride[0]-2padding[0]+kernel\_size[0]\\ H_{out}=(H_{in}-1)stride[1]-2padding[0]+kernel\_size[1]\\ W_{out}=(W_{in}-1)stride[2]-2padding[2]+kernel\_size[2] Dout=(Din−1)stride[0]−2padding[0]+kernel_size[0]Hout=(Hin−1)stride[1]−2padding[0]+kernel_size[1]Wout=(Win−1)stride[2]−2padding[2]+kernel_size[2]
import torch
import torch.nn as nn
pool = nn.MaxPool3d(3, stride=2, return_indices=True)
unpool = nn.MaxUnpool3d(3, stride=2)
input = torch.randn(20, 16, 51, 33, 15)
output, indices = pool(input)
unpooled_output = unpool(output, indices)
print(unpooled_output.shape)
# torch.Size([20, 16, 51, 33, 15])
torch.nn.AvgPool1d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)
:对信号的输入通道,提供 1 维平均池化
重要参数:
(1)ceil_mode - 如果等于 True,计算输出信号大小的时候,会使用向上取整,代替默认
的向下取整的操作
(2)count_include_pad - 如果等于 True,计算平均池化时,将包括 padding 填充的 0
输入尺寸: ( N , C , L i n ) (N,C,L_{in}) (N,C,Lin)
输出尺寸: ( N , C , L o u t ) (N,C,L_{out}) (N,C,Lout)
L o u t = f l o o r ( ( L i n + 2 ∗ p a d d i n g − k e r n e l _ s i z e ) / s t r i d e + 1 ) L_{out}=floor((L_{in}+2∗padding−kernel\_size)/stride+1) Lout=floor((Lin+2∗padding−kernel_size)/stride+1)
import torch
import torch.nn as nn
m = nn.AvgPool1d(3, stride=2)
input = torch.Tensor([[[1,2,3,4,5,6,7]]])
output = m(input)
print(output)
# tensor([[[2., 4., 6.]]])
torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False,count_include_pad=True)
:对信号的输入通道,提供 2 维的平均池化
输入尺寸: ( N , C , H i n , W i n ) (N,C,H_{in},W_{in}) (N,C,Hin,Win)
输出尺寸: ( N , C , H o u t , W o u t ) (N,C,H_{out},W_{out}) (N,C,Hout,Wout)
H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 0 ] − k e r n e l _ s i z e [ 0 ] ) / s t r i d e [ 0 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 1 ] − k e r n e l _ s i z e [ 1 ] ) / s t r i d e [ 1 ] + 1 ) H_{out}=floor((H_{in}+2padding[0]-kernel\_size[0])/stride[0]+1)\\ W_{out}=floor((W_{in}+2padding[1]-kernel\_size[1])/stride[1]+1) Hout=floor((Hin+2padding[0]−kernel_size[0])/stride[0]+1)Wout=floor((Win+2padding[1]−kernel_size[1])/stride[1]+1)
import torch
import torch.nn as nn
m1 = nn.AvgPool2d(3, stride=2)
m2 = nn.AvgPool2d((3, 2), stride=(2, 1))
input = torch.randn(20, 16, 50, 32)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape,)
# torch.Size([20, 16, 24, 15]) torch.Size([20, 16, 24, 31])
torch.nn.AvgPool3d(kernel_size, stride=None)
:对信号的输入通道,提供 3 维的平均池化
输入大小: ( N , C , D i n , H i n , W i n ) (N,C,D_{in},H_{in},W_{in}) (N,C,Din,Hin,Win)
输出大小: ( N , C , D o u t , H o u t , W o u t ) (N,C,D_{out},H_{out},W_{out}) (N,C,Dout,Hout,Wout)
D o u t = f l o o r ( ( D i n + 2 p a d d i n g [ 0 ] − k e r n e l _ s i z e [ 0 ] ) / s t r i d e [ 0 ] + 1 ) H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 1 ] − k e r n e l _ s i z e [ 1 ] ) / s t r i d e [ 1 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 ∗ p a d d i n g [ 2 ] − k e r n e l _ s i z e [ 2 ] ) / s t r i d e [ 2 ] + 1 ) D_{out}=floor((D_{in}+2padding[0]-kernel\_size[0])/stride[0]+1)\\ H_{out}=floor((H_{in}+2padding[1]-kernel\_size[1])/stride[1]+1)\\ W_{out}=floor((W_{in}+2*padding[2]-kernel\_size[2])/stride[2]+1) Dout=floor((Din+2padding[0]−kernel_size[0])/stride[0]+1)Hout=floor((Hin+2padding[1]−kernel_size[1])/stride[1]+1)Wout=floor((Win+2∗padding[2]−kernel_size[2])/stride[2]+1)
import torch
import torch.nn as nn
m1 = nn.AvgPool3d(3, stride=2)
m2 = nn.AvgPool3d((3, 2, 2), stride=(2, 1, 2))
input = torch.randn(20, 16, 50, 44, 31)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape,)
# torch.Size([20, 16, 24, 21, 15]) torch.Size([20, 16, 24, 43, 15])
torch.nn.FractionalMaxPool2d(kernel_size, output_size=None, output_ratio=None, return_indices=False, _random_samples=None)
:对输入的信号,提供 2 维的分数最大化池化操作
重要参数:
(1)output_ratio – 将输入图像的大小的百分比指定为输出图片的大小,使用一个范围在(0,1)之间的数字指定
(2)return_indices - 默认值 False,如果设置为 True,会返回输出的索引,索引对 nn.MaxUnpool2d 有用。
import torch
import torch.nn as nn
m1 = nn.FractionalMaxPool2d(3, output_size=(13, 12))
m2 = nn.FractionalMaxPool2d(3, output_ratio=(0.5, 0.5))
input = torch.randn(20, 16, 50, 32)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape,)
# torch.Size([20, 16, 13, 12]) torch.Size([20, 16, 25, 16])
torch.nn.LPPool2d(norm_type, kernel_size, stride=None, ceil_mode=False)
:对输入信号提供 2 维的幂平均池化操作
f ( X ) = ∑ x ∈ X x p p f(X)=\sqrt[p]{\sum_{x\in X}x^p} f(X)=px∈X∑xp
(1)当 p 为无穷大的时候时,等价于最大池化操作
(2)当 p=1 时,等价于平均池化操作
输入尺寸: ( N , C , H i n , W i n ) (N,C,H_{in},W_{in}) (N,C,Hin,Win)
输出尺寸: ( N , C , H o u t , W o u t ) (N,C,H_{out},W_{out}) (N,C,Hout,Wout)
H o u t = f l o o r ( ( H i n + 2 p a d d i n g [ 0 ] − d i l a t i o n [ 0 ] ( k e r n e l _ s i z e [ 0 ] − 1 ) − 1 ) / s t r i d e [ 0 ] + 1 ) W o u t = f l o o r ( ( W i n + 2 p a d d i n g [ 1 ] − d i l a t i o n [ 1 ] ( k e r n e l _ s i z e [ 1 ] − 1 ) − 1 ) / s t r i d e [ 1 ] + 1 ) H_{out} = floor((H_{in}+2padding[0]-dilation[0](kernel\_size[0]-1)-1)/stride[0]+1)\\ W_{out} = floor((W_{in}+2padding[1]-dilation[1](kernel\_size[1]-1)-1)/stride[1]+1) Hout=floor((Hin+2padding[0]−dilation[0](kernel_size[0]−1)−1)/stride[0]+1)Wout=floor((Win+2padding[1]−dilation[1](kernel_size[1]−1)−1)/stride[1]+1)
import torch
import torch.nn as nn
m1 = nn.LPPool2d(2, 3, stride=2)
m2 = nn.LPPool2d(1.2, (3, 2), stride=(2, 1))
input = torch.randn(20, 16, 50, 32)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape,)
# torch.Size([20, 16, 24, 15]) torch.Size([20, 16, 24, 31])
torch.nn.AdaptiveMaxPool1d(output_size, return_indices=False)
:对输入信号,提供 1 维的自适应最大池化操作 对于任何输入大小的输入,可以将输出尺寸指定为 output_size,但是输入和输出特征的数目(通道数)不会变化。
重要参数:
(1)output_size: 输出信号的尺寸
(2)return_indices - 默认值 False,如果设置为 True,会返回输出的索引,索引对 nn.MaxUnpool2d 有用。
import torch
import torch.nn as nn
m = nn.AdaptiveMaxPool1d(5)
input = torch.randn(1, 64, 8)
output = m(input)
print(output.shape)
# torch.Size([1, 64, 5])
torch.nn.AdaptiveMaxPool2d(output_size, return_indices=False)
:对输入信号,提供 2 维的自适应最大池化操作 对于任何输入大小的输入,可以将输出尺寸指定为output_size,但是输入和输出特征的数目(通道数)不会变化
重要参数:
(1)output_size: 输出信号的尺寸
(2)return_indices - 默认值 False,如果设置为 True,会返回输出的索引,索引对 nn.MaxUnpool2d 有用。
import torch
import torch.nn as nn
m1 = nn.AdaptiveMaxPool2d((5,7))
m2 = nn.AdaptiveMaxPool2d(7)
input = torch.randn(1, 64, 8, 9)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape)
# torch.Size([1, 64, 5, 7]) torch.Size([1, 64, 7, 7])
torch.nn.AdaptiveAvgPool1d(output_size)
:对输入信号,提供 1 维的自适应平均池化操作 对于任何输入大小的输入,可以将输出尺寸指定为output_size,但是输入和输出特征的数目(通道数)不会变化。
import torch
import torch.nn as nn
m = nn.AdaptiveMaxPool1d(5)
input = torch.randn(1, 64, 8)
output = m(input)
print(output.shape)
# torch.Size([1, 64, 5])
torch.nn.AdaptiveAvgPool2d(output_size)
:对输入信号,提供 2 维的自适应平均池化操作 对于任何输入大小的输入,可以将输出尺寸指定为output_size,但是输入和输出特征的数目(通道数)不会变化。
import torch
import torch.nn as nn
m1 = nn.AdaptiveAvgPool2d((5,7))
m2 = nn.AdaptiveAvgPool2d(7)
input = torch.randn(1, 64, 8, 9)
output1 = m1(input)
output2 = m2(input)
print(output1.shape, output2.shape)
# torch.Size([1, 64, 5, 7]) torch.Size([1, 64, 7, 7])
参考目录
https://blog.csdn.net/weixin_40920183/article/details/119814472