Sử dụng tính năng nhúng từ được đào tạo trước (word2vec hoặc Glove) trong TensorFlow


95

Gần đây tôi đã xem xét một triển khai thú vị để phân loại văn bản phức hợp . Tuy nhiên, tất cả mã TensorFlow mà tôi đã xem xét sử dụng vectơ nhúng ngẫu nhiên (không được đào tạo trước) như sau:

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)

Có ai biết cách sử dụng kết quả của Word2vec hoặc nhúng từ được đào tạo trước GloVe thay vì một kết quả ngẫu nhiên không?

Câu trả lời:


130

Có một số cách mà bạn có thể sử dụng phương pháp nhúng được đào tạo trước trong TensorFlow. Giả sử rằng bạn có nhúng trong một mảng NumPy được gọi embedding, với vocab_sizecác hàng và embedding_dimcột và bạn muốn tạo một tensor Wcó thể được sử dụng trong lệnh gọi tới tf.nn.embedding_lookup().

  1. Đơn giản chỉ cần tạo ra Wnhư một tf.constant()mà có embeddinggiá trị:

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

    Đây là cách tiếp cận dễ dàng nhất, nhưng nó không hiệu quả về bộ nhớ vì giá trị của a tf.constant()được lưu trữ nhiều lần trong bộ nhớ. Vì embeddingcó thể rất lớn, bạn chỉ nên sử dụng cách tiếp cận này cho các ví dụ về đồ chơi.

  2. Tạo Wdưới dạng a tf.Variablevà khởi tạo nó từ mảng NumPy thông qua 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})

    Điều này tránh việc lưu trữ một bản sao của embeddingtrong biểu đồ, nhưng nó yêu cầu đủ bộ nhớ để giữ hai bản sao của ma trận trong bộ nhớ cùng một lúc (một cho mảng NumPy và một cho mảng tf.Variable). Lưu ý rằng tôi đã giả định rằng bạn muốn giữ ma trận nhúng không đổi trong quá trình đào tạo, vì vậy Wđược tạo với trainable=False.

  3. Nếu quá trình nhúng được đào tạo như một phần của mô hình TensorFlow khác, bạn có thể sử dụng a tf.train.Saverđể tải giá trị từ tệp điểm kiểm tra của mô hình khác. Điều này có nghĩa là ma trận nhúng có thể bỏ qua Python hoàn toàn. Tạo Wnhư trong tùy chọn 2, sau đó làm như sau:

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

Tôi tạo W như sau: W = np.loadtxt ("/ media / w2vTest.txt", dtype = 'string', delimiter = '') tạo thành một hàng: ['in' '0.070312 ...... '-0,0625']. Có vấn đề ở đây! Tôi có nên coi đây là W của mình sau khi loại bỏ 'in' và chuyển đổi số từ chuỗi thành float32 không? nếu đúng như vậy, thì làm thế nào để kết nối 'in' với vectơ tương ứng của nó? HOẶC tôi cần chuyển đổi các số liệu thành float32 và sau đó để nguyên 'in'; mong đợi rằng tensorflow sẽ thực hiện tất cả các xử lý cần thiết? Cảm ơn!
user3147590 29/02/16

4
À, bạn có một vài lựa chọn ở đây. Bạn có thể sử dụng tf.decode_csv()op TensorFlow để chuyển đổi tệp văn bản thành tensor, nhưng điều này có thể tốn kém (đặc biệt, nó yêu cầu bạn tạo một tệp Tensortrên mỗi cột, sau đó nối các tệp số lại với nhau). Có lẽ một giải pháp thay thế dễ dàng hơn sẽ là sử dụng pandas.read_csv()pandas.DataFrame.as_matrix()lấy đầu vào dưới dạng mảng NumPy.
mrry 29/02/16

3
Mảng NumPy sẽ được thu thập sau khi gọi sess.run(embedding_init, ...)trả về (giả sử bạn không giữ tham chiếu đến nó trong chương trình của mình). Tùy thuộc vào cấu trúc chương trình của bạn, bạn có thể muốn del embedding( embeddingmảng NumPy ở đâu) giải phóng mảng sớm hơn.
mrry

1
@mrry: bạn có thể nói thêm về phương án 1 và cụ thể hơn là "nó không hiệu quả về bộ nhớ vì giá trị của một tf.constant () được lưu nhiều lần trong bộ nhớ". Bộ nhớ không hiệu quả cho GPU hoặc CPU? Tổng quát hơn, tại sao tf.constant () phải có nhiều bản sao trong bộ nhớ, trong khi trình giữ chỗ tf.Variable () + cho ăn của tùy chọn 2 không gặp vấn đề này?
Gabriel Parent

1
Nếu bạn cũng tự hỏi tại sao "giá trị của một tf.constant () được lưu trữ nhiều lần trong bộ nhớ" hãy nhìn vào câu trả lời này: stackoverflow.com/a/42450418/5841473
alyaxey

33

Tôi sử dụng phương pháp này để tải và chia sẻ nhúng.

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

Việc nhúng có nên là cột hoặc hàng trong ma trận numpy không?
Greyshack,

6

Câu trả lời của @mrry là không đúng vì nó cho phép ghi đè trọng số nhúng mỗi mạng được chạy, vì vậy nếu bạn đang theo cách tiếp cận minibatch để đào tạo mạng của mình, bạn đang ghi đè trọng số của các nhúng. Vì vậy, theo quan điểm của tôi, cách phù hợp để nhúng được đào tạo trước là:

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

Bản sao chính xác câu trả lời của LiuJia.
TimZaman

4
@TimZaman .. Trên thực tế, anh ấy đang thiếu đối số có thể đào tạo = False, và do đó sẽ kết thúc việc tinh chỉnh các lần nhúng của anh ấy trong quá trình này.
Shatu

4
Ngoài ra, tôi nghĩ lý do của Eugenio là không chính xác. Bạn không cần phải chạy op "embedding_init" với mỗi đợt nhỏ và mọi thứ sẽ ổn. Đó là, chỉ chạy khởi tạo nhúng chỉ một lần khi bắt đầu đào tạo.
Shatu

@Shatu làm cách nào để đảm bảo rằng quá trình khởi tạo nhúng chỉ được chạy khi bắt đầu đào tạo?

1
@ Dust0x .. Nếu kích thước của các nhúng đủ nhỏ, bạn có thể chỉ định chúng làm giá trị ban đầu. Nếu chúng khá lớn, bạn có thể chuyển chúng vào feed_dict khi chạy trình khởi tạo cho tất cả các biến. Hãy cho tôi biết nếu nó không đủ rõ ràng và tôi sẽ cố gắng đăng một số mã mẫu cho cả hai cách tiếp cận.
Shatu

6

2.0 Câu trả lời tương thích : Có rất nhiều Nhúng được đào tạo trước, được phát triển bởi Google và có Nguồn gốc mở.

Một số trong số họ là Universal Sentence Encoder (USE), ELMO, BERT , v.v. và rất dễ dàng sử dụng lại chúng trong mã của bạn.

Mã để sử dụng lại Pre-Trained Embedding, Universal Sentence Encoderđược hiển thị bên dưới:

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

Để biết thêm thông tin về Nhúng được đào tạo trước do Google phát triển và có nguồn mở, hãy tham khảo Liên kết trung tâm TF .


5

Với tensorflow phiên bản 2, nó khá dễ dàng nếu bạn sử dụng lớp Nhúng

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

Tôi cũng phải đối mặt với vấn đề nhúng, Vì vậy, tôi đã viết hướng dẫn chi tiết với tập dữ liệu. Ở đây tôi muốn thêm những gì tôi đã thử. Bạn cũng có thể thử phương pháp này,

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

Đây là ví dụ về Hướng dẫn Ipython chi tiết nếu bạn muốn hiểu từ đầu, hãy xem.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.