class torch.nn.Parameters
torch.nn.Parameter 是 torch.autograd.Variable
的子类,如果在网络的训练过程中需要更新,就要定义为Parameter, 类似为W(权重)和b(偏置)也都是Parameter。
Variable
默认是不需要求梯度的,还需要手动设置参数 requires_grad=True,而且还不能作为model.parameters()中的参数直接送入优化器中,非常麻烦。
Pytorch主要通过引入nn.Parameter类型的变量和optimizer机制来解决了这个问题。Parameter是Variable的子类,本质上和后者一样,只不过parameter默认是求梯度的,同时一个网络中的parameter变量是可以通过 net.parameters() 来很方便地访问到的,只需将网络中所有需要训练更新的参数定义为Parameter类型,再用以optimizer,就能够完成所有参数的更新了,例如:optimizer = torch.optim.SGD(net.parameters(), lr=1e-1)
。
请注意:net.parameters()中不包含我们在模型中定义的Variable,即使Variable设置了requires_grad=True。所以用Parameters方便很多。
class torch.nn.Module
Module类是所有神经网络模块的基类,我们的自定义模型也应该继承这个类。模块可以以树状结构包含其他的模块。Module类中包含网络层的定义以及forward方法,下面介绍如何定义一个网络:
nn.Module
类,并实现forward
方法__init__()
中;nn.functional
来代替;Autograd
自动实现反向求导。import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
# 添加子模块,也可以通过add_module来添加
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))
当调用.cuda()的时候,submodule(conv1和conv2)的参数也会转换为cuda Tensor。
方法:
forward(* input):定义了每次执行的 计算步骤。在所有的子类中都需要重写这个函数。
train(mode=True):将module设置为 training mode。仅仅当模型中有Dropout和BatchNorm是才会有影响。
zero_grad():将module中的所有模型参数的梯度设置为0,在反向传播之前的步骤。
eval():将模型设置成evaluation模式,仅仅当模型中有Dropout和BatchNorm时才会有影响。
cpu(device_id=None):将模型复制到CPU
cuda(device_id=None):将模型复制到GPU
load_state_dict(state_dict):加载模型参数,将state_dict中的parameters
和buffers复制到此module和它的后代中。
state_dict(destination=None, prefix=’’)[source]:返回一个字典,保存着module的所有状态,包括parameters
和buffers。
# 利用字典的items()函数打印模型的具体参数
model_dict = model.state_dict()
for k,v in model_dict.items():
print(k)
print(v)
# 通过add_module添加子模型
self.add_module("conv",nn.Conv2d(10,20,4))
children():返回当前模型子模块的迭代器。可以利用该函数打印子模块,重复的子模块只被打印一次。
modules():返回一个包含 当前模型 所有模块的迭代器。重复的子模块只被打印一次。与children()不同的是,会打印模块本身及其子模块。
named_children():返回包含模型当前子模块的迭代器,yield 模块名字和模块本身。与上面的children不同,它还会返回子模块对应的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.add_module("conv1",nn.Conv2d(20,10,4))
model = Model()
# 打印模块的名字的模块结构
for name, module in model.named_children():
print(name)
print(module)
结果:
conv
Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
conv1
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__()
submodule = nn.Conv2d(10, 20, 4)
self.add_module("conv", submodule)
self.add_module("conv1", submodule)
model = Model()
# 循环打印这个模型的所有modules
for name, module in model.named_modules():
print(name)
print(module)
结果:
Model(
(conv): Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
(conv1): Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
)
conv
Conv2d(10, 20, kernel_size=(4, 4), stride=(1, 1))
parameters(memo=None):返回一个 包含模型所有参数 的迭代器。一般用来当作optimizer的参数。
named_parameters(prefix=’’, recurse=True):返回一个遍历模块参数的迭代器,生成参数的名称和参数本身。
for name, param in self.named_parameters():
if name in ['bias']:
print(param.size())
double():将parameters和buffers的数据类型转换成double。
float():将parameters和buffers的数据类型转换成float。
half():将parameters和buffers的数据类型转换成half,half是半浮点数类型,即float16。
apply(fn):递归地将函数fn应用到父模块的每个子模块,也包括model这个父模块自身。
@torch.no_grad()
def init_weights(m):
print(m)
if type(m) == nn.Linear:
m.weight.fill_(1.0)
print(m.weight)
net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)
结果:
Linear(in_features=2, out_features=2, bias=True)
Parameter containing:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
Linear(in_features=2, out_features=2, bias=True)
Parameter containing:
tensor([[1., 1.],
[1., 1.]], requires_grad=True)
Sequential(
(0): Linear(in_features=2, out_features=2, bias=True)
(1): Linear(in_features=2, out_features=2, bias=True)
)
class torch.nn.Sequential(* args)
一个时序容器。Modules 会以他们传入的顺序被添加到容器中。用来创建子模块。
# Example of using Sequential
model = nn.Sequential(
nn.Conv2d(1,20,5),
nn.ReLU(),
nn.Conv2d(20,64,5),
nn.ReLU()
)
class torch.nn.ModuleList(modules=None)[source]
将submodules保存在一个list中。
参数说明:
modules (list, optional) – 将要被添加到MuduleList中的 modules 列表
例子:
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):
# ModuleList can act as an iterable, or be indexed using ints
for i, l in enumerate(self.linears):
x = self.linears[i // 2](x) + l(x)
return x
新增方法:
总结:创建子模块的方法:
(1)self.conv1 = nn.Conv2d(1,20,5)
(2)self.add_module(“conv”,nn.Conv2d(10,20,4))
(3)nn.Sequential( nn.Conv2d(1,20,5), nn.ReLU(), nn.Conv2d(20,64,5), nn.ReLU() )
(4)nn.ModuleList([nn.Linear(10, 10) for i in range(10)]),搭配append()和extend()使用
class torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
一维卷积层。
参数:
形状:
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)
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)‘’
三维卷积层。
class torch.nn.ConvTranspose1d(in_channels, out_channels, kernel_size, stride=1, padding=0, output_padding=0, groups=1, bias=True)
一维反卷积。
参数:
output_padding(int or tuple, optional)
- 输出的每一条边补充0的层数形状:
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
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)
三维的反卷积。
class torch.nn.MaxPool1d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
1维最大池化。
参数:
return_indices
- 如果等于True,会返回输出最大值的序号,对于上采样操作会有帮助。用于upMaxPooling
形状:
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)
class torch.nn.MaxPool2d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
2维最大池化。
class torch.nn.MaxPool3d(kernel_size, stride=None, padding=0, dilation=1, return_indices=False, ceil_mode=False)
3维最大池化。
class torch.nn.MaxUnpool1d(kernel_size, stride=None, padding=0)
Maxpool1d
的逆过程,不过并不是完全的逆过程,因为在maxpool1d
的过程中,一些最大值的已经丢失。 MaxUnpool1d
输入MaxPool1d
的输出,包括最大值的索引
,并计算所有maxpool1d
过程中非最大值被设置为零的部分的反向。
参数:
输入:
形状:
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]
也可以使用output_size指定输出的大小
class torch.nn.MaxUnpool2d(kernel_size, stride=None, padding=0)
Maxpool2d
的逆过程。
例子:
import torch
import torch.nn as nn
from torch.autograd import Variable
pool = nn.MaxPool2d(2, stride=2, return_indices=True)
unpool = nn.MaxUnpool2d(2,2)
input = Variable(torch.tensor([[[[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]]]],dtype=torch.float32))
output,indices = pool(input)
print(output)
result = unpool(output,indices)
print(result)
result = unpool(output, indices, output_size=torch.Size([1, 1, 5, 5]))
print(result)
结果:
tensor([[[[ 6., 8.],
[14., 16.]]]])
tensor([[[[ 0., 0., 0., 0.],
[ 0., 6., 0., 8.],
[ 0., 0., 0., 0.],
[ 0., 14., 0., 16.]]]])
tensor([[[[ 0., 0., 0., 0., 0.],
[ 6., 0., 8., 0., 0.],
[ 0., 0., 0., 14., 0.],
[16., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0.]]]])
class torch.nn.MaxUnpool3d(kernel_size, stride=None, padding=0)
Maxpool3d
的逆过程。
class torch.nn.AvgPool1d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)
1维平均池化。
参数:
形状:
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)
class torch.nn.AvgPool2d(kernel_size, stride=None, padding=0, ceil_mode=False, count_include_pad=True)
2维平均池化。
class torch.nn.AvgPool3d(kernel_size, stride=None)
3维的平均池化.
class torch.nn.AdaptiveMaxPool1d(output_size, return_indices=False)
1维的自适应最大池化。
参数:
class torch.nn.AdaptiveMaxPool2d(output_size, return_indices=False)
例子:
import torch
import torch.nn as nn
from torch.autograd import Variable
m = nn.AdaptiveMaxPool2d((5,7))
input = Variable(torch.randn(1, 64, 8, 9))
output = m(input)
print(output.shape)
m = nn.AdaptiveMaxPool2d(7)
input = Variable(torch.randn(1, 64, 10, 9))
output = m(input)
print(output.shape)
结果:
torch.Size([1, 64, 5, 7])
torch.Size([1, 64, 7, 7])
class torch.nn.AdaptiveAvgPool1d(output_size)
1维的自适应平均池化.
class torch.nn.AdaptiveAvgPool2d(output_size)
2维的自适应平均池化.
class torch.nn.ReLU(inplace=False)
对输入运用修正线性单元函数 R e L U ( x ) = m a x ( 0 , x ) {ReLU}(x)= max(0, x) ReLU(x)=max(0,x)。
参数: inplace-选择是否进行覆盖运算
形状:
class torch.nn.ReLU6(inplace=False)
对输入的每一个元素运用函数 R e L U 6 ( x ) = m i n ( m a x ( 0 , x ) , 6 ) {ReLU6}(x) = min(max(0,x), 6) ReLU6(x)=min(max(0,x),6),也就是限制输出的最大值为6,这是为了在一些内存受限的嵌入式设备上使用。
class torch.nn.ELU(alpha=1.0, inplace=False)
对输入的每一个元素运用函数 f ( x ) = m a x ( 0 , x ) + m i n ( 0 , a l p h a ∗ ( e x − 1 ) ) f(x) = max(0,x) + min(0, alpha * (e^x - 1)) f(x)=max(0,x)+min(0,alpha∗(ex−1))。
class torch.nn.PReLU(num_parameters=1, init=0.25)
对输入的每一个元素运用函数 P R e L U ( x ) = m a x ( 0 , x ) + a ∗ m i n ( 0 , x ) PReLU(x) = max(0,x) + a * min(0,x) PReLU(x)=max(0,x)+a∗min(0,x),a是一个可学习参数。这是LeakyReLU的升级版。
注意:当为了表现更佳的模型而学习参数a时不要使用权重衰减(weight decay)
参数:
class torch.nn.LeakyReLU(negative_slope=0.01, inplace=False)
对输入的每一个元素运用 f ( x ) = m a x ( 0 , x ) + n e g a t i v e _ s l o p e ∗ m i n ( 0 , x ) f(x) = max(0, x) + {negative\_slope} * min(0, x) f(x)=max(0,x)+negative_slope∗min(0,x)
参数:
class torch.nn.Threshold(threshold, value, inplace=False)
Threshold定义:
y = x , i f x > = t h r e s h o l d y=x,if x>=threshold y=x,ifx>=threshold
y = v a l u e , i f x < t h r e s h o l d y=value,if x
参数:
输入值小于阈值则会被value代替
class torch.nn.Sigmoid
对每个元素运用Sigmoid函数,Sigmoid 定义如下:
f ( x ) = 1 / ( 1 + e − x ) f(x)=1/(1+e^{−x}) f(x)=1/(1+e−x)
class torch.nn.Tanh
对输入的每个元素,
f ( x ) = ( e x − e − x ) / ( e x + e − x ) f(x)=(e^x−e^{−x})/(e^x+e^{−x}) f(x)=(ex−e−x)/(ex+e−x)
class torch.nn.LogSigmoid
对输入的每个元素,
L o g S i g m o i d ( x ) = l o g ( 1 / ( 1 + e − x ) ) LogSigmoid(x) = log( 1 / ( 1 + e^{-x})) LogSigmoid(x)=log(1/(1+e−x))
class torch.nn.Softplus(beta=1, threshold=20)
对每个元素运用Softplus函数,Softplus 定义如下:
f ( x ) = ( 1 / b e t a ) ∗ l o g ( 1 + e ( b e t a ∗ x i ) ) f(x)=(1/beta)∗log(1+e^{(beta∗xi)}) f(x)=(1/beta)∗log(1+e(beta∗xi))
Softplus函数是ReLU函数的平滑逼近,Softplus函数可以使得输出值限定为正数。
为了保证数值稳定性,线性函数的转换可以使输出大于某个值。
参数:
class torch.nn.Softmax
对n维输入张量运用Softmax函数,将张量的每个元素缩放到(0,1)区间且和为1。
形状:
返回结果是一个与输入维度相同的张量,每个元素的取值范围在(0,1)区间。
class torch.nn.LogSoftmax
对n维输入张量运用LogSoftmax函数,LogSoftmax函数定义如下:
class torch.nn.BatchNorm1d(num_features, eps=1e-05, momentum=0.1, affine=True)
对小批量(mini-batch)的2d或3d输入进行批标准化(Batch Normalization)操作
在每一个小批量(mini-batch)数据中,计算输入各个维度的均值和标准差
。gamma与beta是可学习的大小为C的参数向量(C为输入大小)
在训练时,该层计算每次输入的均值与方差,并进行移动平均。移动平均默认的动量值为0.1。
在验证时,训练求得的均值/方差将用于标准化验证数据。
参数:
alpha和beta
。形状:
class torch.nn.BatchNorm2d(num_features, eps=1e-05, momentum=0.1, affine=True)
对小批量(mini-batch)3d数据组成的4d输入进行批标准化(Batch Normalization)操作
例子
input = Variable(torch.rand((20,100,35,45)))
# bn,学习仿射参数
bn = nn.BatchNorm2d(100)
output = bn(input)
print(output.shape)
# bn,不学习仿射参数
bn = nn.BatchNorm2d(100,affine=False)
output = bn(input)
print(output.shape)
结果:
torch.Size([20, 100, 35, 45])
torch.Size([20, 100, 35, 45])
class torch.nn.BatchNorm3d(num_features, eps=1e-05, momentum=0.1, affine=True)
对小批量(mini-batch)4d数据组成的5d输入进行批标准化(Batch Normalization)操作
class torch.nn.Linear(in_features, out_features, bias=True)
对输入数据做线性变换: y = A x + b y=Ax+b y=Ax+b
参数:
形状:
变量:
例子:
# 线性层
m = nn.Linear(20,30)
input = Variable(torch.rand((128,20)))
output = m(input)
print(output.size())
结果:
torch.Size([128, 30])
class torch.nn.Dropout(p=0.5, inplace=False)
随机将输入张量中部分元素设置为0。
对于每次前向调用,被置0的元素都是随机的。
参数:
形状:
任意。
输入可以为任意形状。例子:
m = nn.Dropout(p=0.2)
input = Variable(torch.rand((20,16))) # 批量一维输入
output = m(input)
print(output.shape)
input = Variable(torch.rand((3,32,20,16))) # 批量三维输入
output = m(input)
print(output.shape)
class torch.nn.Dropout2d(p=0.5, inplace=False)
随机将输入张量中整个通道设置为0。
对于每次前向调用,被置0的通道都是随机的。通常输入来自Conv2d模块。
参数:
形状:
例子:
>>> m = nn.Dropout2d(p=0.2)
>>> input = autograd.Variable(torch.randn(20, 16, 32, 32))
>>> output = m(input)
class torch.nn.Dropout3d(p=0.5, inplace=False)
随机将输入张量中整个通道设置为0。对于每次前向调用,被置0的通道都是随机的。通常输入来自Conv3d模块。
参数:
形状:
基本用法:
criterion = LossCriterion() #构造函数有自己的参数
loss = criterion(x, y) #调用标准时也有参数
计算出来的结果已经对mini-batch取了平均。
class torch.nn.L1Loss(size_average=True)
创建一个衡量输入x(模型预测输出)和目标y之间差的绝对值的平均值的标准。
size_average
=False,那么求出来的绝对值的和将不会除以nclass torch.nn.MSELoss(size_average=True)
创建一个衡量输入x(模型预测输出)和目标y之间均方误差标准。
class torch.nn.CrossEntropyLoss(weight=None, size_average=True)
此标准将LogSoftMax
和NLLLoss
集成到一个类中。
当训练一个多类分类器的时候,这个方法是十分有用的。
weight(tensor)
: 1-D tensor,n个元素,分别代表n类的权重,如果你的训练样本很不均衡
的话,是非常有用的。默认值为None。调用时参数:
input : 包含每个类的得分,2-D tensor,shape为 batch*n
target: 大小为 batch*n 的 2-D tensor,包含类别的索引(0到 n-1)。
Loss可以表述为以下形式:
class torch.nn.SmoothL1Loss(size_average=True)
平滑版L1 loss。
loss的公式如下:
此loss对于异常点的鲁棒性
比MSELoss更强,而且,在某些情况下防止了梯度爆炸,(参照 Fast R-CNN)。这个loss有时也被称为 Huber loss
。
x 和 y 可以是任何包含n个元素的tensor。默认情况下,求出来的loss会除以n。
class torch.nn.SoftMarginLoss(size_average=True)
创建一个标准,用来优化2分类的logistic loss
。输入为 x(一个 2-D mini-batch Tensor)和 目标y(一个包含1或-1的Tensor)。
class torch.nn.MultiLabelSoftMarginLoss(weight=None, size_average=True)
创建一个标准,基于输入x和目标y的 max-entropy
,优化多标签 one-versus-all
的损失。x:2-D mini-batch Tensor;y:binary 2D Tensor。对每个mini-batch中的样本,对应的loss为:
其中 I=x.nElement()-1
, y [ i ] ∈ 0 , 1 y[i] \in {0,1} y[i]∈0,1,y 和 x必须要有同样size。
torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)
该容器通过在批处理维度中分组,将输入分割到指定的设备上,从而并行化给定模块的应用程序。在前向传播时,模块被复制到每个设备上,每个副本处理输入的一部分。在反向传播时,来自每个副本的梯度被累加到原始模块中。
批处理大小应该大于所使用的GPU数量。
参数:
例子:
device_ids = [0, 1] # id为0和1的两块显卡
model = torch.nn.DataParallel(model, device_ids=device_ids)
model = model.cuda()
# 或者
device_ids = [0, 1]
model = torch.nn.DataParallel(model, device_ids=device_ids).cuda()
注:device_ids可以省略不写,根据源码,如果不写的时候,程序会自动帮你寻找可用的GPU设备。