[밑바닥부터 시작하는 딥러닝 2] - 3장 word2vec I
통계 기반 기법 : 학습 데이터를 한꺼번에 처리(배치 학습)하고, 단어의 빈도를 기초로 단어를 표현한다.
추론 기반 기법: 학습 데이터의 일부를 사용하여 순차적으로 학습(미니 배치 학습)
추론 기반 기법과 신경망
맥락 정보를 입력받아 단어의 출현 확률 기반으로 맥락에서 나올 단어를 추측한다. 신경망에서는 단어를 원핫벡터로 변환한다.
인덱스와 단어 ID와 같은 원소를 1로, 나머지는 모두 0으로 설정한다. 원핫벡터 변환 과정을 거치면 단어를 고정길이 벡터로 변환할 수 있다. 단어를 백터로 나타낼 수 있고, 신경망으로 처리할 수 있다.
입력층 뉴런과의 가중합(weighted sum)은 은닉층 뉴런이다.
코드로 구현하면 다음과 같다.
import numpy as np
c = np.array([[1,0,0,0,0,0,0]]) #입력 1*7
W= np.random.randn(7,3) #가중치 7*3
h= np.matmul(c,W) #1*3
print(h) #[[-1.52464989 -0.44265653 0.11759733]]
맨 앞 원소가 1이고 나머지가 0이므로 (1*7)(7*3) 행렬 곱에 의해 (1*3) 의 결과가 나오는데, 맨 앞 행벡터를 추출하는 것과 똑같은 결과다. 앞서 구현한 MatMul로도 코드를 구현할 수 있다.
import numpy as np # 해당 코드는 layer 파일에 존재
class MatMul:
def __init__(self, W):
self.params = [W]
self.grads = [np.zeros_like(W)]
self.x = None
def forward(self, x):
W, = self.params
out = np.dot(x, W)
self.x = x
return out
def backward(self, dout):
W, = self.params
dx = np.dot(dout, W.T)
dW = np.dot(self.x.T, dout)
self.grads[0][...] = dW
return dx
import numpy as np
import sys
from layers import MatMul
c = np.array([[1, 0, 0, 0, 0 ,0 ,0]])
W = np.random.randn(7, 3)
layer = MatMul(W)
h = layer.forward(c)
print(h)
MatMul 계층에 가중치 W를 설정하고 forward() 메서드를 호출해 순전파를 수행한다.
단순한 word2vec
CBOW
you ___ goodbye and I say hello
CBOW(Continuous bag-of-words) 모델은 맥락에서 target을 추측하는 용도의 신경망이다. you와 goodbye의 맥락 단어를 이용해서 가운데의 단어를 추측한다.
입력층 단어가 두개인 이유는 맥락으로 고려할 단어가 you, goodbye 두개 이기 때문이다.
입력층-> 은닉층: 가중치가 Win에 의한 완전연결계층에 의해 이뤄진다. 은닉층 변환시 두개의 평균을 산출(1/2(h1+h2))하여 은닉층 뉴런으로 옮긴다.
은닉층 -> 출력층: 가중치가 Wout에 의한 완전연결계층에 의해 이뤄진다. 출력층 뉴런은 각 단어의 점수를 의미하며 점수에 softmax 함수를 적용해서 확률을 얻는다.
은닉층의 뉴런수 < 입력층의 뉴런수 -> 단어 예측에 필요한 정보를 간결하게 담을 수 있고, 밀집 벡터 표현을 할 수 있다.
가중치 Win의 각 행이 해당 단어의 분산표현을 의미한다. word2vec에서는 입력 측의 가중치(Win)만 이용하는 것이 가장 대중적인 선택이다.
2개의 MatMul 계층 출력을 더함 *0.5 =-> 은닉층 뉴런
은닉층 뉴런 * Wout을 가중치로 하는 Matmul 계층 =-> 출력 스코어
코드로 구현하면 다음과 같다
import sys
import numpy as np
from layers import MatMul
c0 = np.array([1, 0, 0, 0, 0, 0, 0])
c1 = np.array([0, 0, 1, 0, 0, 0, 0])
#가중치 초기화
W_in = np.random.randn(7, 3)
W_out = np.random.randn(3, 7)
# 계층 생성
in_layer0 = MatMul(W_in) #입력층 matmul 계층
in_layer1 = MatMul(W_in)
out_layer = MatMul(W_out) #출력층
h0 = in_layer0.forward(c0)
h1 = in_layer1.forward(c1)
h = 0.5 * (h0 + h1)
s = out_layer.forward(h)
print(s)
#[-0.28418723 -0.86067759 -0.57553732 2.44443733 1.48224567 -2.35013005 0.86157551]
입력층 측의 Matmul 계층이 가중치 W_in을 공유한다는 점 주의.
CBOW 모델 학습
출력층에서 softmax 함수를 적용해서 확률을 도출한다.
노드 값의 크기를 흑백의 진하기로 나타낸다. CBOW 모델의 학습에서는 가중치를 조정하는 일을 하고, 그 결과 가중치 Win과 Wout 모두에 단어의 출현 패턴을 파악한 벡터가 학습된다.
softmax 함수를 이용해 점수를 확률로 변환-> 그 확률과 정답레이블로부터 cross entropy error를 구함 ->구한 loss로 학습 진행
softmax 계층 + cross entropy error 계층 -> softmax with loss 계층
Win : 입력측 완전연결계층의 가중치, 각 행이 각 단어의 분산 표현에 해당
Wout: 출력 측 완전연결계층의 가중치, 출력 가중치는 각 단어의 분산 표현이 열방향(수직 방향)으로 저장됨