【发布时间】:2019-09-19 14:25:30
【问题描述】:
为什么tf.matmul 不适用于转置张量?
transpose_b=True 可以,但tf.transpose(inp) 不行。
此屏幕截图是在 Colab 中使用 tensorflow-gpu==2.0.0-rc1 制作的:
【问题讨论】:
标签: python tensorflow
为什么tf.matmul 不适用于转置张量?
transpose_b=True 可以,但tf.transpose(inp) 不行。
此屏幕截图是在 Colab 中使用 tensorflow-gpu==2.0.0-rc1 制作的:
【问题讨论】:
标签: python tensorflow
transpose_b=True in tf.linalg.matmul 仅转置第二个给定张量的最后两个轴,而 tf.transpose 没有更多参数,完全反转维度。相当于:
inp_t = tf.transpose(inp, (0, 2, 1))
tf.matmul(inp, inp_t)
【讨论】:
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)
【讨论】:
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 参数正在为您进行这种排列。希望有帮助。如有更多问题,请发表评论。
【讨论】: