1、初始化方式
单层网络初始化方式
在创建model后直接调用torch.nn.init里的初始化函数。
conv = torch.nn.Conv2d(3, 64, kernel_size = 3, stride = 1, padding = 1)
torch.nn.init.xavier_uniform_(conv.weight)
torch.nn.init.xavier_uniform_(conv.bias, 0)
多层网络初始化方式
(1). 使用apply函数,在_init_函数中用self.modules()进行初始化
先定义初始化模型方法,运用apply()调用weight_init函数.
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)
#torch中的apply函数通过可以不断遍历model的各个模块,并将weight_init函数应用在这些Module上
(2)定义在模型中,利用self.modules()来进行循环(推荐)
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.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
def forward(self, x):
x = self.layer1(x)
x = self.layer2(x)
x = self.layer3(x)
return x
2、几种常见的参数初始化方式
1、init.uniform均匀分布
init.uniform(tensor, a=0, b=1)
nn.init.uniform(w)
从均匀分布 U ( a , b )中生成值,填充输入的张量或变量
- tensor - n维的torch.Tensor
- a - 均匀分布的下界
- b - 均匀分布的上界
2、nn.init.normal 正太分布
nn.init.normal(tensor, mean=0, std=1)
nn.init.normal(w)
从给定均值和标准差的正态分布N(mean,std)中生成值,填充输入的张量或变量
- tensor – n维的torch.Tensor
- mean – 正态分布的均值
- std – 正态分布的标准差
3、nn.init.constant常数分布
nn.init.constant(tensor, val)
nn.init.constant(w)
用val的值填充输入的张量或变量
- tensor – n维的torch.Tensor 或 autograd.Variable
- val – 用来填充张量的值
4、nn.init.eye 单位分布
nn.init.eye(tensor)
nn.init.eye(w)
用单位矩阵来填充2维输入张量或变量。在线性层尽可能多的保存输入特性
- tensor – 2维的torch.Tensor 或 autograd.Variable
5、nn.init.dirac
nn.init.dirac(tensor)
nn.init.dirac(w)
用Dirac δ 函数来填充{3, 4, 5}维输入张量或变量。在卷积层尽可能多的保存输入通道特性
- tensor – {3, 4, 5}维的torch.Tensor 或 autograd.Variable
6、 nn.init.xavier_uniform
基本思想是维持输入和输出的方差一致,避免了所有的输出值都为0, 使用于任何激活函数,但是Xavier初始化在tanh中表现的很好, 在relu中表现很差
nn.init.xavier_uniform(tensor, gain=1)
nn.init.xavier_uniform(w, gain=math.sqrt(2.0))
用一个均匀分布生成值,填充输入的张量或变量。结果张量中的值采样自U(-a, a)
- tensor – n维的torch.Tensor
- gain - 可选的缩放因子
7、nn.init.xavier_normal
针对Xavier在relu表现不佳被提出。基本思想仍然从“输入输出方差一致性”角度出发,在Relu网络中, 假设每一层有一半的神经元被激活,另一半为0。一般在使用Relu的网络中推荐使用这种初始化方式。
nn.init.xavier_normal(tensor, gain=1)
nn.init.xavier_normal(w)
用一个正态分布生成值,填充输入的张量或变量。结果张量中的值采样自均值为0的正态分布。
- tensor – n维的torch.Tensor
- gain - 可选的缩放因子
8、nn.init.kaiming_uniform
nn.init.kaiming_uniform(tensor, a=0, mode='fan_in',nonlinearity='leaky_relu')
nn.init.kaiming_uniform(w, mode='fan_in')
用一个均匀分布生成值,填充输入的张量或变量。结果张量中的值采样自U(-bound, bound)
- tensor ,n维的torch.Tensor或autograd.Variable
- a -这层之后使用的rectifier的斜率系数(ReLU的默认值为0)
- mode -可以为“fan_in”(默认)或 “fan_out”
- “fan_in”保留前向传播时权值方差的量级
- “fan_out”保留反向传播时的量级
- nonlinearity=‘leaky_relu’ 非线性函数 建议“relu”或“leaky_relu”(默认值)使用。
9、nn.init.kaiming_normal
nn.init.kaiming_normal(tensor, a=0, mode='fan_in')
nn.init.kaiming_normal(w, mode='fan_out')
用一个正态分布生成值,填充输入的张量或变量。结果张量中的值采样自均值为0的正态分布.
- tensor – n维的torch.Tensor或 autograd.Variable
- a -这层之后使用的rectifier的斜率系数(ReLU的默认值为0)
- mode -可以为“fan_in”(默认)或 “fan_out”
- “fan_in”保留前向传播时权值方差的量级
- “fan_out”保留反向传播时的量级
10、nn.init.orthogonal正交矩阵初始化
主要是解决神经网络中出现的梯度消失和梯度爆炸等问题,是RNN中常用的初始化方法
nn.init.orthogonal(tensor, gain=1)
nn.init.orthogonal(w)
用正交矩阵填充输入的张量或变量。输入张量必须至少是2维的,对于更高维度的张量,超出的维度会被展平,视作行等于第一个维度,列等于稀疏矩阵乘积的2维表示【其中非零元素生成自均值为0,标准差为std的正态分布】
- tensor – n维的torch.Tensor 或 autograd.Variable,其中n>=2
- gain -可选
11、nn.init.sparse稀疏矩阵
nn.init.sparse(tensor, sparsity, std=0.01)
# 非零元素采用正态分布 N(0, 0.01) 初始化.
nn.init.sparse(w, sparsity=0.1)
将2维的输入张量或变量当做 稀疏矩阵填充,其中非零元素根据一个均值为0,标准差为std的正态分布生成。
- tensor – n维的torch.Tensor或autograd.Variable
- sparsity - 每列中需要被设置成零的元素比例
- std - 用于生成非零值的正态分布的标准差