在numpy
中,您可以将 2D 数组与 3d 数组相乘,如下例所示:
>>> X = np.random.randn(3,5,4) # [3,5,4]
... W = np.random.randn(5,5) # [5,5]
... out = np.matmul(W, X) # [3,5,4]
据我了解,np.matmul()
W
并沿着X
的第一个维度进行广播。但在tensorflow
中,这是不允许的:
>>> _X = tf.constant(X)
... _W = tf.constant(W)
... _out = tf.matmul(_W, _X)
ValueError: Shape must be rank 2 but is rank 3 for 'MatMul_1' (op: 'MatMul') with input shapes: [5,5], [3,5,4].
那么np.matmul()
在tensorflow
中所做的是否有等效物?将 2d 张量乘以 3d 张量的tensorflow
最佳实践是什么?
尝试在乘法之前使用 tf.tile 匹配矩阵的维度。numpy 的自动广播功能似乎没有在 tensorflow 中实现。您必须手动执行此操作。
W_T = tf.tile(tf.expand_dims(W,0),[3,1,1])
这应该可以解决问题
import numpy as np
import tensorflow as tf
X = np.random.randn(3,4,5)
W = np.random.randn(5,5)
_X = tf.constant(X)
_W = tf.constant(W)
_W_t = tf.tile(tf.expand_dims(_W,0),[3,1,1])
with tf.Session() as sess:
print(sess.run(tf.matmul(_X,_W_t)))
您可以改用tensordot
:
tf.transpose(tf.tensordot(_W, _X, axes=[[1],[1]]),[1,0,2])
以下是来自张量流XLA广播语义
XLA语言尽可能严格和明确,避免隐含和"神奇"的特征。这些功能可能会使一些计算稍微更容易定义,但代价是用户代码中存在更多假设,从长远来看很难改变。
所以Tensorflow不提供内置的广播功能。
然而,它确实提供了一些可以重塑张量的东西,就像它被广播一样。此操作称为 tf.tile
签名如下:
tf.tile(input, multiples, name=None)
此操作通过以下方式创建新的张量 多次复制输入。输出张量的第 i 维 具有 input.dims(i( * 倍数 [i] 元素,输入的值为 沿"i"维度复制倍数[i]次。
您还可以使用tf.einsum
来避免平铺张量:
tf.einsum("ab,ibc->iac", _W, _X)
一个完整的例子:
import numpy as np
import tensorflow as tf
# Numpy-style matrix multiplication:
X = np.random.randn(3,5,4)
W = np.random.randn(5,5)
np_WX = np.matmul(W, X)
# TensorFlow-style multiplication:
_X = tf.constant(X)
_W = tf.constant(W)
_WX = tf.einsum("ab,ibc->iac", _W, _X)
with tf.Session() as sess:
tf_WX = sess.run(_WX)
# Check that the results are the same:
print(np.allclose(np_WX, tf_WX))
在这里我将使用 keras 后端K.dot
和 tensorflowtf.transpose
。 3 D 张量的第一次交换内暗
X=tf.transpose(X,perm=[0,-1,1]) # X shape=[3,4,5]
现在像这样乘法
out=K.dot(X,W) # out shape=[3,4,5]
现在再次交换轴
out = tf.transpose(out,perm=[0,-1,1]) # out shape=[3,5,4]
上述解决方案以很少的时间成本节省内存,因为您不会平铺W
。