TensorFlow和NumPy矩阵乘法的区别。

7

我有一个案例,在numpy中特定维度的两个矩阵相乘可以正常运行,但在tensorflow中无法运行。

x = np.ndarray(shape=(10,20,30), dtype = float)
y = np.ndarray(shape=(30,40), dtype = float)
z = np.matmul(x,y)
print("np shapes: %s x %s = %s" % (np.shape(x), np.shape(y), np.shape(z)))

这个程序按预期运行并打印输出:
np shapes: (10, 20, 30) x (30, 40) = (10, 20, 40)

然而,在tensorflow中,当我试图将占位符和与上述numpy数组相同形状的变量相乘时,会出现错误。

x = tf.placeholder(tf.float32, shape=(10,20,30))
y = tf.Variable(tf.truncated_normal([30,40], name='w'))
print("tf shapes: %s x %s" % (x.get_shape(), y.get_shape()))
tf.matmul(x,y)

结果显示

tf shapes: (10, 20, 30) x (30, 40)
InvalidArgumentError: 
Shape must be rank 2 but is rank 3 for 'MatMul_12' 
(op: 'MatMul') with input shapes: [10,20,30], [30,40].

为什么这个操作失败了?

numpy matmul 在这里做什么?将第二个条目广播到10,20,30并通过(30,40)进行10次20,30的matmul?似乎TF matmul缺少广播,可能值得提出功能请求。您可以通过执行y = tf.Variable(tf.truncated_normal([30,40], name='w')+tf.zeros((10,30,40)))来触发广播。相关问题(可能因错误而关闭)-- https://github.com/tensorflow/tensorflow/issues/216 - Yaroslav Bulatov
matmul在这里的作用与np.einsum('ijk,kl->ijl', x, y)相同。 - Kuba
3个回答

2
我不知道为什么tf.matmul不支持这种乘法(也许核心开发人员可以给出有意义的答案)。
但是,如果您只想以这种方式能够进行张量乘法,请查看tf.einsum函数。它可以处理任意秩的张量。

0

正如Dmytro所建议的那样,可以使用tf.einsum来乘以这两个数组。

x = np.ndarray(shape=(10,20,30), dtype = float)
y = np.ndarray(shape=(30,40), dtype = float)

这两个操作产生完全相同的结果:

np.einsum('ijk,kl->ijl', x, y)
np.matmul(x,y)

相应的TensorFlow操作也可以正常工作

tf.einsum('ijk,kl->ijl', tf_x,tf_y)

0

已经有人告诉过你,可以使用tf.einsum()来获得你想要的结果。

import tensorflow as tf
x = tf.random_normal([10, 20, 30])
y = tf.random_normal([30, 40])
z = tf.einsum('ijk,kl->ijl', x, y)

为什么tf.matmul()不按你的期望方式工作的原因已写在文档中。

输入必须是矩阵(或代表矩阵批量的秩>2的张量),具有匹配的内部维度,可能需要转置。

在您的案例中,您有一个矩阵y和一个张量x(秩3> 2)。 在您的情况下,内部维度不匹配。 如果您希望它们匹配,您需要像这样:

import tensorflow as tf
a, b, c = 12, 50, 20
x = tf.random_normal([a, b, c])
y = tf.random_normal([a, c, b])
z = tf.matmul(x, y)

但显然它没有计算出你想要的东西。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接