假设我有一个神经网络,我使用正态分布初始化,我想使用用于初始化的平均值作为网络参数。
我有一个小例子:

import torch
parameter_vector = torch.tensor(range(10), dtype=torch.float, requires_grad=True)
sigma = torch.ones(parameter_vector.size(0), dtype=torch.float)*0.1
init_result = torch.normal(parameter_vector, sigma)
print('requires_grad:', init_result.requires_grad)
print('result:       ', init_result)

这将导致:
requires_grad: True
result:        tensor([ 0.1026,  0.9183,  1.9586,  3.1778,  4.0538,  4.8056,  5.9561,
         6.9501,  7.7653,  8.9583])

因此,requires_grad标志明显地被平均值张量resp所取代。parameter_vector
但这是否自动意味着parameter_vector将通过backward()init_result影响最终结果的较大网络中更新?
尤其是当normal()看起来不像是正常的手术,因为它涉及随机性。

最佳答案

感谢@iacolippo(请参阅问题下方的注释)现在问题已解决。我只是想通过发布我现在使用的代码来补充这一点,所以这可能对其他人有帮助。
正如问题中的假设和@iacolippo所述,问题中发布的代码是不可反向传播的:

import torch
parameter_vector = torch.tensor(range(5), dtype=torch.float, requires_grad=True)
print('- initial parameter weights:', parameter_vector)
sigma = torch.ones(parameter_vector.size(0), dtype=torch.float)*0.1
init_result = torch.normal(parameter_vector, sigma)
print('- normal init result requires_grad:', init_result.requires_grad)
print('- normal init vector', init_result)
#print('result:       ', init_result)
sum_result = init_result.sum()
sum_result.backward()
print('- summed dummy-loss:', sum_result)
optimizer = torch.optim.SGD([parameter_vector], lr = 0.01, momentum=0.9)
optimizer.step()
print()
print('- parameter weights after update:', parameter_vector)

输出:
- initial parameter weights: tensor([0., 1., 2., 3., 4.], requires_grad=True)
- normal init result requires_grad: True
- normal init vector tensor([-0.0909,  1.1136,  2.1143,  2.8838,  3.9340], grad_fn=<NormalBackward3>)
- summed dummy-loss: tensor(9.9548, grad_fn=<SumBackward0>)

- parameter weights after update: tensor([0., 1., 2., 3., 4.], requires_grad=True)

如您所见,调用backward()不会引发错误(请参阅上面注释中的链接问题),但参数也不会使用SGD步骤更新。
工作示例1
一种解决方案是使用此处给出的公式/技巧:https://stats.stackexchange.com/a/342815/133099
x=μ+σ样本(N(0,1))
要存档:
sigma = torch.ones(parameter_vector.size(0), dtype=torch.float)*0.1
init_result = torch.normal(parameter_vector, sigma)

更改为:
dim = parameter_vector.size(0)
sigma = 0.1
init_result = parameter_vector + sigma*torch.normal(torch.zeros(dim), torch.ones(dim))

在更改这些行之后,代码变回可能值,并在调用backward()和SGD Step之后更新参数向量。
换行输出:
- initial parameter weights: tensor([0., 1., 2., 3., 4.], requires_grad=True)
- normal init result requires_grad: True
- normal init vector tensor([-0.1802,  0.9261,  1.9482,  3.0817,  3.9773], grad_fn=<ThAddBackward>)
- summed dummy-loss: tensor(9.7532, grad_fn=<SumBackward0>)

- parameter weights after update: tensor([-0.0100,  0.9900,  1.9900,  2.9900,  3.9900], requires_grad=True)

工作示例2
另一种方法是使用torch.distributions(Documentation Link)
执行此操作时,上述代码中的相应行必须替换为:
i = torch.ones(parameter_vector.size(0))
sigma = 0.1
m = torch.distributions.Normal(parameter_vector, sigma*i)
init_result = m.rsample()

换行输出:
- initial parameter weights: tensor([0., 1., 2., 3., 4.], requires_grad=True)
- normal init result requires_grad: True
- normal init vector tensor([-0.0767,  0.9971,  2.0448,  2.9408,  4.1321], grad_fn=<ThAddBackward>)
- summed dummy-loss: tensor(10.0381, grad_fn=<SumBackward0>)

- parameter weights after update: tensor([-0.0100,  0.9900,  1.9900,  2.9900,  3.9900], requires_grad=True)

从上面的输出中可以看出-使用torch.distributions也会产生回概码,在调用backward()和SGD步骤后,参数向量会更新。
我希望这对某人有帮助。

关于python - PyTorch-normal()初始化对渐变的影响,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51751231/

10-12 17:40