1.nn.functional 和nn.Module
pytorch和神经网络相关的功能组件(激活函数、模型层、损失函数),大多封装在torch.nn下。
这些功能组件既有函数形式(torch.nn.functional)的实现,又有类形式(torch.nn.Module)的实现
import torch.nn.functional as F | from torch import nn |
---|---|
F.relu、F.sigmoid、F.tanh、F.softmax | nn.ReLU、nn.Sigmoid、nn.Tanh、nn.Softmax |
F.linear、F.conv2d、F.max_pool2d、F.dropout2d、F.embedding | nn.Linear、nn.Conv2d、nn.MaxPool2d、nn.Dropout2d、nn.Embedding |
F.binary_cross_entropy、F.mse_loss、F.cross_entropy | nn.BCELoss、nn.MSELoss、nn.CrossEntropyLoss |
类形式相对于函数形式,参数管理更加方便。nn.Module除了可以管理参数,还可以管理子模块。
2.使用nn.Module来管理参数
设置requires_grad=True 的张量是可以训练的
Pytorch一般将参数用nn.Parameter来表示,并且用nn.Module来管理其结构下的所有参数。
w = nn.Parameter(torch.randn(2,2))
params_list = nn.ParameterList([nn.Parameter(torch.rand(8,i)) for i in range(1,3)])
params_dict = nn.ParameterDict({"a":nn.Parameter(torch.rand(2,2)),
"b":nn.Parameter(torch.zeros(2))})
# 可以用Module将它们管理起来
# module.parameters()返回一个生成器,包括其结构下的所有parameters
module = nn.Module()
module.w = w
module.params_list = params_list
module.params_dict = params_dict
#实践当中,一般通过继承nn.Module来构建模块类,并将所有含有需要学习的参数的部分放在构造函数中。
三,使用nn.Module来管理子模块
一般情况下,我们都很少直接使用 nn.Parameter来定义参数构建模型,而是通过一些拼装一些常用的模型层来构造模型。
这些模型层也是继承自nn.Module的对象,本身也包括参数,属于我们要定义的模块的子模块。
nn.Module提供了一些方法可以管理这些子模块。
-
children() 方法: 返回生成器,包括模块下的所有子模块。
-
named_children()方法:返回一个生成器,包括模块下的所有子模块,以及它们的名字。
-
modules()方法:返回一个生成器,包括模块下的所有各个层级的模块,包括模块本身。
-
named_modules()方法:返回一个生成器,包括模块下的所有各个层级的模块以及它们的名字,包括模块本身。
其中chidren()方法和named_children()方法较多使用。
modules()方法和named_modules()方法较少使用,其功能可以通过多个named_children()的嵌套使用实现。
下面我们通过named_children方法找到embedding层,并将其参数设置为不可训练(相当于冻结embedding层)。
children_dict = {name:module for name,module in net.named_children()}
print(children_dict)
embedding = children_dict["embedding"]
embedding.requires_grad_(False) #冻结其参数
#可以看到其第一层的参数已经不可以被训练了。
for param in embedding.parameters():
print(param.requires_grad)
print(param.numel())