tensorflow中的外积

时间:2015-11-22 17:47:06

标签: tensorflow

在tensorflow中,有很好的入门和矩阵乘法功能,但在浏览文档之后,我找不到任何内部函数来获取两个张量的外积,即做大张量较小的张量元素的所有可能产品(如numpy.outer):

v_{i,j} = x_i*h_j

M_{ij,kl} = A_{ij}*B_{kl}

tensorflow有这样的功能吗?

6 个答案:

答案 0 :(得分:19)

是的,您可以通过利用tensorflow的广播语义来实现这一点。将第一个大小调整为自身的大小1xN,将第二个大小调整为大小Mx1,并且当您将它们相乘时,您将获得所有结果的MxN广播。

(你可以在numpy中使用相同的东西来看看它在更简单的上下文中的表现,顺便说一下:

a = np.array([1, 2, 3, 4, 5]).reshape([5,1])
b = np.array([6, 7, 8, 9, 10]).reshape([1,5])
a*b

在tensorflow中你究竟是如何做到的,取决于你想要使用哪些轴以及你想要的结果乘法的语义,但总体思路适用。

答案 1 :(得分:4)

如果其他人偶然发现这种情况,根据tensorflow文档,您可以使用tf.einsum()函数计算两个张量ab的外积:

# Outer product
>>> einsum('i,j->ij', u, v)  # output[i,j] = u[i]*v[j]

答案 2 :(得分:3)

令人惊讶的是,直到最近,在张量流中的任意张量(也称为“张量积”)之间没有简单而“自然”的方式来做外积,特别是考虑到库的名称... / p>

借助tensorflow>=1.6,您现在可以通过一个简单的方法最终获得所需的内容:

M = tf.tensordot(A, B, axes=0)

在tensorflow的早期版本中,axes=0引发ValueError: 'axes' must be at least 1.tf.tensordot()过去至少需要一个维度才能实际求和。最简单的方法是使用tf.expand_dims()添加一个“假”尺寸。

tensorflow<=1.5上,您可以通过执行以下操作获得与上述相同的结果:

M = tf.tensordot(tf.expand_dims(A, 0), tf.expand_dims(B, 0), axes=[[0],[0]])

这将在两个张量的位置0处添加一个新的尺寸为1的索引,然后让tf.tensordot()对这些索引求和。

答案 3 :(得分:3)

tf.multiply(及其“ *”快捷方式)会产生外部产品,无论是否使用批次。特别是,如果两个输入张量具有[batch,n,1]和[batch,1,n]的3D形状,则此op将计算[n,1],[1,n] 批次中的每个样品。如果没有批次,则两个输入张量为2D,此运算将计算外部乘积相同。 另一方面,虽然tf.tensordot产生了2D矩阵的外部乘积,但是添加一批时,它的广播效果并不相同。

无批次:

a_np = np.array([[1, 2, 3]]) # shape: (1,3) [a row vector], 2D Tensor
b_np = np.array([[4], [5], [6]]) # shape: (3,1) [a column vector], 2D Tensor
a = tf.placeholder(dtype='float32', shape=[1, 3])
b = tf.placeholder(dtype='float32', shape=[3, 1])
c = a*b # Result: an outer-product of a,b
d = tf.multiply(a,b) # Result: an outer-product of a,b
e = tf.tensordot(a,b, axes=[0,1]) # Result: an outer-product of a,b

批量处理:

a_np = np.array([[[1, 2, 3]], [[4, 5, 6]]]) # shape: (2,1,3) [a batch of two row vectors], 3D Tensor
b_np = np.array([[[7], [8], [9]], [[10], [11], [12]]]) # shape: (2,3,1) [a batch of two column vectors], 3D Tensor
a = tf.placeholder(dtype='float32', shape=[None, 1, 3])
b = tf.placeholder(dtype='float32', shape=[None, 3, 1])
c = a*b # Result: an outer-product per batch
d = tf.multiply(a,b) # Result: an outer-product per batch
e = tf.tensordot(a,b, axes=[1,2]) # Does NOT result with an outer-product per batch

运行以下两个图形中的任何一个:

sess = tf.Session()
result_astrix = sess.run(c, feed_dict={a:a_np, b: b_np})
result_multiply = sess.run(d, feed_dict={a:a_np, b: b_np})
result_tensordot = sess.run(e, feed_dict={a:a_np, b: b_np})
print('a*b:')
print(result_astrix)
print('tf.multiply(a,b):')
print(result_multiply)
print('tf.tensordot(a,b, axes=[1,2]:')
print(result_tensordot)

答案 4 :(得分:1)

在其他答案中指出,可以使用广播来完成外部产品:

a = tf.range(10)
b = tf.range(5)
outer = a[..., None] * b[None, ...]

tf.InteractiveSession().run(outer)
# array([[ 0,  0,  0,  0,  0],
#        [ 0,  1,  2,  3,  4],
#        [ 0,  2,  4,  6,  8],
#        [ 0,  3,  6,  9, 12],
#        [ 0,  4,  8, 12, 16],
#        [ 0,  5, 10, 15, 20],
#        [ 0,  6, 12, 18, 24],
#        [ 0,  7, 14, 21, 28],
#        [ 0,  8, 16, 24, 32],
#        [ 0,  9, 18, 27, 36]], dtype=int32)

说明:

  • a[..., None]在最后一个轴之后插入长度为1的新尺寸。
  • 类似地,b[None, ...]在第一个轴之前插入长度为1的新尺寸。
  • 元素范围的乘法然后将张量从形状(10, 1) * (1, 5)传播到(10, 5) * (10, 5),计算出外部积。

要在其中插入附加尺寸的地方确定要计算出哪些外部尺寸。例如,如果两个张量都具有批处理大小,则可以使用给出:的{​​{1}}跳过该张量。这可以进一步缩写为a[:, ..., None] * b[:, None, ...]。要在最后一个尺寸上执行外部产品并由此支持任意数量的批次尺寸,请使用a[..., None] * b[:, None]

答案 5 :(得分:1)

我本来会对MasDra发表评论,但不允许我成为新的注册用户。

可以通过

获得以长度顺序排列的列表U排列的多个向量的一般外积。
tf.einsum(','.join(string.ascii_lowercase[0:order])+'->'+string.ascii_lowercase[0:order], *U)