Использование предварительно обученного встраивания слов (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 вместо случайного?

user3147590
источник

Ответы:

130

Есть несколько способов использовать предварительно обученное встраивание в TensorFlow. Допустим, у вас есть встраивание в массив NumPy с именем embedding, со vocab_sizeстроками и embedding_dimстолбцами, и вы хотите создать тензор, Wкоторый можно использовать при вызове tf.nn.embedding_lookup().

  1. Просто создайте Wкак объект, 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? если это так, то как подключиться к соответствующему вектору? ИЛИ мне нужно преобразовать числа в float32, а затем оставить in как есть; ожидаете, что тензорный поток выполнит всю необходимую обработку? Спасибо!
user3147590
4
Ах, у вас есть несколько вариантов. Вы можете использовать операцию TensorFlow tf.decode_csv()для преобразования текстового файла в тензор, но это может быть дорогостоящим (в частности, вам потребуется создать по одному для Tensorкаждого столбца, а затем объединить числовые значения вместе). Возможно, более простой альтернативой было бы использовать pandas.read_csv()и pandas.DataFrame.as_matrix()получать входные данные в виде массива NumPy.
Мрри
3
Массив NumPy должен быть собран в мусор после вызова функции sess.run(embedding_init, ...)return (при условии, что вы не храните ссылку на него в своей программе). В зависимости от структуры вашей программы вы можете захотеть del embedding(где embeddingнаходится массив NumPy) освободить массив раньше.
мрри
1
@mrry: не могли бы вы подробнее рассказать о варианте 1 и, в частности, «он неэффективен с точки зрения памяти, потому что значение tf.constant () сохраняется в памяти несколько раз». Память неэффективна для графического процессора или процессора? В более общем плане, почему tf.constant () должен иметь несколько копий в памяти, в то время как заполнитель tf.Variable () + feed из варианта 2 не имеет этой проблемы?
Габриэль Родитель
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))
Эухенио Мартинес Камара
источник
Точная копия ответа Люцзя.
TimZaman
4
@TimZaman .. Фактически, ему не хватает аргумента trainable = False, и, таким образом, он в конечном итоге будет настраивать свои вложения в процессе.
Шату
4
Кроме того, я считаю, что рассуждения Эухенио неверны. Вам просто не нужно запускать операцию "embedding_init" с каждым мини-пакетом, и все будет хорошо. То есть просто запускайте инициализацию встраивания только один раз в начале обучения.
Shatu 03
@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 .

Поддержка Tensorflow
источник
5

С tenorflow версии 2 это довольно просто, если вы используете слой 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

Я также столкнулся с проблемой встраивания, поэтому я написал подробное руководство с набором данных. Здесь я хотел бы добавить то, что пробовал. Вы также можете попробовать этот метод,

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, если вы хотите разобраться с нуля, посмотрите.

Аадитья Ура
источник