Tf.nn.embedding_lookup işlevi ne işe yarar?


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

Bu işlevin görevini anlayamıyorum. Bir arama tablosu gibi mi? Her bir kimliğe (kimlikleriyle) karşılık gelen parametreleri döndürmek için hangi yöntem kullanılır?

Örneğin, skip-grameğer kullanırsak tf.nn.embedding_lookup(embeddings, train_inputs), modelde , her biri train_inputiçin karşılık gelen gömme bulur?


"Bu bir arama tablosu gibi mi?" tldr - Evet. Her x (ids) için bana y (params) yardımcısını verin.
David Refaeli

Yanıtlar:


147

embedding_lookupfonksiyonu paramstensörün satırlarını alır . Davranış, dizilerle dizin oluşturmayı numpy olarak kullanmaya benzer. Örneğin

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] 

paramsargüman aynı zamanda tensörlerin bir listesi olabilir, bu durumda tensörler arasında idsdağıtılacaktır. Örneğin, 3 tansörleri listesi verilen [2, 64], varsayılan davranış temsil ettikleri olmasıdır ids: [0, 3], [1, 4], [2, 5].

partition_strategyidslisteye nasıl dağıtıldığını kontrol eder . Bölümleme, matris tek parça halinde tutulamayacak kadar büyük olduğunda daha büyük ölçekli sorunlar için kullanışlıdır.


21
Neden böyle diyorlar select_rows?
Lenar Hoyt

12
@LenarHoyt çünkü bu arama fikri Word Embeddings'den geliyor. ve "satırlar", kelimelerin bir vektör uzayı içindeki temsilleridir (düğünlerdir) ve bunların içinde yararlıdır. Genellikle gerçek ağdan daha fazla.
Lyndon White

2
Tensorflow gömme yapısını nasıl öğrenir? Bu işlev bu süreci de yönetiyor mu?
vgoklani

19
@vgoklani, hayır, embedding_lookupsadece kimliğe karşılık gelen düğünleri almak için uygun (ve paralel) bir yol sağlar ids. paramsFonksiyon kaybına (örneğin doğrudan ya da dolaylı olarak, örneğin bileşenleri kullanıldığı bir TF değişkeni - tensör genellikle eğitim işleminin bir parçası olarak öğrenilir bir TF değişkendir tf.l2_lossbir optimizasyon (örneğin optimize edilir) tf.train.AdamOptimizer).
Shobhit

5
@ Rafał Józefowicz Neden "varsayılan davranış kimlikleri temsil etmeleridir: [0, 3], [1, 4], [2, 5]."? Açıklayabilir misiniz?
Aerin

219

Evet, bu işlevi anlayana kadar anlaşılması zor.

En basit haliyle, buna benzer tf.gather. paramsÖğesinin belirttiği dizinlere göre döndürür ids.

Örneğin (içinde olduğunuzu varsayarak tf.InteractiveSession())

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

döneceğini [10 20 30 40], birinci elemanın (indeks 0) için params olup 10, params ikinci elemanın (dizin 1) olup 20, vs.

Benzer şekilde,

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

dönecekti [20 20 40].

Ama embedding_lookupbundan daha fazlası. paramsArgüman bir olabilir liste tensörlerinin yerine tek tensör.

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)

Böyle bir durumda, içinde belirtilen dizinler, varsayılan bölümleme stratejisinin 'mod' olduğu idsbir bölümleme stratejisine göre tansör elemanlarına karşılık gelir .

'Mod' stratejisinde, indeks 0 listedeki ilk tensörün ilk elemanına karşılık gelir. Dizin 1 , ikinci tensörün birinci elemanına karşılık gelir . Dizin 2 üçüncü tensörün birinci elemanına karşılık gelir ve bu böyle devam eder. Basitçe indeks , (i + 1) th tensörünün ilk elemanına karşılık gelir, tüm indeksler için , parametrelerin tensörlerin bir listesi olduğunu varsayarsak .i0..(n-1)n

Şimdi, dizin sadece tensörleri içerdiğinden dizin nn + 1 tensörüne karşılık gelemez . Böylece indeks birinci tensörün ikinci elemanına karşılık gelir . Benzer şekilde, indeks ikinci tensörün vb. İkinci elemanına karşılık gelir.paramsnnn+1

Yani, kodda

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)

indeks 0, birinci tensörün ilk elemanına karşılık gelir: 1

indeks 1 ikinci tensörün ilk elemanına karşılık gelir: 10

indeks 2 ilk tensörün ikinci elemanına karşılık gelir: 2

indeks 3, ikinci tensörün ikinci elemanına karşılık gelir: 20

Böylece sonuç şöyle olur:

[ 2  1  2 10  2 20]

8
bir not: kullanabilirsiniz partition_strategy='div've alırsınız [10, 1, 10, 2, 10, 20], yani id=1ilk parametrenin ikinci elemanıdır. Temelde: partition_strategy=mod(varsayılan) id%len(params): params param endeksi id//len(params)yukarıda param içindeki elemanın endeksi: partition_strategy=*div*tersi
Mario Alemi

3
@ asher-stern "mod" stratejisinin neden varsayılan olduğunu açıklayabilir misiniz? "div" stratejisi, standart tensör dilimlemeye (verilen indekslere göre seçme satırları) daha benzerdir. "Div" durumunda bazı performans sorunları var mı?
svetlov.vsevolod

46

Evet, amacı tf.nn.embedding_lookup()fonksiyonuna bir gerçekleştirmektir arama içinde gömme matrisin ve kelimelerin düğünlerini (veya basit bir ifadeyle vektör temsilini) döndürmektir.

Basit bir gömme matrisi (şekil:) vocabulary_size x embedding_dimensionaşağıdaki gibi görünecektir. (yani her kelime bir sayı vektörü ile temsil edilecektir ; dolayısıyla word2vec adı )


Gömme Matrisi

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 

I matris gömme üzerinde ayrılır ve yalnızca yüklü kelime olarak vocabbizim kelime ve karşılık gelen vektörleri olacak embdizisi.

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)

Aramayı TensorFlow'a gömme

Şimdi bazı keyfi giriş cümleleri için nasıl gömme araması yapabileceğimizi göreceğiz .

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)

Elimizdeki nasıl gözlemleyin katıştırmalarını (sözlerle) orijinal gömme matrisinden kullanarak kelimelerin endekslerini bizim kelime içinde.

Genellikle, böyle bir gömme araması, daha sonra daha fazla işlem için bu düğünleri RNN / LSTM / GRU katmanlarına geçiren ilk katman ( Gömme katmanı olarak adlandırılır ) tarafından gerçekleştirilir .


Yan Not : Genellikle kelime haznesi de özel bir unkjetona sahip olacaktır . Dolayısıyla, kelime girişimizde giriş cümlemizden bir belirteç yoksa, karşılık gelen dizin unkgömme matrisinde aranacaktır.


PS Not embedding_dimension, bir uygulama için ayarlanması gereken bir hiperparametre ama Word2Vec ve GloVe gibi popüler modeller kullanıyor300 her kelimeyi temsil etmek boyut vektörü .

Bonus Okuma word2vec skip-gram modeli


17

İşte arama gömme işlemini gösteren bir resim.

Resim: Arama işlemini gömme

Kısacası, bir kimlik listesi tarafından belirtilen bir gömme katmanının karşılık gelen satırlarını alır ve bunu bir tensör olarak sağlar. Aşağıdaki işlemle elde edilir.

  1. Bir yer tutucu tanımlayın lookup_ids = tf.placeholder([10])
  2. Gömme katmanı tanımlama embeddings = tf.Variable([100,10],...)
  3. Tensorflow işlemini tanımlayın embed_lookup = tf.embedding_lookup(embeddings, lookup_ids)
  4. Sonuçları çalıştırarak alın lookup = session.run(embed_lookup, feed_dict={lookup_ids:[95,4,14]})

6

Params tensörü yüksek boyutlarda olduğunda idler sadece üst boyuta işaret eder. Belki çoğu insan için açıktır ama bunu anlamak için aşağıdaki kodu çalıştırmak zorunda:

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)

Sadece 'div' stratejisini denemek ve bir tensör için hiç fark etmez.

İşte çıktı:

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

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

 [[11 11]
  [12 12]
  [13 13]
  [14 14]]]

3

Buna bakmanın bir başka yolu, tensörleri bir boyutlu diziye düzleştirdiğinizi ve ardından bir arama gerçekleştirdiğinizi varsayalım.

(örn.) Tensör0 = [1,2,3], Tensör1 = [4,5,6], Tensör2 = [7,8,9]

Düzleştirilmiş tensör aşağıdaki gibi olacaktır [1,4,7,2,5,8,3,6,9]

Şimdi [0,3,4,1,7] araması yaptığınızda sarılacak [1,2,5,4,6]

(i, e) örneğin arama değeri 7 ise ve 3 tensörümüz (veya 3 sıralı bir tensörümüz) varsa,

7/3: (Hatırlatma 1, Bölüm 2) Tensor1'in 2. elemanı gösterilecek, bu da 6


2

Ben de bu işlev beni ilgilendirdiğinden, iki sentimi vereceğim.

2D durumda gördüğüm gibi, bir matris çarpımı gibidir (diğer boyutlara genellemek kolaydır).

N sembollü bir kelime haznesi düşünün. Daha sonra, x sembolünü bir sıcak kodlu Nx1 boyutlarının bir vektörü olarak temsil edebilirsiniz .

Ancak bu sembolün bir Nx1 vektörü olarak değil, Mx1 boyutlarında y olarak adlandırılan bir gösterim olarak istiyorsunuz .

Bu yüzden, dönüştürme x içine y , kullanmak ve matris gömme olabilir E boyutları MxN ile:

Y = e x .

Bu tf.nn.embedding_lookup (parametreler, kimlikleri, ...) o nüans ile, ne yaptığını temelde kimlikleri tek sıcak kodlanmış vektör içinde 1 konumunu temsil sadece bir dizi x .


0

Asher Stern'in cevabına eklemek, büyük bir gömme tensörünün paramsbir bölümü olarak yorumlanır . Tüm gömme tensörünü temsil eden tek bir tensör veya parçalanmış gömme tensörlerini temsil eden birinci boyut haricinde aynı şekle sahip X tensörlerin bir listesi olabilir.

İşlev tf.nn.embedding_lookup, gömme (parametreler) büyük olacağı düşünülerek yazılmıştır. Bu yüzden ihtiyacımız var partition_strategy.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.