it-swarm.com.de

Was macht die Funktion tf.nn.embedding_lookup?

tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None)

Ich kann die Pflicht dieser Funktion nicht verstehen. Ist es wie eine Nachschlagetabelle? Was bedeutet, die Parameter zurückzugeben, die jeder id (in ids) entsprechen?

Wenn wir beispielsweise im skip-gram-Modell tf.nn.embedding_lookup(embeddings, train_inputs) verwenden, wird für jeden train_input die entsprechende Einbettung gefunden.

123
Poorya Pzm

Die embedding_lookup-Funktion ruft Zeilen des params-Tensors ab. Das Verhalten ähnelt dem Verwenden der Indexierung mit Arrays in numpy. Z.B.

matrix = np.random.random([1024, 64])  # 64-dimensional embeddings
ids = np.array([0, 5, 17, 33])
print matrix[ids]  # prints a matrix of shape [4, 64] 

Das Argument params kann auch eine Liste von Tensoren sein. In diesem Fall wird die Variable ids unter den Tensoren verteilt. Wenn Sie beispielsweise eine Liste von 3 Tensoren [2, 64] angeben, wird standardmäßig ids angezeigt: [0, 3], [1, 4], [2, 5]

partition_strategy steuert, wie die ids auf die Liste verteilt wird. Die Partitionierung ist für größere Probleme nützlich, wenn die Matrix zu groß ist, um sie in einem Stück zu halten.

127

Ja, diese Funktion ist schwer zu verstehen, bis Sie den Punkt verstanden haben.

In seiner einfachsten Form ähnelt es tf.gather. Es gibt die Elemente von params gemäß den durch ids angegebenen Indizes zurück.

Zum Beispiel (vorausgesetzt, Sie befinden sich in tf.InteractiveSession())

params = tf.constant([10,20,30,40])
ids = tf.constant([0,1,2,3])
print tf.nn.embedding_lookup(params,ids).eval()

würde [10 20 30 40] zurückgeben, da das erste Element (Index 0) der Parameter 10 ist, das zweite Element der Parameter (Index 1) 20 usw.

Ähnlich, 

params = tf.constant([10,20,30,40])
ids = tf.constant([1,1,3])
print tf.nn.embedding_lookup(params,ids).eval()

würde [20 20 40] zurückgeben.

Aber embedding_lookup ist mehr als das. Das params-Argument kann eine Liste von Tensoren sein und nicht ein einzelner Tensor.

params1 = tf.constant([1,2])
params2 = tf.constant([10,20])
ids = tf.constant([2,0,2,1,2,3])
result = tf.nn.embedding_lookup([params1, params2], ids)

In einem solchen Fall entsprechen die in ids angegebenen Indizes Elementen von Tensoren gemäß einer Partitionsstrategie , wobei die Standardpartitionsstrategie 'mod' ist.

In der 'mod'-Strategie entspricht der Index 0 dem ersten Element des ersten Tensors in der Liste. Index 1 entspricht dem first - Element des second tensor. Index 2 entspricht dem first - Element des dritten Tensors und so weiter. Der Index i entspricht einfach dem ersten Element des (i + 1) -ten Tensors. Für alle Indizes 0..(n-1) wird angenommen, dass Parameter eine Liste von n-Tensoren sind.

Index n kann nun nicht dem Tensor n + 1 entsprechen, da die Liste params nur n Tensoren enthält. Der Index n entspricht also dem second - Element des ersten Tensors. In ähnlicher Weise entspricht der Index n+1 dem zweiten Element des zweiten Tensors usw.

Also im Code

params1 = tf.constant([1,2])
params2 = tf.constant([10,20])
ids = tf.constant([2,0,2,1,2,3])
result = tf.nn.embedding_lookup([params1, params2], ids)

index 0 entspricht dem ersten Element des ersten Tensors: 1

index 1 entspricht dem ersten Element des zweiten Tensors: 10

index 2 entspricht dem zweiten Element des ersten Tensors: 2

index 3 entspricht dem zweiten Element des zweiten Tensors: 20

Das Ergebnis wäre also:

[ 2  1  2 10  2 20]
193
Asher Stern

Ja, der Zweck von tf.nn.embedding_lookup() - Funktion besteht darin, ein Lookup in der Einbettungsmatrix auszuführen und die Einbettungen (oder in einfachen Worten die Vektordarstellung) von zurückzugeben Wörter.

Eine einfache Einbettungsmatrix (von Shape: vocabulary_size x embedding_dimension) würde wie folgt aussehen. (d. h. jedes Wort wird durch einen Vektor von Zahlen dargestellt, daher der Name Word2vec)


Einbettungsmatrix

the 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862
like 0.36808 0.20834 -0.22319 0.046283 0.20098 0.27515 -0.77127 -0.76804
between 0.7503 0.71623 -0.27033 0.20059 -0.17008 0.68568 -0.061672 -0.054638
did 0.042523 -0.21172 0.044739 -0.19248 0.26224 0.0043991 -0.88195 0.55184
just 0.17698 0.065221 0.28548 -0.4243 0.7499 -0.14892 -0.66786 0.11788
national -1.1105 0.94945 -0.17078 0.93037 -0.2477 -0.70633 -0.8649 -0.56118
day 0.11626 0.53897 -0.39514 -0.26027 0.57706 -0.79198 -0.88374 0.30119
country -0.13531 0.15485 -0.07309 0.034013 -0.054457 -0.20541 -0.60086 -0.22407
under 0.13721 -0.295 -0.05916 -0.59235 0.02301 0.21884 -0.34254 -0.70213
such 0.61012 0.33512 -0.53499 0.36139 -0.39866 0.70627 -0.18699 -0.77246
second -0.29809 0.28069 0.087102 0.54455 0.70003 0.44778 -0.72565 0.62309 

Ich teile die obige Einbettungsmatrix und lade nur die Wörter in vocab, die unser Vokabular sind, und die entsprechenden Vektoren im emb-Array.

vocab = ['the','like','between','did','just','national','day','country','under','such','second']

emb = np.array([[0.418, 0.24968, -0.41242, 0.1217, 0.34527, -0.044457, -0.49688, -0.17862],
   [0.36808, 0.20834, -0.22319, 0.046283, 0.20098, 0.27515, -0.77127, -0.76804],
   [0.7503, 0.71623, -0.27033, 0.20059, -0.17008, 0.68568, -0.061672, -0.054638],
   [0.042523, -0.21172, 0.044739, -0.19248, 0.26224, 0.0043991, -0.88195, 0.55184],
   [0.17698, 0.065221, 0.28548, -0.4243, 0.7499, -0.14892, -0.66786, 0.11788],
   [-1.1105, 0.94945, -0.17078, 0.93037, -0.2477, -0.70633, -0.8649, -0.56118],
   [0.11626, 0.53897, -0.39514, -0.26027, 0.57706, -0.79198, -0.88374, 0.30119],
   [-0.13531, 0.15485, -0.07309, 0.034013, -0.054457, -0.20541, -0.60086, -0.22407],
   [ 0.13721, -0.295, -0.05916, -0.59235, 0.02301, 0.21884, -0.34254, -0.70213],
   [ 0.61012, 0.33512, -0.53499, 0.36139, -0.39866, 0.70627, -0.18699, -0.77246 ],
   [ -0.29809, 0.28069, 0.087102, 0.54455, 0.70003, 0.44778, -0.72565, 0.62309 ]])


emb.shape
# (11, 8)

Nachschlagen in TensorFlow

Jetzt werden wir sehen, wie wir Embedding Lookup für einen beliebigen Eingabesatz ausführen können.

In [54]: from collections import OrderedDict

# embedding as TF tensor (for now constant; could be tf.Variable() during training)
In [55]: tf_embedding = tf.constant(emb, dtype=tf.float32)

# input for which we need the embedding
In [56]: input_str = "like the country"

# build index based on our `vocabulary`
In [57]: Word_to_idx = OrderedDict({w:vocab.index(w) for w in input_str.split() if w in vocab})

# lookup in embedding matrix & return the vectors for the input words
In [58]: tf.nn.embedding_lookup(tf_embedding, list(Word_to_idx.values())).eval()
Out[58]: 
array([[ 0.36807999,  0.20834   , -0.22318999,  0.046283  ,  0.20097999,
         0.27515   , -0.77126998, -0.76804   ],
       [ 0.41800001,  0.24968   , -0.41242   ,  0.1217    ,  0.34527001,
        -0.044457  , -0.49687999, -0.17862   ],
       [-0.13530999,  0.15485001, -0.07309   ,  0.034013  , -0.054457  ,
        -0.20541   , -0.60086   , -0.22407   ]], dtype=float32)

Beobachten Sie, wie wir das embeddings aus unserer ursprünglichen Einbettungsmatrix (mit Wörtern) mithilfe der Wortindizes in unserem Vokabular erhalten.

Normalerweise wird eine solche Einbettung von der ersten Schicht (mit dem Namen Einbettungsebene) durchgeführt, die diese Einbettungen dann zur weiteren Verarbeitung an RNN/LSTM/GRU-Schichten weiterleitet.


Randnotiz: Normalerweise hat das Vokabular auch ein spezielles unk-Token. Wenn also kein Token aus unserem Eingabesatz in unserem Vokabular vorhanden ist, wird der Index, der unk entspricht, in der Einbettungsmatrix nachgeschlagen.


P.S. Beachten Sie, dass embedding_dimension ein Hyperparameter ist, den Sie für ihre Anwendung einstellen müssen, aber gängige Modelle wie Word2Vec und GloVe verwenden den 300-Dimensionsvektor zur Darstellung jedes Words.

Bonus ReadingWord2vec-Überspringmodell

32
kmario23

Hier ist ein Bild, das den Prozess des Einbettens der Suche darstellt. 

Image: Embedding lookup process

Kurz gesagt, er erhält die entsprechenden Zeilen einer Einbettungsebene, die durch eine Liste von IDs angegeben wird, und stellt diese als Tensor bereit. Dies wird durch den folgenden Prozess erreicht.

  1. Einen Platzhalter definieren lookup_ids = tf.placeholder([10])
  2. Definiere eine Einbettungsebene embeddings = tf.Variable([100,10],...)
  3. Definieren Sie die Tensorflow-Operation embed_lookup = tf.embedding_lookup(embeddings, lookup_ids)
  4. Holen Sie sich die Ergebnisse, indem Sie lookup = session.run(embed_lookup, feed_dict={lookup_ids:[95,4,14]}) ausführen.
7
thushv89

Wenn der Params-Tensor hoch dimensioniert ist, bezieht sich die IDs nur auf die obere Dimension. Für die meisten Leute ist es offensichtlich, aber ich muss den folgenden Code ausführen, um das zu verstehen:

embeddings = tf.constant([[[1,1],[2,2],[3,3],[4,4]],[[11,11],[12,12],[13,13],[14,14]],
                          [[21,21],[22,22],[23,23],[24,24]]])
ids=tf.constant([0,2,1])
embed = tf.nn.embedding_lookup(embeddings, ids, partition_strategy='div')

with tf.Session() as session:
    result = session.run(embed)
    print (result)

Nur die 'div'-Strategie zu versuchen und für einen Tensor macht es keinen Unterschied.

Hier ist die Ausgabe:

[[[ 1  1]
  [ 2  2]
  [ 3  3]
  [ 4  4]]

 [[21 21]
  [22 22]
  [23 23]
  [24 24]]

 [[11 11]
  [12 12]
  [13 13]
  [14 14]]]
4
Yan Zhao

Eine andere Sichtweise besteht darin, anzunehmen, dass Sie die Tensoren zu einem eindimensionalen Array ausflachen und dann eine Suche durchführen

(zB) Tensor0 = [1,2,3], Tensor1 = [4,5,6], Tensor2 = [7,8,9]

Der abgeflachte Tensor wird wie folgt aussehen: [1,4,7,2,5,8,3,6,9]

Wenn Sie nun nach [0,3,4,1,7] suchen, werden Sie [1,2,5,4,6]

(i, e) wenn der Suchwert beispielsweise 7 ist und wir 3 Tensoren (oder einen Tensor mit 3 Reihen) haben, dann 

7/3: (Erinnerung ist 1, Quotient ist 2) Also wird das zweite Element von Tensor1 angezeigt, welches 6 ist 

3

Da ich auch von dieser Funktion fasziniert war, gebe ich meine zwei Cent.

Wie ich es im 2D-Fall sehe, ist dies nur eine Matrixmultiplikation (es ist leicht, auf andere Dimensionen zu verallgemeinern).

Betrachten Sie ein Vokabular mit N Symbolen . Dann können Sie ein Symbol x als einen Vektor der Dimensionen Nx1 darstellen, der nur einen Hot-Code enthält.

Sie möchten jedoch eine Darstellung dieses Symbols nicht als Vektor von Nx1, sondern als eine mit Dimensionen Mx1, genannt y.

Um x in y umzuwandeln, können Sie die Matrix E mit den Dimensionen MxN verwenden und einbetten: 

y = Ex.

Dies ist im Wesentlichen das, was tf.nn.embedding_lookup (params, ids, ...) tut, mit der Nuance, dass ids nur eine Zahl sind, die die Position der 1 im ein-heiß-codierten Vektor darstelltx.

1
joaoaccarvalho

Zur Antwort von Asher Stern hinzugefügt params ist interpretiert als Partitionierung eines großen Einbettungstensors. Es kann ein einzelner Tensor sein, der den vollständigen Einbettungstensor darstellt oder eine Liste von X-Tensoren, die alle dieselbe Form haben, mit Ausnahme der ersten Dimension, Scherben eingebettete Tensoren darstellen. 

Die Funktion tf.nn.embedding_lookup wird unter Berücksichtigung der Tatsache geschrieben, dass die Einbettung (Params) groß ist. Deshalb brauchen wir partition_strategy.

0
Aerin