Respostas:
Não há .dot_product
método nativo . No entanto, um produto escalar entre dois vetores é somado por multiplicação por elementos, portanto, o exemplo a seguir funciona:
import tensorflow as tf
# Arbitrarity, we'll use placeholders and allow batch size to vary,
# but fix vector dimensions.
# You can change this as you see fit
a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))
c = tf.reduce_sum( tf.multiply( a, b ), 1, keep_dims=True )
with tf.Session() as session:
print( c.eval(
feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
) )
A saída é:
[[ 20.]
[ 92.]]
Outra opção que vale a pena conferir é [tf.einsum][1]
- é essencialmente uma versão simplificada do Einstein Notation .
Seguindo os exemplos de Neil e dumkar:
import tensorflow as tf
a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))
c = tf.einsum('ij,ij->i', a, b)
with tf.Session() as session:
print( c.eval(
feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
) )
O primeiro argumento para einsum
é uma equação que representa os eixos a serem multiplicados e somados. As regras básicas para uma equação são:
No nosso caso, ij,ij->i
significa que nossas entradas serão 2 matrizes de forma igual (i,j)
e nossa saída será um vetor de forma (i,)
.
Depois de pegar o jeito, você verá que einsum
generaliza um grande número de outras operações:
X = [[1, 2]]
Y = [[3, 4], [5, 6]]
einsum('ab->ba', X) == [[1],[2]] # transpose
einsum('ab->a', X) == [3] # sum over last dimension
einsum('ab->', X) == 3 # sum over both dimensions
einsum('ab,bc->ac', X, Y) == [[13,16]] # matrix multiply
einsum('ab,bc->abc', X, Y) == [[[3,4],[10,12]]] # multiply and broadcast
Infelizmente, é einsum
preciso um desempenho considerável quando comparado a uma multiplicação manual + redução. Onde o desempenho é crítico, eu recomendaria definitivamente continuar com a solução de Neil.
Tomar a diagonal de tf.tensordot também faz o que você deseja, se você definir o eixo como, por exemplo,
[[1], [1]]
Eu adaptei o exemplo de Neil Slater:
import tensorflow as tf
# Arbitrarity, we'll use placeholders and allow batch size to vary,
# but fix vector dimensions.
# You can change this as you see fit
a = tf.placeholder(tf.float32, shape=(None, 3))
b = tf.placeholder(tf.float32, shape=(None, 3))
c = tf.diag_part(tf.tensordot( a, b, axes=[[1],[1]]))
with tf.Session() as session:
print( c.eval(
feed_dict={ a: [[1,2,3],[4,5,6]], b: [[2,3,4],[5,6,7]] }
) )
que agora também fornece:
[ 20. 92.]
Isso pode ser abaixo do ideal para matrizes grandes (veja a discussão aqui )
reduce_sum
)