2022. 1. 7. 00:41ㆍNLP
저번 포스트에서는 논문 Efficient Estimation Of Word Representations In Vector Space를 소개하고 Word2Vec의 아키테쳐에 대해 설명했습니다. 이번에는 Word2Vec 중 CBOW 모델을 구현해보겠습니다.
Word2Vec은 단어출현 패턴을 학습해 단어의 분산표현을 도출합니다. 다중 클래스 분류이기 때문에 소프트맥스와 교차 엔트로피 오차만 사용하면 됩니다. 소프트맥스 함수를 이용해 점수를 확률로 변환하고, 그 확률과 정답레이블로부터 교차엔트로피 오차로 구한 손실을 사용해 학습합니다.
CBOW는 Word2Vec에서 제시한 두개의 모델 중 하나입니다. CBOW는 주변단어로부터 중심단어를 예측합니다. 주변단어의 개수만큼 input layers가 있고 hidden layer를 거쳐 하나의 output layer로 출력됩니다. hidden layer의 뉴런은 input의 평균으로 구합니다.
1. CBOW 클래스
class SimpleCBOW:
def __init__(self, vocab_size, hidden_size):
V, H = vocab_size, hidden_size
# 가중치 초기화
W_in = 0.01 * np.random.randn(V, H).astype('f')
W_out = 0.01 * np.random.randn(H, V).astype('f')
# 계층 생성
# window 크기 만큼 입력층 만들어야함(여기에서는 2개)
self.in_layer0 = MatMul(W_in) # 입력층
self.in_layer1 = MatMul(W_in) # 입력층
self.out_layer = MatMul(W_out) # 출력층
self.loss_layer = SoftmaxWithLoss() # Softmax 계층
# 모든 가중치와 기울기를 리스트에 모은다.
layers = [self.in_layer0, self.in_layer1, self.out_layer]
self.params, self.grads = [], []
for layer in layers:
self.params += layer.params
self.grads += layer.grads
# 인스턴스 변수에 단어의 분산 표현을 저장한다.
self.word_vecs = W_in
- SimpleCBOW 클래스의 인수
vocab_size : 어휘 수
hidden_size : hidden layer의 뉴런 수
- W_in , W_out 두개의 가중치
각각 작은 무작위 값으로 초기화 됩니다.
- 계층 생성
입력층의 Matmul 계층 주변단어 수(=윈도우 크기) 만큼 (여기서는 2개)
출력층의 Matmul 계층 1개
Softmax with Loss 계층 1개 ( softmax와 cross entropy error를 softmax with loss로 합침 )
2. 순전파
def forward(self, contexts, target):
h0 = self.in_layer0.forward(contexts[:, 0])
h1 = self.in_layer1.forward(contexts[:, 1])
h = (h0 + h1) * 0.5
score = self.out_layer.forward(h)
loss = self.loss_layer.forward(score, target)
return loss
3. 역전파
def backward(self, dout=1):
dl1 = self.loss_layer1.backward(dout)
dl2 = self.loss_layer2.backward(dout)
ds = dl1 + dl2
dh = self.out_layer.backward(ds)
self.in_layer.backward(dh)
return None
4. 학습
window_size = 1
hidden_size = 5 # 은닉층의 뉴런수
batch_size = 3
max_epoch = 1000
text = 'You say goodbye and I say hello.' # 학습데이터
corpus, word_to_id, id_to_word = preprocess(text)
vocab_size = len(word_to_id) # 어휘수
contexts, target = create_contexts_target(corpus, window_size) # 주변단어와 중심단어 생성
target = convert_one_hot(target, vocab_size) # one-hot encoding
contexts = convert_one_hot(contexts, vocab_size)
model_1 = SimpleCBOW(vocab_size, hidden_size)
optimizer = Adam() # 매개변수 갱신 알고리즘
trainer_1 = Trainer(model_1, optimizer)
trainer_1.fit(contexts, target, max_epoch, batch_size)
다음 포스팅에서는 이어서 Skip-gram 모델을 구현해보겠습니다!
reference
Word2Vec ⌜Efficient Estimation Of Word Representations In Vector Space⌟
밑바닥부터 시작하는 딥러닝2 (사이토 고키)
https://github.com/WegraLee/deep-learning-from-scratch-2/tree/master/ch03
https://www.kaggle.com/ashukr/implementation-of-word2vec-paper/data
'NLP' 카테고리의 다른 글
Fasttext 논문 리뷰 : Enriching Word Vectors with Subword Information (0) | 2022.01.22 |
---|---|
GloVe 논문 리뷰 : Global Vectors forWord Representation (0) | 2022.01.16 |
Skip-gram 코드 구현 : Word2Vec의 Skip-gram 모델 구현 (0) | 2022.01.10 |
Word2Vec 논문 리뷰 : Efficient Estimation Of Word Representations In Vector Space (0) | 2022.01.03 |
토픽모델링: LDA(Latent Dirichlet Allocation) (0) | 2021.08.18 |