在 Pytorch 中的两层(模块)之间共享权重的正确方法是什么?
根据我在 Pytorch 论坛上的发现,有几种方法可以做到这一点。
例如,基于这个讨论,我认为简单地分配转置权重就可以了。那是在做:
self.decoder[0].weight = self.encoder[0].weight.t()
然而,这被证明是错误的并导致错误。然后我尝试将上面的行包装在nn.Parameter()
:
self.decoder[0].weight = nn.Parameter(self.encoder[0].weight.t())
这消除了错误,但话又说回来,这里没有发生共享。通过这个,我刚刚初始化了一个新的张量,其值与encoder[0].weight.t()
.
然后我找到了这个链接,它提供了不同的权重共享方式。但是,我怀疑那里给出的所有方法实际上是否正确。
例如,一种方法如下所示:
# tied autoencoder using off the shelf nn modules
class TiedAutoEncoderOffTheShelf(nn.Module):
def __init__(self, inp, out, weight):
super().__init__()
self.encoder = nn.Linear(inp, out, bias=False)
self.decoder = nn.Linear(out, inp, bias=False)
# tie the weights
self.encoder.weight.data = weight.clone()
self.decoder.weight.data = self.encoder.weight.data.transpose(0,1)
def forward(self, input):
encoded_feats = self.encoder(input)
reconstructed_output = self.decoder(encoded_feats)
return encoded_feats, reconstructed_output
基本上,它使用创建一个新的权重张量nn.Parameter()
并将其分配给每个层/模块,如下所示:
weights = nn.Parameter(torch.randn_like(self.encoder[0].weight))
self.encoder[0].weight.data = weights.clone()
self.decoder[0].weight.data = self.encoder[0].weight.data.transpose(0, 1)
这真的让我很困惑,这如何在这两层之间共享相同的变量?不只是克隆“原始”数据吗?
当我使用这种方法并可视化权重时,我注意到可视化是不同的,这让我更加确定有些事情是不对的。
我不确定不同的可视化是否仅仅是由于一个是另一个的转置,或者正如我已经怀疑的那样,它们是独立优化的(即权重不在层之间共享)