如何初始化网络的权重和偏差(例如通过 He 或 Xavier 初始化)?
原文由 Fábio Perez 发布,翻译遵循 CC BY-SA 4.0 许可协议
如何初始化网络的权重和偏差(例如通过 He 或 Xavier 初始化)?
原文由 Fábio Perez 发布,翻译遵循 CC BY-SA 4.0 许可协议
如果遵循 [奥卡姆剃刀](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)
Validation Accuracy
9.625% -- All Zeros
10.050% -- All Ones
Training Loss
2.304 -- All Zeros
1552.281 -- All Ones
均匀分布 具有从一组数字中选择任何数字的相同概率。
让我们看看使用统一权重初始化的神经网络训练效果如何,其中 low=0.0
和 high=1.0
。
下面,我们将看到另一种方式(除了在 Net 类代码中)来初始化网络的权重。要在模型定义之外定义权重,我们可以:
- 定义一个按网络层类型分配权重的函数, 然后
- 使用
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)
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
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 的性能,一个使用 均匀分布 初始化,另一个使用 正态分布 初始化
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 许可协议
4 回答4.4k 阅读✓ 已解决
4 回答3.8k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
1 回答4.5k 阅读✓ 已解决
1 回答3.8k 阅读✓ 已解决
1 回答2.8k 阅读✓ 已解决
2 回答1.9k 阅读✓ 已解决
单层
要初始化单层的权重,请使用
torch.nn.init
中的函数。例如:或者,您可以通过写入
conv1.weight.data
(即torch.Tensor
)来修改参数。例子:这同样适用于偏见:
nn.Sequential
或自定义nn.Module
将初始化函数传递给
torch.nn.Module.apply
。它将递归地初始化整个nn.Module
中的权重。例子: