为什么我只使用 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.Wself.m(加上激活,尽管您确实应该将其传递给构造函数,而不是 forward...)。

All self.M 是某种与模块同时创建的随机正态张量,它只是将 self.W 矩阵初始化为具体值。所以 self.W 是一个单独的张量,它在计算上不以任何方式依赖于 self.M