Sentiment Analysis | Use Pretrained Word2Vec #3

이지수·2022년 2월 11일
0

ML/DL

목록 보기
3/3

Google Pretrained Word2Vec

  • Sentiment Analysis #2 에서 Word Embedding Layer을 사용
  • 사전의 단어 개수 X 워드 벡터 사이즈만큼의 크기를 가진 학습 파라미터
  • 감성분류 모델이 학습이 잘 되었다면, Embedding 레이어에 학습된 워드 벡터들도 의미 공간상에 유의미한 형태로 학습되었을 것

# 워드 벡터 다루기 위한 gensim 패키지 확인 
!pip list | grep gensim
gensim                   4.0.1
import os
from os.path import join
os.getcwd()
'/Volumes/GoogleDrive/My Drive/Colab_Notebook/aiffel_lms/E7_text_sentiment'

root_path = '/Volumes/GoogleDrive/My Drive/Colab_Notebook/aiffel_lms/E7_text_sentiment/data'

  • Model_1의 Embedding Layer weights 확인
model_1.summary()
Model: "model1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
word_embedding (Embedding)   (None, None, 16)          160000    
_________________________________________________________________
lstm_5 (LSTM)                (None, 32)                6272      
_________________________________________________________________
dense_26 (Dense)             (None, 8)                 264       
_________________________________________________________________
dense_27 (Dense)             (None, 1)                 9         
=================================================================
Total params: 166,545
Trainable params: 166,545
Non-trainable params: 0
_________________________________________________________________
embedding_layer = model_1.layers[0] # model_1의 embedding layer 
weights = embedding_layer.get_weights()[0]
print(weights.shape)    # shape: (vocab_size, embedding_dim)
(10000, 16)

  • 워드 벡터 파일을 저장할 디렉토리를 먼저 생성
# 학습한 Embedding 파라미터를 파일에 써서 저장

word2vec_file_path = join(root_path, 'word2vec.txt')

f = open(word2vec_file_path, 'w')
f.write('{} {}\n'.format(vocab_size-4, word_vector_dim))  # 몇개의 벡터를 얼마 사이즈로 기재할지 타이틀 기재 

# 단어 개수(에서 특수문자 4개는 제외하고)만큼의 워드 벡터를 파일에 기록

vectors = model_1.get_weights()[0]

for i in range(4,vocab_size):
    f.write('{} {}\n'.format(index_to_word[i], ' '.join(map(str, list(vectors[i, :])))))
f.close()

  • gensim에서 제공하는 패키지를 이용해, 위에 남긴 임베딩 파라미터를 읽어서 word vector로 활용할 수 있음
from gensim.models.keyedvectors import Word2VecKeyedVectors

word_vectors = Word2VecKeyedVectors.load_word2vec_format(word2vec_file_path, binary=False)
vector = word_vectors['computer']
vector
array([ 0.05835353,  0.02972049,  0.00399579,  0.01061273, -0.03945053,
       -0.06081106, -0.00823087, -0.07572383, -0.05524068, -0.01307657,
        0.00311514, -0.0067417 , -0.07293623, -0.01328314,  0.02848107,
       -0.00361134], dtype=float32)

  • gensim을 활용하여 워드 벡터가 의미벡터 공간상에 유의미하게 학습되었는지 확인하는 방법 중에, 단어를 하나 주고 그와 가장 유사한 단어와 그 유사도를 확인하는 방법
word_vectors.similar_by_word("love")
[('remakes', 0.9091728925704956),
 ('stardom', 0.898648202419281),
 ('jealousy', 0.8963329792022705),
 ('brutality', 0.8921096324920654),
 ('der', 0.8868229985237122),
 ('expressions', 0.8729190826416016),
 ('live', 0.872138261795044),
 ('sheila', 0.8695423007011414),
 ('depicts', 0.8669462203979492),
 ('sack', 0.8613362312316895)]
  • 유사한 다른 단어를 잘 찾았다고 느껴지지는 않음
  • 간단한 데이터로 감성분류 테스크를 학습한 것으로는 워드 벡터가 유의미하게 학습되기는 어려워 보임
  • 구글에서 제공하는 Word2Vec이라는 사전학습된(Pretrained) 워드 임베딩 모델을 가져다 활용하고자 함
  • Word2Vec은 1억 개의 단어로 구성된 Google News dataset을 바탕으로 학습된 것
  • 총 300만 개의 단어를 각각 300차원의 벡터로 표현한 것
  • 학습된 Word2Vec이라는 것도 Embedding Layer와 원리는 동일
  • 전이학습 떄문에 사전학습된 임베딩을 활용하는 것이 유리한 것

from gensim.models import KeyedVectors

word2vec_path = 
word2vec = KeyedVectors.load_word2vec_format(word2vec_path, binary=True, limit=1000000)
vector = word2vec['computer']
vector     # 300dim의 워드 벡터
  • 300dim의 벡터로 이루어진 300만 개의 단어
  • 이 단어 사전을 메모리에 모두 로딩하면 메모리 사용이 너무 높아짐
  • KeyedVectors.load_word2vec_format 메소드로 워드 벡터를 로딩할 때 가장 많이 사용되는 상위 100만 개만 limt으로 조건을 주어 로딩

word2vec.similar_by_word("love")
vocab_size = 10000    # 어휘 사전의 크기 (10,000개의 단어)
word_vector_dim = 300  # 워드 벡터의 차원수 (변경가능한 하이퍼파라미터)

embedding_matrix = np.random.rand(vocab_size, word_vector_dim)

# embedding_matrix에 Word2Vec 워드 벡터를 단어 하나씩마다 차례차례 카피

for i in range(4,vocab_size):
    if index_to_word[i] in word2vec:
        embedding_matrix[i] = word2vec[index_to_word[i]]
from tensorflow.keras.initializers import Constant

vocab_size = 10000    # 어휘 사전의 크기 (10,000개의 단어)
word_vector_dim = 300  # 워드 벡터의 차원 수 (변경가능한 하이퍼파라미터)

# 모델 구성
model = keras.Sequential()
model.add(keras.layers.Embedding(vocab_size, 
                                 word_vector_dim, 
                                 embeddings_initializer=Constant(embedding_matrix),  # 카피한 임베딩을 여기서 활용
                                 input_length=maxlen, 
                                 trainable=True))   # trainable을 True로 주면 Fine-tuning
model.add(keras.layers.Conv1D(16, 7, activation='relu'))
model.add(keras.layers.MaxPooling1D(5))
model.add(keras.layers.Conv1D(16, 7, activation='relu'))
model.add(keras.layers.GlobalMaxPooling1D())
model.add(keras.layers.Dense(8, activation='relu'))
model.add(keras.layers.Dense(1, activation='sigmoid')) 

model.summary()
# 학습의 진행
model.compile(optimizer='adam',
              loss='binary_crossentropy',
              metrics=['accuracy'])
              
epochs=20  # 몇 epoch를 훈련하면 좋을지 결과를 보면서 바꾸어 봅시다. 

history = model.fit(partial_x_train,
                    partial_y_train,
                    epochs=epochs,
                    batch_size=512,
                    validation_data=(x_val, y_val),
                    verbose=1)
# 테스트셋을 통한 모델 평가
results = model.evaluate(x_test,  y_test, verbose=2)

print(results)

0개의 댓글