Come fare il prodotto interno in lotti a Tensorflow?


10

Risposte:


9

Non esiste un .dot_productmetodo nativo . Tuttavia, un prodotto punto tra due vettori viene semplicemente sommato in base all'elemento, quindi il seguente esempio funziona:

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]] }
    ) )

L'output è:

[[ 20.]
 [ 92.]]

Ha risolto il mio problema, grazie!
HenrySky,


1
Apparentemente non c'è nulla che gli sviluppatori di TF amino di più che cambiare l'API ...
Emre


@sajedzarrinpour Grazie. Spero che sia apparso qualche tempo tra il 2016 e ora? Adatterò la mia risposta in modo appropriato
Neil Slater

6

Un'altra opzione che vale la pena provare è [tf.einsum][1]: è essenzialmente una versione semplificata della notazione di Einstein .

Di seguito insieme agli esempi di 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]] }
    ) )

Il primo argomento einsumè un'equazione che rappresenta gli assi da moltiplicare e sommare. Le regole di base per un'equazione sono:

  1. I tensori di input sono descritti da una stringa di etichette di dimensioni separate da virgola
  2. Le etichette ripetute indicano che le dimensioni corrispondenti verranno moltiplicate
  3. Il tensore di output è descritto da un'altra stringa di etichette dimensionali che rappresentano input (o prodotti) corrispondenti
  4. Le etichette mancanti nella stringa di output vengono sommate

Nel nostro caso, ij,ij->isignifica che i nostri input saranno 2 matrici di forma uguale (i,j)e il nostro output sarà un vettore di forma (i,).

Una volta capito, scoprirai che einsumgeneralizza un numero enorme di altre operazioni:

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

Sfortunatamente, einsumsubisce un notevole aumento delle prestazioni rispetto a una moltiplicazione + riduzione manuale. Laddove le prestazioni sono fondamentali, consiglio vivamente di attenersi alla soluzione di Neil.


3

Prendere la diagonale di tf.tensordot fa anche quello che vuoi, se imposti l'asse su es

[[1], [1]]

Ho adattato l'esempio di 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]] }
    ) )

che ora dà anche:

[ 20.  92.]

Questo potrebbe non essere ottimale per matrici di grandi dimensioni (vedere la discussione qui )


1
La marcia del progresso :-), non sono sicuro in quale versione API sia stata aggiunta? Suggerisco di espandere la tua risposta con un breve esempio (forse basato sul mio, ma dovrebbe essere più semplice, dal momento che non avrà bisogno del reduce_sum)
Neil Slater,

Ho aggiunto l'esempio! In realtà fornisce anche prodotti dot diagonali se non usi tf.diag_part, quindi la tua risposta sarà probabilmente più veloce. Non sono sicuro di quale versione dell'API tf.tensordot sia stata introdotta, ma potrebbe essere molto tempo fa poiché è anche disponibile in numpy.
Dumkar,

Questo non richiederebbe molta più memoria rispetto alla moltiplicazione e alla somma degli elementi?
kbrose,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.