Sequential 允许我们构建序列化的模块,而 Module 是一种更加灵活的模型定义方式,我们下面分别用 Sequential 和 Module 来定义上面的神经网络
# Sequential
seq_net = nn.Sequential(
nn.Linear(2, 4), # PyTorch 中的线性层,wx + b
nn.Tanh(),
nn.Linear(4, 1)
)
序列模块可以通过索引访问每一层
seq_net[0] # 第一层
打印出第一层的权重
w0 = seq_net[0].weight
print(w0)
保存模型的两种方式
保存模型在 PyTorch 中有两种方式,一种是将模型结构和参数都保存在一起,一种是只将参数保存下来
将模型和参数保存在一起
(1)保存模型和参数
# 将参数和模型保存在一起
torch.save(seq_net, 'save_seq_net.pth')
上面就是保存模型的方式,torch.save
里面有两个参数,第一个是要保存的模型,第二个参数是保存的路径,读取模型的方式也非常简单
(2)读取保存的模型
# 读取保存的模型
seq_net1 = torch.load('save_seq_net.pth')
seq_net1
输出保存的mo'i
输出权重参数
print(seq_net1[0].weight)
第二种保存模型的方式,只保存参数而不保存模型结构
# 保存模型参数
torch.save(seq_net.state_dict(), 'save_seq_net_params.pth')
通过上面的方式,我们保存了模型的参数,如果要重新读入模型的参数,首先我们需要重新定义一次模型,接着重新读入参数
seq_net2 = nn.Sequential(
nn.Linear(2, 4),
nn.Tanh(),
nn.Linear(4, 1)
)
seq_net2.load_state_dict(torch.load('save_seq_net_params.pth'))
seq_net2
输出第一层的权重参数
print(seq_net2[0].weight)
上面的两种方式,推荐使用第二种,因为第二种可移植性更强。
再用 Module 定义这个模型,下面是使用 Module 的模板
class 网络名字(nn.Module):
def __init__(self, 一些定义的参数):
super(网络名字, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.Sequential(...)
...
定义需要用的网络层
def forward(self, x): # 定义前向传播
x1 = self.layer1(x)
x2 = self.layer2(x)
x = x1 + x2
...
return x
注意的是,Module 里面也可以使用 Sequential,同时 Module 非常灵活,具体体现在 forward 中,如何复杂的操作都能直观的在 forward 里面执行
比如定义如下网络结构:
class module_net(nn.Module):
def __init__(self, num_input, num_hidden, num_output):
super(module_net, self).__init__()
self.layer1 = nn.Linear(num_input, num_hidden)
self.layer2 = nn.Tanh()
self.layer3 = nn.Linear(num_hidden, num_output)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
mo_net = module_net(2, 4, 1)
访问模型中的某层可以直接通过名字
# 第一层
l1 = mo_net.layer1
print(l1)
打印出第一层的权重
print(l1.weight)
import torch
from torch import nn
seq_net = nn.Sequential(
nn.Linear(2,4),
nn.Tanh(),
nn.Linear(4,1)
)
seq_net
print(seq_net[0].weight)
for layer in seq_net.modules():
print(layer)
上面的例子,modules 不仅访问到了 Sequential,也访问到了 Sequential 里面