TensorFlow에서 사전 학습 된 단어 임베딩 (word2vec 또는 Glove) 사용


95

최근에 convolutional text classification에 대한 흥미로운 구현을 검토했습니다 . 그러나 내가 검토 한 모든 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 배열 embeddingvocab_size행과 함께 임베딩이 있다고 가정 해 보겠습니다.embedding_dim 열 그리고 당신은 텐서 만들려 W에 대한 호출에 사용할 수 있습니다 tf.nn.embedding_lookup().

  1. 간단하게 만들 WA와tf.constant()embedding그 가치 를 취하는 로 .

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

    이것은 가장 쉬운 방법이지만 a 값이 tf.constant()메모리에 여러 번 저장 되기 때문에 메모리 효율성이 떨어 집니다. 때문에 embedding매우 클 수, 당신은 단지 장난감 예제는이 방법을 사용합니다.

  2. a로 생성 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 모델의 일부로 학습 된 경우를 사용 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']. 여기에 문제가 있습니다! 'in'을 제거하고 숫자를 문자열에서 float32로 변환 한 후 이것을 내 W로 간주해야합니까? 이 경우 'in'을 해당 벡터에 연결하는 방법은 무엇입니까? 또는 숫자를 float32로 변환 한 다음 'in'을 그대로 두어야합니다. tensorflow가 필요한 모든 처리를 수행 할 것으로 기대하십니까? 감사!
user3147590

4
아, 여기에 몇 가지 옵션이 있습니다. 당신은 할 수 TensorFlow의 사용 tf.decode_csv()텐서에 텍스트 파일을 변환 연산을하지만,이 비싼 수 있습니다 (특히, 그것은 하나 만들어야합니다 Tensor열당하고 함께 숫자 사람을 연결). 아마도 더 쉬운 대안은 NumPy 배열로 입력 을 사용 pandas.read_csv()하고 pandas.DataFrame.as_matrix()얻는 것입니다.
mrry

3
NumPy 배열은 sess.run(embedding_init, ...)return 호출 후 가비지 수집되어야 합니다 (프로그램에서 참조를 유지하지 않는다고 가정). 프로그램의 구조에 따라 del embedding( embeddingNumPy 배열이있는 위치 ) 배열을 더 일찍 해제 할 수 있습니다.
mrry

1
@mrry : 옵션 1에 대해 더 구체적으로 말씀해 주시겠습니까? "tf.constant ()의 값이 메모리에 여러 번 저장되기 때문에 메모리 효율적이지 않습니다". GPU 또는 CPU에 비효율적 인 메모리? 더 일반적으로, 옵션 2의 tf.Variable () + 공급 자리 표시 자에는이 문제가 없는데 tf.constant ()가 메모리에 여러 복사본을 가져야하는 이유는 무엇입니까?
가브리엘 부모

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 .. 실제로 그는 trainable = False 인수가 누락되어 프로세스에서 임베딩을 미세 조정하게됩니다.
Shatu

4
또한 Eugenio의 추론이 잘못된 것 같습니다. 모든 미니 배치에서 "embedding_init"작업을 실행할 필요가 없으며 모든 것이 정상입니다. 즉, 학습 시작시 임베딩 초기화를 한 번만 실행하면됩니다.
Shatu

@Shatu 임베딩 초기화가 교육 시작시에만 실행되도록하려면 어떻게해야합니까?

1
@ dust0x .. 임베딩의 크기가 충분히 작 으면 초기 값으로 지정할 수 있습니다. 크기가 상당히 크면 모든 변수에 대해 이니셜 라이저를 실행할 때 feed_dict에 전달할 수 있습니다. 명확하지 않은 경우 알려 주시면 두 가지 접근 방식에 대한 샘플 코드를 게시 해 보겠습니다.
Shatu

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 Link를 참조하세요 .


5

Tensorflow 버전 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 예제를 살펴보세요.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.