Como fazer produto interno em lote no Tensorflow?


10

Respostas:


9

Não há .dot_productmé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.]]

Resolveu o meu problema, thx!
HenrySky


1
Aparentemente, não há nada que os desenvolvedores de TF adorem mais do que mudar a API ...
Emre


@sajedzarrinpour Thanks. Espero que tenha aparecido algum tempo entre 2016 e agora? Ajustarei minha resposta adequadamente
Neil Slater

6

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:

  1. Os tensores de entrada são descritos por uma sequência de rótulos de dimensão separados por vírgula
  2. Etiquetas repetidas indicam que as dimensões correspondentes serão multiplicadas
  3. O tensor de saída é descrito por outra sequência de rótulos de dimensão que representam entradas (ou produtos) correspondentes
  4. Os rótulos ausentes da sequência de saída são somados

No nosso caso, ij,ij->isignifica 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 einsumgeneraliza 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, é einsumpreciso 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.


3

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 )


1
A marcha do progresso :-), não tenho certeza em qual versão da API foi adicionada? Eu sugiro expandir a sua resposta com um exemplo curto (talvez com base na minha, mas deve ser mais simples, uma vez que não será necessário o reduce_sum)
Neil Slater

Eu adicionei o exemplo! Na verdade, ele também fornece produtos de pontos fora da diagonal se você não usar tf.diag_part, portanto sua resposta provavelmente será mais rápida. Não tenho muita certeza de qual versão da API tf.tensordot foi introduzida, mas pode ser há muito tempo, já que também está disponível em numpy.
dumkar

Isso não exigiria muito mais memória do que a multiplicação e soma por elementos?
Kbrose
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.