TensorFlow'da önceden eğitilmiş bir kelime yerleştirme (word2vec veya Glove) kullanma


95

Yakın zamanda evrişimli metin sınıflandırması için ilginç bir uygulamayı gözden geçirdim . Ancak incelediğim tüm TensorFlow kodu, aşağıdakiler gibi rastgele (önceden eğitilmemiş) gömme vektörleri kullanıyor:

with tf.device('/cpu:0'), tf.name_scope("embedding"):
    W = tf.Variable(
        tf.random_uniform([vocab_size, embedding_size], -1.0, 1.0),
        name="W")
    self.embedded_chars = tf.nn.embedding_lookup(W, self.input_x)
    self.embedded_chars_expanded = tf.expand_dims(self.embedded_chars, -1)

Word2vec veya GloVe önceden eğitilmiş bir kelime yerleştirmenin rastgele yerine nasıl kullanılacağını bilen var mı?

Yanıtlar:


130

TensorFlow'da önceden eğitilmiş bir yerleştirmeyi kullanmanın birkaç yolu vardır. Diyelim ki, satırlar ve sütunlar embeddingile adlandırılan bir NumPy dizisinde gömme var ve bir çağrıda kullanılabilecek bir tensör oluşturmak istiyorsunuz .vocab_sizeembedding_dimWtf.nn.embedding_lookup()

  1. Basitçe değerini alan Wbir yaratın :tf.constant()embedding

    W = tf.constant(embedding, name="W")
    

    Bu en kolay yaklaşımdır, ancak bellek açısından verimli değildir çünkü a'nın değeri tf.constant()bellekte birden çok kez depolanır. Yana embeddingçok büyük olabilir, sadece oyuncak örnekler için bu yaklaşımı kullanmalıdır.

  2. WBir olarak oluşturun tf.Variableve onu NumPy dizisinden a tf.placeholder():

    W = tf.Variable(tf.constant(0.0, shape=[vocab_size, embedding_dim]),
                    trainable=False, name="W")
    
    embedding_placeholder = tf.placeholder(tf.float32, [vocab_size, embedding_dim])
    embedding_init = W.assign(embedding_placeholder)
    
    # ...
    sess = tf.Session()
    
    sess.run(embedding_init, feed_dict={embedding_placeholder: embedding})
    

    Bu embedding, grafiğin bir kopyasını depolamaktan kaçınır , ancak matrisin iki kopyasını aynı anda bellekte tutmak için yeterli bellek gerektirir (biri NumPy dizisi için ve biri için tf.Variable). Eğitim sırasında gömme matrisini sabit tutmak istediğinizi varsaydığımı unutmayın, bu yüzden Wile oluşturulur trainable=False.

  3. Gömme başka bir TensorFlow modelinin parçası olarak eğitildiyse tf.train.Saver, değeri diğer modelin denetim noktası dosyasından yüklemek için a kullanabilirsiniz . Bu, gömme matrisinin Python'u tamamen atlayabileceği anlamına gelir. W2. seçenekteki gibi oluşturun , ardından aşağıdakileri yapın:

    W = tf.Variable(...)
    
    embedding_saver = tf.train.Saver({"name_of_variable_in_other_model": W})
    
    # ...
    sess = tf.Session()
    embedding_saver.restore(sess, "checkpoint_filename.ckpt")
    

W'yi şu şekilde oluşturuyorum: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = '') satır olarak oluşturan: ['in' '0.070312 ...... '-0.0625']. Burada sorunlar var! 'in'i çıkardıktan ve sayıları dizeden float32'ye dönüştürdükten sonra bunu W olarak kabul etmeli miyim? eğer durum buysa, o zaman kendi vektörüne 'in' nasıl bağlanır? YA DA rakamları float32'ye dönüştürmem ve ardından 'in'i olduğu gibi bırakmam gerekiyor; tensorflow'un gerekli tüm işlemleri yapmasını mı bekliyorsunuz? Teşekkürler!
user3147590

4
Ah, burada birkaç seçeneğiniz var. Sen olabilir TensorFlow kullanmak tf.decode_csv()bir tensör içine metin dosyasını dönüştürmek için op ama bu pahalı olabilir (özellikle, bu bir oluşturmanızı gerektirir TensorSütun başına, sonra da hep birlikte sayısal olanları bağlamak). Belki daha kolay bir alternatif , girdiyi NumPy dizisi olarak kullanmak pandas.read_csv()ve pandas.DataFrame.as_matrix()almak olabilir.
mrry

3
NumPy dizisi, return çağrısından sonra çöp toplanmalıdır sess.run(embedding_init, ...)(programınızda ona bir referans tutmadığınız varsayılarak). Programınızın yapısına bağlı olarak , diziyi daha önce serbest bırakmak isteyebilirsiniz del embedding( embeddingNumPy dizisi nerede ).
mrry,

1
@mrry: 1. seçenek hakkında ve daha spesifik olarak "bir tf.constant () değeri bellekte birçok kez saklandığı için bellek açısından verimli değildir" hakkında daha fazla konuşabilir misiniz? GPU veya CPU için bellek verimsiz mi? Daha genel olarak, seçenek 2'nin tf.Variable () + besleme yer tutucusunda bu sorun yokken tf.constant () neden bellekte birden çok kopyaya sahip olmak zorunda?
Gabriel Parent

1
"Bir tf.constant () değerinin neden bellekte birden çok kez saklandığını" da merak ediyorsanız şu yanıta bir göz atın: stackoverflow.com/a/42450418/5841473
alyaxey

33

Bu yöntemi yerleştirmeyi yüklemek ve paylaşmak için kullanıyorum.

W = tf.get_variable(name="W", shape=embedding.shape, initializer=tf.constant_initializer(embedding), trainable=False)

Gömme, numpy matrisinde sütunlar mı yoksa satırlar mı olmalıdır?
Greyshack

6

@Mrry'nin cevabı doğru değil çünkü ağın çalıştırıldığı her bir ağda yapılan düğün ağırlıklarının üzerine yazılmasına neden oluyor, bu nedenle ağınızı eğitmek için bir mini parti yaklaşımı izliyorsanız, düğünlerin ağırlıklarının üzerine yazıyorsunuz. Öyleyse, benim görüşüme göre, önceden eğitilmiş düğünlere giden doğru yol:

embeddings = tf.get_variable("embeddings", shape=[dim1, dim2], initializer=tf.constant_initializer(np.array(embeddings_matrix))

LiuJia'nın cevabının tam bir kopyası.
TimZaman

4
@TimZaman .. Aslında, o eğitilebilir = Yanlış argümanını kaçırıyor ve bu nedenle işlemdeki gömme işlemlerine ince ayar yapacaktır.
Shatu

4
Ayrıca Eugenio'nun mantığının yanlış olduğunu düşünüyorum. Her mini grupla "embedding_init" işlemini çalıştırmanız gerekmez ve her şey yoluna girecektir. Yani, gömme başlatma işlemini eğitimin başında yalnızca bir kez çalıştırın.
Shatu

@Shatu Gömme başlatmanın yalnızca eğitimin başında çalıştırılmasını nasıl sağlayabilirim?

1
@ dust0x .. Eğer düğünlerin boyutu yeterince küçükse, bunları başlangıç ​​değeri olarak belirtebilirsiniz. Oldukça büyüklerse, tüm değişkenler için başlatıcıyı çalıştırdığınızda bunları feed_dict içinde geçirebilirsiniz. Yeterince açık değilse bana haber verin, her iki yaklaşım için de bazı örnek kodlar göndermeye çalışacağım.
Shatu

5

2.0 Uyumlu Cevap : Google tarafından geliştirilen ve Açık Kaynaklı birçok Ön Eğitimli Gömme vardır.

Onlardan bazıları Universal Sentence Encoder (USE), ELMO, BERT vs .. ve bunları kodunuzda yeniden kullanmak çok kolaydır.

Yeniden Kod Pre-Trained Embedding, Universal Sentence Encoderaşağıda gösterilmiştir:

  !pip install "tensorflow_hub>=0.6.0"
  !pip install "tensorflow>=2.0.0"

  import tensorflow as tf
  import tensorflow_hub as hub

  module_url = "https://tfhub.dev/google/universal-sentence-encoder/4"
  embed = hub.KerasLayer(module_url)
  embeddings = embed(["A long sentence.", "single-word",
                      "http://example.com"])
  print(embeddings.shape)  #(3,128)

Google tarafından geliştirilmiş ve açık kaynaklı Ön Eğitimli Gömme hakkında daha fazla bilgi için TF Hub Bağlantısına bakın .


5

Tensorflow sürüm 2 ile Gömme katmanını kullanırsanız oldukça kolaydır

X=tf.keras.layers.Embedding(input_dim=vocab_size,
                            output_dim=300,
                            input_length=Length_of_input_sequences,
                            embeddings_initializer=matrix_of_pretrained_weights
                            )(ur_inp)


3

Ben de gömme sorunuyla karşı karşıyaydım, bu yüzden veri kümesiyle ayrıntılı eğitim yazdım. Burada denediğimi eklemek istiyorum Bu yöntemi de deneyebilirsiniz,

import tensorflow as tf

tf.reset_default_graph()

input_x=tf.placeholder(tf.int32,shape=[None,None])

#you have to edit shape according to your embedding size


Word_embedding = tf.get_variable(name="W", shape=[400000,100], initializer=tf.constant_initializer(np.array(word_embedding)), trainable=False)
embedding_loopup= tf.nn.embedding_lookup(Word_embedding,input_x)

with tf.Session() as sess:
        sess.run(tf.global_variables_initializer())
        for ii in final_:
            print(sess.run(embedding_loopup,feed_dict={input_x:[ii]}))

Burada ayrıntılı Eğitim Ipython örneği çalışıyoruz , sıfırdan anlamak istiyorsanız bir göz atın.

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.