Transformer가 나오기 전까지 Sequential data는 RNN, LSTM, GRU와 같은 모델들을 이용해 처리했으나, transformer의 등장으로 sequential data를 처리할 때 대부분 transformer를 사용하게 되었으며, tranformer를 이용해 BERT, ViT와 같은 유명한 모델들이 탄생할 수 있었다. 오늘은 그 transformer에 대해 간략하게 알아보고자 한다.
Sequential data를 처리하기 힘들게 하는 요인은 길이가 정해져 있지 않다는 것도 있지만, 데이터의 순서가 바뀌었을때 같은 내용을 가질수도 있고 다른 내용을 가질 수도 있는 등, sequence의 변화에 따라 고려할 점이 많기 때문이다. Transformer는 이런 여러 어려움을 수반하는 sequential data를 attention이라는 개념을 이용해 처리한다.
Transformer의 기본 구조에 대해 먼저 알아보자면, transformer는 같은 구조를 가지지만 parameter는 다른 encoder여러겹과, encoder의 마지막 층과 연결되는, 마찬가지로 같은 구조를 가지지만 parameter는 다른 decoder 여러겹으로 구성되어 있다. 초기에 고안된 transformer는 번역 문제등을 해결하기 위해 고안된 모델로, 예를 들어 "I am a student"를 입력받았을 때 "나는 학생이다" 출력하는 모델이다.
RNN의 경우, input sequence의 길이만큼 재귀적으로 실행되지만, transformer는 input의 길이에 상관없이 encoder가 정보를 한번에 처리한다.
Transformer에서 먼저 encoder의 구조를 알아보자
1. Encoder
Encoder는 self-attention - feed forward neural network의 구조를 가진다.
예를 들어 I love you 라는 문장을 받으면, 각 단어에 대한 embedding vector를 생성한다.
self-attention은 이 각 단어들의 embedding을 feature 벡터로 변환해준다. 이때 이 과정은 각각의 벡터들이 independent하게 계산하는 것이 아닌, 같이 입력된 다른 벡터들에 영향을 받아 계산해준다.
그 과정을 자세히 보면, attention은 위처럼 각 단어에 대해 query, key, value 벡터를 생성한다.
attention은 이렇게 얻어진 벡터들 중 query 벡터와 key벡터를 내적하여(벡터곱이 아님) score라는 값을 생성한다. 이때, qeury와 key를 내적해야 하기 때문에 두 벡터는 처음에 attention을 생성할 때 항상 같은 차원으로 생성해야 한다. 또한, score 값을 구할때, 계산에 사용하는 qeury 벡터는 해당 단어의 query만 사용하지만, key벡터는 모든 단어의 key 벡터를 사용하여 각각의 내적값을 구한다. 이를 통해 transformer는 해당 단어와 다른 단어와의 연관성을 score라는 값을 이용해 나타낼 수 있다.
그리고, 구해진 내적값을 key 벡터의 제곱근으로 나눠주고, softmax 계산을 하여 최종적인 값을 얻게 되고, 이 값을 attention이라고 한다.
그리고 attention 값을 value벡터에 스칼라곱으로 곱해준 값들의 합이 최종적인 각 단어의 feature 벡터가 되는 것이다.
위의 과정을 하나의 식으로 나타내면 다음과 같이 나타난다.
이런 과정을 거치는 transformer는 attention의 계산 특성상, 같은 단어를 입력값으로 넣더라도 같이 입력된 단어들의 값에 따라 다른 feature가 출력되는 것을 볼 수 있다. 또한, 결국 모든 query 벡터와와 key 벡터를 곱해야 하기 때문에 주어진 input의 길이의 제곱만큼 연산을 수행해야한다. 따라서 input의 길이가 길어지면 연산에 오랜 시간이 걸리는 특성이 있다.
Multihead attention (MHA)
MHA는 query, key, value 벡터를 여러개 만들어서 계산하는 것으로, n개의 attention을 계산하여 여러개의 feature vector를 구할 수 있다. MHA는 이 결과값을 모두 반영하기 위해 feature vector를 전부 연결하고 행렬을 곱해 input과 같은 dimension으로 축소한다.
Positional Encoding
위에서 feature vector를 얻는 과정을 한번 돌아보자. 계산 결과에 입력값의 순서가 영향을 주는가? 놀랍게도 아무 영향이 없다!
하지만 sequential data는 순서가 영향을 주기 때문에 input의 순서 정보인 bias를 더해줘야 한다. 단, positional encoding은 predefined 된 방법으로 연산하므로 크게 설명할 부분이 없다.
하나의 Encoder가 이런 과정들을 거치며, 이 과정을 여러개의 encoder를 거치며 반복한다.
Decoder
위의 그림의 오른쪽이 하나의 decoder단위를 보여준다.
각 decoder는 가장 상위단계에 있는 encoder에게 key와 value를 전달받고, 이 벡터들을 이용해 하나씩 단어를 생성한다.
처음의 디코더는 encoder에 입력값으로 들어갔던 x1, x2, ... 의 벡터들과, decoder에서 출력할 문장의 <sos(start of sentence)> 값이 포함된 행렬을 입력받는다.
이 때, 입력받는 행렬은 뒷부분이 masking되어 있는데, 이는 decoder가 encoder처럼 parallel하게 한번에 모든 입력을 처리하는 것과 달리, 한번에 하나의 출력만 만들어내는 autoregressive한 알고리즘이기 때문이다. 즉, 반복적으로 decoder층을 행렬이 통과하면서 한번에 한 단어씩 출력을 생성하기 때문에 행렬의 뒷부분에 영향을 받지 않기 위해 뒷값을 없는 것으로 취급하기 위해 masking을 해주는 것이다.
참고로, 행렬의 뒷값이 의미가 있어서 maksing을 해주는 것이 아닌, 실제로 의미가 없는 값이어도, 행렬로 연산을 하기 시작하면 그 값이 영향을 주기 때문에 masking을 해주는 것이다.
이렇게 입력값이 decoder의 self-attention layer를 지나고 연산을 거치게 되면, 바로 위의 encoder - decoder attention layer가 그 값을 전달받는다. 이 encoder - decoder attention layer는 key와 vector를 encoder에서 제공받는 점을 제외하면 MHA와 동일하게 동작한다.
행렬을 연산한 값이 final decoder에 도달하면 transformer는 decoder stack을 하나씩 결과로 출력하기 시작하며, 문장을 전부 출력하면 <EoS(End of Sentence> 토큰을 출력하고 종료된다.
Transformer는 원래는 문장 번역을 위해 제작된 모델이었으나, 지금은 이미지 처리같은 문제에도 사용된다.
그 결과를 한번 체험해보고 싶은 사람은 사이트를 방문해보자
https://openai.com/product/dall-e-2
DALL·E 2
DALL·E 2 is an AI system that can create realistic images and art from a description in natural language.
openai.com
'AI 중급이론' 카테고리의 다른 글
Multi-Modal 학습이란 무엇일까? (0) | 2023.04.11 |
---|---|
CNN의 학습과정을 시각화하는 방법 (0) | 2023.04.07 |
댓글