我如何初始化网络的权重和偏差(通过例如He或Xavier初始化)?
当前回答
我们比较了使用同一神经网络架构的不同权重初始化模式。
都是0或1
如果您遵循奥卡姆剃刀原理,您可能认为将所有权重设置为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.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)
2个时代之后:
Validation Accuracy
36.667% -- Uniform Weights
Training Loss
3.208 -- Uniform Weights
设置权重的一般规则
在神经网络中设置权重的一般规则是将它们设置为接近零而又不会太小。
好的做法是在[-y, y]范围内开始权重,其中y=1/根号(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/√(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)
下面我们展示了两个神经网络的性能,一个使用均匀分布初始化,另一个使用正态分布初始化
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
其他回答
我们比较了使用同一神经网络架构的不同权重初始化模式。
都是0或1
如果您遵循奥卡姆剃刀原理,您可能认为将所有权重设置为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.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)
2个时代之后:
Validation Accuracy
36.667% -- Uniform Weights
Training Loss
3.208 -- Uniform Weights
设置权重的一般规则
在神经网络中设置权重的一般规则是将它们设置为接近零而又不会太小。
好的做法是在[-y, y]范围内开始权重,其中y=1/根号(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/√(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)
下面我们展示了两个神经网络的性能,一个使用均匀分布初始化,另一个使用正态分布初始化
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
如果您看到deprecation警告(@Fábio Perez)…
def init_weights(m):
if type(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)
如果您想要一些额外的灵活性,还可以手动设置权重。
假设你有所有1的输入:
import torch
import torch.nn as nn
input = torch.ones((8, 8))
print(input)
tensor([[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1., 1., 1.]])
你想要做一个没有偏差的密集层(所以我们可以可视化):
d = nn.Linear(8, 8, bias=False)
将所有权重设置为0.5(或任何其他值):
d.weight.data = torch.full((8, 8), 0.5)
print(d.weight.data)
权重:
Out[14]:
tensor([[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000],
[0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000, 0.5000]])
你的重量现在都是0.5。传递数据:
d(input)
Out[13]:
tensor([[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.],
[4., 4., 4., 4., 4., 4., 4., 4.]], grad_fn=<MmBackward>)
请记住,每个神经元接收8个输入,所有输入的权重都为0.5,值为1(并且没有偏差),因此每个神经元的总和为4。
抱歉这么晚才来,希望我的回答能有所帮助。
用正态分布初始化权重:
torch.nn.init.normal_(tensor, mean=0, std=1)
或者使用常数分布:
torch.nn.init.constant_(tensor, value)
或者使用均匀分布:
torch.nn.init.uniform_(tensor, a=0, b=1) # a: lower_bound, b: upper_bound
你可以用其他方法来初始化张量
import torch.nn as nn
# a simple network
rand_net = nn.Sequential(nn.Linear(in_features, h_size),
nn.BatchNorm1d(h_size),
nn.ReLU(),
nn.Linear(h_size, h_size),
nn.BatchNorm1d(h_size),
nn.ReLU(),
nn.Linear(h_size, 1),
nn.ReLU())
# initialization function, first checks the module type,
# then applies the desired changes to the weights
def init_normal(m):
if type(m) == nn.Linear:
nn.init.uniform_(m.weight)
# use the modules apply function to recursively apply the initialization
rand_net.apply(init_normal)
推荐文章
- 有没有办法在python中做HTTP PUT
- “foo Is None”和“foo == None”之间有什么区别吗?
- 类没有对象成员
- Django模型“没有显式声明app_label”
- 熊猫能自动从CSV文件中读取日期吗?
- 在python中zip的逆函数是什么?
- 有效的方法应用多个过滤器的熊猫数据框架或系列
- 如何检索插入id后插入行在SQLite使用Python?
- 我如何在Django中添加一个CharField占位符?
- 如何在Python中获取当前执行文件的路径?
- 我如何得到“id”后插入到MySQL数据库与Python?
- super()失败,错误:TypeError "参数1必须是类型,而不是classobj"当父不继承对象
- Python内存泄漏
- 实现嵌套字典的最佳方法是什么?
- 如何在tensorflow中获得当前可用的gpu ?