python matrix - Tensorflow-matmul della matrice di input con dati batch




transpose multiply (5)

1. Voglio moltiplicare un lotto di matrici con un lotto di matrici della stessa lunghezza, a coppie

M = tf.random_normal((batch_size, n, m))
N = tf.random_normal((batch_size, m, p))

# python >= 3.5
MN = M @ N
# or the old way,
MN = tf.matmul(M, N)
# MN has shape (batch_size, n, p)

2. Voglio moltiplicare una serie di matrici con un lotto di vettori della stessa lunghezza, a coppie

Ritorniamo al caso 1 aggiungendo e rimuovendo una dimensione a v .

M = tf.random_normal((batch_size, n, m))
v = tf.random_normal((batch_size, m))

Mv = (M @ v[..., None])[..., 0]
# Mv has shape (batch_size, n)

3. Voglio moltiplicare una singola matrice con un lotto di matrici

In questo caso, non possiamo semplicemente aggiungere una dimensione batch di 1 alla singola matrice, perché tf.matmul non trasmette nella dimensione batch.

3.1. La matrice singola è sul lato destro

In tal caso, possiamo trattare il batch di matrici come una singola grande matrice, usando una semplice risagoma.

M = tf.random_normal((batch_size, n, m))
N = tf.random_normal((m, p))

MN = tf.reshape(tf.reshape(M, [-1, m]) @ N, [-1, n, p])
# MN has shape (batch_size, n, p)

3.2. La matrice singola è sul lato sinistro

Questo caso è più complicato. Possiamo ricorrere al caso 3.1 trasponendo le matrici.

MT = tf.matrix_transpose(M)
NT = tf.matrix_transpose(N)
NTMT = tf.reshape(tf.reshape(NT, [-1, m]) @ MT, [-1, p, n])
MN = tf.matrix_transpose(NTMT)

Tuttavia, la trasposizione può essere un'operazione costosa e qui viene eseguita due volte su un intero lotto di matrici. Potrebbe essere meglio duplicare semplicemente M per abbinare la dimensione batch:

MN = tf.tile(M[None], [batch_size, 1, 1]) @ N

Il profilo indicherà quale opzione funziona meglio per un dato problema / combinazione hardware.

4. Voglio moltiplicare una singola matrice con un gruppo di vettori

Questo sembra simile al caso 3.2 dato che la matrice singola è a sinistra, ma in realtà è più semplice perché trasporre un vettore è essenzialmente un no-op. Finiamo con

M = tf.random_normal((n, m))
v = tf.random_normal((batch_size, m))

MT = tf.matrix_transpose(M)
Mv = v @ MT

Che mi dici di einsum ?

Tutte le precedenti moltiplicazioni avrebbero potuto essere scritte con il tf.einsum svizzero tf.einsum . Ad esempio, la prima soluzione per 3.2 potrebbe essere scritta semplicemente come

MN = tf.einsum('nm,bmp->bnp', M, N)

Tuttavia, si noti che einsum si basa in ultima analisi su tranpose e matmul per il calcolo.

Quindi, anche se einsum è un modo molto conveniente per scrivere le moltiplicazioni delle matrici, nasconde la complessità delle operazioni sottostanti - ad esempio non è semplice indovinare quante volte un'espressione di einsum trasporrà i dati, e quindi quanto costosa sarà l'operazione . Inoltre, potrebbe nascondere il fatto che potrebbero esserci diverse alternative per la stessa operazione (vedere caso 3.2) e potrebbe non necessariamente scegliere l'opzione migliore.

Per questo motivo, personalmente utilizzerei formule esplicite come quelle sopra per trasmettere meglio la loro rispettiva complessità. Anche se sai cosa stai facendo e ti piace la semplicità della sintassi einsum , allora con tutti i mezzi per farlo.

Ho alcuni dati rappresentati da input_x . È un tensore di dimensioni sconosciute (dovrebbe essere immesso in batch) e ogni elemento è di dimensione n . input_x subisce tf.nn.embedding_lookup , così che embed ora ha dimensioni [?, n, m] dove m è la dimensione di incorporamento e ? si riferisce alla dimensione del lotto sconosciuto.

Questo è descritto qui:

input_x = tf.placeholder(tf.int32, [None, n], name="input_x") 
embed = tf.nn.embedding_lookup(W, input_x)

Ora sto cercando di moltiplicare ogni campione nei miei dati di input (che ora è espanso incorporando la dimensione) da una variabile matriciale, U , e non riesco a capire come farlo.

Ho provato per la prima volta a utilizzare tf.matmul ma dà un errore a causa della mancata corrispondenza delle forme. Ho quindi provato quanto segue, espandendo la dimensione di U e applicando batch_matmul (ho anche provato la funzione da tf.nn.math_ops. , Il risultato è stato lo stesso):

U = tf.Variable( ... )    
U1 = tf.expand_dims(U,0)
h=tf.batch_matmul(embed, U1)

Questo passa la compilazione iniziale, ma poi quando vengono applicati i dati reali, ottengo il seguente errore:

In[0].dim(0) and In[1].dim(0) must be the same: [64,58,128] vs [1,128,128]

So anche perché questo sta accadendo - ho replicato la dimensione di U e ora è 1 , ma la dimensione minibatch, 64 , non si adatta.

Come posso eseguire la moltiplicazione della matrice sull'input del mio tensore-matrice correttamente (per le dimensioni del batch sconosciuto)?


Come risposto da @Stryke, ci sono due modi per ottenere questo risultato: 1. Scansione e 2. Rimodellamento

  1. tf.scan richiede funzioni lambda ed è generalmente utilizzato per operazioni ricorsive. Alcuni esempi per lo stesso sono qui: https://rdipietro.github.io/tensorflow-scan-examples/

  2. Personalmente preferisco rimodellare, dal momento che è più intuitivo. Se stai provando a matrice moltiplicare ogni matrice nel tensore 3D per la matrice che è il tensore 2D, come Cijl = Aijk * Bkl, puoi farlo con un semplice rimodellamento.

    A' = tf.reshape(Aijk,[i*j,k])
    C' = tf.matmul(A',Bkl)
    C = tf.reshape(C',[i,j,l])

Le risposte precedenti sono obsolete. Attualmente tf.matmul() supporta i tensori con rank> 2:

Gli input devono essere matrici (o tensori di rango> 2, che rappresentano lotti di matrici), con dimensioni interne corrispondenti, eventualmente dopo la trasposizione.

Anche tf.batch_matmul() stato rimosso e tf.matmul() è il modo giusto per eseguire la moltiplicazione batch. L'idea principale può essere compresa dal seguente codice:

import tensorflow as tf
batch_size, n, m, k = 10, 3, 5, 2
A = tf.Variable(tf.random_normal(shape=(batch_size, n, m)))
B = tf.Variable(tf.random_normal(shape=(batch_size, m, k)))
tf.matmul(A, B)

Ora riceverai un tensore della forma (batch_size, n, k) . Ecco cosa sta succedendo qui. Supponiamo di avere batch_size di matrici nxm e batch_size di matrici batch_size . Ora per ogni coppia si calcola nxm X mxk che fornisce una matrice nxk . Avrai batch_size di loro.

Si noti che qualcosa di simile è anche valido:

A = tf.Variable(tf.random_normal(shape=(a, b, n, m)))
B = tf.Variable(tf.random_normal(shape=(a, b, m, k)))
tf.matmul(A, B)

e ti darà una forma (a, b, n, k)


Sembra che in TensorFlow 1.11.0 i documenti per tf.matmul non tf.matmul per tf.matmul che funzioni per rank> = 2.

Invece, la migliore alternativa pulita che ho trovato è usare tf.tensordot(a, b, (-1, 0)) ( docs ).

Questa funzione ottiene il prodotto punto di qualsiasi asse della matrice a e qualsiasi asse della matrice b nella sua forma generale tf.tensordot(a, b, axis) . Fornendo axis come (-1, 0) ottiene il prodotto punto standard di due array.


Nel mio caso la versione python utilizzata (3.4) non soddisfaceva i requisiti delle dipendenze di Django 2.1 (python> = 3.5).







python tensorflow