本文主要内容:
__init__
函数使用self.modules()
初始化torch.nn.innit
里的初始化函数layer1 = torch.nn.Linear(10,20)
torch.nn.init.xavier_uniform_(layer1.weight)
torch.nn.init.constant_(layer1.bias, 0)
reset_parameters()
方法,并不推荐tf.Sequential() ,请查看pytorch系列7 -----nn.Sequential讲解
apply(fn)
: 看一下apply
在Module的实现。
将函数fn
递归的运用在每个子模块上,这些子模块由self.children()
返回.
关于self.children()和self.modules()的工作方式,请查看此篇博文pytorch系列8 --self.modules() 和 self.children()的区别
常被用来初始化网络层参数。注意fn需要一个参数。
具体步骤是:
在以下的代码中只初始化线性层,至于卷积层,批归一化层后面会讲到的
示例:https://github.com/pytorch/examples/blob/master/dcgan/main.py#L95
# -*- coding: utf-8 -*-
import torch
from torch import nn
# hyper parameters
in_dim=1
n_hidden_1=1
n_hidden_2=1
out_dim=1
class Net(nn.Module):
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super().__init__()
self.layer = nn.Sequential(
nn.Linear(in_dim, n_hidden_1),
nn.ReLU(True),
nn.Linear(n_hidden_1, n_hidden_2),
nn.ReLU(True),
nn.Linear(n_hidden_2, out_dim)
)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
# 1. 根据网络层的不同定义不同的初始化方式
def weight_init(m):
if isinstance(m, nn.Linear):
nn.init.xavier_normal_(m.weight)
nn.init.constant_(m.bias, 0)
# 也可以判断是否为conv2d,使用相应的初始化方式
elif isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
# 是否为批归一化层
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
# 2. 初始化网络结构
model = Net(in_dim, n_hidden_1, n_hidden_2, out_dim)
# 3. 将weight_init应用在子模块上
model.apply(weight_init)
注意:此种初始化方式采用的递归,而在python中,对递归层数是有限制的,所以当网络结构很深时,可能会递归层数过深的错误
__init__
中迭代循环self.modules()
来初始化网络参数初始化后并使用apply函数将参数信息打印出来
import torch
from torch import nn
# hyper parameters
in_dim=1
n_hidden_1=1
n_hidden_2=1
out_dim=1
class Net(nn.Module):
def __init__(self, in_dim, n_hidden_1, n_hidden_2, out_dim):
super().__init__()
self.layer = nn.Sequential(
nn.Linear(in_dim, n_hidden_1),
nn.ReLU(True),
nn.Linear(n_hidden_1, n_hidden_2),
nn.ReLU(True),
nn.Linear(n_hidden_2, out_dim)
)
# 迭代循环初始化参数
for m in self.modules():
if isinstance(m, nn.Linear):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, -100)
# 也可以判断是否为conv2d,使用相应的初始化方式
elif isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight.item(), 1)
nn.init.constant_(m.bias.item(), 0)
def forward(self, x):
x = self.layer(x)
return x
model = Net(in_dim, n_hidden_1, n_hidden_2, out_dim)
# 打印参数信息
def print_weight(m):
if isinstance(m, nn.Linear):
print("weight", m.weight.item())
print("bias:", m.bias.item())
print("next...")
model.apply(print_weight)
out:
weight 1.0
bias: -100.0
next…weight 1.0
bias: -100.0
next…weight 1.0
bias: -100.0
next…
自己计算std,然后调用torch.nn.init.normal_(tensor, maen, std)
就OK了。
至于官方的kaiming和Xavier是如何计算fan_in(输入神经元个数)和fan_out(输出神经元个数),参考这篇博客https://blog.csdn.net/dss_dssssd/article/details/83992701
还需要注意一点,在pytorch 0.4中不存在Variable了,所以weight和bias就直接是tensor类型了。
参考文章: