일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 옵티마이저
- 트위치
- 원신
- 조축회
- 토픽 모델링
- CTM
- 피파온라인 API
- 개체명 인식
- 블루 아카이브
- BERTopic
- 데이터넥스트레벨챌린지
- SBERT
- 블루아카이브 토픽모델링
- 포아송분포
- 구글 스토어 리뷰
- 데벨챌
- 붕괴 스타레일
- Tableu
- 코사인 유사도
- geocoding
- 클래스 분류
- 데이터리안
- Roberta
- 자연어 모델
- 다항분포
- Optimizer
- 문맥을 반영한 토픽모델링
- LDA
- KeyBert
- NLP
- Today
- Total
분석하고싶은코코
NLP - Bert이해하기(2)_트랜스포머(transformer) 본문
이번 포스팅에서는 Bert의 핵심인 transformer에 대해서 이해해보겠습니다. 본 내용에 앞서서 이 트랜스포머는 RNN, Attention 이 두 가지에 대해서 알지 못하면 과정 자체를 이해하는데 큰 어려움이 있으니 꼭 두 가지에 대해서는 알아두시는게 좋습니다.
우선 아래 그림이 트랜스포머로 이뤄진 모델의 작동 순서도입니다. 왼쪽이 기존 인코더의 역할을 수행하고 오른쪽이 기존의 디코더 역할을 수행하게 됩니다. 이 과정에 대해서 하나씩 서술해보겠습니다. 우선 트랜스포머의 아이디어는 RNN의 한계점을 극복하고자 탄생했던 Attention을 이용한 것입니다. 이 어텐션을 통해서 RNN의 예측에 도움을 주었습니다. 하나의 RNN들이 인코더와 디코더를 구성하고 있었는데 이를 어텐션만으로 대체하자는 아이디어에서 고안된 것이 트랜스포머입니다. 트랜스포머가 동작하는 순서를 따라가면서 하나씩 알아가보도록 하겠습니다.
0) 트랜스포머의 하이퍼파라미터
트랜스포머에는 사용자가 직접 지정해줄 수 있는 값들이 있습니다.
- d_model : 트랜스포머의 인코더와 디코더의 입출력 크기
- num_headers : 트랜스포머에서는 하나의 층에서 작업을 병렬적으로 하고 다시 하나로 합치는데 병렬 작업을 몇개로 할지 정합니다.
- num_layers : 인코더와 디코더를 몇개의 층(layer)로 구성할지 정합니다.
- d_ff : FFNN 은닉층의 크기
1) 포지셔널인코딩(Positinal Encoding)
기존의 인코더, 디코더에서 진행된 LSTM을 생각해보면 들어온 시퀀스에 대해서 시점마다 단어를 예측하고 그 예측을 통해서 나온 결과값과 히든 셀을 활용하여 다음 단어를 예측하여 순서에 대한 정보가 모델 내에서 파악할 수 있도록 되어 있었습니다. 그런데 트랜스포머가 그 자리를 대체하려면 이 순서에 대한 문제점을 해결할 수 있어야 합니다. 그래서 등장하는 것이 포지셔널 인코딩입니다.
포지셔널 인코딩은 의도 그대로 임베딩 백터에 단어들의 위치에 대한 정보를 더해주는 작업을 의미합니다. 이를 통해서 동일한 단어가 들어왔다고 하더라도 각 백터에는 포지셔널 인코딩 값들이 더해졌기 때문에 어느 위치에 등장했는지에 대한 정보가 들어가 있어 그 위치를 알 수 있습니다.
포지셔널 인코딩의 값을 정하는 방법은 홀수 인덱스와 짝수 인덱스인 경우 그 값들이 다른데 이 값을 구하는 식은 다음과 같습니다. pos와 i값이 있는데 이는 행렬에서의 위치를 나타냅니다.
2) Multi -head Self - Attention (멀티 헤드 셀프 어텐션)
트랜스포머에서의 어텐션은 조금 다른 방식으로 진행됩니다. Multi-head라는 뜻은 앞서 num_heads라는 하이퍼파라미터에서 설정한 수만큼 병렬적으로 진행한다는 의미를 갖고 있습니다. 그런데 뒤에 붙은 Self라는 단어가 기존의 어텐션과 다르게 작동함을 나타냅니다.
기존의 어텐션 과정에 대해서 생각해보면 디코더에서 각 시점에서 은닉셀(Query)를 인코더으 각 시점으로 보냅니다. 인코더는 당연히 각 시점마다 은닉셀(Key)를 갖고 있을 것이고 이를 전치하여 은닉셀과 곱하면 해당되는 값(Value)가 나오는 방식으로 앞선 글에서 어텐션에 대해서 이야기했습니다. 그런데 트랜스포머의 인코더에서 어텐션은 Q, K, V는 모든 값이 동일한 값을 사용하게 됩니다. 그렇기 때문에 셀프 어텐션이라 불리게 됩니다. 이게 무슨 말이냐하면 아래 그림과 같이 it이라는 단어가 무엇을 의미하는지 우리는 쉽게 animal이라는 것을 알 수 있지만 컴퓨터는 쉽게 알 수 없는 것을 셀프 어텐션을 통해 쉽게 찾아갈 수 있게 해준다는 것이죠.
2-1) 셀프 어텐션의 진행방식
셀프 어텐션이 어떻게 진행되는지 하나의 단어를 예시로 이해해보겠습니다. 하나의 단어를 예로드는 이유는 모든 단어에 대해서 동일하게 작업이 진행되기 때문입니다. 우선 하나의 단어에 대한 셀프 어텐션을 진행하기 위해서는 Q, K, V의 백터를 얻어야 합니다. 이 백터들을 얻는 방법은 하이퍼파라미터들에 의해 결정됩니다. d_model을 num_heads로 나눈 값으로 Q, K, V 백터의 차원이 결정됩니다. 논문에서는 d_modle = 512, num_heads = 8의 값으로 설정했기 때문에 Q, K, V 백터들은 64차원 갖게 됩니다. 하나의 단어 백터로부터 Q, K, V백터를 만들어내는데 가중치과 곱해지면서 64차원을 갖는 백터들이 탄생합니다. 각각의 가중치행렬은 훈련을 통해 값을 갖습니다.
이렇게 얻은 Q, K, V백터에 대해서는 앞선 어텐션 과정과 동일한 작업을 진행하게 됩니다. Q를 각 K 전치 행렬과 곱하면 값이 나오는데 이게 어텐션 스코어(Attention Score)가 되고 이 값들을 모아두면 어텐션 분포(Attention Distrubution)이 되고 이를 소프트 맥스를 통해 합이 1인 값들로 변환시켜 V백터와 곱해 가중합을 진행하면 어텐션 값(Attention Value)이 나오는 것입니다.
트랜스포머에서는 Q 백터를 하나씩 작업할 필요가 없이 하나의 행렬로 보고 작업을 진행하면 한 번에 처리가 가능합니다. 따라서 아래와 같이 작업을 진행할 수 있는데 기존의 닷-프로덕트 어텐션과 다른점은 d_k의 제곱의 값으로 스케일링을 해주는 작업이 추가 되었습니다. 그래서 이를 스케일드-닷-프로덕트 어텐션이라고 합니다.
2-2) 멀티 헤드(Multi-head)
앞의 과정을 통해서 셀프어텐션의 값이 구해주는 과정을 확인했습니다. 그런데 셀프어텐션을 진행하기전에 Q, K, V 백터를 구할때 num_heads의 값으로 나눠주었습니다. 그렇기 때문에 하나의 head에서 진행한 결과는 현재는 64차원을 갖고 있습니다. 결국 다른 head에 진행한 작업들이 있고 그 결과들과 연결(concatenate)해주는 작업을 해줄 필요가 있습니다. 그래야 다음 FFNN 서브층으로 넘어갈때 기존의 입력 크기였던 d_model의 크기를 유지할 수 있기 때문입니다. 이렇게 num_heads의 수만큼 나눠서 진행하고 이를 다시 합치는 작업을 하는 이유는 단어간의 연관을 동시에 고려하는게 아니라 각 head마다 다르게 연과성에 집중하고 그 결과를 후에 합치는 작업을 진행하므로서 단어간 유사도를 보다 정확하게 파악할 수 있게 되는 것입니다. 앞선 예시에 있던 it을 animal과의 연관성에 주목하는 head가 있고 street와 연관성을 주목하는 head가 있었고 이에 대한 결과를 합치는 것이라 생각하시면 됩니다. 이렇게 합쳐진 행렬은 초기 입력 크기였던 (seq_len, d_model)의 크기를 갖게 됩니다. 이렇게 나온 병합 행렬에 또 다른 가중치 행렬을 곱하여 서브층의 최종 결과물이 나오게 됩니다.
3) 포지션-와이즈 피드 포워드 신경망(Position-wise FFNN)
멀티-헤드 셀프어텐션 층을 지나 나온 값들이 두 번째 서브층인 포지션-와이즈 피드 포워드 신경망으로 들어오게 되는데 이 때 어텐션층에서 전달된 값을 x라합니다. 이 값에 가중치 행렬W_1을 곱해주는데 이때 하이퍼파라미터중 하나였던 d_ff가 사용됩니다. W_1의 크기는 (d_model, d_ff)이고 W_2는 원래의 입력크기로 돌려주는 (d_ff, d_model)의 크기를 갖습니다. 이 과정이 num_layers로 설정한 층마다 동일하게 작동하는데 이때의 가중치 행렬과 편향들은 하나의 층 안에서는 모두 동일하지만 서로 층이 다르다면 그 값들도 다름을 유의해야합니다. 이렇게 두 개의 층을 지나 나온 값들이 디코더로 전달되는 값들이 되겠습니다.
4) 잔차 연결과 층 정규화
인코더에서 이뤄지는 주요 서브층에 대한 설명은 끝났지만 추가적으로 잔차연결과 층 정규화 기법을 통해 모델이 학습을 더 잘 하도록 돕는 장치들이 있습니다. 이 잔차결결과 층 정규화 작업은 모든 서브층에서 작업이 끝나면 한 번 씩 진행되는 작업입니다.
4-1) 잔차 연결
잔차연결의 경우 입력값을 학습한 결과값과 합쳐주는 작업을 의미합니다. 잔차연결을 하는 이유는 전체에 대한 학습을 진행하는 것이 아니라 F(x)만 학습을 하면 되는 상황을 만들어주는 것입니다. 따라서 이전보다 학습이 쉬워지고, 수렴을 더 잘 할 수 있게됩니다. 이를 통해 모델의 학습을 돕는 역할을 하게 됩니다.
4-2) 층 정규화
층 정규화는 텐서의 마지막 차원에 대해서 평균과 분산을 구하고, 이를 가지고 어떤 수식을 통해 값을 정규화하여 학습을 돕습니다. 텐서의 마지막 차원이란 트랜스포머에서의 d_model의 값을 의미합니다. 하나의 백터에 대한 정규화 과정중 입실론의 값이 분모에 더해지는데 이는 0이 되는것을 방지하기 위함입니다.
정규화 방법에는 또 다른 방법인 BN(Batch Normalization)이 있는데 이를 간단하게 비교 해보겠습니다.
BN의 경우 하나의 피처에 대해서 평균과 분산을 구하여 정규화 작업을 진행하게 됩니다. 반대로 LN은 하나의 샘플에 대한 평균과 분산으로 정규화를 작업하게 됩니다. 이렇다면 트랜스포머에서 BN이 아닌 LN을 선택한 이유는 다음과 같습니다.
- BN의 경우 batch_size에 의존적인데 크기가 1일경우 정규화 작업을 진행할 수 없다
- BN의 경우 각 피처에 대한 평균가 분산에 대한 값을 계산해야하는데 층을 지날때마다 이 값을 매번 계산해야하므로 복잡도가 높다
5) 마스크드 멀티-헤드 셀프어텐션(Masked Multi-head Self-Attention)
이 부분부터는 이제 디코더 영역에 해당하는 부분입니다. 앞서 설명한 부분에 대한 이해가 됐다면 사실 이부분부터는 크게 추가되는 점은 몇가지가 없습니다. 대부분 과정들이 비슷하게 진행됩니다. 마스크드 멀티-헤드 셀프어텐션의 경우 인코더의 첫 번째 서브층이과 수행하는 작업이 동일합니다. 다만 앞에 마스크드라는 단어가 붙었는데 이에 대해서만 이해하면 되겠습니다.
트랜스포머의 디코더의 입력은 인코더의 결과로 입력을 받게 됩니다. 그런데 여기서 기존의 RNN으로 구성된 Seq-to-Seq와 다른점이 존재합니다. Seq-to-Seq는 하나에 단어가 들어오면 다음 값을 예측하고 그 예측값이 아닌 실제 레이블을 다음 셀의 입력값으로 사용하는 교사 강요 방법을 사용했는데 이 방법이 트랜스포머에도 동일하게 적용되지만 다른점이 있습니다. RNN의 경우 t시점이라면 t시점까지의 단어들로만 예측하는 작업을 진행하도록 설정이 되어있는데 트랜스포머는 그렇지 못합니다. 그렇기 때문에 입력에서 이미 모든 레이블 정보가 들어가 있고 답을 이미 알고 있는 상황에서 예측을 해야하는 겁니다. 그래서 해당 시점 이후에 나올 단어에 대해서는 블라인드 처리를 해줄 필요가 있는데 이를 룩-어헤드-마스크(look-ahead-mask)라 합니다. 아래의 그림과 같이 첫 셀에서는 문장의 시작을 알리는 토큰인 <sos>에 대한 정보를 제외한 나머지 정보를 모두 블라인드 처리를 해주는 겁니다. 그 다음 단어인 je의 경우 <sos>와 je에 대한 정보만을 가지고 예측하게 합니다. 이 부분이 마스크드 멀티-헤드 셀프어텐션층의 핵심입니다. 나머지 부분은 인코더에서 진행한 셀프어텐션과 동일하게 진행됩니다.
6) 멀티-헤드 어텐션(Multi-head Attention)
이제 마지막 서브층인 멀티-헤드 어텐션입니다. 이 부분은 셀프라는 단어가 빠졌습니다. 즉 기존에 알고 있던 어텐션과 동일한 작업을 한다고 생각하시면 됩니다. 인코더 층과 디코더층을 사용한 어텐션 작업이 이뤄집니다. Query는 디코더 행렬을 사용하게되고 K, V는 인코더에서 전달받은 행렬을 사용하게 됩니다.
위 과정들을 모두 따라왔다면 하나의 트랜스포머에 대한 이해가 끝났습니다!
참고문헌
'머신러닝&딥러닝 > NLP' 카테고리의 다른 글
NLP - BERT 실전 활용(2) (1) | 2023.10.03 |
---|---|
NLP - BERT 실전 활용(1) (1) | 2023.10.01 |
NLP - Bert이해하기(1)_어텐션 매커니즘(Attention) (0) | 2023.09.29 |
NLP - 토픽 모델링(LSA, LDA) (0) | 2023.09.26 |
서브워드 토크나이저(Subword Tokenizer) (0) | 2023.09.22 |