Module类
import torch
from torch import nn
class MLP(nn.Module):
# 声明带有模型参数的层,这里声明了两个全连接层
def __init__(self, **kwargs):
# 调用MLP父类Module的构造函数来进行必要的初始化。这样在构造实例时还可以指定其他函数
# 参数,如“模型参数的访问、初始化和共享”一节将介绍的模型参数params
super(MLP, self).__init__(**kwargs)
self.hidden = nn.Linear(784, 256) # 隐藏层
self.act = nn.ReLU()
self.output = nn.Linear(256, 10) # 输出层
# 定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
def forward(self, x):
a = self.act(self.hidden(x))
return self.output(a)
args表示任何多个无名参数,它是一个tuple;**kwargs表示关键字参数,它是一个dict。并且同时使用args和kwargs时,必须*args参数列要在kwargs前,像foo(a=1, b=‘2’, c=3, a’, 1, None, )这样调用的话,会提示语法错误“SyntaxError: non-keyword arg after keyword arg”。
X = torch.rand(2,784)
net = MLP()
print(net(X))
# 通过net()调用,MLP继承于Module类的__call()__函数,调用forward完成前向计算
Sequential类
net = Sequential(
nn.Linear(784, 256),
nn.ReLU(),
nn.Linear(256, 10),
)
print(net)
net(X)
Sequential类允许传入OrderedDict或者是例如Linear,ReLu之类的子模块
ModuleList
net = nn.ModuleList([nn.Linear(784, 256), nn.ReLU()])
net.append(nn.Linear(256, 10)) # # 类似List的append操作
print(net[-1]) # 类似List的索引访问
print(net)
# net(torch.zeros(1, 784)) # 会报NotImplementedError
ModuleList接受一个子模块的列表,也有append添加单个元素,和extend添加一个列表的功能
和Sequential的区别是没有实现forward功能,仅仅作为储存子模块的列表。
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
在前向传播时,更加灵活,并且在ModuleList里的网络参数已被自动添加到net的parameter中。相反,
self.linears = [nn.Linear(10, 10) for i in range(10)]
则没有自动添加到parameter中。
ModuleDict
储存子模块的字典。各属性和ModuleList类似。没有实现forward,并且网络自动添加到参数中。