tf.nn.embedding_lookup(params, ids, partition_strategy='mod', name=None)
Je ne peux pas comprendre le devoir de cette fonction. Est-ce comme une table de consultation? Quels moyens de retourner les paramètres correspondant à chaque id (en ids)?
Par exemple, dans le skip-gram
modèle si nous utilisons tf.nn.embedding_lookup(embeddings, train_inputs)
, alors pour chacun, train_input
il trouve l'incorporation correspondante?
Réponses:
embedding_lookup
La fonction récupère les lignes duparams
tenseur. Le comportement est similaire à l'utilisation de l'indexation avec des tableaux dans numpy. Par exempleparams
L'argument peut être aussi une liste de tenseurs, auquel cas leids
sera réparti entre les tenseurs. Par exemple, étant donné une liste de 3 tenseurs[2, 64]
, le comportement par défaut est qu'ils représententids
:[0, 3]
,[1, 4]
,[2, 5]
.partition_strategy
contrôle la manière dont lesids
sont répartis dans la liste. Le partitionnement est utile pour les problèmes à plus grande échelle lorsque la matrice peut être trop grande pour être conservée en un seul morceau.la source
select_rows
?embedding_lookup
fournit simplement un moyen pratique (et parallèle) de récupérer les incorporations correspondant à id inids
. Leparams
tenseur est généralement une variable tf apprise dans le cadre du processus d'apprentissage - une variable tf dont les composants sont utilisés, directement ou indirectement, dans une fonction de perte (telle quetf.l2_loss
) qui est optimisée par un optimiseur (tel quetf.train.AdamOptimizer
).Oui, cette fonction est difficile à comprendre, jusqu'à ce que vous ayez compris.
Dans sa forme la plus simple, il est similaire à
tf.gather
. Il retourne les éléments deparams
selon les index spécifiés parids
.Par exemple (en supposant que vous êtes à l'intérieur
tf.InteractiveSession()
)retournerait
[10 20 30 40]
, car le premier élément (index 0) de params est10
, le deuxième élément de params (index 1) est20
, etc.De même,
reviendrait
[20 20 40]
.Mais
embedding_lookup
c'est plus que ça. L'params
argument peut être une liste de tenseurs, plutôt qu'un seul tenseur.Dans un tel cas, les index, spécifiés dans
ids
, correspondent à des éléments de tenseurs selon une stratégie de partition , où la stratégie de partition par défaut est «mod».Dans la stratégie 'mod', l'indice 0 correspond au premier élément du premier tenseur de la liste. L'indice 1 correspond au premier élément du deuxième tenseur. L'indice 2 correspond au premier élément du troisième tenseur, et ainsi de suite. L'index
i
correspond simplement au premier élément du (i + 1) ème tenseur, pour tous les indices0..(n-1)
, en supposant que params est une liste den
tenseurs.Or, l'index
n
ne peut pas correspondre au tenseur n + 1, car la listeparams
ne contient que desn
tenseurs. L'indexn
correspond donc au deuxième élément du premier tenseur. De même, l'indicen+1
correspond au deuxième élément du deuxième tenseur, etc.Donc, dans le code
l'indice 0 correspond au premier élément du premier tenseur: 1
l'indice 1 correspond au premier élément du deuxième tenseur: 10
l'indice 2 correspond au deuxième élément du premier tenseur: 2
l'indice 3 correspond au deuxième élément du deuxième tenseur: 20
Ainsi, le résultat serait:
la source
partition_strategy='div'
, et obtiendriez[10, 1, 10, 2, 10, 20]
, c'est à direid=1
est le deuxième élément du premier paramètre. En gros:partition_strategy=mod
(par défaut)id%len(params)
: index du paramètre dans paramsid//len(params)
: index de l'élément dans le paramètre ci-dessus danspartition_strategy=*div*
l'autre sensOui, le but de la
tf.nn.embedding_lookup()
fonction est d'effectuer une recherche dans la matrice d'intégration et de renvoyer les plongements (ou en termes simples la représentation vectorielle) des mots.Une simple matrice d'incorporation (de forme
vocabulary_size x embedding_dimension
:) ressemblerait à celle ci-dessous. (c'est-à-dire que chaque mot sera représenté par un vecteur de nombres; d'où le nom word2vec )Matrice d'intégration
J'ai divisé la matrice d'incorporation ci-dessus et chargé uniquement les mots dans
vocab
lesquels seront notre vocabulaire et les vecteurs correspondants dans leemb
tableau.Intégration de la recherche dans TensorFlow
Nous allons maintenant voir comment pouvons-nous effectuer une recherche d'incorporation pour une phrase d'entrée arbitraire.
Observez comment nous avons obtenu les plongements à partir de notre matrice d'intégration originale (avec des mots) en utilisant les indices de mots de notre vocabulaire.
Habituellement, une telle recherche d'intégration est effectuée par la première couche (appelée couche d'intégration ) qui transmet ensuite ces plongements aux couches RNN / LSTM / GRU pour un traitement ultérieur.
Note latérale : Habituellement, le vocabulaire aura également un
unk
jeton spécial . Ainsi, si un jeton de notre phrase d'entrée n'est pas présent dans notre vocabulaire, alors l'index correspondant àunk
sera recherché dans la matrice d'intégration.PS Notez qu'il
embedding_dimension
s'agit d'un hyperparamètre qu'il faut régler pour leur application mais les modèles populaires comme Word2Vec et GloVe utilisent300
un vecteur de dimension pour représenter chaque mot.Bonus de lecture word2vec modèle skip-gramme
la source
Voici une image illustrant le processus d'intégration de la recherche.
De manière concise, il obtient les lignes correspondantes d'une couche d'incorporation, spécifiées par une liste d'ID et les fournit sous forme de tenseur. Il est réalisé grâce au processus suivant.
lookup_ids = tf.placeholder([10])
embeddings = tf.Variable([100,10],...)
embed_lookup = tf.embedding_lookup(embeddings, lookup_ids)
lookup = session.run(embed_lookup, feed_dict={lookup_ids:[95,4,14]})
la source
Lorsque le tenseur des paramètres est en dimensions élevées, les identifiants se réfèrent uniquement à la dimension supérieure. C'est peut-être évident pour la plupart des gens, mais je dois exécuter le code suivant pour comprendre cela:
Essayer simplement la stratégie «div» et pour un tenseur, cela ne fait aucune différence.
Voici la sortie:
la source
Une autre façon de voir les choses est de supposer que vous aplatissez les tenseurs en un tableau à une dimension, puis que vous effectuez une recherche
(par exemple) Tensor0 = [1,2,3], Tensor1 = [4,5,6], Tensor2 = [7,8,9]
Le tenseur aplati sera le suivant [1,4,7,2,5,8,3,6,9]
Maintenant, lorsque vous effectuez une recherche sur [0,3,4,1,7], vous obtiendrez [1,2,5,4,6]
(i, e) si la valeur de recherche est 7 par exemple, et que nous avons 3 tenseurs (ou un tenseur à 3 lignes) alors,
7/3: (Le rappel est 1, le quotient est 2) Donc le 2ème élément de Tensor1 sera affiché, soit 6
la source
Comme j'ai également été intrigué par cette fonction, je vais donner mes deux cents.
La façon dont je le vois dans le cas 2D est juste comme une multiplication matricielle (il est facile de généraliser à d'autres dimensions).
Considérons un vocabulaire avec N symboles. Ensuite, vous pouvez représenter un symbole x comme un vecteur de dimensions Nx1, codé à chaud.
Mais vous voulez une représentation de ce symbole non pas comme un vecteur de Nx1, mais comme un de dimensions Mx1, appelé y .
Ainsi, pour transformer x en y , vous pouvez utiliser et incorporer la matrice E , de dimensions MxN:
y = E x .
C'est essentiellement ce que fait tf.nn.embedding_lookup (params, ids, ...), avec la nuance que les ids ne sont qu'un nombre qui représente la position du 1 dans le vecteur x codé à chaud .
la source
L'ajout à la réponse d'Asher Stern
params
est interprété comme un partitionnement d'un grand tenseur d'enrobage. Il peut s'agir d'un seul tenseur représentant le tenseur d'enrobage complet, ou d'une liste de tenseurs X tous de même forme à l'exception de la première dimension, représentant les tenseurs d'inclusion fragmentés.La fonction
tf.nn.embedding_lookup
est écrite en tenant compte du fait que l'incorporation (params) sera grande. Par conséquent, nous avons besoinpartition_strategy
.la source