【问题标题】:PyTorch - Effect of normal() initialization on gradientsPyTorch - normal() 初始化对梯度的影响
【发布时间】:2019-01-15 23:41:26
【问题描述】:

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

我有一个小例子:

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 标志显然是从均值张量中接管的。 parameter_vector.

但这是否自动意味着parameter_vector 将在init_result 影响最终结果的更大网络中通过backward() 更新?

尤其是normal() 看起来并不像正常操作,因为它涉及随机性。

【问题讨论】:

  • 如果您想这样做,最好使用重新参数化技巧stats.stackexchange.com/a/342815/133099,它允许您通过采样操作进行反向传播
  • @iacolippo 谢谢,这真的很高兴知道!我会这样尝试,但是你知道它是如何在 pytorch 中实现的吗?尚未找到生成完成的实际源代码。
  • 相关问题(指导性阅读):github.com/pytorch/pytorch/issues/4620 他们建议使用torch.distributions
  • 谢谢,我会通过问题线程。我实现了您从交叉验证中建议的方式。到目前为止它工作正常,但打印输出中显示了一个新标志:tensor([-0.0047, 0.8995, 1.9992, 2.9483, 3.9291, 4.8601, 5.9526, 6.9122, 8.0088, 8.8857], grad_fn=<ThAddBackward>) - 知道grad_fn=<ThAddBackward> 是什么意思吗?以前没见过。
  • 好吧,它似乎只是说这是添加张量的结果。所以我想它现在可以工作了 - 非常感谢!

标签: python neural-network deep-learning pytorch backpropagation


【解决方案1】:

感谢@iacolippo(请参阅问题下方的 cmets)问题现已解决。我只是想通过发布我现在使用的代码来补充这一点,所以这可能对其他人有所帮助。

正如问题中假设的那样,@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() 不会引发错误(请参阅上面 cmets 中的链接问题),但参数也不会使用 SGD-Step 更新。


工作示例 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-Step 后更新。

我希望这对某人有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-23
    • 2016-10-19
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多