elevne's Study Note
NLP 공부 (2: Embedding(Word2Vec)) 본문
이전 글에 썼던 것처럼, 자연어데이터를 컴퓨터에서 처리하기 위해서는 이를 숫자들로만 이루어진 데이터로 변환해주는 과정이 필요하다. 자연어데이터를 수치화할 때는 주로 벡터로 표현을 하게 되고 이를 Word Embedding이라고 표현한다.
Word Embedding의 한 방법으로 One-Hot-Encoding 방식이 있다. 데이터에 있는 총 단어의 종류가 벡터의 길이가 되고, 단어벡터는 해당 단어의 위치에만 1, 나머지는 전부 0을 갖는 벡터이다.
Keras에서 제공하는 to_categorical 함수를 통해서 다음과 같이 간단한 코드로 One-Hot-Encoding을 구현할 수 있다.
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.utils import to_categorical
text = "나는 오늘 자연어처리 공부를 하는 중이다"
tokenizer = Tokenizer()
tokenizer.fit_on_texts([text])
print("단어:", tokenizer.word_index)
encoded = tokenizer.texts_to_sequences([text])[0]
print("Encoded:", encoded)
one_hot = to_categorical(encoded)
print("One Hot:", one_hot)
One-Hot-Encoding은 데이터가 많아질수록 단어 벡터의 크기가 너무 커지고 희소(Sparse)해진다는 점과, 단어 벡터가 단어의 의미와 특성을 전혀 표현할 수 없다는 점이 문제점이다. 이를 해결하기 위해 다른 방안들이 제안되었다. 특정 문맥 안에서 단어들이 동시에 등장하는 횟수를 직접 세는 방법인 카운트기반 방법, 신경망 등을 통해 문맥 안의 단어들을 예측하는 방법인 예측방법이 있다.
1. 카운트기반
카운트기반 방법에서는 데이터를 통해 단어의 동시출현 행렬을 생성하고 이를 다시 단어벡터로 만드는 방법을 사용한다. 아래 표는 동시출현 행렬의 예시이다.
이러한 방식으로 만들어진 동시출현행렬을 토대로 SVD 등의 방법을 통해 단어벡터를 생성할 수 있다고 한다. 카운트기반의 방식은 적은 시간으로 단어벡터를 만들 수 있고 단어가 효율적으로 잘 표현되기에 데이터가 많을 경우에는 많이 사용되는 방식이라고 한다.
2. 예측기반
예측기반 방식은 신경망 등을 사용하여 특정 문맥에서 어떤 단어가 나올지를 예측하면서 단어를 벡터로 만드는 방식이다. 예측기반 방식 중 가장 많이 사용되는 방법은 Word2Vec 이라고 한다. Word2Vec은 또 그 안에서 CBOW(Continuous Bag of Words)와 Skip-Gram 두 가지 모델로 나뉘는데 이 둘은 서로 상반되는 개념이다.
CBOW: 단어를 문맥 안의 주변 단어들을 통해 예측하는 방법
1. 각 주변 단어를 원핫 벡터로 만들어 입력값으로 사용한다.
2. 가중치행렬을 각 원핫 벡터에 곱해서 n차원 벡터를 만든다.
3. 만들어진 n차원 벡터를 모두 더한 후 개수로 나누어 평균 n차원 벡터를 만든다.
4. n차원 벡터에 다시 가중치 행렬을 곱해서 원핫 벡터와 같은 차원의 벡터로 만든다.
5. 결과를 실제 예측하려는 단어의 원핫 벡터와 비교하며 학습한다.
Skip-Gram: 특정 단어를 통해 문맥 안의 주변 단어들을 예측하는 방법
1. 하나의 단어를 원핫 벡터로 만들어서 입력값으로 사용한다.
2. 가중치 행렬을 원핫 벡터에 곱해서 n차원 벡터를 만든다.
3. n차원 벡터에 다시 가중치 행렬을 곱해서 원핫 벡터와 같은 차원의 벡터로 만든다.
4. 만들어진 벡터를 실제 예측하려는 주변 단어들 각각의 원핫 벡터와 비교해서 학습한다.
이러한 방식으로 만들어진 단어벡터는 기존의 카운트 기반 방법으로 만든 단어벡터보다 단어 간의 유사도를 잘 측정하고 단어들의 복잡한 특징까지도 잘 잡아낸다는 장점이 있다.
두 방법 중 예측 기반 방법의 성능이 보통 더 뛰어나다고 한다. 또, 두 가지 방법을 모두 포함하는 Glove 단어 표현 방법 또한 자주 사용된다고 한다.
그렇다면 텍스트 간 유사도는 어떻게 측정되는 것일까. 우선 텍스트를 벡터화 한 뒤에 벡터화된 각 문장, 단어를 각종 방법을 통해 비교해볼 수 있다. 그 중 가장 널리 쓰이는 방법 중 하나인 코사인 유사도에 대해 알아보았다.
코사인유사도는 다른 방식들과 다르게 벡터 간의 각도를 구하는 것이라 벡터의 방향성 개념이 더해지기 때문에 성능이 좋은 면이 있다. 공식은 다음과 같다.
위 공식의 값이 1에 가깝게 나올수록 유사한 것이고, -1에 가까울 수록 반대의 것이 되는 것이다.
마지막으로 Word2Vec을 실제 코드로 구현해보고자 하였다.
from gensim.models import word2vec
data = ["나는 오늘 자연어처리 공부를 하는 중이다", ...]
model = word2vec.Word2Vec(data)
gensim 라이브러리에 있는 word2vec을 통해서 구현할 수 있다. 위 코드에서는 파라미터를 따로 넣지 않았지만, 아래의 파라미터들을 Word2Vec에 추가해줄 수 있다.
workers: 모델 학습 시 학습을 위한 프로세스 개수 지정
size: 각 단어에 임베딩된 벡터의 차원 지정
min_count: 모델에 의미 있는 단어를 가지고 학습하기 위해 적은 빈도 수의 단어들은 제외하고 학습하는 것을 지정
window: 수행을 위한 컨텍스트 윈도우 크기(컨텍스트 윈도우는 각 단어의 문맥을 판단하는 데 몇 개의 단어를 사용할 것인지를 나타낸다)
downsampling: 학습을 수행할 때 빠른 학습을 위해 정답 단어 라벨에 대한 단운샘플링 비율 지정(0.001이 좋다고 함) (Downsampling이란 신호처리에서 말하는 용어로 sample의 개수를 줄이는 처리과정을 의미한다. 딥러닝에서는 인코딩할때 data의 개수를 줄이는 처리과정이라고 볼 수 있다)
Word2Vec 모델도 model.save, Word2Vec.load() 함수를 통해 저장/불러오기를 간편하게 할 수 있다. 또, 아래의 함수들을 사용하여 다양한 값들을 확인할 수 있다.
model.wv["단어1"] #단어를 벡터로 변환
model.wv.similarity("단어1", "단어2") #두 단어의 코사인 유사도
model.wv.most_similar("단어1") #단어1과 가장 유사한 단어
model.wv.most_similar(positive=['단어1', '단어2'], negative=['단어3']) #단어1, 2와 유사하지만 단어3과 반대되는 의미의 단어
또, Gensim으로 학습한 단어임베딩을 Keras에서 사용하기 위해 필요한 코드를 아래에 정리해두었다.
#Gensim으로 학습한 단어임베딩 Keras에서 사용하기
from keras.models import Sequential
from keras.layers import Embedding
NUM_WORDS, EMB_DIM = model.wv.vectors.shape
emb = Embedding(input_dim=NUM_WORDS, output_dim=EMB_DIM,
trainable=False, weights=[model.wv.vectors])
kModel = Sequential()
kModel.add(emb)
i = model.wv.index2word.index('princess')
kModel.predict([i])
출처:
http://doc.mindscale.kr/km/unstructured/11.html
https://ko.wikipedia.org/wiki/%EC%BD%94%EC%82%AC%EC%9D%B8_%EC%9C%A0%EC%82%AC%EB%8F%84
'Machine Learning > NLP' 카테고리의 다른 글
NLP 공부 (5-1: Transformer) (0) | 2022.10.23 |
---|---|
NLP 공부 (4-2: Seq2Seq with Attention) (0) | 2022.10.22 |
NLP 공부 (4-1: Seq2Seq with Attention) (0) | 2022.10.21 |
NLP 공부 (3: 감성분석) (1) | 2022.10.18 |
NLP 공부 (1: Vectorizer, 형태소분석기, re) (0) | 2022.10.15 |