首页 文章

tensorflow中的外积

提问于
浏览
13

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

v_{i,j} = x_i*h_j

要么

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

tensorflow有这样的功能吗?

6 回答

  • 1

    是的,您可以通过利用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

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

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

    有点令人惊讶的是,直到最近,在张量流中,在任意张量(也称为“张量积”)之间进行外部产品没有简单而“自然”的方式,特别是考虑到图书馆的名称......

    使用 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() 添加"fake"维度 .

    tensorflow<=1.5 上,您可以通过以下方式获得与上述相同的结果:

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

    这为两个张量的位置0添加了维度1的新索引,然后让 tf.tensordot() 对这些索引求和 .

  • 3

    无论是否使用批处理,tf.multiply(及其'*'快捷方式)都会生成外部产品 . 特别是,如果两个输入张量具有[batch,n,1]和[batch,1,n]的3D形状,则此op将计算每个[n,1],[1,n]的外积 . 批次中的样品 . 如果没有批处理,那么两个输入张量是2D,这个op将计算外部产品相同 . 另一方面,虽然tf.tensordot产生2D矩阵的外部产品,但是当添加批次时它没有类似地广播 .

    Without a batch:

    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
    

    With a batch:

    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
    

    Running any of these two graphs:

    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)
    
  • 19

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

    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) 广播张量,计算外部产品 .

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

  • 4

    我会评论MasDra,但不会让我作为新的注册用户 .

    可以通过以下方式获得排列在长度顺序列表U中的多个向量的一般外积

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

相关问题