• Home
  • About
    • Yerim Oh photo

      Yerim Oh

      Happy and worthwhile day by day :)

    • Learn More
    • Email
    • LinkedIn
    • Instagram
    • Github
    • Youtube
  • Posts
    • All Posts
    • All Tags
  • Projects

[14] Deep learning 2: 추론기반 기법 word2vec (CBOW,skip-gram 모델)

26 Feb 2020

Reading time ~13 minutes

Table of Contents
  • 목차
  • 자연어처리의 의미
  • 추론기반 기법 word2vec
    • 준비: 원핫 one-hot 표현
  • CBOW 모델
    • CBOW 모델 사용
    • 학습 데이터 준비
    • CBOW 모델 구현
    • CBOW 모델과 확률
  • skip-gram 모델
    • skip-gram 모델을 확률로
  • 통계 기반 vs 추론 기반

목차

  • 자연어처리의 의미
  • 추론기반 기법 word2vec
    • 준비: 원핫 one-hot 표현
  • CBOW 모델
    • CBOW 모델 사용
    • 학습 데이터 준비
    • CBOW 모델 구현
    • CBOW 모델과 확률
  • skip-gram 모델
    • skip-gram 모델을 확률로
  • 통계 기반 vs. 추론 기반

👀, 🤷‍♀️ , 📜
이 아이콘들을 누르시면 코드, 개념 부가 설명을 보실 수 있습니다:)



자연어처리의 의미

Natural Language Processing (NLP)
자연어: 한국어와 영어 등 우리가 평소에 쓰는 말
자연어 처리: 컴퓨터가 우리 말을 알아듣게(이해하게)만드는 것 으로 ‘단어의 의미’를 이해시키는 게 중요

단어의 의미를 잘 파악하는 법

  • 1) 시소러스를 활용한 기법
  • 2) 통계 기반 기법
  • 3) 추론 기반 기법(word2vec)

지난 포스트에서 1) 과 2)를 봤으니 이번엔 3)을 보겠다!



추론기반 기법 word2vec

신경망(word2vec)을 이용하여 추론을 하는 기법

⛔ 통계 기반 기법의 문제점

  • 주변 단어의 빈도를 기초로 단어 표현 ➡ 대규모 말뭉치를 다룰 때 문제가 발생.
  • 말뭉치 전체의 통계(동시발생 행렬과 PPMI 등)를 이용해 단 1회의 처리 (SVD 등)만에 단어의 분산 표현을 얻음( 추론기반에선 배치학습이라는 전체가 아닌 국소적 단위를 이용함)
  • 이런 거대 행렬에 SVD를 적용하는 일은 현실적이지 않다.

⭕ 추론 기반 기법
추론 기반 기법: 주변 단어 (맥락)가 주어졌을 때 “?”에 무슨 단어가 들어가는지를 추측하는 작업
image 신경망을 이용하는 경우는 미니배치로 학습하는 것이 일반적 -> 신경망이 한번에 소량(미니배치)의 학습 샘플씩 반복해서 학습하며 가중치를 갱신.
➡ 말뭉치의 어휘 수가 많아 SVD 등 계산량이 큰 작업을 처리하기 어려운 경우에도 신경망을 학습 가능
image

➕ 추론기반, 통계기반 공통점
분포 가설에 기초: 단어의 의미는 주변 단어에 의해 형성된다에 기반 ➡ 단어의 동시발생 가능성


준비: 원핫 one-hot 표현

= 원핫 벡터
신경망에서의 단어 처리
신경망은 “you”와 “say” 등의 단어를 있는 그대로 처리할 수 없으니 단어를 ‘고정 길이의 벡터’로 변환 필요
➡ 단어를 one-hot 표현으로 변환.

원핫 표현: 벡터 원소 중 하나만 1이고 나머지는 모두 0인 벡터
[ex] “You say goodbye and I say hello.”
image

[만드는 법]
1) 총 어휘 수만큼의 원소를 갖는 벡터를 준비
2) 인덱스가 단어 ID와 같은 원소를 1로, 나머지는 모두 0으로
3) 이처럼 단어를 고정 길이 벡터로 변환하면 우리 신경망의 입력
층은 밑처럼 뉴런의 수를 ‘고정’가능
image

[장점]

  • 단어를 벡터로 나타내기 가능
  • 신경망을 구성하는 ‘계층’들은 벡터 처리 가능.
  • 단어를 신경망으로 처리 가능

[신경망 처리]
image 원핫 표현으로 된 단어 하나를 완전연결계층을 통해 변환

  • 완전연결계층: 각각의 노드가 이웃 층의 모든 노드와 화살표로 연결
    • 이 화살표에는 가중치(매개변수)가 존재: 입력층 뉴런과의 가중합 weighted sum 이 은닉층 뉴런
    • 편향을 생략(뒤에 설명)

가중치를 명확하게 보여주기 위해 이를 단순화 해서 그리면, image

👀 코드 보기
import numpy as np
c = np.array([[1, 0, 0, 0, 0, 0, 0]]) # 입력/원핫표현
W = np.random.randn(7, 3) # 가중치
h = np.matmul(c, W) # 중간 노드
print(h)
# [[-0.70012195 0.25204755 -0.79774592]]

WARNING_ 이 코드에서 입력 데이터(c )의 차원 수(ndim)는 2입니다. 이는 미니배치 처리를 고려한 것으로, 최초의 차원(0번째 차원)에 각 데이터를 저장.

위의 그림의 행렬의 곱을 MatMul 계층으로 구현한다.

계산된 가중치에 해당 입력층에 맞는 인덱스에 해당하는 가중치를 뽑아낸다.
image 다시 설명하면 앞의 코드에서 c와 W의 행렬 곱 부분에 주목해보자.
➡️ c는 원핫 표현이므로 단어 ID에 대응하는 원소만 1이고 그 외에는 0인 벡터이다.
➡️ 따라서 앞 코드의 c와 W의 행렬 곱은 결국 위의 그림처럼 가중치의 행벡터 하나를 ‘뽑아낸’ 것과 같다.

🚫 문제점
그런데 위의 가중치 추출에서 가중치로부터 행벡터를 뽑아낼 뿐인데 행렬 곱을 계산하는 건 비효율적이다.
word2vec 개선 ① 절에서 개선할 예정이다.

또한, 앞의 코드로 수행한 작업은 (1장에서 구현한) MatMul 계층으로도 수행할 수 있다.

👀 코드, 코드 설명 보기
import sys
sys.path.append('..')
import numpy as np from common.layers import MatMul ## 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)
# [[-0.70012195 0.25204755 -0.79774592]]
  • common 디렉터리에 있는 MatMul 계층을 임포트해 사용.
  • MatMul 계층에 가중치 W를 설정하고
  • forward ( ) 메서드를 호출해 순전파를 수행합니다.


CBOW 모델

앞의 원핫벡터를 이용한 가중치 신경망을 구현해봤으니 단순한 word2vec 구현을 위한 준비는 끝났다.
이제 word2vec을 구현해보자.
word2vec의 대표적인 모델로는 크게 2가지인 CBOW 모델과 skip-gram모델이 있다.
그럼 그 중 하나인 CBOW 모델부터 구현해보자.
즉, 앞에서 설명한 밑의 그림을 구현해보자는 것이다.
image


CBOW 모델 사용

  • ‘모델’을 신경망으로 구축이 목표
  • word2vec에서 제안하는 CBOW continuous bag-of-words 신경망 사용
    (CBOW 모델과 skip-gram 모델은 word2vec에서 사용되는 신경망)

[이 모델의 추론 처리]
CBOW 모델은 맥락으로부터 타깃 target을 추측하는 용도

  • ‘타깃’: 중앙 단어
  • ‘맥락’: 그 주변 단어들

[처리 overview]
입력을 원핫 표현으로 변환하여 시작한다
CBOW 모델의 입력: 맥락(그 주변 단어들)
원핫표현으로 변환함으로써, CBOW 모델이 처리할 수 있도록 준비
image

  • 입력층이 2개 있고, 은닉층을 거쳐 출력층에 도달.
  • 두 입력층에서 은닉층으로의 변환은 똑같은 완전연결계층(가중치는 W_in )이 처리
  • 은닉층에서 출력층 뉴런으로의 변환은 다른 완전연결계층(가중치는 W out )이 처리
🤷‍♀️ 이 그림에서 입력층이 2개인 이유

맥락으로 고려할 단어를 2개로 정했기 때문.(you, goodbye)
즉, 맥락에 포함시킬 단어가 N개라면 입력층도 N개.
image

[은닉층]
은닉층의 뉴런은 입력층의 완전연결계층에 의해 변환된 값이 되는데,
입력층이 여러 개이면 전체를 ‘평균’하면 됨.

[출력층]
출력층의 뉴런은 총 7개인데, 이 뉴런 하나하나가 각각의 단어에 대응.
즉 결과로 나올 수 있는 값의 개수를 말함

  • 출력층 뉴런은 각 단어의 ‘점수’를 뜻함
    • 점수: 확률로 해석되기 전의 값
    • 점수에 소프트맥스 함수를 적용해서 ‘확률’획득 가능
  • 값이 높을수록 대응 단어의 출현 확률도 높아짐

입력층에서 은닉층으로의 변환은 완전연결계층(가중치는 \(W_{in}\) )에 의해서 이뤄짐
이때 완전연결계층의 가중치 \(W_{in}\) 은 7×3 행렬이며, 이 가중치가 바로 단어의 분산 표현의 정체. image

  • 가중치 \(W_{in}\) 의 각 행 = 해당 단어의 분산 표현
  • 학습을 진행할수록 맥락에서 출현하는 단어를 잘 추측하는 방향으로 이 분산 표현들이 갱신
    • 찾고자 하는 값인 “say”가 제일 까맣죠?

[핵심] 은닉층의 뉴런 수 < 입력층의 뉴런 수
은닉층: 단어 예측에 필요한 정보를 ‘간결하게’ 담음
➡ 결과적으로 밀집벡터 표현을 얻기 가능.

인코딩: 은닉층의 정보는 인간은 이해할 수 없는 코드로 쓰임.
디코딩: 은닉 층의 정보로부터 원하는 결과를 얻는 작업
➡ 인코딩 된 정보를 이해 가능한 표현으로 복원하는 작업
더 알아보기: 대충 이런 느낌이구나 라는 것만 가져가자

지금까지 우리는 CBOW 모델을 ‘뉴런 관점’에서 그림
‘계층 관점’에서 그림(밑) image

주의) 편향을 사용하지 않는 완전연결계층의 처리는 MatMul 계층의 순전파와 같음
계층은 내부에서 행렬 곱을 계산.

👀 CBOW 모델의 추론 처리 구현 코드 보기

추론 처리란 ‘점수’를 구하는 처리임

import sys
sys.path.append('..')
import numpy as np from common.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)

# 계층 생성
# 처리하는 MatMul 계층을 맥락 수만큼 (여기에서는 2개) 생성
# 출력층 측의 MatMul 계층은 1개만 생성합니다
in_layer0 = MatMul(W _in) 
in_layer1 = MatMul(W _in) 
out_layer = MatMul(W _out)

# 순전파
# 입력층 측의 MatMul 계층들(in_layer0과 in_layer1 )의 forward ( )메서드를 호출해 중간 데이터를 계산하고, 
# 출력층 측의 MatMul 계층(out_layer)을 통과시켜 각 단어의 점수 구함
h0 = in_layer0.forward(c0) 
h1 = in_layer1.forward(c1) 
h = 0.5 * (h0 + h1) 
s = out_layer.forward(h)

print(s)
# [[ 0.30916255 0.45060817 -0.77308656 0.22054131 0.15037278
# -0.93659277 -0.59612048]]

-> CBOW 모델은 활성화 함수를 사용 하지 않는 간단한 신경망

[결과]
확률은 맥락(전후 단어) 이 주어졌었을 때 그 중앙에 어떤 단어가 출현하는지를 나타냄
위의 예에서 맥락은 “you”와 “goodbye”이고,
정답 레이블(신경망이 예측해야 할단어)은 “say”.
이때 ‘가중치가 적절히 설정된’ 신경망이라면 ‘확률’을 나타내는 뉴런들 중 정답에 해당하는 뉴런의 값이 클 것이라 기대
image (노드의 값이 클수록 진하게 나타냄)

  • CBOW 모델의 학습에서는 올바른 예측을 할 수 있도록 가중치를 조정하는 일을 함
  • 그 결과로 가중치 W_{in} 에(정확하게는 \(W_{in}\) 과 \(W_{out}\) 모두에) 단어의 출현 패턴을 파악한 벡터가 학습

➕ 말뭉치가 다르면 학습 후 얻게 되는 단어의 분산 표현도 달라짐
예컨대 말뭉치로 ‘스포츠’ 기사만을 사용하는 경우와 ‘음악’ 관련 기사만을 사용하는 경우는 얻게 되는 단어의 분산 표현이 크게 다름.

[학습 과정]
1) 소프트맥스 함수를 이용해 점수를 확률로 변환
2) 그 확률과 정답 레이블로부터 교차 엔트로피 오차를 구함
3) 값을 손실로 사용해 학습을 진행.

image

여기선, Softmax 계층과 Cross Entropy Error 계층을 사용,
But, 우리는 이 두 계층을 Softmax with Loss라는 하나의 계층으로 구현.
➡ Softmax 계층과 Cross Entropy Error 계층을 Softmax with Loss 계층으로 합침

image

[word2vec의 가중치와 분산 표현]
word2vec에서 사용되는 신경망에는 두 가지 가중치 존재

  • 입력 측 완전연결계층의 가중치(\(W_{in}\) )
    • 입력 측 가중치 \(W_{in}\) 의 각 행: 각 단어의 분산 표
  • 출력 측 완전연결계층의 가중치(\(W_{out}\) )
    • 출력 측 가중치 \(W_{out}\) = 단어 의미가 인코딩된 벡터가 저장
    • 다만, 출력측가중치는 분산표현이 열 방향(수직방향)으로 저장

image

최종적으로 이용하는 단어의 분산 표현으로 선택할 가중치는?
선택지는 세 가지
1) 입력 측의 가중치만 이용한다.
2) 출력 측의 가중치만 이용한다.
3) 양쪽 가중치를 모두 이용한다.

A와 B 안은 어느 한쪽 가중치만 이용한다는 것.
마지막 C 안에서는 두 가중치를 어떻게 조합하느냐에 따라 다시 몇 가지 방법을 생각 가능
➡ 그 중 하나는 두 가중치를 단순히 합치는 것.

word2vec (특히 skip-gram 모델)
1) 안인 ‘입력 측의 가중치만 이용한다’가 가장 대중적인 선택.


학습 데이터 준비

word2vec 학습에 쓰일 학습 데이터를 준비.
말뭉치로부터 맥락과 타깃을 만드는 함수를 구현

[맥락과 타깃]

  • 맥락: 신경망의 입력
  • 타깃: 정답 레이블은 맥락에 둘러 싸인 중앙의 단어

목표: 신경망에 ‘맥락’을 입력했을때 ‘타깃’이 출현할 확률을 높이는 것(그렇게 되도록 학습시킬 겁니다).

[EX] 말뭉치에서 맥락과 타깃을 만드는 예
image

  • 각 샘플 데이터에서 맥락의 수는 여러 개(이 예에서는 2개)가 될 수 있으나, 타깃은 오직 하나 뿐.
  • 그래서 맥락을 영어로 쓸 때는 끝에 ‘s’를 붙여 복수형임을 명시하는 게 좋음

1️⃣ 말뭉치 텍스트를 단어 ID로 변환
preprocess( ) 함수를 사용: 말뭉치 전처리 함수

👀 코드 보기
import sys
sys.path.append('..') 
from common.util import preprocess

text = 'You say goodbye and I say hello.'
corpus, word_to_id, id_to_word = preprocess(text)
print(corpus)
# [0 1 2 3 4 1 5 6]

print(id_to_word) 
# {0:'you', 1:'say', 2:'goodbye', 3:'and', 4:'i', 5: 'hello', 6: '.'}

2️⃣ 단어 ID의 배열인 corpus로부터 맥락과 타깃을 만들어 냄.
맥락은 2차원 배열

  • 맥락의 N번째 차원: 각 N 번째 맥락 데이터가 저장
    • contexts[0]에는 0번째 맥락이 저장
    • contexts[1]에는 1번째 맥락이 저장
  • 타깃의 N번째 차원: 각 N 번째 타깃 데이터가 저장
    • target[0]에는 0번째 타깃이 저장
    • target[1]에는 1번째 타깃이 저장

image (윈도우 크기는 1)

👀 코드 보기
create_contexts_target (corpus, window_size)

# 인수를 두 개 받음.
# 하나는 단어 ID의 배열(corpus), 다른 하나는 맥락의 윈도우 크기(window_size)
def create_contexts_target(corpus, window_size=1):
  target = corpus[window _size:-window_size] 
  contexts = []

  for idx in range(window_size, len(corpus)-window_size):
  cs = [] 
  for t in range(-window_size, window_size + 1):
    if t == 0:
      continue
    cs.append(corpus[idx + t]) 
  contexts.append(cs)

  # 맥락과 타깃을 각각 넘파이 다차원 배열로 돌려줌
  return np.array(contexts), np.array(target)

  # 실제로 사용
  contexts, target = create_contexts_target(corpus, window_size=1)

print(contexts)
# [[0 2] 
#  [1 3] 
#  [2 4] 
#  [3 1] 
#  [4 5] 
#  [1 6]]

print(target)
# [1 2 3 4 1 5]

image 이 그림과 같은 결과가 나왔다

3️⃣ 이를 원핫 표현으로 변환
image 다차원 배열의 형상에 주목: 이 그림에서는 단어 ID를 이용했을 때의 맥락의 형상은 (6, 2)
이를 원핫 표현으로 변환하면 (6, 2, 7 )
(데이터 개수, 맥락개수, 전체 문장길이)

  • convert_one_hot ( ) 함수를 사용: common/utill.py에 구현

CBOW 모델 구현

전체 신경망 SimpleCBOW라는 이름으로 구현
image

👀 코드 보기
import sys
sys.path.append('..')
import numpy as np 
from common.layers import MatMul, SoftmaxWithLoss

# 이 초기화 메서드는 인수로 
# 어휘 수(vocab _size )와 
은닉층의 뉴런 수(hidden _size )받음
class SimpleCBOW:
 def __init__(self, vocab_size, hidden_size):
  V, H = vocab_size, hidden_size

  # 가중치 초기화 두 가중치는 각각 작은 무작위 값으로 초기화
  # 이때 넘파이 배열의 데이터 타입을 astype ('f ') 즉, 32비트 부동소수점 수로 초기화
  W_in = 0.01 * np.random.randn(V, H).astype('f')
  W_out = 0.01 * np.random.randn(H, V).astype('f')

  # 계층 생성
  # 입력 측의 MatMul 계층을 2개,
  ## 입력 측의 맥락 처리계층은 맥락에서 사용하는 단어의 수(윈도우 크기)만큼 만들어야 함
  ## 입력 측 MatMul 계층들은 모두 같은 가중치를 이용하도록 초기화
  # 출력 측의 MatMul 계층을 하나, 
  # Softmax with Loss 계층을 하나 생성
  self.in_layer0 = MatMul(W_in) 
  self.in_layer1 = MatMul(W_in) 
  self.out_layer = MatMul(W_out) 
  self.loss_layer = SoftmaxWithLoss()

  # 모든 가중치와 기울기를 리스트에 모은다
  # 이 신경망에서 사용되는 매개변수와 기울기를 인스턴스 변수 params와 grads 리스트에 각각 모아둠
  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

 # 신경망의 순전파인 forward ( ) 메서드를 구현
 # 인수로 맥락 (contexts)과 타깃(target)을 받아 손실(loss)을 반환
 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

➕ 인수 contexts는 3차원 넘파이 배열이라고 가정.
image 위 예에서라면,

배열의 형상은 (6, 2, 7 )

  • 0번째 차원의 원소 수: 미니배치의 수
  • 1번째 차원의 원소 수: 맥락의 윈도우 크기
  • 2번째 차원: 원핫 벡터의 길이

target의 형상은 2차원, (6, 7)

# 마지막으로 역전파인 backward ( )를 구현 
def backward(self, dout=1):
 ds = self.loss_layer.backward(dout) 
 da = self.out_layer.backward(ds) 
 da *= 0.5
 self.in_layer1.backward(da)
 self.in_layer0.backward(da) 
 return None

image

이미 각 매개변수의 기울기를 인스턴스 변수 grads에 모아둠
따라서 forward ( ) 메서드를 호출한 다음 backward ( ) 메서드를 실행하는 것만으로 grads 리스트의 기울기가 갱신

[학습 코드 구현]
1) 학습 데이터를 준비해 신경망에 입력
2) 기울기를 구하고
3) 가중치 매개변수를 순서대로 갱신해 감

👀 코드 보기
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) 
contexts, target = create_contexts_target(corpus, window_size) 
target = convert_one_hot(target, vocab_size) 
contexts = convert _one _hot(contexts, vocab _size)

model = SimpleCBOW(vocab_size, hidden_size) 
optimizer = Adam() 
 
# 신경망을 학습 학습 데이터로부터 미니배치를 선택한 다음, 
# 신경망에 입력해 기울기를 구하고, 
# 그 기울기를 Optimizer 에 넘겨 매개변수를 갱신하는 일련의 작업을 수행
trainer = Trainer(model, optimizer)

trainer.fit(contexts, target, max_epoch, batch_size) 
trainer.plot()

[결과] image ➡ 학습을 거듭할수록 손실이 줄어듦

[학습이 끝난 후의 가중치 매개변수] 앞의 코드 바로 뒤에 다음 코드를 추가합니다.

👀 코드 보기
word_vecs = model.word_vecs 
for word_id, word in id_to_word.items():
 print(word, word_vecs[word _id])

[결과] image 단어를 밀집벡터로 나타냄


CBOW 모델과 확률

CBOW 모델을 ‘확률’ 관점에서 다시 살펴보겠다.
‘확률’의 표기법

  • \(P(A)\): A라는 현상이 일어날 확률
  • 동시 확률 \(P(A,B)\): ‘A와 B가 동시에 일어날 확률’
  • 사후 확률 $$P(A B)$$ : ‘사건이 일어난 후 의 확률 ’ ,‘B 가 주어졌을 때 A가 일어날 확률’

CBOW 모델을 확률 표기법으로 기술:
맥락을 주면 타깃 단어가 출현할 확률을 출력
image

[EX] 맥락 \(w_{t-1}\) 과 \(w_{t+1}\) 이 주어질 때, 타깃이 \(w_t\) 가 될 확률?
\(P(w_t | w_{t−1} ,w_{t+1})\)

  • ‘\(w_{t-1}\) 과 \(w_{t+1}\) 이 일어난 후 \(w_t\)가 일어날 확률’
  • ‘\(w_{t-1}\) 과 \(w_{t+1}\) 이 주어졌을 때 \(w_t\)가 일어날 확률’

CBOW 모델의 손실 함수도 간결하게 표현: 교차 엔트로피 오차 image

  • \(y_k\):‘k번째에 해당하는 사건이 일어날 확률’
  • \(t_k\) : 정답 레이블(원핫 벡터로 표현)
  • 여기서 문제의 정답: ‘\(w_t\) 가 발생’
    • \(w_t\) 해당 원소만 1, 나머지는 0
    • 즉, \(w_t\) 이외의 일이 일어날 경우에 대해서는 해당 원핫 레이블의 요소는 0

[적용]
음의 로그 가능도(negative log likelihood)
image -> CBOW 모델의 손실 함수는 단순히 확률에 log를 취한 다음 마이너스를 붙이면 됨

[말뭉치 전체로 확장] image CBOW 모델의 학습이 수행하는 일:

  • 이 손실 함수의 값을 가능한 한 작게 만드는 것.
  • 이때의 가중치 매개변수:우리가 얻고자 하는 단어의 분산 표현.


skip-gram 모델

word2vec은 2개의 모델 제안_ CBOW 모델, skip-gram 모델

  • skip-gram은 CBOW에서 다루는 맥락과 타깃을 역전시킨 모델

image CBOW 모델: 맥락이 여러 개 존재, 이로부터 타깃 추측.
skip-gram 모델: 타깃으로부터 주변의 여러 단어 (맥락)를 추측

[skip-gram 모델의 구성]
image

  • skip-gram 모델의 입력층: 하나
  • 출력층(답이 될 수 있는 것): 맥락의 수만큼 존재

1) 각 출력층에서는 (Softmax with Loss 계층 등을 이용해) 개별적으로 손실을 구함
2) 이 개별 손실들을 모두 더한 값이 최종 손실.


skip-gram 모델을 확률로

1️⃣ 먼저 확률 식을 보자
image

2️⃣ 여기서 맥락의 단어들 사이에 관련성이 없다고 가정 후 분해 (‘조건부 독립’이라고 가정). image 3️⃣ 손실함수 유도 image skip-gram 모델의 손실 함수는 맥락별 손실을 구한 다음 모두 더함.

[말뭉치 전체로 확장]
image

  • 단어 분산 표현의 정밀도 면에서 skip-gram 모델의 결과가 더 좋은 경우가 많아 앞의 모델보다 이걸 쓰는 것을 추천(특히 말뭉치가 커질수록 저빈도 단어나 유추 문제의 성능 면에서 skip-gram 모델이 더 뛰어남)
  • 속도는 CBOW가 더 빠름

통계 기반 vs 추론 기반

학습하는 틀

  • 통계 기반 기법: 말뭉치의 전체 통계로부터 1회 학습하여 단어의 분산 표현을 얻음
  • 추론 기반 기법: 말뭉치를 일부분씩 여러 번 보며 학습(미니배치 학습).

단어의 분산 표현을 갱신해야 하는 상황(새 어휘 추가)

  • 통계 기반 기법: 계산을 처음부터 다시 단어의 분산 표현을 조금만 수정하고 싶어도, 동시발생 행렬을 다시 만들고 SVD를 수행하는 일련의 작업을 다시 해야 함.
  • 추론 기반 기법: 기존에 학습한 경험을 해치지 않으면서 단어의 분산 표현을 효율적으로 갱신 가능.

단어의 분산 표현의 성격이나 정밀도

  • 통계 기반 기법: 분산표현이 주로 단어의 유사성이 인코딩됨.
  • 추론 기반 기법: 분산표현이 복잡한 단어 사이의 패턴까지도 파악되어 인코딩.

단어의 유사성을 정량 평가해본 결과,
의외로 추론 기반과 통계 기반 기법의 우열을 가릴 수 없음

  • 두 방법은 (특정 조건 하에서) ‘서로 연결되어 있다’


Deep Learning Share Tweet +1