Skip to content

模型初始化(参数初始化)(权重初始化)

解决(或至少减轻)梯度消失和梯度爆炸问题的一种方式是进行参数初始化, 优化期间的注意和适当的正则化也可以进一步提高稳定性。

权重初始化的质量对于神经网络的训练效果至关重要。在过去的几年里,研究人员们提出了许多不同的权重初始化方法,其中Xavier和Kaiming是最著名的两种。

默认初始化

如果我们不指定初始化方法, 框架将使用默认的随机初始化方法,对于中等难度的问题,这种方法通常很有效。

Xavier初始化

Xavier方法(音译:泽维尔),也称为Glorot(音译:格洛洛)方法,是一种针对不同层类型和神经元数量的权重初始化方法。其核心思想是根据输入和输出神经元的数量以及层类型来计算权重的均值和方差,然后将其用于初始化权重。具体步骤如下:

  • 计算输入神经元数量n_in和输出神经元数量n_out。
  • 根据层类型(全连接层或卷积层)计算常数factor。
  • 计算权重的均值和方差:mean = sqrt(6 / (n_in + n_out)),variance = mean^2。
  • 使用均值和方差初始化权重。

代码示例

python
import torch
import torch.nn as nn

def xavier_init(module, bias=False):
    if not bias:
        nn.init.xavier_uniform_(module.weight.data)
    else:
        nn.init.xavier_uniform_(module.weight.data)
        nn.init.zeros_(module.bias.data)

# 使用Xavier方法初始化全连接层
class LinearLayer(nn.Module):
    def __init__(self, n_in, n_out):
        super(LinearLayer, self).__init__()
        self.weight = nn.Parameter(torch.randn(n_in, n_out))
        self.bias = nn.Parameter(torch.randn(n_out))

    def forward(self, x):
        return torch.mm(x, self.weight) + self.bias

# 初始化层
linear_layer = LinearLayer(10, 5)

# 使用Xavier方法初始化权重和偏置
xavier_init(linear_layer)

Kaiming方法

Kaiming(音译:卡明)方法,也称为He方法,是一种针对卷积层的权重初始化方法。其核心思想是通过对权重的分布进行调整来实现初始化。具体步骤如下:

  • 计算输入神经元数量n_in和输出神经元数量n_out。
  • 根据层类型(卷积层)计算常数factor。
  • 计算权重的均值和方差:mean = sqrt(2 / n_in),variance = mean^2。
  • 对权重进行调整,使其遵循正态分布。

代码示例

python
import torch
import torch.nn as nn

def kaiming_init(module, a=0, mode='fan_in', bias=False):
    if 'bias' in module.named_parameters() and bias:
        nn.init.constant_(module.bias, a)
    if mode == 'fan_in':
        fan_in, _ = nn.init._calculate_fan_in_and_fan_out(module.weight)
        v = nn.init.calculate_fan_in_fan_out(module.weight)
        bound = nn.init.scale_(v, a)
    elif mode == 'fan_out':
        fan_out, _ = nn.init._calculate_fan_in_and_fan_out(module.weight)
        v = nn.init.calculate_fan_in_fan_out(module.weight)
        bound = nn.init.scale_(v, a)
    else:
        raise ValueError('Invalid value for mode: {}'.format(mode))
    nn.init.uniform_(module.weight, -bound, bound)

# 使用Kaiming方法初始化卷积层
class ConvLayer(nn.Module):
    def __init__(self, n_in, n_out, kernel_size, stride=1, padding=0):
        super(ConvLayer, self).__init__()
        self.weight = nn.Parameter(torch.randn(n_out, n_in, kernel_size, kernel_size))
        self.bias = nn.Parameter(torch.randn(n_out))

    def forward(self, x):
        return nn.functional.conv2d(x, self.weight, self.bias, stride, padding)

# 初始化层
conv_layer = ConvLayer(3, 64, kernel_size=3, stride=1, padding=0)

# 使用Kaiming方法初始化权重和偏置
kaiming_init(conv_layer, a=0.02)

区别:

  • Xavier方法适用于全连接层和卷积层,而Kaiming方法则专门针对卷积层设计
  • Xavier方法的初始化方法是根据输入和输出神经元的数量以及层类型来计算权重的均值和方差,然后将其用于初始化权重。而Kaiming方法则通过对权重的分布进行调整来实现初始化。

京ICP备2024093538号-1