如何在 PyTorch 中初始化权重?

新手上路,请多包涵

如何初始化网络的权重和偏差(例如通过 He 或 Xavier 初始化)?

原文由 Fábio Perez 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1k
2 个回答

单层

要初始化单层的权重,请使用 torch.nn.init 中的函数。例如:

 conv1 = torch.nn.Conv2d(...)
torch.nn.init.xavier_uniform(conv1.weight)

或者,您可以通过写入 conv1.weight.data (即 torch.Tensor )来修改参数。例子:

 conv1.weight.data.fill_(0.01)

这同样适用于偏见:

 conv1.bias.data.fill_(0.01)

nn.Sequential 或自定义 nn.Module

将初始化函数传递给 torch.nn.Module.apply 。它将递归地初始化整个 nn.Module 中的权重。

apply( fn ):将 fn 递归应用到每个子模块(由 .children() 返回)以及 self.典型用途包括初始化模型的参数(另请参见 torch-nn-init)。

例子:

 def init_weights(m):
    if isinstance(m, nn.Linear):
        torch.nn.init.xavier_uniform(m.weight)
        m.bias.data.fill_(0.01)

net = nn.Sequential(nn.Linear(2, 2), nn.Linear(2, 2))
net.apply(init_weights)

原文由 Fábio Perez 发布,翻译遵循 CC BY-SA 4.0 许可协议

我们使用相同的神经网络 (NN) 架构比较不同的权重初始化模式。

全零或全一

如果遵循 [奥卡姆剃刀](https://en.wikipedia.org/wiki/Occam’s_razor) 原则,您可能会认为将所有权重设置为 0 或 1 将是最佳解决方案。不是这种情况。

在每个权重相同的情况下,每一层的所有神经元都产生相同的输出。这使得很难决定调整哪些权重。

     # initialize two NN's with 0 and 1 constant weights
    model_0 = Net(constant_weight=0)
    model_1 = Net(constant_weight=1)

  • 2个时代之后:

权重初始化为常数的训练损失图

 Validation Accuracy
9.625% -- All Zeros
10.050% -- All Ones
Training Loss
2.304  -- All Zeros
1552.281  -- All Ones

统一初始化

均匀分布 具有从一组数字中选择任何数字的相同概率。

让我们看看使用统一权重初始化的神经网络训练效果如何,其中 low=0.0high=1.0

下面,我们将看到另一种方式(除了在 Net 类代码中)来初始化网络的权重。要在模型定义之外定义权重,我们可以:

  1. 定义一个按网络层类型分配权重的函数, 然后
  2. 使用 model.apply(fn) 将这些权重应用于初始化模型,它将一个函数应用于每个模型层。
     # takes in a module and applies the specified weight initialization
    def weights_init_uniform(m):
        classname = m.__class__.__name__
        # for every Linear layer in a model..
        if classname.find('Linear') != -1:
            # apply a uniform distribution to the weights and a bias=0
            m.weight.data.uniform_(0.0, 1.0)
            m.bias.data.fill_(0)

    model_uniform = Net()
    model_uniform.apply(weights_init_uniform)

  • 2个时代之后:

在此处输入图像描述

 Validation Accuracy
36.667% -- Uniform Weights
Training Loss
3.208  -- Uniform Weights

设置权重的一般规则

在神经网络中设置权重的一般规则是将它们设置为接近于零但又不会太小。

好的做法是在 [-y, y] 范围内开始你的权重,其中 y=1/sqrt(n)

(n 是给定神经元的输入数)。

     # takes in a module and applies the specified weight initialization
    def weights_init_uniform_rule(m):
        classname = m.__class__.__name__
        # for every Linear layer in a model..
        if classname.find('Linear') != -1:
            # get the number of the inputs
            n = m.in_features
            y = 1.0/np.sqrt(n)
            m.weight.data.uniform_(-y, y)
            m.bias.data.fill_(0)

    # create a new model with these weights
    model_rule = Net()
    model_rule.apply(weights_init_uniform_rule)

下面我们比较 NN 的性能,使用均匀分布 [-0.5,0.5) 初始化的权重与使用 一般规则 初始化权重的 NN

  • 2个时代之后:

显示权重统一初始化性能与初始化一般规则的图

 Validation Accuracy
75.817% -- Centered Weights [-0.5, 0.5)
85.208% -- General Rule [-y, y)
Training Loss
0.705  -- Centered Weights [-0.5, 0.5)
0.469  -- General Rule [-y, y)

正态分布来初始化权重

正态分布的均值为 0,标准差为 y=1/sqrt(n) ,其中 n 是 NN 的输入数

    ## takes in a module and applies the specified weight initialization
    def weights_init_normal(m):
        '''Takes in a module and initializes all linear layers with weight
           values taken from a normal distribution.'''

        classname = m.__class__.__name__
        # for every Linear layer in a model
        if classname.find('Linear') != -1:
            y = m.in_features
        # m.weight.data shoud be taken from a normal distribution
            m.weight.data.normal_(0.0,1/np.sqrt(y))
        # m.bias.data should be 0
            m.bias.data.fill_(0)

下面我们展示了两个 NN 的性能,一个使用 均匀分布 初始化,另一个使用 正态分布 初始化

  • 2个时代之后:

使用均匀分布与正态分布进行权重初始化的性能

 Validation Accuracy
85.775% -- Uniform Rule [-y, y)
84.717% -- Normal Distribution
Training Loss
0.329  -- Uniform Rule [-y, y)
0.443  -- Normal Distribution

原文由 ashunigion 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题