我试图从PyTorch构建的一个简单网络中提取权重和偏置。我的整个网络由nn.Linear层组成。当我通过调用nn.Linear(in_dim, out_dim)
创建一个层时,我期望通过调用model.parameters()
获取的参数形状为权重(in_dim, out_dim)
,偏置(out_dim)
。然而,从model.parameters()
中得到的权重形状却是(out_dim, in_dim)
。
我的代码意图是能够使用矩阵乘法来执行仅使用numpy的正向传播,而不使用任何PyTorch。由于形状不一致,矩阵乘法会抛出错误。我该如何修复这个问题?
这是我的确切代码:
class RNN(nn.Module): def __init__(self, dim_input, dim_recurrent, dim_output): super(RNN, self).__init__() self.dim_input = dim_input self.dim_recurrent = dim_recurrent self.dim_output = dim_output self.dense1 = nn.Linear(self.dim_input, self.dim_recurrent) self.dense2 = nn.Linear(self.dim_recurrent, self.dim_recurrent, bias = False) self.dense3 = nn.Linear(self.dim_input, self.dim_recurrent) self.dense4 = nn.Linear(self.dim_recurrent, self.dim_recurrent, bias = False) self.dense5 = nn.Linear(self.dim_recurrent, self.dim_output)#有一个定义的正向传播model = RNN(12, 100, 6)for i in model.parameters(): print(i.shape())
输出是:
torch.Size([100, 12])torch.Size([100])torch.Size([100, 100])torch.Size([100, 12])torch.Size([100])torch.Size([100, 100])torch.Size([6, 100])torch.Size([6])
如果我的理解正确,输出应该为:
torch.Size([12, 100])torch.Size([100])torch.Size([100, 100])torch.Size([12, 100])torch.Size([100])torch.Size([100, 100])torch.Size([100, 6])torch.Size([6])
我的问题是什么?
回答:
你看到的并不是(out_dim, in_dim),那只是权重矩阵的形状。当你调用print(model)
时,你可以看到输入和输出特征是正确的:
RNN( (dense1): Linear(in_features=12, out_features=100, bias=True) (dense2): Linear(in_features=100, out_features=100, bias=False) (dense3): Linear(in_features=12, out_features=100, bias=True) (dense4): Linear(in_features=100, out_features=100, bias=False) (dense5): Linear(in_features=100, out_features=6, bias=True))
你可以查看源代码,会发现权重在调用matmul
之前实际上是转置的。
nn.Linear
在这里定义:
https://pytorch.org/docs/stable/_modules/torch/nn/modules/linear.html#Linear
你可以查看forward
,它看起来像这样:
def forward(self, input): return F.linear(input, self.weight, self.bias)
F.linear
在这里定义:
https://pytorch.org/docs/stable/_modules/torch/nn/functional.html
用于乘权重的相应行是:
output = input.matmul(weight.t())
如上所述,你可以看到权重在应用matmul
之前是转置的,因此权重的形状与你预期的不同。
所以如果你想手动进行矩阵乘法,你可以这样做:
# 长度为5的虚拟输入input = torch.rand(5, 12)# 应用dense1层(不包括偏置,如果需要偏置只需加上model.dense1.bias)output_first_layer = input.matmul(model.dense1.weight.t())print(output_first_layer.shape)
正如你对dense1
的预期,它返回:
torch.Size([5, 100])
我希望这能解释你对形状的观察 🙂