0. Transformer의 등장
기존 seq2seq에서는 명백한 문제가 존재했다. Encoder과정에서 이전의 시계열 데이터에 대한 state vector h가 준비되어야 하는데, 이는 병렬연산이 불가능한 직렬연산이라는 문제였다. 이전 상태 값이 준비되어야 현재 상태를 연산할 수 있다는 구조적 문제를 극복해야할 필요성이 존재했다.
1. Transformer의 기본 개념
이과정에서 등장한 것이 self-attention을 활용한 Transformer이다. 간단하게 이야기하자면 기존에는 Encoder에서 추출한 state들과 Decoder에서 추론한 state vector을 dot product과 softmax를 하여 시계열 데이터 내 각 데이터에 대한 가중치를 뽑는 방법이였다. 그런데 이것을 다른 문제로 치환하자는 것이다. 이 논문에서는 이 과정을 <Query, Key, Value>로 나타낸다. 쉽게 매칭하자면 Query는 Decoder에서 Encoder가 추출한 state와 비교하던 state vector와 유사하고, Key는 가중치를 얻기 위해 Decoder의 Query와 내적하던 Encoder의 hs의 역할과 유사하고, Value는 실제 Encoder에서 추출한 hs 그자체와 유사하다.
그렇다면 이 <Query, Key, Value>를 어떻게 뽑을까? 단어 Embedding에서 이 정보를 뽑는 Weight들과 단어 Embedding을 행렬곱해서 얻는다. 여기서 우리의 최종 목표는 단어에서 이 정보를 뽑는 Weight를 적절하게 학습하는 것이다.
그리고 Encoder에서 모든 단어 Embedding에 대해 행렬곱으로 Q,K,V를 추출하고, 모든 Embedding에 Attention연산을 진행하여 시계열 데이터의 문맥을 학습한다. 여기서 두가지를 눈여겨 볼 수 있다. 바로 Embedding들에서 Q,K,V를 뽑을 때 이전 Embedding의 출력을 기다릴 필요 없이 병렬 연산인 행렬곱으로 한번에 된다는 것과 모든 Embedding간(N X N)의 맥락을 뽑는다는 점이다.
이러한 이론을 네트워크를 보며 알아보자
2. Transformer의 구조
여기서 Multi-Head attention은 그냥 attention을 여러개 병렬로 붙여놓은 구조라고 생각하면 된다. 논문에서는 output 채널의 크기를 512로 가정하고 설명하였다. 그리고 각 attention은 512/h 크기의 채널의 ouptut을 생성하고, 그렇게 생성된 h개의 512/h크기의 output을 concat하고 Feed Forward(FC)돌림으로서 출력을 얻을 수 있게된다. 여기서 Masked Multi-Head attention이 있는데, 이는 아직 예측하지 않은 데이터들이 결과에 영향을 주지 않도록 아직 추론하지 않은 다른 부분을 마스킹하고 추론한 embedding끼리 먼저 attention하는 것을 의미한다. 이때는 Encoder에서 추출한 정보를 사용하지 않고, 추론간의 attention연산임을 그래프에서 확인할 수 있다.
그 외에 구조에 대해서 눈 여겨 볼 만한 부분은 Position encoding이랑 Residual connection정도인 것 같다. 추론 과정에 position정보가 유용하다 + 하지만 추론 과정에서 position와 그 외의 모든 데이터는 희미해진다. 때문에 residual connection으로 position encoding 정보를 유지시키는것이다. 여기서 position은 일정 각의 cos와 sin으로 얻는데, 각이 겹치지 않게 할 뿐만 아니라 position간의 linear관계를 유지시킨다고 한다. (그렇게 함으로서 좋다는데, 진짜 좋은지는 더 생각해봐야할 문제인 것 같다.)
3. Transformer의 특징
그래서 왜 Transformer냐? 왜 이게 트랜딩하냐? 물론 성능이 좋으니까. 근데 왜 성능이 좋냐? 하면 병렬성으로 인한 1) 병렬연산을 통한 학습 속도 향상 과 2)학습 효율의 증가를 통한 성능 증가 때문이다. 기존 RNN기반은 시계열 데이터가 길어지면 길어질수록, 레이어의 깊이가 깊어지면 깊어질 수록 Gradient vanishing으로 인해 학습효율이 좋아지지 않고 성능이 나빠진다.
병렬로 연산이 빨라진다는것은 매우 쉽게 이해가 된다
병렬로, 모든 embedding을 representation demension만큼 곱한다. 그리고, 일반적으로 dimension이 n보다 작으므로 연산효율은 수치적으로 좋은것이 쉽게 이해가 된다.
하지만 학습 효율이 좋으니 파라미터가 많더라도 학습이 잘 된다. 그리고 그것이 높은 성능의 이유이다? 또한 모든 Embedding과 다른 모든 Embedding간의 Attention연산을 하니까 더 학습이 효율이 높을지도? 어쨋든 왜 좋은지에 대한 것은 명확하게 와닫지 않는다. 실험적인 결과인건가?