Pytorch 模型参数管理
1. 参数初始化
- 使用
self.modules ,声明网络时初始化并加载权重
pytorch 模型应是 nn.Module 的子类 self.modules : nn.Module 类中的一个方法, 返回该网络中的所有 modules 可以利用 self.modules 来对网络进行初始化。
class Network(nn.Module):
def __init__(self):
supe().__init__()
self.Conv2d = nn.Conv2d(3, 10)
sefl.bn = nn.BatchNorm2d(10)
self.relu = nn.ReLU()
self._init_weight()
def forward(self, x):
x = self.Conv2d(x)
x = self.bn(x)
return self.relu(x)
def _init_weight(self):
for m in self.modules()
if isinstance(m, nn.Conv2d):
torch.nn.init.kaiming_normal_(m.weight)
elif isinstance(m, nn.BatchNorm2d):
m.weight.data.fill_(1)
m.bias.data.zero_()
- 先定义网络,后加载权重, 使用
net.apply()
import torch.nn as nn
class NET(nn.Module):
'''
定义网络层
'''
net = NET()
def weight_init(m):
if isinstance(m, nn.Conv3d):
n = m.kernel_size[0] * m.kernel_size[1] * m.kernel_size[2] * m.out_channels
m.weight.data.normal_(0, math.sqrt(2.0 / n))
m.bias.data.zero_()
elif isinstance(m, nn.BatchNorm3d):
m.weight.data.fill_(1)
m.bias.data.zero_()
elif isinstance(m, nn.Linear):
m.weight.data.normal_(0, 0.02)
m.bias.data.zero_()
net.apply(weight_init)
2. 参数访问
从已有的模型中访问参数 通过Module 类的 parameters() 或者named_parameters() 来访问参数
- 使用
net.named_parameters()
class Net(nn.Modules):
def __init__(self):
super(LeNet, self).__init__()
pass
def forward(x):
pass
net = Net()
for name, param in net.named_parameters():
print(name, ' ', param.size())
conv.0.weight torch.Size([6, 1, 5, 5])
conv.0.bias torch.Size([6])
conv.3.weight torch.Size([16, 6, 5, 5])
conv.3.bias torch.Size([16])
fc.0.weight torch.Size([120, 256])
fc.0.bias torch.Size([120])
fc.2.weight torch.Size([84, 120])
fc.2.bias torch.Size([84])
fc.4.weight torch.Size([10, 84])
fc.4.bias torch.Size([10])
- 使用
net.state_dict() 当通过Sequential类定义模型时,我们可以通过索引来访问模型的任意层。 这就像模型是?个列表?样。每层的参数都在其属性中。
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(), nn.Linear(8, 1))
print(net[2].state_dict())
OrderedDict([('weight', tensor([[-0.0578, 0.2847, 0.0501, -0.1246, 0.2490, -0.0303, 0.1356, 0.2373]])), ('bias', tensor([0.1629]))])
3. 参数共享
有时我们希望在多个层间共享参数。让我们看看如何优雅地做这件事。在下面,我们定义?个稠密层,然后使用它的参数来设置另?个层的参数。
shared = nn.Linear(8, 8)
net = nn.Sequential(nn.Linear(4, 8), nn.ReLU(),
shared, nn.ReLU(),
shared, nn.ReLU(),
nn.Linear(8, 1))
net(X)
print(net[2].weight.data[0] == net[4].weight.data[0])
net[2].weight.data[0, 0] = 100
print(net[2].weight.data[0] == net[4].weight.data[0])
tensor([True, True, True, True, True, True, True, True])
tensor([True, True, True, True, True, True, True, True])
这个例子表明第?层和第三层的参数是绑定的。它们不仅值相等,而且由相同的张量表示。因此,如果我们改变其中?个参数,另?个参数也会改变。你可能会想,当参数绑定时,梯度会发?什么情况?答案是由于模型参数包含梯度,因此在反向传播期间第?个隐藏层和第三个隐藏层的梯度会加在?起。
|