Seq2Seq with Attention

2021. 04. 15. — Attention Mechanism, Transformer

Joonghoon Choi
생각기록장
8 min readApr 15, 2021

--

이번 스프린트에서 자연어 처리에 대해서 한 주간 다루어 보고 있다. 모든 개념이 너무 생소하게 느껴지고, 이해가 잘 가지 않는 부분이 많지만.. 열심히!

해당 포스팅에서는 Attention 이란 무엇이고, 기본 알고리즘을 내가 이해한 선에서 정리해보려고 한다. 앞서 배웠던 자연어 처리의 기본 흐름과 벡터화, Word2Vec, RNN 등에 대해 미쳐 정리하지 못했다. 주말에 시간을 내어서 쭉 정리해봐야겠다.

공부한 내용을 정리하는 것이기 때문에 틀린 내용이 많을 수 있습니다. 잘못된 부분이 있다면 알려주시면 감사하겠습니다 :)

장기 의존성(long-term dependency) 이란?

기존의 Neural Network 모델이 시계열 패턴의 데이터를 잡아내지 못하는 단점을 극복하기 위해 RNN(Recurrent Neural Network) 모델이 등장했다. 얼마나 멀리 떨어져 있는가의 문제보다 시퀀스 즉 순서가 더 중요할 수 있기 때문이다.번역을 예시로 보면, 문장 내 단어의 고유한 의미도 중요하겠지만 순서가 뒤죽박죽이되면 말도 안되는 결과물을 뱉어내는 것이다.

https://towardsdatascience.com/growing-your-own-rnn-cell-simplified-b68ba2c0f082

이렇게 신경망에 재귀적 연결을 추가한 RNN 모델이 등장해서 시계열 패턴을 잡아낼 수 있게 되었다. RNN 모델은 현재 time step 은닉층의 노드에서 나온 출력값을 다음 time step에 입력값으로 넣어줌으로써 재귀적 연결을 한다. 모델이 현재의 입력값만을 보는 것이 아니라 이전의 입력값까지 함께 보는 것이다.

하지만 이런 RNN모델에는 장기 의존성 문제가 있다. 시계열 패턴(ex. 문장)이 길어질수록 학습과정의 미분값 즉 gradient 변화량이 너무 작아져서 효과적인 학습이 어려워 진다는 것이다. 이전에 쌓인 데이터의 정보가 소실되는 것이다; vanishing gradient

https://towardsdatascience.com/growing-your-own-rnn-cell-simplified-b68ba2c0f082

이런 vanishing gradient 문제를 해결하기 위해 활성함수 네트워크를 추가하고, 시간적 흐름에 따라 이전의 정보를 껐다 켰다(유지할 지, 버릴 지) 정할 수 있는 LSTM, GRU 모델도 등장했다.

하지만 결국 시계열 패턴에 따라 쌓인 Context Vector의 사이즈는 고정되어 있고, 문장이 길어질수록 모든 단어의 정보를 고정된 길이의 Hidden state 벡터에 담기 어렵다는 문제는 해결하지 못했다. 이러한 RNN 기반 모델이 가진 가장 큰 단점 중 하나인 장기의존성 문제를 해결하기 위해 Attention Mechanism이 등장한다.

Attention

말 그대로 Attention!! 어디에 주목할 지 보는 것이다.

인코더의 time step마다 생성되는 n개의 Hidden state 벡터를 모두 쌓아두고 간직한다. 모든 토큰이 입력된 후 생성된 H벡터 전부를 디코더에 넘겨주는 방식이다.

1. 모든 cell에 hidden state를 활용해서 계산하자!2. 더 이상 고정된 사이즈의 context vector가 아님(각 state별로 문맥벡터 생성)3. 디코더에서 결과값을 생성할 때, 모든 h벡터와 얼마나 관련있는지 가중치 계산
=> (인코더의 출력벡터) * (디코더의 입력벡터) = Attention Score
4. Fully connected network => Softmax =>5. Time step마다 타겟이 어떤 H벡터와 연관성을 띄는지 확인하는 것이기 때문에 어떤 단어에 집중할 지 확률적으로 구해낼 수 있음** Attention Mechanism의 가정은 인코더가 'love'를 입력받아서 출력 벡터로 만든 값은 디코더가 '사랑'을 예측할 때 쓰는 입력 벡터와 유사할 것이라는 것** Teacher Forcing: 예측값이 틀린걸 또 fc로 넣어주면 학습이 잘 안되니까 실제 라벨값을 디코더의 다음 인풋으로 넣어 줌

Transformer

“Attention is all you need!”

> CNN, RNN 등을 사용하지 않고 Attention만으로 모델을 구현
> RNN 기반 모델이 재귀적으로 연산하는 반면, 병렬화해서 한방에 처리
> 인코더/디코더의 컨셉은 유지

Trnsformer model architecture

Positional-Encoding

병렬화 연산을 하므로 모든 단어가 동시에 입력되어서 순서 정보가 사라지게 됨. 이를 해결하기위해 문장 내에서 각 단어의 임베딩 벡터에 위치 정보를 더해서 모델의 입력으로 사용

Self-Attention

Transformer의 주요 메카니즘. 문장 내부에서의 각 단어 간 관계를 파악하기 위해 문장 자신에 대해 Attention !

입력 벡터로 들어오는 단어벡터와 준비된 가중치 벡터를 내적해서 query, key, value 벡터를 만들어 냄 (준비된 가중치 벡터는 학습 과정에서 업데이트되는 파라미터)

q벡터 : 분석하고자 하는 단어에 대한 가중치 벡터
k벡터 : 들어온 단어벡터가 해당 쿼리와 얼마나 관련있는지 비교하기 위한 가중치 벡터
v벡터 : 각 단어벡터의 실제 의미를 살려주기 위한 가중치 벡터
1. q * k 내적 => attention score2. 계산보정 (q,k,v 벡터 차원의 제곱근으로 나눠줌)3. softmax => 전체 단어와 얼마나 연관이 있는지4. 쿼리에 해당하는 단어와 문장 내 다른 단어 간 관계 비율을 구함5. 마지막 계산값과 각 v벡터를 내적하면 최종 벡터 반환

Multi-Head Attention

우리가 사용하는 언어라는게 하나의 Attention 만으로 모호함을 해결하기 어렵다.

가중치 초기화를 여러개로 다르게 해줘서 self-attention을 동시에 여러개로 실행한다. 각 Attention마다 다르게 나오므로 앙상블과 유사한(?) 효과를 볼 수 있다. 머리가 여러개 있는데 각 헤드가 다른 곳에 집중할 수 있도록 해주는 것이다.

각 헤드의 출력행렬을 모두 concatenate 해주고, 파라미터 벡터 W와 내적으로 최종 행렬을 반환환다. 이 과정에서 나온 최종 행렬은 토큰(입력으로 들어온 행렬)과 같은 크기를 나타낸다.

Layer normalization & Skip connection

모든 sub-layer에서 나온 벡터값은 이과정을 거친다. Layer normalization은 MLP 모델에서 Batch Normalization과 유사한데 학습이 훨씬 잘되도록 한다. Skip connection은 역전파 과정에서의 정보 소실을 방지한다.

Feed Forward Neural Network

Multi-head attention를 했기 때문에 은닉층의 모든 벡터 차원을 원래대로 줄여줘야 한다. 단순 2층 신경망(ReLU 사용)

Masked Self-Attention

디코더 블럭에서 사용되는 Self-attention이다. Auto-Regressive한 학습방법을 사용하기 때문에 앞 단어부터 보고 뒤로 점점 가는데, 이 과정에서 타겟 뒤의 단어가 노출되어서 Self-Attention에 영향을 주지 않도록 마스킹 해주는 것이다.

Softmax를 취하기 전에 마스킹 할 단어에 -무한대를 더해줘서 0으로 만들어 줌

Encoder-Decoder Attention

번역할 문장과 번역되어서 나오는 문장의 정보 관계를 엮어주는 부분
디코더 블럭의 Masked-self-attention에서 출력된 벡터를 쿼리벡터로 사용
최상위 인코더 블럭에서 사용했던 값을 키, 벨류 벡터로 사용

Linear => Softmax => Label Smoothing => Output prop

예측할 단어의 확률을 구해줌
label smoothing은 BLEU score/accuracy 개선에 도움을 줌

나름 정리를 했는데도 정확히 이해가 가진 않는다. 하루만에 이 많은 개념을 다 이해하면 그게 이상한거지.

GPT, BERT 관련해서도 같이 정리하려 했는데 이것들 만으로도 너무 벅차서 다음으로…

--

--