Transformer_Encoder

byeo1019·2022년 1월 17일
0

Transformer

목록 보기
3/4
post-thumbnail

한빛미디어 출판 "구글 BERT의 정석 " 책을 참고해서 작성하는 개인 공부 자료입니다.
혹시 내용에 저작권 등 문제가 있다면 알려주시면 감사하겠습니다.

! 내용에 신뢰도가 떨어지거나 상당부분 요약 되어 있을 가능성이 있음 !
! 제가 수식 보는 것을 싫어하기 때문에 꼭 필요하지 않다면 생략되있을 가능성이 높습니다 !


이전 포스팅까지 Self-Attention까지 다뤄보았고, 이제 Transformer를 위한 기반지식을 갖추게 되었다.

다시 상기해보면

  1. 쿼리 행렬( Q )과 키 행렬( K )간의 내적을 계산하고 유사도 값을 산출한다.
  2. 유사도 값을 행렬의 차원의 제곱근으로 나누어 스코어 행렬을 구한다.
  3. 스코어 행렬에 소프트맥스 함수를 적용해 정규화한다.
  4. 마지막으로 스코어 행렬에 밸류 행렬( V )를 곱해 어텐션 행렬( Z )를 산출한다.

기본적으로 Transformer 모델은 여러 개의 Attention 모델을 다양하게 조합시킨 입력 시퀀스를 통해 목표 시퀀스를 출력하는 Seq2Seq 모델이다.

다만 이전의 모델처럼 RNN의 보완하는 역할로 Attention 모델을 사용한 것이 아니라 오로지 Attention모델만으로 인코더-디코더 구조를 구현한 모델인데, 지금부터 내부 구조에 대해 자세히 알아보겠다.


Overview

트랜스포머는 인코더-디코더로 구성된 모델이다.

먼저 인코더에 문장을 입력하면 인코더에서 학습된 문장의 표현을 도출해 내고 디코더에 전달한다.

또한 디코더에서는 전달 받은 표현을 통해 사용자가 원하는 문장을 생성한다.

e.g. 프랑스어 번역 프로세스

  1. 인코더에 영어 문장 입력
  2. 입력 받은 문장에 대한 학습된 표현 도출 및 디코더에 전달
  3. 디코더에서 프랑스어로 번역된 문장 생성

즉, Transformer 모델의 목적은 입력 시퀀스의 표현에 대한 목표 시퀀스를 얻기 위함인데, 시작하기에 앞서 전체 프로세스에 대해 정리해보면 다음과 같다.

  1. 인코더에 대한 입력 문장을 임베딩 행렬로 변환

  2. Positional Encoding 기법을 통해 문장의 위치 정보 추가

  3. Encoder( x N )
    3-1. Multi-Head Attention Layer에 통과시켜 어텐션 행렬 출력
    3-2. Feed Forward Network에 통과시켜 인코더 표현 출력
    3-4. 인코더가 중첩된 개수 N 만큼 반복( 이전 출력값을 입력값으로 사용 )
    3-5. 최상위 인코더에서 최종 인코더 표현 R 출력

  4. 최초 입력 문장을 <SOS> 심볼로 초기화 후 디코더에 입력

  5. 디코더에 대한 입력 문장을 임베딩 행렬로 변환

  6. Positional Encoding 기법을 통해 문장의 위치 정보 추가

  7. Decoder( x N )
    7-1. Masked Multi-Head Attention Layer에 통과시켜 어텐션 행렬 M 출력
    7-2. 어텐션 행렬 M과 인코더 표현 R을 입력으로 하는 Multi-Head Attention Layaer에 통과시켜 새로운 어텐션 행렬 출력
    7-3. Feed-Forward Network에 통과시켜 디코더 표현 출력
    7-4. 디코더가 중첩된 개수 N만큼 반복
    7-5. 최상위 디코더에서 최종 디코더 표현 출력

  8. 단어 예측
    8-1. Linear Layer에 통과시켜 로짓 벡터 출력
    8-2. Softmax Layer에 통과시켜 로짓 벡터를 확률값으로 변환
    8-3. 디코더에서 가장 높은 확률값을 갖는 인덱스의 단어 출력
    8-4. 디코더에 대한 입력 문장에 해당 단어를 Concaternate

  9. <EOS> 심볼을 반환할 때까지 디코더에 문장 입력 및 단어 예측( 5번부터 )을 반복

! 각 서브레이어의 출력을 Add & Norm Layer에 통과시킴으로써 정규화 및 잔차 연결 !

생소하고 어려워 보이는 명칭도 보이고, 다소 복잡한 절차로 보이지만 앞선 포스팅에서 알아봤던 Attention 메커니즘에 대해 이해하고 있다면 Transformer의 80%는 알고 시작하는 것이기 때문에 겁먹지 않아도 된다.

먼저 인코더의 자세한 작동방식을 알아보자.


Encoder

Input Embedding

"I am good"이라는 입력 문장이 있다고 가정해보자.

제일 먼저 자연어를 임베딩해 입력 행렬로 만드는 과정이 필요한데, RNN과 같은 순환구조에서는 단어 단위로 입력으로 전달받기 때문에 "I"가 입력된후 "am"이 입력되고 "good"이 입력되는 것처럼 순차적으로 입력되지만,

트랜스포머 모델에서는 학습 시간을 줄이고, RNN모델의 고질적인 문제인 장기 의존성 문제를 해결하기 위해 순환구조를 따르지 않고 문장안에 모든 단어를 병렬로 입력하는 방식을 사용한다.

하지만 병렬 입력 구조 때문에 단어의 순서 정보 유지에 문제가 생기고 이로 인해 문장의 의미를 명확히 이해하지 못하게 되기 때문에 별도의 순서 정보 입력 과정을 거치게 된다.

이를 바로 위치 인코딩( Positional Encoding )이라고 한다.


Positional Encoding

임베딩과정을 거친 입력 행렬이 다음과 같다고 가정 하자.

이 입력 행렬을 트랜스포에 바로 입력하게 된다면 단어의 순서 정보를 이해할 수 없다.

위치 인코딩 행렬 P는 입력 행렬 X의 차원과 같으며 네트워크에 입력하기 전에 입력 행렬에 더해 단어의 순서 정보를 행렬에 추가한다.

위치 인코딩의 계산하기 위한 함수로 사인파 함수( Sinusoidal Function )을 사용한다

P(pos,2i)=sin(pos100002i/dmodel)P(pos, 2i)=sin({pos \over 10000^{2i/d_{model}}})
P(pos,2i+1)=cos(pos100002i/dmodel)P(pos, 2i+1)=cos({pos \over 10000^{2i/d_{model}}})

pos는 문장에서 단어위 위치를 의미하고, i는 해당 위치의 임베딩을 의미한다.

이렇게 생성된 벡터들은 모델이 학습하는 특정한 패턴을 따르는데, 이 패턴을 통해 모델이 각 단어의 위치나 시퀀스 내의 다른 단어 간의 위치 차이에 대한 정보를 알 수 있게 해준다.

또한 이 벡터 값을 입력 임베딩에 추가하는 것이 후에 Query, Key, Value 벡터로 변환 되었을 때 단어 간 거리를 늘릴 수 있다는 점이 있다.

결론적으로 특정 패턴을 가지는 함수의 출력 값을 입력 임베딩 각각의 값에 더해줌으로써 위치 정보를 추가해주는 것이라고만 이해하고 넘어가겠다.


Multi-head Attention

이렇게 위치 정보까지 추가해준 입력 임베딩을 어텐션 모델에 넣게 되는데, 이전에 정리한 어텐션의 경우에는 단일 헤드이다.

즉, 어텐션 모델을 하나만 쓰고 하나의 어텐션 행렬( ZZ )을 출력하는 모델인데,

멀티 헤드 어텐션 모델의 경우에는 여러 개의 어텐션 모델을 중첩해서 사용해 여러 개의 어텐션 행렬( Z1Z_1, Z2Z_2, Z3Z_3, ... )을 출력한 결과를 연결( Concatenate )한 후

새로운 가중치 행렬( WOW^O )을 곱해 최종적으로 단일 헤드 어텐션 보다 문장을 더 정확히 이해할 수 있는 어텐션 출력 값을 얻기 위함에 목적이 있는 모델이다.

앞서 말한 어텐션 행렬 계산 방법에서 처음에 입력 행렬과 가중치 행렬을 각각 곱해 Q, K, V 행렬을 생성한다고 했었던 것과 같은 방식으로 어텐션 행렬을 출력해 낸다.

다만, 여러 개의 어텐션 행렬( Z1Z_1, Z2Z_2, Z3Z_3, ... ) 각각 3개의 서로 다른 가중치 행렬을 곱해 생섬함으로써 멀티 헤드 어텐션을 구현하게 된다.

e.g. )
Z1Z_1의 가중치 행렬 W1QW_1^Q, W1KW_1^K, W1VW_1^V 로 생성된 Q1Q_1, K1K_1, V1V_1 벡터
Z2Z_2의 가중치 행렬 W2QW_2^Q, W2KW_2^K, W2VW_2^V 로 생성된 Q2Q_2, K2K_2, V2V_2 벡터

+ QQ, KK, VV 벡터의 차원은 이 입력 임베딩의 차원과 head의 개수를 통해 결정된다.
( QQ, KK, VV 벡터의 차원 = 입력임베딩의차원Head의개수입력 임베딩의 차원 \over Head의 개수 )

마지막으로 8개의 어텐션 행렬( Z1Z_1, Z2Z_2, Z3Z_3, ..., Z8Z_8 )을 구했다고 하면 모든 출력된 결과를 병합( Concatenate )한 후 새로운 가중치 행렬( WOW^O )을 곱하게 되면 최종적으로 원하는 어텐션 행렬을 얻게 된다.

Multi-Head Attention = concatenate(Z1,Z2,...,Z8)W0concatenate(Z_1, Z_2, ..., Z_8)W_0

Add & Norm

그리고 매 서브 레이어 마다 잔차 연결 및 정규화 과정을 거치게 된다.

잔차 연결( Residual Connection )은 서브 레이어의 입력과 출력을 단순 덧셈 연산해주는 것을 말하는 학습을 돕는 기법이다.
( 모든 행렬의 차원이 같도록 설계되었기 때문에 단순 덧셈이 가능 )

e.g. ) 모델을 거치며 흐려진 정보를 Remind

정규화( Layer Normalization )는 모든 데이터가 동일한 정도의 중요도로 반영되도록 하는 것을 목표로 하며, Gradient가 Exploding 하거나 Vanishing 하는 문제를 완화 시키고 안정적인 경사값을 가짐으로써 더 빠르게 학습시키기 위해 진행한다고만 알아두고 넘어가겠다.


Feed-forward Network

마지막으로 최종 인코더 표현을 얻기 위해 2개의 전결합층( Dense layer )과 ReLU 함수로 구성된 레이어로, 한 인코더 블록 내의 서로 다른 문장, 단어에 대해서는 모두 동일한 네트워크를 사용한다.

서로 다른 인코더 블록에서는 다른 네트워크를 사용한다.

Add & Norm

마찬가지로 잔차 연결 및 정규화를 진행해 최종 인코더 표현을 얻는다.


Component Integration

모든 구성요소를 정리해보면 다음과 같다.

  1. Encoder( x N )
  2. Multi-Head Attention Layer에 통과시켜 어텐션 행렬 출력
  3. Feed Forward Network에 통과시켜 인코더 표현 출력
  4. 인코더가 중첩된 개수 N 만큼 반복( 이전 출력값을 입력값으로 사용 )
  5. 최상위 인코더에서 최종 인코더 표현 R 출력

이렇게 얻은 인코더 표현을 디코더에 입력으로 사용하게 되는데, 다음 포스팅으로 디코더를 알아보고 트랜스포머를 마무리하겠다.


이상 인코더에 대해서 정리해봤습니다.

최대한 자연어로만 설명하려다 보니 글이 길어지고.. 정확히 이해하려다 보니 생각보다 많은 시간이 드는 것 같네요.

최초에는 누가 봐도 잘 알아듣도록 쓰자는 목표를 가졌지만 이제는 제 스스로 정리하는 것을 주된 목표로 바꿔야겠습니다..

애초에 전공자가 아니라면 읽지 않ㅇ..

두서 없이 작성된 글이지만 누군가에게는 도움이 되기를 바라며 글 마치겠습니다.

profile
Data Study

0개의 댓글