\(d_{model}\) : embedding dimension이며, 논문에서는 512 사용
Pytorch에서는 embedding layer를 다음과 같이 만들어 줄 수 있습니다.
Embedding Layer는 위의 그림에서 나왔듯이, Input Embedding, Output Embedding 두군데에서 사용 되기 때문에
각각 따로 Embedding을 사용하는 것보다는 모듈을 하나 만들어서 동시에 사용하는게 효율적인 접근입니다.
예를 들어서 60000단어 그리고 embedding dimension을 512로 사용시 다음과 같습니다.
2.3 Positional Encoding
Transformer는 RNN의 recurrence 사용하지 않기 때문에, sequence상에서의 단어의 위치를 알려줄 필요가 있습니다.
Positional Encoding은 Encoder 그리고 Decoder에 들어가는 embeddings 이후에 사용이 되며,
embeddings와 동일한 \(d_{model}\) (embedding dimension) 을 사용하기 때문에
단순히 embedding 과 positional embedding을 더하기를 해서 사용하면 됩니다.
Positional Encoding은 constant matrix 라고 생각하면 쉽습니다.
\[\mathbf{pe} \in \mathbb{R}^{\text{max_sequence } x \ d_{model}}\]
\(i\) : Embedding의 \(d_{model}\) (embedding dimension)과 동일하며, 해당 위치를 말합니다.
아래는 positional encoding matrix 를 만드는 방법과, 그래프로 그려서 대략적인 intuition을 알 수 있습니다.
핵심은 특정 wavelength를 만들어낸다는 것이고, monotonic 하게 증가하는 position값이 아니라,
sin, cos을 사용해서 상대적인 값으로 만들어냈다는 것입니다.
2.3.1 논문과 가장 흡사하게 구현한 positional matrix
2.3.2 Github에 구현한 코드 (pytorch 문서 참고)
pe의 shape은 (1, 400, 512) 로서, 400은 maximum sequence length 이고 512는 embedding dimension과 동일한 크기.
아래의 코드는 Pytorch Tutorial 에서 참고했습니다.
2.4 Masking
Masking은 Transformer에서 중요한 역활을 합니다.
Padding Mask: input sentence안에 padding이 있을경우 masking은 attention outputs을 zero out 시킵니다.
Look Ahead Mask: Decoder가 다음 단어를 예측할때, 그 다음 단어 및 뒤에 나오는 문장을 미리 peaking ahead하지 않도록 막습니다. (A.K.A No Peaking Mask)
2.4.1 Padding Mask 핵심 내용
source sentence에 적용합니다.
예를 들어, (256, 33) 형태의 tensor가 존재합니다.
(256은 batch_size, 33은 maximum setence length 로서 33보다 작은 문장은 padding index=1로 채워집니다. )
mask는 padding index는 False로 만들고, 글자 부분은 True로 동일하게 만들고,
이후 no peaking mask와 동일한 형태를 가져가지 위해서 차원을 하나 더 더해줍니다. (256, 1, 33) 형태로~
예를 들어서 아래와 같습니다.
2.4.2 No Peaking Mask (Look Ahead Mask 핵심)
Target의 경우 학습시 그 다음 단어를 보지 못하도록 만들어야 합니다.
(256, 33) shape을 -> (256, 33, 33) 형태로 만들며,
33개의 다음 단어를 마스킹한 형태로 나오게 됩니다.
이후 & operation으로 둘을 합치며, 문장마다 단어가 차례대로 가려진 tensor를 만듭니다.
2.5 Residual Dropout
논문의 내용을 간추리면 다음의 순서를 갖습니다.
(최대한 정확하게 해석해서 간추렸는데 좀 틀린부분이 있으면 알려주세요)
Sentence Tensor
Embeddings
Positional encodings
Dropout(0.1)
Iterate Sublayers
Normalization
Do sublayer (such as MultiHead, PositionalFeedForward)
Dropout(0.1)
Skip Connection
2.6 Multi-Headed Attention
지금까지, Embedding Layer 를 거쳐서 단어를 one-hot encoding으로 만들었고, positional encoding을 거쳤습니다.
여기부터 Transformer의 핵심이 되는 attention을 시작할수 있습니다.
Transformer는 \(d_{model}\) (embedding dimension)에 대해서 single attention function을 사용하는 대신에,
\(d_{model}\) dimension (embedding dimension)을 갖은 keys, values, queries 를 사용합니다.
V: \(d_{model}\) dimensional Values
K: \(d_{model}\) dimensional Keys
Q: \(d_{model}\) dimensional Queries
\(d_{model}\) : embedding dimension 이며, 논문에서는 512 사용
2.6.1 Q, K, and V
Encoder에서 Q, K, V 가 뭐 특별한 것이 아니고, positional encoding까지 거친 embedding vector를 복사 붙여넣기 한 것입니다.
(즉 3개를 복사 붙여넣기 한 것이기 때문에 모두 동일한 것)
해당 embedding vector의 dimension은 batch_size * sequence_lenth * d_model (256, 33, 512) 갖고 있습니다.
Decoder에서의 Q, K, V를 단순히 복사 붙여넣기 한것이 아닙니다.
위의 그림처럼 target input 으로 해당되는 Q, K, V는 처음 Multi Head Attention을 들어가기 전에,
encoder와 마찬가지로 Q, K, V모두 복사 붙여넣기로 동일한 값이 들어가게 됩니다.
두번재 Multi-Head Attention을 들어가기전에 Endoer의 output과 함께 사용됩니다.
Q: 첫번째 multi-head attention의 output (즉 target input) 을 사용
K and V: encoder input을 사용
결국 Multi Head Attention의 핵심은 Q 와 K를 dot product로 연결 시켜서 유사성을 찾아내는 것입니다.
2.6.2 Linear Model
자 그러면 왜 이렇게 3개로 복사 붙여넣기를 한것인가?
그건 아주 쉽게 말하면 embedding vector를 하나만 사용하는 것보다, 3개의 각각 다른 linear projection을 적용 함으로서
각각 서로 다른 subspace에서 정보를 끄집어 낼수 있기 때문입니다. -> 그래서 더 좋았다 (뭐 항상 뻔한 내용.. 증명은 못하고 더 좋았다)
결국 linear transformation을 함으로서 동일한 정보를 다른 방향에서 바라본다. 저는 이렇게 해석하고 있습니다.
2.6.3 Multi-Head
예를 들어서 Q (256, 33, 512), K (256, 33, 512), V (256, 33, 512) 이렇게 embedding vectors가 있을때,
33은 33개의 단어가 있다는 뜻이고, 단어 하나당 512개의 dense vector로 표현이 됩니다.
이때 512에 해당되는 부분에 대해서, single attention을 하는 것이 아니라, 512이 부분을 \(h\) 개로 쪼개서 multi-head attention을 합니다.
Q, K, V 모두 encoder input (256 batch_size, 38 sequence_length, 512 embedding_dimension)에서 만들어진 텐서입니다.
2.7.1 QK^T
q, k, v를 linear transformation해준뒤, h갯수(8개)로 나누었습니다.
이후 과정은 scaled dot-product attention을 해줘야 합니다.
위의 공식을 보면 먼저 \(Q\) 그리고 \(K^T\) 를 matrix multiplication (dot product)를 해줘야 합니다.
이때 아래의 두개의 코드를 좀 비교해 보겠습니다.
첫번째는 matrix multiplication을 해버리면 (256, 33, 8, 8) 값이 나오고 3388=2112 가 됩니다.
두번째는 (256, 8, 33, 33) 형태가 나오며, 83333=8712 가 나옵니다.
matrix multiplication을 하면서 궁극적으로는 각 vector마다의 similarity를 계산하며,
이때 2112 또는 8712를 정보의 양이라고 했을때, 정보의 손실이 없는 방향으로 계산을 하는게 좋습니다.
여기에 대한 저의 개인적인 해석입니다. (틀릴수 있으니 참고만)
2.7.2 1/sqrt(d_k)
Attention의 방법으로 여러가지 방법이 있을수 있습니다.
예를 들어서 query vector와 key vector를 더할 수도 있고, dot product를 할 수도 있죠.
이 두가지 방법은 모두 많이 사용되는 방법들 입니다.
논문에서는 additive attention이 dot product attention을 뛰어 넘었다고 했습니다.
(1/sqrt(d_k) 사용하지 않은.. 그냥 dot product)
저자의 생각은 dot product를 그냥 사용시 값이 지나치게 커지는 경향이 있고,
softmax 함수가 매우 작은 gradient값을 내놓도록 만들었다고 추정합니다.
이러한 경향을 없애기 위해서 1/sqrt(d_k) 로 scaled dot product 를 해주었습니다.
2.7.3 Masking and Dropout
논문에는 나와 있지 않은 2가지가 있습니다.
Masking before softmax function
Dropout after softmax function
1번의 경우 padding index로 들어간 부분을 mask를 하되, padding부분을 -1000000000 처럼 큰 음수값을 할당 합니다.
softmax 값을 거치면서 해당 값을 0으로 나오게 만듭니다.
즉 exponent는 음수값에 커질수록 0에 가까워지는 성질을 이용한 것입니다.
MultiHead 부분과 더불어, Positiion-wise FFN 도 sublayer안에 적용해야 합니다.
위의 공식에서 보이듯이 2개의 lienar model 그리고 relu를 사용합니다.
MultiHead에서 linear를 사용한 것과는 좀 다르게, bias값이 있는것이 특징인듯 합니다.
2개의 linear모델을 사용하면서 내부 dimension을 다르게 가져갑니다.
d_ff 라는 값을 사용하며 d_ff=2048을 기본값으로 사용합니다.
이것은 kernel size 1인 convolution을 사용하는데, dimenstion을 다르게 가져가는 것과 같은 것으로 봐도 됩니다.
3 Training
3.1 Optimizer and Learning Rate
Attention is All You Need 논문에서는 다음과 같이 optimizer를 사용했습니다.
Adam Optimizer 사용
\(\beta_1 = 0.9\) .
\(\beta_2 = 0.98\) .
\(\epsilon = 10^{-9}\) .
또한 learning rate는 training 도중에, 다음의 공식대로 변경되도록 하였습니다.
예를 들어서 warumup step=200 일 경우 다음과 같은 그래프가 그려지게 됩니다.
즉.. warmup_steps 까지는 learning rate는 linear하게 증가하게 됩니다.
하지만 step의 inverse square root 에 따라서 감소하게 됩니다.
3.2 Loss Function
3.2.1 Y_true and Y_pred
y_pred: (batch * seq_len, trg_vocab_size)
y_true: (batch * seq_len)
Loss는 cross entropy를 사용하며 내부적으로 log-softmax 를 사용합니다.
중요한점은 padding값은 loss 계산에서 빠져야 합니다.
Pytorch에서는 F.cross_entropy를 사용할수 있으며 ignore_index=trg_pad_idx 를 사용해서
padding값에 대해서는 무시하도록 만들수 있습니다. (개편하네)
3.2.2 Cross Entropy Pytorch Version
3.2.3 Cross Entropy Numpy Version
4 Pytorch Tutorial
4.1 torch.triu
정사각형의 n by n 매트릭스가 있을때, 위쪽 삼각부분만 리턴시킨다.
4.2 torch.narrow (narrow dimension)
Returns a new tensor that is a narrowed version of :attr:input tensor.
The dimension :attr:dim is input from :attr:start to :attr:start + length.
The returned tensor and :attr:input tensor share the same underlying storage.