【问题标题】:Difference between Tensorflow's tf.keras.layers.Dense and PyTorch's torch.nn.Linear?Tensorflow 的 tf.keras.layers.Dense 和 PyTorch 的 torch.nn.Linear 的区别?
【发布时间】:2021-03-14 16:11:59
【问题描述】:

我有一个关于 Tensorflow 如何定义其线性层的快速(可能是愚蠢的)问题。在 PyTorch 中,线性(或密集)层定义为 y = x A^T + b,其中 A 和 b 是线性层的权重矩阵和偏置向量(请参阅here)。

但是,我无法准确找到 Tensorflow 的等效方程!它和 PyTorch 一样还是只是 y = x A + b ?

提前谢谢你!

【问题讨论】:

    标签: tensorflow pytorch


    【解决方案1】:

    如果我们在keras API 的密集层中将激活设置为None,那么它们在技术上是等效的。

    Tensorflow 的

    tf.keras.layers.Dense(..., activation=None) 
    

    根据doc,更多学习here

    activation:要使用的激活函数。如果您不指定任何内容,则不会应用任何激活(即“线性”激活:a(x) = x)。

    在 PyTorch 的 src 中。

    torch.nn.Linear
    

    此时它们是相等的。对传入数据的线性变换:y = x*W^T + b。请参阅下面这两者的更具体的等效实现。在PyTorch,我们这样做

    class Network(torch.nn.Module):
        def __init__(self):
            super(Network, self).__init__()
            self.fc1 = torch.nn.Linear(5, 30)
        def forward(self, state):
            return self.fc1(state)
    

    或者,

    trd = torch.nn.Linear(in_features = 3, out_features = 30)
    y = trd(torch.ones(5, 3))
    print(y.size())
    # torch.Size([5, 30])
    

    其等效的tf 实现将是

    model = tf.keras.models.Sequential()
    model.add(tf.keras.layers.Dense(30, input_shape=(5,), activation=None)) 
    

    或者,

    tfd = tf.keras.layers.Dense(30, input_shape=(3,), activation=None)
    x = tfd(tf.ones(shape=(5, 3)))
    print(x.shape)
    # (5, 30)
    

    【讨论】:

    • 我的意思是,就差异而言,纯粹是关于运算的线性代数。而不仅仅是输出张量的形状。例如,Tensorflow 的 Dense 层似乎是 y = xA + b 或 y = Ax + b,而 PyTorch 的线性层是 y = xA^T + b。虽然,它们给出相同的形状,但它们的衍生物却不同。
    • 哦,我明白了。问题标题让我很困惑。似乎您想知道它们是如何计算的。亚历克斯的回答对你来说应该没问题。
    • 是的,我本可以更好地表达它。但无论如何,我只需要澄清线性代数本身以及这些层在线性之间有何不同。导数是它们如何不同的一个例子(因为它们是不同的线性代数运算)。我确实对 TF 的 Dense 层是什么以及是否相同做了一个“猜测”。所以,如果其他人认为这有助于澄清,我可能会对标题进行编辑!感谢您对 TF 的 Dense 层的解释! :D
    【解决方案2】:

    tf.keras.layers.Dense在tensorflow源码中定义在这里:

    https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/keras/layers/core.py#L1081

    如果您遵循其call 函数中的引用,它会引导您找到此处使用的操作的定义,这确实是输入和权重的矩阵乘法加上预期的偏置向量:

    https://github.com/tensorflow/tensorflow/blob/a68c6117a1a53431e739752bd2ab8654dbe2534a/tensorflow/python/keras/layers/ops/core.py#L74

    outputs = gen_math_ops.MatMul(a=inputs, b=kernel)
    ...
    outputs = nn_ops.bias_add(outputs, bias)
    
    

    【讨论】:

    • 那么,kernel 变量的定义是一个权重矩阵,但与 PyTorch 的权重矩阵的维度相反?因此,假设我有批量大小为 N 的 A 输入特征和 B 输出特征。 kernel 的维度是 [A, B] 而在 PyTorch 的情况下是 [B, A] (因为应用了转置?)
    • 是的,它们存储的权重略有不同(W.T 与 W),但结果仍然相同。 PyTorch 的表示更接近教科书中的符号。您可以通过在 torch 和 tf 中打印出线性/密集权重的形状来快速检查这一点。
    • 在上面 TF 源代码的第一个链接的 line 1192 中,权重用 shape=[last_dim, self.units] (N_feats, N_out) 初始化,在 PyTorch (source code link) 中,权重用 @ 初始化987654331@ (N_out, N_feats)
    • 好的,所以对于形状为 (N_samp, N_feats) 的输入 x 的线性层,TF 的输出将是 matmul(x, A) + b 其中 A 是 (N_feats, N_out) 而 b 是(N_out, ),对于 PyTorch,它是 matmul(x, A^T) + b,其中 A 现在是 (N_out, N_feats),b 是 (N_out, )。好吧,看来这两个库定义它们的线性层不同!谢谢@Alex!
    猜你喜欢
    • 2020-10-01
    • 2018-12-11
    • 1970-01-01
    • 2020-05-21
    • 2017-04-13
    • 2019-11-10
    • 2016-09-03
    • 2018-08-20
    相关资源
    最近更新 更多