在TensorFlow中计算两个向量的点积

30

我想知道在tensorflow中是否有一种简单的方法来计算两个向量(即1-d张量)的点积并返回一个标量值。

假设有两个向量X=(x1,...,xn)和Y=(y1,...,yn),它们的点积是 dot(X,Y) = x1 * y1 + ... + xn * yn

我知道可以通过将向量X和Y广播到一个2-d张量,然后使用tf.matmul来实现这一点。但是,结果是一个矩阵,而我需要的是一个标量。

是否有类似于tf.matmul的特定于向量的运算符?

10个回答

33

计算两个张量的点积(向量是1D张量)最简单的方法之一是使用tf.tensordot函数。

a = tf.placeholder(tf.float32, shape=(5))
b = tf.placeholder(tf.float32, shape=(5))

dot_a_b = tf.tensordot(a, b, 1)

with tf.Session() as sess:
    print(dot_a_b.eval(feed_dict={a: [1, 2, 3, 4, 5], b: [6, 7, 8, 9, 10]}))
# results: 130.0

27
除了tf.reduce_sum(tf.multiply(x, y)),你还可以使用tf.matmul(x, tf.reshape(y, [-1, 1]))

请注意,如果您有一个维度为(1234,)的向量,则以下是唯一正确的答案。 - ihadanny

20

您可以使用tf.matmul和tf.transpose。

tf.matmul(x,tf.transpose(y))
或者
tf.matmul(tf.transpose(x),y)

根据x和y的尺寸而定


12
matmul 可以帮你进行转置:例如,tf.matmul(a, b, transpose_a=True, transpose_b=False),当然你也可以转置 b。 - Charlie Parker

4
import tensorflow as tf

x = tf.Variable([1, -2, 3], tf.float32, name='x')
y = tf.Variable([-1, 2, -3], tf.float32, name='y')

dot_product = tf.reduce_sum(tf.multiply(x, y))

sess = tf.InteractiveSession()
init_op = tf.global_variables_initializer()
sess.run(init_op)

dot_product.eval()

Out[46]: -14

在这里,x和y都是向量。我们可以进行逐元素乘积,然后使用tf.reduce_sum对结果向量的元素求和。这个解决方案易于阅读,不需要重塑。
有趣的是,在docs中似乎没有内置的点积运算符。
请注意,您可以轻松检查中间步骤:
In [48]: tf.multiply(x, y).eval()
Out[48]: array([-1, -4, -9], dtype=int32)

3
在更新版本中(我认为是从0.12版本开始),您应该能够执行以下操作:
tf.einsum('i,i->', x, y)

在此之前,将减少到标量似乎是不允许/不可能的。(参见此处


显然,einsum很慢。 - joel
这取决于具体的操作以及减少优化的程度。请参见opt-einsum - phipsgabler

2
您可以使用tf.mul(x,y),然后使用tf.reduce_sum()。

(当然应该是tf.multiply(x,y)) - Mathy

2

只需使用 * 和 reduce_sum

ab = tf.reduce_sum(a*b)

以一个简单的例子来说明:

import tensorflow as tf
a = tf.constant([1,2,3])
b = tf.constant([2,3,4])

print(a.get_shape())
print(b.get_shape())

c = a*b
ab = tf.reduce_sum(c)

with tf.Session() as sess:
    print(c.eval())
    print(ab.eval())

# output
# (3,)
# (3,)
# [2 6 12]
# 20

关于使用'*'的问题:https://dev59.com/nlsW5IYBdhLWcg3wVWDj#35095052 - jensph

1
假设您有两个列向量。
u = tf.constant([[2.], [3.]])
v = tf.constant([[5.], [7.]])

如果您想要一个1x1的矩阵,可以使用:

tf.einsum('ij,ik->jk',x,y)

如果您对标量感兴趣,可以使用以下代码:

tf.einsum('ij,ik->',x,y)

1
也许使用新文档,您可以将转置选项设置为点积的第一个参数或第二个参数的 true 值:
tf.matmul(a, b, transpose_a=False, transpose_b=False, adjoint_a=False, adjoint_b=False, a_is_sparse=False, b_is_sparse=False, name=None)

领先:

tf.matmul(a, b, transpose_a=True, transpose_b=False)
tf.matmul(a, b, transpose_a=False, transpose_b=True)

0

如果您想要两个向量的点积,请使用tf.reduce_sum(tf.multiply(x,y))。

需要明确的是,即使您在之后将矩阵的所有元素相加,使用tf.matmul(x,tf.transpose(y))也无法获得点积。

我之所以提到这一点,是因为在上面的答案中经常出现这种情况,而它与所提问的问题无关。我只是想发表评论,但没有足够的声望来这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接