Pre-Trained Word Embedding

( 참고 : “딥러닝을 이용한 자연어 처리 입문” (https://wikidocs.net/book/2155) )


1. Introduction

Embedding된 단어를 사용하는 법

  • 방법 1) 지금 가지고 있는 train data를 사용하여 word를 embedding하기
  • 방법 2) 사전에 학습된 (ex. Wikipedia 등 대량의 텍스트 데이터) embedding된 단어 사용하기


이번 포스트에서는,

  • 방법 1)처럼 하기 위해, keras의 embedding layer를 사용하여 우리가 가진 데이터를 embedding 할 것이다.
  • 방법 2)처럼 하기 위해, pre-trained된 word embedding을 가져와서 사용할 것이다.


2. 방법 1) Word Embedding하기

범주형인 단어가, 수치형인 dense vector로 변형되는 과정은 아래와 같다.

  • 1) word
  • 2) Integer로 encoding
  • 3) Look-up Table 학습
  • 4) 위 table을 참조하여 embedding Vector 찾기

.


실습 : 긍/부정 판별하기

  • (1) Library를 불러온다
import numpy as np
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences


  • (2) 다음과 같은 7개의 긍/부정 문장이 있다
sentences = ['nice great best amazing', 'stop lies', 'pitiful nerd', 'excellent work', 'supreme quality', 'bad', 'highly respectable']
y_train = [1, 0, 0, 1, 1, 0, 1]


  • (3) 위 문장들의 각 단어를 토큰화 한다. 확인해본 결과, 총 16 종류의 단어가 존재한다.
t = Tokenizer()
t.fit_on_texts(sentences)
vocab_size = len(t.word_index) + 1


  • (4) 정수 Encoding을 해준다.
X_encoded = t.texts_to_sequences(sentences)
print(X_encoded)
[[1, 2, 3, 4], [5, 6], [7, 8], [9, 10], [11, 12], [13], [14, 15]]


  • (5) 문장의 최대 길이인 4를 기준으로 padding해준다.
max_len=max(len(l) for l in X_encoded)
X_train=pad_sequences(X_encoded, maxlen=max_len, padding='post')

y_train=np.array(y_train)


  • (6) 위의 16단어들을 5차원의 dense vector로 embedding해준다.
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Embedding, Flatten

z_dim = 5
model = Sequential()
model.add(Embedding(vocab_size, z_dim, input_length=max_len)) 
model.add(Flatten()) 
model.add(Dense(1, activation='sigmoid'))

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
model.fit(X_train, y_train, epochs=100, verbose=2)


3. 방법 2) Pre-trained Word Embedding

위의 방법1)에서는, 우리에게 주어진 7개의 문장을 사용하여 word를 embedding하였다. 하지만, 방법 2) Pre-trained Word Embedding에서는, 우리의 데이터로 단어를 embedding하지 않고, 이전에 다른 누군가가 더 방대한 data로 단어들을 embedding했던 것을 사용할 것이다.

사전 훈련된 Glove와 Word2Vec를 사용하여, 위의 방법 1)에서 사용했던 데이터를 긍/부정 분류할 것이다.


3-1. pre-trained GloVe

100차원으로 embedding된 word 모음

import numpy as np

!wget http://nlp.stanford.edu/data/glove.6B.zip
!unzip glove*.zip
f = open('glove.6B.100d.txt', encoding="utf8")


해당 embedding된 단어들을 불러와서 embedding_dict에 dictionary 형태로 저장한다

  • key : 단어
  • value : (100차원의) embedding vector
embedding_dict = dict()

for line in f:
    word_vector = line.split()
    word = word_vector[0]
    word_vector_arr = np.asarray(word_vector[1:], dtype='float32') 
    embedding_dict[word] = word_vector_arr
f.close()


우리의 (16종류의 단어를 담고 있는) 7개의 문장을, 위의 pre-trained된 embedding에서 참고하여 가져온다.

embedding_matrix = np.zeros((vocab_size, 100))

for word, i in t.word_index.items(): 
    temp = embedding_dict.get(word) 
    if temp is not None:
        embedding_matrix[i] = temp


pre-trained된 word embedding은 100차원이기 때문에, output_dim의 값으로는 100을 설정해야한다.

우리는 우리의 문장을 통해서 새롭게 embedding하는 것이 아니라, pre-trained된 word embedding을 그대로 사용할 것이므로, trainable=False를 지정해줘야 한다.

model = Sequential()
model.add(Embedding(vocab_size, 100, weights=[embedding_matrix], input_length=max_len, trainable=False))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
model.fit(X_train, y_train, epochs=100, verbose=2)


3-2. pre-trained word2vec

import numpy as np
import gensim


pre-trained된 word2vec embedding 불러오기 ( embedding dimension = 300 )

!wget "https://s3.amazonaws.com/dl4j-distribution/GoogleNews-vectors-negative300.bin.gz"

word2vec_model = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin.gz', binary=True)  


get_vector : 단어를 input으로 넣었을 때, pre-trained된 embedding에서 해당 단어의 embedding vector를 반환하는 함수이다.

def get_vector(word):
    if word in word2vec_model:
        return word2vec_model[word]
    else:
        return None


우리의 7개의 문장을, 위의 pre-trained embedding에서 참고하여 가져온다.

embedding_matrix = np.zeros((vocab_size, 300))

for word, i in t.word_index.items(): 
    temp = get_vector(word)
    if temp is not None: 
        embedding_matrix[i] = temp


아래 과정은 2와 동일하다.

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Embedding, Flatten

model = Sequential()
model.add(Embedding(vocab_size, 300, weights=[embedding_matrix], input_length=max_len, trainable=False))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
model.fit(X_train, y_train, epochs=100, verbose=2)