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)