为什么`tf.matmul`不能与转置张量一起工作?

时间:2019-09-19 14:25:30

标签: python tensorflow

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

transpose_b=True没问题,但tf.transpose(inp)没问题。

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

enter image description here

3 个答案:

答案 0 :(得分:1)

tf.linalg.matmul中的

transpose_b=True仅对第二个给定张量的最后两个轴进行转置,而tf.transpose在没有更多参数的情况下将完全反转尺寸。等效为:

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

答案 1 :(得分:1)

tf.transpose()默认执行常规的二维矩阵转置(将perm参数设置为input_tensor_rank-1),如果您未明确指定perm(permutation)参数。 因此,请适当设置perm参数

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

答案 2 :(得分:1)

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

  

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

因此,如果您忽略较大尺寸的烫发,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参数正在为您完成这种排列。希望能有所帮助。请进一步评论。