如何在张量流中使用 3d 张量对 2d 张量进行矩阵处理?



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

最新更新