为什么 PyTorch 的线性层将权重存储在形状(out、in)中并在前向传递中转置它?

问题描述 投票:0回答:1

PyTorch 的

Linear
层将
weight
属性存储在形状
(out_features, in_features)
中。在前向传播中,执行以下操作:

def forward(self, input: Tensor) -> Tensor:
    return F.linear(input, self.weight, self.bias)

相当于:

def forward(self, input: Tensor) -> Tensor:
    return torch.addmm(self.bias, input, self.weight.t())

这很奇怪。为什么

weight
属性不以
(in_features, out_features)
的形式存储,从而消除前向和后向传递中转置的需要?

我进行了基准测试来比较两种存储方法(前向和后向传递超过 10,000 次迭代),发现预转置权重每次迭代快约 10μs。该基准测试使用具有 100 个特征和 128 列随机数据的张量。为了确保公平性,两个

Linear
层都配置了相同的参数,包括权重和偏差,并应用于相同的随机数据。

python pytorch tensor
1个回答
0
投票

选择将权重存储在 PyTorch 线性层中的形状(out_features、in_features)中并在前向传递期间进行转置是库内的约定和一致性问题。

在数学符号中,典型的线性变换表示为 (y = Wx + b),其中 (W) 的形状为 (out_features, in_features)。通过使用此约定,PyTorch 保持与其他线性代数例程和典型数学符号的一致性。这种选择可以让熟悉线性变换数学公式的人有更直观的理解。

您在基准测试中观察到的转置开销通常很小,并且通常会被大多数现实场景中的其他计算成本所掩盖。虽然您确实注意到微基准的差异,但在实践中,设计选择对整体性能的影响通常可以忽略不计。

在 TensorFlow 中,密集(全连接)层中权重矩阵的约定与 PyTorch 相反。权重矩阵由形状 (in_features, out_features) 定义,与操作 (y = xW + b) 对齐。这与 TensorFlow 的内部设计以及框架内处理矩阵乘法的方式一致。

PyTorch 和 TensorFlow 在这方面的差异表明,这些约定是特定于库的,并且可能会根据开发人员所做的设计选择而有所不同。虽然它们可能会导致性能或实现方面略有差异,但这两种方法都是有效的,并且与各自库的内部逻辑和其他操作保持一致。

© www.soinside.com 2019 - 2024. All rights reserved.