Tensorflow 张量流中的外积

Tensorflow 张量流中的外积,tensorflow,Tensorflow,在tensorflow中,有很好的入口和矩阵乘法函数,但在查看文档后,我找不到任何内部函数来获取两个张量的外积,即,通过较小张量元素的所有可能乘积(如numpy.outer)生成更大的张量: 或 tensorflow有这样的功能吗 是的,您可以利用tensorflow的广播语义来实现这一点。将第一个输出的大小调整为自身的1xN大小,第二个输出的大小调整为自身的Mx1大小,当您将结果相乘时,您将得到所有结果的广播 (您可以在numpy中使用相同的东西,看看它在更简单的上下文中的行为,顺便说一句:

在tensorflow中,有很好的入口和矩阵乘法函数,但在查看文档后,我找不到任何内部函数来获取两个张量的外积,即,通过较小张量元素的所有可能乘积(如numpy.outer)生成更大的张量:


tensorflow有这样的功能吗

是的,您可以利用tensorflow的广播语义来实现这一点。将第一个输出的大小调整为自身的1xN大小,第二个输出的大小调整为自身的Mx1大小,当您将结果相乘时,您将得到所有结果的广播

(您可以在numpy中使用相同的东西,看看它在更简单的上下文中的行为,顺便说一句:

a=np.数组([1,2,3,4,5])。重塑([5,1])
b=np.数组([6,7,8,9,10])。重塑([1,5])
a*b

在tensorflow中,具体如何实现这一点在一定程度上取决于您想要使用的轴以及您想要得到的乘法的语义,但总体思路是适用的。

如果其他人偶然发现了这一点,根据tensorflow文档,您可以使用该函数计算两个张量的外积
a
b

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

令人有些惊讶的是,直到最近,在tensorflow中,还没有一种简单而“自然”的方法来做任意张量之间的外积(也称为“张量积”),特别是考虑到库的名称

使用
tensorflow>=1.6
现在,您可以通过一个简单的:

M = tf.tensordot(A, B, axes=0)
在tensorflow的早期版本中,
axes=0
会引发一个
ValueError:“axes”必须至少为1。
。不知何故,
tf.tensordot()
过去至少需要一个维度才能真正求和。简单的解决方法是使用
tf.expand_dims()
添加一个“伪”维度

tensorflowtf.multiply(及其“*”快捷方式)上,无论是否使用批次,都会生成一个外积。特别是,如果两个输入张量具有[batch,n,1]和[batch,1,n]的3D形状,则此op将计算[n,1],[1,n]的外积如果没有批次,因此两个输入张量为2D,此op将计算相同的外积。
另一方面,虽然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)
批处理:

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)
运行这两个图形中的任意一个:

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)

正如其他答案中所指出的,外部产品可以通过广播完成:

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[…,无]
    在最后一个轴后插入长度为1的新标注
  • 类似地,
    b[None,…]
    在第一个轴之前插入长度为1的新标注
  • 然后,元素范围的乘法将张量从形状
    (10,1)*(1,5)
    广播到
    (10,5)*(10,5)
    ,计算外积

插入附加尺寸的位置决定了计算外积的尺寸。例如,如果两个张量都有一个批量大小,则可以使用
跳过该步骤,它给出
a[:,…,None]*b[:,None,…]
。这可以进一步缩写为
a[…,None]*b[:,None]
。要在最后一个维度上执行外部产品,从而支持任意数量的批量维度,请使用
a[…,None]*b[…,None,:]

我会向MasDra发表评论,但不允许我作为新注册用户

按长度顺序排列的多个向量的一般外积可以通过

tf.einsum(','.join(string.ascii_lowercase[0:order])+'->'+string.ascii_lowercase[0:order], *U)

是的,但这很乏味,因为
einsum()
的第一个参数取决于你想要取其外积的张量的形状。你可以通过:
tf.einsum('{0}xz,{0}xz->{0}xy'.格式(string.ascii\u小写[:A.\u rank()-2]),A,B将其推广到形状(…,x,d)的更大张量
B
还有
a[…,None]*b[None,…]
使用Tensorflow 2,它看起来像
a=tf.expand_dims(a,axis=-1)
b=tf.expand_dims(b,axis=-1)
outer=tf.matmul(a,b,transpose_b=True)
实际上是唯一对我有效的解决方案。谢谢你清晰的解释