การใช้การฝังคำที่ผ่านการฝึกอบรมมาแล้ว (word2vec หรือ Glove) ใน TensorFlow


95

เราได้ตรวจสอบการดำเนินงานเมื่อเร็ว ๆ นี้ที่น่าสนใจสำหรับการจัดหมวดหมู่ข้อความสับสน อย่างไรก็ตามโค้ด TensorFlow ทั้งหมดที่ฉันได้ตรวจสอบจะใช้การฝังเวกเตอร์แบบสุ่ม (ไม่ได้รับการฝึกฝนมาก่อน) ดังต่อไปนี้:

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 หรือการฝังคำที่ได้รับการฝึกฝนมาก่อนของ GloVe แทนที่จะเป็นการสุ่มหรือไม่?

คำตอบ:


130

มีสองสามวิธีที่คุณสามารถใช้การฝังที่ผ่านการฝึกอบรมล่วงหน้าใน TensorFlow สมมติว่าคุณมีการฝังในอาร์เรย์ NumPy เรียกว่าembeddingมีvocab_sizeแถวและembedding_dimคอลัมน์และคุณต้องการสร้างเมตริกซ์ที่สามารถใช้ในการเรียกร้องให้Wtf.nn.embedding_lookup()

  1. เพียงแค่สร้างWสิ่งtf.constant()ที่ใช้embeddingเป็นมูลค่า:

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

    นี่เป็นวิธีที่ง่ายที่สุด แต่หน่วยความจำไม่เต็มประสิทธิภาพเนื่องจากค่าของ a tf.constant()ถูกเก็บไว้ในหน่วยความจำหลายครั้ง เนื่องจากembeddingอาจมีขนาดใหญ่มากคุณควรใช้แนวทางนี้สำหรับตัวอย่างของเล่นเท่านั้น

  2. สร้างWเป็นtf.Variableและเริ่มต้นจากอาร์เรย์ NumPy ผ่าน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})
    

    วิธีนี้หลีกเลี่ยงการจัดเก็บสำเนาembeddingในกราฟ แต่ต้องใช้หน่วยความจำเพียงพอที่จะเก็บสองสำเนาของเมทริกซ์ไว้ในหน่วยความจำพร้อมกัน (หนึ่งชุดสำหรับอาร์เรย์ NumPy และอีกชุดสำหรับtf.Variable) โปรดทราบว่าฉันได้สันนิษฐานว่าคุณต้องการคงค่าคงที่เมทริกซ์การฝังไว้ในระหว่างการฝึกดังนั้นจึงWถูกสร้างขึ้นด้วยtrainable=False.

  3. หากการฝังได้รับการฝึกฝนเป็นส่วนหนึ่งของโมเดล TensorFlow อื่นคุณสามารถใช้ a tf.train.Saverเพื่อโหลดค่าจากไฟล์จุดตรวจสอบของโมเดลอื่น ซึ่งหมายความว่าเมทริกซ์การฝังสามารถข้าม Python ได้ทั้งหมด สร้างWในตัวเลือกที่ 2 จากนั้นดำเนินการดังต่อไปนี้:

    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 ดังนี้: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = '') ที่สร้างเป็นแถว: ['in' '0.070312 ...... '-0.0625'] มีปัญหาที่นี่! ฉันจะถือว่านี่เป็น W ของฉันหลังจากลบ 'in' และแปลงตัวเลขจากสตริงเป็น float32 หรือไม่ ถ้าเป็นกรณีนี้จะเชื่อมต่อ 'in' กับเวกเตอร์ของมันได้อย่างไร? หรือฉันต้องการแปลงตัวเลขเป็น float32 แล้วปล่อยให้ 'in' ตามที่เป็นอยู่ คาดหวังว่าเทนเซอร์โฟลว์จะทำการประมวลผลที่จำเป็นทั้งหมด? ขอบคุณ!
user3147590

4
อ่าคุณมีสองตัวเลือกที่นี่ คุณสามารถใช้ TensorFlow tf.decode_csv()op เพื่อแปลงไฟล์ข้อความเป็นเทนเซอร์ได้ แต่อาจมีราคาแพง (โดยเฉพาะอย่างยิ่งคุณต้องสร้างหนึ่งรายการTensorต่อคอลัมน์จากนั้นจึงเชื่อมต่อตัวเลขเข้าด้วยกัน) บางทีทางเลือกที่ง่ายกว่าคือการใช้pandas.read_csv()และpandas.DataFrame.as_matrix()รับอินพุตเป็นอาร์เรย์ NumPy
mrry

3
อาร์เรย์ NumPy ควรเป็นขยะที่รวบรวมหลังจากการเรียกให้sess.run(embedding_init, ...)ส่งคืน (สมมติว่าคุณไม่ได้เก็บข้อมูลอ้างอิงไว้ในโปรแกรมของคุณ) ขึ้นอยู่กับโครงสร้างของโปรแกรมของคุณคุณอาจต้องการdel embedding( embeddingอาร์เรย์ NumPy อยู่ที่ไหน) เพื่อปล่อยอาร์เรย์ก่อนหน้านี้
mrry

1
@mrry: คุณสามารถพูดคุยเพิ่มเติมเกี่ยวกับตัวเลือกที่ 1 และเฉพาะเจาะจงมากขึ้นได้ไหม "หน่วยความจำไม่ค่อยมีประสิทธิภาพเนื่องจากค่าของ tf.constant () ถูกเก็บไว้ในหน่วยความจำหลายครั้ง" หน่วยความจำไม่มีประสิทธิภาพสำหรับ GPU หรือ CPU? โดยทั่วไปทำไม tf.constant () จึงต้องมีหลายสำเนาในหน่วยความจำในขณะที่ tf.Variable () + ตัวยึดการป้อนของตัวเลือก 2 ไม่มีปัญหานี้
Gabriel Parent

1
หากคุณยังสงสัยว่าทำไม "ค่าของ tf.constant () จึงถูกเก็บไว้หลายครั้งในหน่วยความจำ" ลองดูคำตอบนี้: stackoverflow.com/a/42450418/5841473
alyaxey

33

ฉันใช้วิธีนี้เพื่อโหลดและแชร์การฝัง

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

การฝังควรเป็นคอลัมน์หรือแถวในเมทริกซ์ numpy?
Greyshack

6

คำตอบของ @mrry ไม่ถูกต้องเพราะมันกระตุ้นให้เกิดการเขียนทับของน้ำหนักที่ฝังในแต่ละเครือข่ายที่รันอยู่ดังนั้นหากคุณปฏิบัติตามแนวทางมินิแบทช์ในการฝึกอบรมเครือข่ายของคุณคุณจะเขียนทับน้ำหนักของการฝัง ดังนั้นในมุมมองของฉันวิธีที่ถูกต้องในการฝังข้อมูลล่วงหน้าคือ:

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

คำตอบของ LiuJia ซ้ำกัน
TimZaman

4
@TimZaman .. ในความเป็นจริงเขาไม่มีข้อโต้แย้งที่สามารถฝึกได้ = เท็จดังนั้นจะลงเอยด้วยการปรับแต่งการฝังตัวของเขาในกระบวนการ
Shatu

4
นอกจากนี้ฉันคิดว่าเหตุผลของ Eugenio ไม่ถูกต้อง คุณไม่จำเป็นต้องเรียกใช้ op "embedding_init" กับทุกชุดขนาดเล็กและทุกอย่างก็จะเรียบร้อย นั่นคือเพียงเรียกใช้การเริ่มต้นการฝังเพียงครั้งเดียวเมื่อเริ่มการฝึกอบรม
Shatu

@Shatu ฉันจะแน่ใจได้อย่างไรว่าการเริ่มต้นการฝังจะทำงานเมื่อเริ่มต้นการฝึกเท่านั้น

1
@ dust0x .. ถ้าขนาดของการฝังมีขนาดเล็กพอคุณสามารถระบุเป็นค่าเริ่มต้นได้ หากมีขนาดค่อนข้างใหญ่คุณสามารถส่งผ่านใน feed_dict เมื่อคุณเรียกใช้ initializer สำหรับตัวแปรทั้งหมด โปรดแจ้งให้เราทราบหากยังไม่ชัดเจนพอฉันจะพยายามโพสต์โค้ดตัวอย่างสำหรับทั้งสองวิธี
Shatu

5

2.0 คำตอบที่เข้ากันได้ : มี Embeddings ก่อนการฝึกอบรมจำนวนมากซึ่งพัฒนาโดย Google และได้รับการเปิดแหล่งที่มา

บางส่วนเป็นUniversal Sentence Encoder (USE), ELMO, BERTฯลฯ และง่ายมากที่จะใช้ซ้ำในรหัส

รหัสที่จะนำมาใช้ใหม่Pre-Trained Embedding, Universal Sentence Encoderแสดงอยู่ด้านล่าง:

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

สำหรับข้อมูลเพิ่มเติม Pre-ฝึกอบรม embeddings พัฒนาและเปิดมาโดย Google ดูTF Hub เชื่อมโยง


5

ด้วยเทนเซอร์โฟลว์เวอร์ชัน 2 มันค่อนข้างง่ายหากคุณใช้เลเยอร์การฝัง

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

ฉันประสบปัญหาการฝังด้วยดังนั้นฉันจึงเขียนบทช่วยสอนโดยละเอียดพร้อมชุดข้อมูล ที่นี่ฉันต้องการเพิ่มสิ่งที่ฉันลองคุณสามารถลองวิธีนี้

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

นี่คือตัวอย่างการสอนIpythonโดยละเอียดที่ใช้งานได้หากคุณต้องการทำความเข้าใจตั้งแต่เริ่มต้นลองดู

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.