为什么我只使用 PyTorch 中的参数包装器进行收敛?
Why do I converge only using a parameter wrapper in PyTorch?
我正在编写 Bayesian Dropout 的实现,经过几个小时的调试,以下代码可以正常工作:
class DropoutLayer(nn.Module):
def __init__(self, n_in, n_out, dropout_rate):
super(DropoutLayer,self).__init__()
self.M = Parameter(torch.normal(torch.zeros(n_in,n_out),0.01))
self.m = Parameter(torch.rand(n_out))
# 1-p is used to be consistent with original dropout definition
self.z = Bernoulli(torch.tensor([1-dropout_rate]))
self.W = Parameter(torch.mm(
torch.diagflat(self.z.sample(sample_shape=(n_in,))),
self.M))
def forward(self,x,act):
activation = torch.mm(x,self.W) + self.m
out = act(activation)
return out
但是,我似乎不太明白,为什么self.W中的矩阵乘法需要参数包装。我会假设一旦我指定 self.M 作为 autograd 中的参数,我就不需要为任何使用它的值做它。为什么我需要它?
添加这个包装器后,神经网络收敛没有问题。
你能告诉我为什么会这样吗?是否有更简单的替代方案来替代我不喜欢的解决方案?
首先,你不需要将self.M
传递给Parameter
,因为梯度不需要 通过它。您 forward
函数仅使用 self.W
和 self.m
(加上激活,尽管您确实应该将其传递给构造函数,而不是 forward
...)。
All self.M
是某种与模块同时创建的随机正态张量,它只是将 self.W
矩阵初始化为具体值。所以 self.W
是一个单独的张量,它在计算上不以任何方式依赖于 self.M
。
我正在编写 Bayesian Dropout 的实现,经过几个小时的调试,以下代码可以正常工作:
class DropoutLayer(nn.Module):
def __init__(self, n_in, n_out, dropout_rate):
super(DropoutLayer,self).__init__()
self.M = Parameter(torch.normal(torch.zeros(n_in,n_out),0.01))
self.m = Parameter(torch.rand(n_out))
# 1-p is used to be consistent with original dropout definition
self.z = Bernoulli(torch.tensor([1-dropout_rate]))
self.W = Parameter(torch.mm(
torch.diagflat(self.z.sample(sample_shape=(n_in,))),
self.M))
def forward(self,x,act):
activation = torch.mm(x,self.W) + self.m
out = act(activation)
return out
但是,我似乎不太明白,为什么self.W中的矩阵乘法需要参数包装。我会假设一旦我指定 self.M 作为 autograd 中的参数,我就不需要为任何使用它的值做它。为什么我需要它?
添加这个包装器后,神经网络收敛没有问题。 你能告诉我为什么会这样吗?是否有更简单的替代方案来替代我不喜欢的解决方案?
首先,你不需要将self.M
传递给Parameter
,因为梯度不需要 通过它。您 forward
函数仅使用 self.W
和 self.m
(加上激活,尽管您确实应该将其传递给构造函数,而不是 forward
...)。
All self.M
是某种与模块同时创建的随机正态张量,它只是将 self.W
矩阵初始化为具体值。所以 self.W
是一个单独的张量,它在计算上不以任何方式依赖于 self.M
。