一个 torch.Storage 是一个单一数据类型的连续一维数组。每个 torch.Tensor 都有一个对应的、相同数据类型的存储。
class torch.nn.Parameter()
: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())
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))
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))
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()也是)。
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())
# torch.Size([20, 10, 4, 4])
# torch.Size([20])
# torch.Size([10, 20, 4, 4])
# torch.Size([10])
self.register_buffer('running_mean', torch.zeros(num_features))
hook(module, input, output) -> None
,hook 不 应 该 修 改 input 和 output 的 值 。 这 个 函 数 返 回 一 个 句 柄 (handle) 。 它 有 一 个 方 法 handle.remove(),可以用这个方法将 hook 从 module 移除。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方法。
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)的计算方式: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)
: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)
: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 操作)。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 操作)。输入尺寸: ( 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 维的转置卷积操作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)操作。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)操作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)操作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 可以将多个输入大小映射到相同的输出大小。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 的输出,包括最大值的索引。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 的输出,包括最大值的索引。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 维平均池化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 维的平均池化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 维的平均池化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 维的分数最大化池化操作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 维的幂平均池化操作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,但是输入和输出特征的数目(通道数)不会变化。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,但是输入和输出特征的数目(通道数)不会变化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