공부/밑바닥부터 시작하는 딥러닝

[밑시딥2] Chapter 3. word2vec

셩잇님 2024. 7. 8. 20:14
반응형

 

 

 

 

본 포스팅은 '밑바닥부터 시작하는 딥러닝2'를 읽고 공부 및 학습 내용을 정리한 글입니다. 언제든지 다시 참고할 수 있도록, 지식 공유보단 개인적인 복습을 목적으로 포스팅하였습니다.

 

 

3.1 추론 기반 기법과 신경망

 단어를 벡터로 표현하는 방법은 크게 두 부류로 나눌 수 있다. 하나는 '통계 기반 기법' 이하 A와 나머지는 '추론 기반 기법' 이하 B라 한다. 이번 장에서는 이전 시간에 학습했던 A의 문제를 지적하고 그 대안으로서 사용하는 B의 이점을 알아보자.

 

3.1.1 통계 기반 기법의 문제점

 A의 문제점은 대규모 말뭉치를 다룰 때 발생한다. 기존까지는 적은 말뭉치를 통해 A를 처리했지만, 현업에서 쓰는 말뭉치는 100만이라는 수를 훌쩍 넘는다고 한다. 만약 어휘가 100만 개라면, A는 100만 * 100만이라는 거대한 행렬을 만들게 된다. 생각만해도 비효율적이라는 것을 알 수 있다.

 

 A는 말뭉치 전체의 통계를 통해 단어의 분산 표현을 얻지만, B는 미니배치를 통해 학습하는 것이 일반적이다. 아래 사진은 A와 B의 기법을 비교한 것이다.

 

 

 기법을 비교해 보았을 때 B는 여러 장점을 가진다. 예를들어 말뭉치의 어휘수가 많아진다고 하더라도 데이터를 작게 나눠서 학습하기 때문에 부담이 적고, 아울러 여러 GPU를 통한 병렬계산도 가능하여 학습 속도를 높일 수 있다는 장점이 존재한다.

 

3.1.2 추론 기반 기법 개요

 B에서 말하는 '추론'이란 주변 단어(맥락)이 주어졌을 때 '?'에 무슨 단어가 들어가는지를 추측하는 작업이다.

 

 

 위 그림처럼 B에는 모델이 등장하는데, 우리는 이 모델을 바탕으로 맥락 정보를 입력받아 출현할 수 있는 단어의 출현 확률을 출력한다. 이 학습의 결과로 단어의 분산 표현을 얻는 것이 B의 전체적 맥락이다.

 

3.1.3 신경망에서의 단어 처리

 신경망은 단어를 있는 그대로 처리할 수 없어 '고정 길이의 벡터'로 변환하는데 이 때 사용하는 방법이 원핫 표현 (=원핫 벡터)로 변환하는 것이다. 원핫 벡터란 벡터의 원소 중 하나만 1이고 나머지는 모두 0인 벡터를 뜻한다.

 

 

 단어를 원핫 벡터로 변환하는 방법은 다음과 같다.

1. 어휘 수 만큼의 원소를 갖는 벡터를 생성한다

2. 인덱스가 단어 ID와 같은 원소를 1로, 나머지는 0으로 설정한다.

 

 위와 같이 단어를 벡터로 변환하면 신경망의 입력층은 아래 이미지와 같이 뉴런의 수를 고정할 수 있다.

 

 

 따라서 단어는 벡터로, 신경망을 구성하는 계층들은 이러한 벡터를 처리할 수 있다. 즉 단어를 신경망으로 처리할 수 있게 되는 것이다.

 

 


 

3.2 단순한 word2vec

 이제 B를 배우고 신경망으로 단어를 처리하는 방법을 배웠으니 '모델'을 신경망으로 구축하는 방법에 대해서 알아보자. 이번 시간에는 CBOW 모델을 알아볼 것이다.

 

3.2.1 CBOW 모델의 추론 처리

 CBOW 모델은 맥락으로부터 '타깃'을 추측하는 용도의 신경망이다. 이 때 '타깃'은 중앙 단어이며, 그 주변단어들을 맥락이라고 한다. CBOW 모델에서 입력은 이 '맥락'이다. 맥락을 윈핫 벡터로 변환하여 CBOW 모델이 처리할 수 있도록 설정한다.

 

 

 입력층이 2개가 있으며 이는 은닉층을 거쳐 출력층에 도달하는데 두 입력층에서 은닉층으로 변환은 같은 완전연결계층이 처리하고, 은닉층에서 출력층 뉴런으로의 변환은 다른 완전 연결계층이 처리한다.

 

 그림을 보면 은닉층의 뉴런은 입력층에 의해 변환 되는데 이 때 입력충이 여러개일 경우 전체를 '평균'처리하면 된다. 출력층은 총 7개의 뉴런인데 이 뉴런 하나하나가 단어의 대응하는 것이며 출력층의 뉴런은 각 단어의 '점수' (=확률)을 나타낸다.

 

 

 계층 관점에서 CBOW의 모델은 2개의 입력층 MatMul 계층이 있고 이어서 두 계층의 출력이 더해진다. 더해진 값에 0.5를 곱하면 평균이 되며 이 평균이 은닉층 뉴런이 된다.

 

3.2.2 CBOW 모델의 학습

 CBOW 모델을 알아보며 출력층에서 각 단어의 점수를 출력했고, 이 점수에 소프트맥스 함수를 적용하면 확률을 얻을 수 있다고 했다. 이 확률은 맥락(전후 단어)이 주어졌을 때 그 중앙(=타깃)에 어떤 단어가 출현하는지를 나타낸다.

 

 

 CBOW 모델의 학습에서는 가중치를 조정하여 올바른 예측을 할 수 있도록 일을 한다. 그 결과로 가중치 Win에 단어의 출현 패턴을 파악한 벡터가 학습된다.

 

 

3.2.3 word2vec의 가중치와 분산 표현

 word2vec는 2가지 가중치가 있다. 입력측과 출력측이다. 입력 측 가중치 Win의 각 행은 단어의 분산 표현을 나타내고, 출력 측 Wout에는 단어의 의미가 인코딩된 벡터가 저장되어 있다. 다만, 출력 측 가중치는 단어 분산 표현이 수직 방향으로 저장된다.

 

 


 

3.3 학습 데이터 준비

3.3.1 맥락과 타깃

 word2vec에서 이용하는 신경망의 입력은 '맥락'이다. 정답 레이블은 맥락에 둘러 싸인 중앙의 단어, 즉 '타깃'이다. 다시 말해 우리가 할 일은 '맥락'을 입력했을 경우 '타깃'이 출현할 확률을 높이는 것이다.

 

3.3.2 원핫 표현으로 변환

 

 위 그림과 같이 맥락과 타깃을 단어 ID에서 원핫 벡터로 변환하면 된다.


 

3.4 CBOW 모델 구현

 

3.4.1 학습 코드 구현

# chap03/train.py
import sys
sys.path.append('..')
from common.trainer import Trainer
from common.optimizer import Adam
from simple_cbow import SimpleCBOW
from common.util import preprocess, create_contexts_target, convert_one_hot


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)
# cbow 학습 데이터셋 생성
contexts, target = create_contexts_target(corpus, window_size)
# Input에 맞는 one-hot 표현 변환
target = convert_one_hot(target, vocab_size)
contexts = convert_one_hot(contexts, vocab_size)

# 모델 초기화
model = SimpleCBOW(vocab_size, hidden_size)
optimizer = Adam()
trainer = Trainer(model, optimizer)

word_vecs1 = model.word_vecs1
for word_id, word in id_to_word.items():
    print(word, word_vecs1[word_id])

>> you [-1.3807591 -1.0351917 -1.1238494 -1.0471877  1.0710732]
say [-0.24706812  1.125094    1.1692127   1.155186   -1.1067501 ]
goodbye [-0.56422764 -0.8567286  -0.70119053 -0.8194563   0.9058622 ]
and [-1.9357495   0.7339323   0.7825899   0.7863268  -0.90669537]
i [-0.5696927  -0.82052916 -0.6930974  -0.81896836  0.91717815]
hello [-1.3897839 -1.0456055 -1.1249272 -1.0641869  1.0661185]
. [ 1.6761091  1.2073398  1.221956   1.2177749 -1.0616693]

 


 

3.5 word2vec 보충

3.5.1 CBOW 모델과 확률

... (생략)

 

3.5.2 skip-gram 모델

 word2vec는 2개의 모델을 제안하고 있다. 하나는 CBOW 모델이고 다른 하나는 skip-gram 모델이다. CBOW 모델은 여태까지 알아보았으므로 설명은 생략한다. 그러나 skip-gram 모델은 CBOW 모델에서 다루는 맥락과 타깃을 역전시킨 모델이다. 사진으로 본다면 단번에 이해가 될 것이다.

 

 

 그림과 같이 CBOW 모델은 여러 맥락을 통해 중앙의 단어(='타깃')를 추측한다. skip-gram 모델은 중앙의 단어(='타깃') 로부터 주변의 여러 단어를 추측한다.

 

3.5.3 통계기반 vs 추론기반

 

A는 말뭉치의 전체 통계로부터 1회 학습하여 단어의 분산 표현을 얻는다. B는 말뭉치를 일부분씩 여러 번 보면서 학습한다. (미니배치)

 

 또한 어휘에 추가할 새 단어가 생겨서 갱신해야 하는 상황에서는 A는 계산을 처음부터 다시 해야 하는 한다. 단어의 분산 표현을 조금만 수정하고 싶어도 동시발생 행렬을 다시 만들고 SVD를 수행하는 일련의 작업을 다시 해야 한다. 그에 반해 B는 매개변수를 다시 학습할 수 있다. 물론 학습한 가중치를 초깃값으로 사용해 다시 학습하면 되지만 이런 특성 덕분에 기존에 학습한 경험을 해치지 않으면서 단어의 분산 표현을 효율적으로 갱신할 수 있다.

 A는 주로 단어의 유사성이 인코딩이 되는 반면, B는(특히 skip-gram)에서는 단어의 유사엉은 물론 한층 복잡한 단어 사이의 패턴까지도 파악되어 인코딩된다. 이런 이유로 B가 A보다 정확하다고 흔히들 오해한다. 하지만 실제로 단어의 유사성을 정량 평가하면 의외로 B와 A의 우열을 가릴 수 없다고 한다.

 하지만, word2vec 이후 A+B를 융합한 GloVe 기법이 등장했으며, GloVe의 기본 아이디어는 말뭉치 전체의 통계 정보를 손실 함수에 도입해 미니배치 학습을 하는 것이다.

 


 

3.6 결론

  • 추론 기반 기법은 '추측' 하는 것이 목적이며, 그 부산물로 단어의 분산 표현을 얻을 수 있다.
  • word2vec은 추론 기반 기법이며, 단순한 2층 신경망이다.
  • word2vec은 skip-gram 모델과 CBOW 모델을 제공한다
  • CBOW 모델은 여러 단어(맥락)로부터 하나의 단어(타깃)을 추측한다.
  • 반대로 skip-gram 모델은 하나의 단어(타깃)으로부터 다수의 단어(맥락)을 추측한다.
  • word2vec는 가중치를 다시 학습할 수 있으므로, 단어의 분산 표현 '갱신'이나 새로운 단어 '추가'를 할 때 효율적으로 수행할 수 있다.

 


 

3.7 소감

 지난 주 통계 기반 기법을 곰곰히 읽다보니 말뭉치 크기에 따라서 처리해야 하는 크기의 값이 n×n이여서, 나중에 큰 말뭉치가 나오면 어떻게 해야하지? 라고 생각하자마자 word2vec 학습 첫 장에서 통계 기반 기법의 문제점으로 거대해진 행렬의 크기에 대해서 문제점으로 삼는점이 나와서 내심 놀랐다.

 

 그렇다면 '이럴 때에는 어떻게 처리해야 하는가?' 고민했는데 책에서 너무 자세하게 이런 나를 위해 '이렇게 처리하면 되겠지~?..'하고 알려주는 것 같아서 시간 가는줄 모르고 또 재미있게 읽었다. 이런 해결방법은 어떻게 생각하고 처리했을까? 가만보면 세상에는 똑똑한 사람이 정말 너무 많은 것 같다.

 

 

반응형