각 단어의 확률을 계산하는 모델
전체 말뭉치 중에서 시작하는 단어의 횟수 토대로 확률을 구합니다. 다음에 어떤 문장이 왔는지도 계산하여(조건부) 확률을 구한 뒤 서로 곱하면 문장이 등장할 확률을 구할 수 있습니다.
말뭉치에 없는 단어가 있다면 예측이 불가능하다는 한계점이 있습니다.
말뭉치에 등장하지 않더라도 의미적, 문법적으로 유사한 단어를 선택할 수 있습니다.
횟수 기반이 아닌 Word2Vec, fasttext등의 임베딩 벡터를 사용하기에 가능합니다.
연속형 데이터(어떤 순서로 오느냐에 따라 단위의 의미가 달라지는 데이터) 를 잘 처리하기 위해 고안된 신경망
3번 화살표는 기존 신경망에서는 없었던 과정입니다.
이 화살표는 특정 시점에서의 은닉 벡터가 다음 시점의 입력 벡터로 다시 들어가는 과정을 나타내고 있습니다.
출력 벡터가 다시 입력되는 특성 때문에 '순환(Recurrent) 신경망' 이라는 이름이 붙었습니다.
𝑡−1 시점에서는 𝑥𝑡−1 와 ℎ𝑡−2 가 입력되고 𝑜𝑡−1 이 출력됩니다.
𝑡 시점에서는 𝑥𝑡 와 ℎ𝑡−1 가 입력되고 𝑜𝑡 이 출력됩니다.
𝑡+1 시점에서는 𝑥𝑡+1 와 ℎ𝑡 가 입력되고 𝑜𝑡+1 이 출력됩니다.
t 시점의 RNN 계층은 그 계층으로의 입력 벡터 와 1개 전의 RNN 계층의 출력 벡터 를 받아들입니다.
입력된 두 벡터를 바탕으로 해당 시점에서의 출력을 아래와 같이 계산합니다.
가중치는 2개가 있습니다.
각각 입력 x를 h로 변환하기 위한 와 RNN의 은닉층의 출력을 다음 h로 변환해주는 입니다.
b는 각 편향(bias)을 단순화하여 나타낸 항입니다.
이런 단점을 극복하기 위해 고안된 것이 장단기 기억망(Long-Short Term Memory,LSTM) 입니다.
RNN에 기울기 정보 크기를 조절하기 위한 Gate 를 추가한 모델입니다.
현재는 RNN이라 하면 LSTM이나 GRU를 지칭할 정도로 대표적인 모델이 되었습니다.
기존에 설명한 RNN은 Vanilla RNN으로 따로 구분하여 표현합니다.
LSTM은 기울기 소실 문제를 해결하기 위해 3가지 게이트(gate)를 추가하였습니다. 각 게이트는 다음과 같은 역할을 합니다.
hidden-state 말고도 활성화 함수를 직접 거치지 않는 상태인 cell-state 가 추가되었습니다.
cell-state는 역전파 과정에서 활성화 함수를 거치지 않아 정보 손실이 없기 때문에
뒷쪽 시퀀스의 정보에 비중을 결정할 수 있으면서 동시에 앞쪽 시퀀스의 정보를 완전히 잃지 않을 수 있습니다.
LSTM은 실제로 굉장히 많은 곳에 사용됩니다.
여러 언어 모델에서 LSTM을 사용하고 있습니다.
Gate가 적용되지 않은 RNN, 즉 Vanilla RNN은 10~20 단어로 이루어진 문장에 대한 분류/생성/번역 등의 성능이 매우 낮습니다.
Vanilla RNN이 가지고 있는 기울기 소실/폭발 문제 때문입니다.
언어 모델 뿐만 아니라 신경망을 활용한 시계열 알고리즘에는 대부분 LSTM을 사용하고 있습니다.
LSTM에서 있었던 cell-state가 사라졌습니다.
cell-state 벡터 와 hidden-state 벡터 가 하나의 벡터 로 통일되었습니다.
하나의 Gate 가 forget, input gate를 모두 제어합니다.
가 1이면 forget 게이트가 열리고, input 게이트가 닫히게 되는 것과 같은 효과를 나타냅니다.
반대로 가 0이면 input 게이트만 열리는 것과 같은 효과를 나타냅니다.
GRU 셀에서는 output 게이트가 없어졌습니다.
대신에 전체 상태 벡터 가 각 time-step에서 출력되며, 이전 상태의 의 어느 부분이 출력될 지 새롭게 제어하는 Gate인 가 추가되었습니다.
RNN이 가진 가장 큰 단점 중 하나는 기울기 소실로부터 나타나는 장기 의존성(Long-term dependency) 문제입니다.
장기 의존성 문제란 문장이 길어질 경우 앞 단어의 정보를 잃어버리게 되는 현상입니다.
장기 의존성 문제를 해결하기 위해 나온 것이 셀 구조를 개선한 LSTM과 GRU입니다.
기계 번역에서 RNN 기반의 모델(LSTM, GRU)이 단어를 처리하는 방법은 아래와 같다고 할 수 있습니다.
위 구조의 문제는 고정 길이의 hidden-state 벡터에 모든 단어의 의미를 담아야 한다는 점입니다.
아무리 LSTM, GRU가 장기 의존성 문제를 개선하였더라도 문장이 매우 길어지면(30-50 단어) 모든 단어 정보를 고정 길이의 hidden-state 벡터에 담기 어렵습니다.
이런 문제를 해결하기 위해서 고안된 방법이 바로 Attention(어텐션) 입니다.
Attention은 각 인코더의 Time-step 마다 생성되는 hidden-state 벡터를 간직합니다.
입력 단어가 N개라면 N개의 hidden-state 벡터를 모두 간직하게 됩니다.
모든 단어가 입력되면 생성된 hidden-state 벡터를 모두 디코더에 넘겨줍니다.
디코더는 받은 N개의 hidden-state 벡터를 어떻게 활용할까요?
잠시 돌아가 검색 시스템에 대해 알아봅시다.
아래는 구글에서 "what is attention in nlp" 라는 검색어를 구글에 입력했을 때의 검색 결과를 나타낸 이미지입니다.
그림에서 볼 수 있듯이 검색 시스템은 아래와 같은 3단계를 거쳐 작동합니다.
디코더에서 단어를 생성하는 과정을 알아보겠습니다.
디코더의 각 time-step 마다의 hidden-state 벡터는 쿼리(query)로 작용합니다.
인코더에서 넘어온 N개의 hidden-state 벡터를 키(key)로 여기고 이들과의 연관성을 계산합니다.
이 때 계산은 내적(dot-product)을 사용하고 내적의 결과를 Attention 가중치로 사용합니다.
아래는 디코더 첫 단어 "I"(Time-step 4
)에 대한 어텐션 가중치가 구해지는 과정입니다.
1. 쿼리(Query)인 디코더의 hidden-state 벡터, 키(Key)인 인코더에서 넘어온 hidden-state 벡터를 준비합니다.
2. 각각의 벡터를 내적한 값을 구합니다.
3. 이 값에 소프트맥스(softmax) 함수를 취해줍니다.
4. 소프트맥스를 취하여 나온 값에 밸류(Value)에 해당하는 인코더에서 넘어온 hidden-state 벡터를 곱해줍니다.
5. 이 벡터를 모두 더해줍니다. 이 벡터의 성분 중에는 쿼리-키 연관성이 높은 밸류 벡터의 성분이 더 많이 들어있게 됩니다.
6. (그림에는 나와있지 않지만) 최종적으로 5에서 생성된 벡터와 디코더의 hidden-state 벡터를 사용하여 출력 단어를 결정하게 됩니다.
디코더는 인코더에서 넘어온 모든 Hidden state 벡터에 대해 위와 같은 계산을 실시합니다.
그렇기 때문에 Time-step마다 출력할 단어가 어떤 인코더의 어떤 단어 정보와 연관되어 있는지, 즉 어떤 단어에 집중(Attention)할 지를 알 수 있습니다.
Attention을 활용하면 디코더가 인코더에 입력되는 모든 단어의 정보를 활용할 수 있기 때문에 장기 의존성 문제를 해결할 수 있습니다.
아래는 예시로 제시되었던 문장을 번역(Je suis etudiant => I am a student
)했을 때 각 단어마다의 Attention 스코어를 시각화 한 그림입니다.
"I" -> "Je"
"am" -> "suis"
"a" -> "suis", "etudiant"
"student" -> "etudiant"
왼쪽 단어가 생성될 때 오른쪽 단어와 연관되어 있음을 확인할 수 있습니다.