【问题标题】:Why doesn't `tf.matmul` work with transposed tensor?为什么 `tf.matmul` 不适用于转置张量?
【发布时间】:2019-09-19 14:25:30
【问题描述】:

为什么tf.matmul 不适用于转置张量?

transpose_b=True 可以,但tf.transpose(inp) 不行。

此屏幕截图是在 Colab 中使用 tensorflow-gpu==2.0.0-rc1 制作的:

【问题讨论】:

    标签: python tensorflow


    【解决方案1】:

    transpose_b=True in tf.linalg.matmul 仅转置第二个给定张量的最后两个轴,而 tf.transpose 没有更多参数,完全反转维度。相当于:

    inp_t = tf.transpose(inp, (0, 2, 1))
    tf.matmul(inp, inp_t)
    

    【讨论】:

      【解决方案2】:

      tf.transpose() 如果您没有明确指定perm(permutation) 参数,则默认执行常规二维矩阵转置(它将 perm 参数设置为 input_tensor_rank-1)。 所以适当设置perm参数

      inp_t = tf.transpose(inp, perm=[0,2,1])
      y = tf.matmul(inp, x)
      print(y)
      

      【讨论】:

        【解决方案3】:

        Tensorflow 告诉您的是,将两个张量相乘时尺寸不匹配。用基本的线性代数术语来考虑它。矩阵相乘时,只能将矩阵相乘,其中第一个矩阵的最后一维与第二个矩阵的第一维相同。例如。您可以将 2x4 矩阵与 4x2 矩阵相乘(这是 transpose 为您所做的。来自 the docs

        如果没有给出perm,则设置为(n-1...0),其中n是输入张量的秩。因此,默认情况下,此操作对二维输入张量执行常规矩阵转置。

        因此,如果您在更高维度上省略 perm,tf.transform() 会像二维张量(矩阵)一样切换维度:

        inp_t_without_perm = tf.transpose(inp)
        inp_t_without_perm
        # Output: <tf.Tensor 'transpose_8:0' shape=(1, 4, 2) dtype=float32>
        

        所以它只是切换第一个维度的最后一个维度,而第二个维度保持不变。这相当于:

        inp_t_with_wrong_perm = tf.transpose(inp, perm=[2,1,0])
        inp_t_with_wrong_perm
        # Output: <tf.Tensor 'transpose_8:0' shape=(1, 4, 2) dtype=float32>
        

        如果你这样做:

        mul = tf.matmul(inp, inp_t_without_perm) # or with inp_t_with_wrong_perm
        

        您收到此错误,因为您的前两个或后两个维度不匹配。

        现在,当将高阶张量相乘时,您必须以与 2d 中相同的方式对齐不同的维度(将其视为将张量划分为矩阵和向量。在您的情况下,您有一个向量和一个矩阵……抱歉,我还没想出更好的比喻,当我找到一个安静的半小时用笔和纸,我可以用爱因斯坦符号让它更正式,但这基本上是它是如何工作的......)。

        对于您的情况,有效的是:

        inp = tf.reshape(tf.linspace(-1.0, 1.0, 8), (2,4,1))
        # switch the last two dimensions so you can multiply 4x1 by 1x4
        # and leave first dimension as it is.
        inp_t = tf.transpose(inp, perm=[0,2,1])
        mul = tf.matmul(inp, inp_t)
        mul
        # Output: <tf.Tensor 'MatMul_8:0' shape=(2, 4, 4) dtype=float32>
        

        请注意,在您的情况下,这是唯一有效的排列,因为这种乘法是不可交换的。所以你必须从左到右匹配尺寸(再次,抱歉挥手,但正式的数学证明需要我做一些高阶张量代数,但我认为这正是你想要实现的...)。我没有深入研究文档,但我认为 transform_b 参数正在为您进行这种排列。希望有帮助。如有更多问题,请发表评论。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-08
          • 2012-12-23
          • 1970-01-01
          • 1970-01-01
          • 2023-02-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多