Frage

Ich habe zwei Tensor a:[batch_size, dim] b:[batch_size, dim]. Ich möchte für jedes Paar in der Charge innere Produkte machen und generieren c:[batch_size, 1], wo c[i,0]=a[i,:].T*b[i,:]. Wie?

War es hilfreich?

Lösung

Es gibt keinen Einheimischen .dot_product Methode. Ein Punktprodukt zwischen zwei Vektoren ist jedoch nur ein elementanter Multiplikum, sodass das folgende Beispiel funktioniert:

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

Die Ausgabe ist:

[[ 20.]
 [ 92.]]

Andere Tipps

Eine weitere Option, die es wert ist, überprüft zu werden, ist [tf.einsum][1] - Es ist im Wesentlichen eine vereinfachte Version von Einstein Notation.

Nachfolger mit den Beispielen von Neil und 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]] }
    ) )

Das erste Argument an einsum ist eine Gleichung, die die Achsen darstellt, die multipliziert und summiert werden. Die Grundregeln für eine Gleichung sind:

  1. Eingangstensoren werden durch eine von Kommas getrennte Reihe von Dimensionsmarken beschrieben
  2. Wiederholte Etiketten zeigen, dass die entsprechenden Abmessungen multipliziert werden
  3. Der Ausgangstensor wird durch eine andere Reihe von Dimensionsmarken beschrieben, die entsprechende Eingänge (oder Produkte) darstellen,
  4. Etiketten, die in der Ausgangszeichenfolge fehlen

In unserem Fall, ij,ij->i bedeutet, dass unsere Eingaben 2 Matrizen gleicher Form betragen werden (i,j), und unsere Ausgabe wird ein Formvektor sein (i,).

Sobald Sie den Dreh raus haben, werden Sie das finden einsum verallgemeinert eine große Anzahl anderer Operationen:

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

Leider, einsum Ernimmt einen ziemlich kräftigen Leistungsakt im Vergleich zu einer manuellen Multiplikum+Reduzierung. Wo die Leistung kritisch ist, würde ich auf jeden Fall empfehlen, bei Neils Lösung zu bleiben.

Einnahme der Diagonale von tf.tenSudot Tut auch das, was Sie wollen, wenn Sie die Achse auf z. B. einstellen

[[1], [1]]

Ich habe das Beispiel von Neil Slater angepasst:

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

was jetzt auch gibt:

[ 20.  92.]

Dies könnte jedoch für große Matrizen suboptimal sein (siehe Diskussion hier)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit datascience.stackexchange
scroll top