Menggunakan penyematan kata terlatih (word2vec atau Glove) di TensorFlow


95

Saya baru-baru ini meninjau implementasi menarik untuk klasifikasi teks konvolusional . Namun semua kode TensorFlow yang saya tinjau menggunakan vektor penyematan acak (tidak terlatih sebelumnya) seperti berikut:

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)

Adakah yang tahu cara menggunakan hasil Word2vec atau penyematan kata terlatih GloVe daripada yang acak?

Jawaban:


130

Ada beberapa cara untuk menggunakan penyematan terlatih di TensorFlow. Katakanlah Anda memiliki embedding dalam array NumPy yang dipanggil embedding, dengan vocab_sizebaris dan embedding_dimkolom dan Anda ingin membuat tensor Wyang dapat digunakan dalam panggilan ke tf.nn.embedding_lookup().

  1. Cukup buat Wsebagai tf.constant()yang mengambil embeddingnilainya:

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

    Ini adalah pendekatan yang paling mudah, tetapi tidak efisien dalam memori karena nilai a tf.constant()disimpan beberapa kali dalam memori. Karena embeddingbisa sangat besar, Anda sebaiknya hanya menggunakan pendekatan ini untuk contoh mainan.

  2. Buat Wsebagai tf.Variabledan inisialisasi dari array NumPy melalui 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})

    Hal ini menghindari penyimpanan salinan embeddingdalam grafik, tetapi memerlukan cukup memori untuk menyimpan dua salinan matriks dalam memori sekaligus (satu untuk larik NumPy, dan satu untuk larik tf.Variable). Perhatikan bahwa saya berasumsi bahwa Anda ingin menahan matriks embedding secara konstan selama pelatihan, jadi Wdibuat dengan trainable=False.

  3. Jika penyematan dilatih sebagai bagian dari model TensorFlow lain, Anda dapat menggunakan a tf.train.Saveruntuk memuat nilai dari file checkpoint model lain. Ini berarti matriks embedding dapat melewati Python sama sekali. Buat Wseperti pada opsi 2, lalu lakukan hal berikut:

    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")

Saya membuat W sebagai berikut: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = '') yang dibuat sebagai baris: ['in' '0.070312 ...... '-0,0625']. Ada masalah disini! haruskah saya menganggap ini sebagai W saya setelah menghapus 'in' dan mengubah angka dari string ke float32? jika ini masalahnya, lalu bagaimana menghubungkan 'in' ke vektornya masing-masing? ATAU Saya perlu mengubah angka menjadi float32 dan kemudian membiarkan 'masuk' apa adanya; mengharapkan tensorflow akan melakukan semua pemrosesan yang diperlukan? Terima kasih!
pengguna3147590

4
Ah, Anda punya beberapa opsi di sini. Anda dapat menggunakan tf.decode_csv()op TensorFlow untuk mengonversi file teks menjadi tensor, tetapi ini mungkin mahal (khususnya, Anda harus membuatnya Tensorper kolom, lalu menggabungkan yang numerik). Mungkin alternatif yang lebih mudah adalah menggunakan pandas.read_csv()dan pandas.DataFrame.as_matrix()mendapatkan input sebagai array NumPy.
Tuan

3
Larik NumPy harus dikumpulkan sampahnya setelah panggilan untuk sess.run(embedding_init, ...)kembali (dengan asumsi Anda tidak menyimpan referensi ke sana dalam program Anda). Bergantung pada struktur program Anda, Anda mungkin ingin del embedding(di mana embeddingarray NumPy) untuk merilis array sebelumnya.
Tuan

1
@mrry: dapatkah Anda berbicara lebih banyak tentang opsi 1 dan lebih spesifik lagi "ini tidak efisien memori karena nilai tf.constant () disimpan beberapa kali dalam memori". Memori tidak efisien untuk GPU atau CPU? Secara umum, mengapa tf.constant () harus memiliki banyak salinan dalam memori, sedangkan placeholder makan tf.Variable () + opsi 2 tidak memiliki masalah ini?
Gabriel Parent

1
Jika Anda juga bertanya-tanya mengapa "nilai a tf.constant () disimpan beberapa kali dalam memori" lihat jawaban ini: stackoverflow.com/a/42450418/5841473
alyaxey

33

Saya menggunakan metode ini untuk memuat dan membagikan penyematan.

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

Haruskah embedding berupa kolom atau baris dalam matriks numpy?
Greyshack

6

Jawaban dari @mrry tidak benar karena memicu penimpaan bobot embeddings setiap jaringan dijalankan, jadi jika Anda mengikuti pendekatan minibatch untuk melatih jaringan Anda, Anda menimpa bobot embeddings. Jadi, menurut saya, cara yang benar untuk embeddings terlatih adalah:

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

Duplikat jawaban LiuJia.
TimZaman

4
@TimZaman .. Faktanya, dia kehilangan argumen trainable = False, dan dengan demikian akan menyempurnakan embeddingsnya dalam proses tersebut.
Shatu

4
Juga, saya pikir alasan Eugenio tidak benar. Anda hanya tidak perlu menjalankan operasi "embedding_init" dengan setiap tumpukan mini, dan semuanya akan baik-baik saja. Artinya, jalankan inisialisasi penyematan hanya sekali di awal pelatihan.
Shatu

@ Shatu bagaimana cara memastikan bahwa inisialisasi embedding dijalankan hanya pada awal pelatihan?

1
@ dust0x .. Jika ukuran embeddings cukup kecil, Anda dapat menentukannya sebagai nilai awal. Jika ukurannya cukup besar, Anda bisa meneruskannya di feed_dict saat Anda menjalankan penginisialisasi untuk semua variabel. Beri tahu saya jika tidak cukup jelas, dan saya akan mencoba memposting beberapa kode contoh untuk kedua pendekatan.
Shatu

6

2.0 Jawaban yang Kompatibel : Ada banyak Embeddings yang Dilatih, yang dikembangkan oleh Google dan telah Bersumber Terbuka.

Beberapa di antaranya adalah Universal Sentence Encoder (USE), ELMO, BERT, dll .. dan sangat mudah untuk digunakan kembali dalam kode Anda.

Kode untuk menggunakan kembali Pre-Trained Embedding, Universal Sentence Encoderditunjukkan di bawah ini:

  !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)

Untuk informasi lebih lanjut tentang Embeddings yang Dilatih yang dikembangkan dan bersumber terbuka oleh Google, lihat TF Hub Link .


5

Dengan tensorflow versi 2 cukup mudah jika Anda menggunakan lapisan Embedding

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

Saya juga menghadapi masalah embedding, jadi saya menulis tutorial mendetail dengan dataset. Di sini saya ingin menambahkan apa yang saya coba. Anda juga dapat mencoba metode ini,

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

Berikut ini adalah contoh detail kerja Tutorial Ipython jika Anda ingin memahami dari awal, lihat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.