Використання попередньо навченого вбудовування слів (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стовпцями, і ви хочете створити тензор, Wякий можна використовувати у виклику tf.nn.embedding_lookup().

  1. Просто створіть Wяк a, tf.constant()що приймає embeddingза значення:

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

    Це найпростіший підхід, але він не є ефективним для пам'яті, оскільки значення a tf.constant()зберігається кілька разів у пам'яті. Оскільки це embeddingможе бути дуже великим, ви повинні використовувати цей підхід лише для прикладів іграшок.

  2. Створіть Wяк a 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' як є; очікуючи, що tensorflow виконає всю необхідну обробку? Дякую!
user3147590

4
А, у вас тут є кілька варіантів. Ви можете використати tf.decode_csv()оператор TensorFlow для перетворення текстового файлу в тензор, але це може бути дорогим (зокрема, для цього потрібно створити по одному Tensorна стовпець, а потім об’єднати числові). Можливо, простішою альтернативою було б використання pandas.read_csv()та pandas.DataFrame.as_matrix()отримання вхідних даних як масиву NumPy.
mrry

3
Масив NumPy повинен бути сміттям, зібраним після виклику sess.run(embedding_init, ...)return (припускаючи, що ви не зберігаєте посилання на нього у своїй програмі). Залежно від структури вашої програми, можливо, ви захочете del embedding(де embeddingзнаходиться масив NumPy) звільнити масив раніше.
mrry

1
@mrry: чи можете ви поговорити більше про варіант 1 і конкретніше "це не ефективно для пам'яті, оскільки значення tf.constant () зберігається кілька разів у пам'яті". Пам'ять неефективна для графічного або центрального процесора? Більш загально, чому 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 .. Насправді, йому не вистачає аргументу, який можна навчити = False, і, отже, в підсумку буде налаштована його вбудованість в процес.
Шату

4
Крім того, я думаю, що міркування Євгеніо є неправильними. Вам просто не потрібно запускати операцію "embedding_init" з кожною міні-партією, і все буде добре. Тобто, просто запустіть ініціалізацію вбудовування лише один раз на початку навчання.
Шату

@Shatu, як я можу забезпечити, щоб ініціалізація вбудовування виконувалася лише на початку навчання?

1
@ dust0x .. Якщо розмір вкладень досить малий, ви можете просто вказати їх як початкове значення. Якщо вони досить великі, ви можете передати їх у feed_dict під час запуску ініціалізатора для всіх змінних. Повідомте мене, якщо це недостатньо ясно, і я спробую опублікувати зразок коду для обох підходів.
Шату,

6

2.0 Сумісна відповідь : Є багато попередньо підготовлених вкладень, які розроблені 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)

Для отримання додаткової інформації про попередньо підготовлені вставки, розроблені та відкриті Google, зверніться до посилання TF Hub .


5

З версією tensorflow 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, якщо ви хочете зрозуміти з нуля, подивіться.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.