트랜스포머 기반 자연어처리(NLP) - 디코딩, 트레이닝 (2)

개요

해당 글에서는 트랜스포머의 디코더를 사용하여 문장을 생성해내는 inference 동작 및 디코더를 학습시키는 training 동작에 대해서 설명한다.

앞선 글에서 설명한 인코딩 과정에서는 인코더에 입력된 문장이 압축된 정보로 인코딩 된다. 인코딩된 압축된 정보는 디코더에 전달되며 디코더가 문장을 생성해 낼 때 사용된다. 아래 그림은 논문에서 소개한 그림의 디코더 부분이다. 
디코더 구조

디코더로 해내려는 것은 인코더에 입력된 문장 이후에 나올 문장을 디코더의 inference 동작 한번당 한 토큰씩 차근차근 생성해 문장을 완성하는 것이다. 한가지 예를 들어본다. 트랜스포머 모델이 "한가지 예를"을 input문장으로 받으면, "들어본다"가 최종 output으로 나오게끔 이미 training되어 있다고 가정해보자. 그러면 디코더 단에서는 대략 이러한 흐름으로 여러번의 inference 동작이 진행된다. 

왼쪽 괄호안은 인코더가 준 압축된 정보이고, 오른쪽 부분은 [디코더 입력]->[디코더 출력] 이다.
(한가지 예를) 문장시작토큰 -> 들
(한가지 예를) 문장시작토큰,들 -> 어
(한가지 예를) 문장시작토큰,들,어 ->본
(한가지 예를) 문장시작토큰,들,어,본 -> 다
(한가지 예를) 문장시작토큰,들,어,본,다 -> 문장완료토큰

문장시작 토큰이 디코더로 들어가며 시작되고, inference 동작 한번당 한 토큰이 나오며, 그 토큰이 다시 디코더의 입력으로 이어붙여 들어가면서, 문장완료 토큰이 나올 때까지 inference를 반복하는 것이다. 그렇게 input문장 다음 나올 문장을 완성한다.  

Training하는 경우에 사용되는 디코더 동작은 조금 다른 설명이 필요한 부분이 있다. 아래에서 이에 대해 추가적으로 설명하며 디코더 내부의 구성 요소들에 대해서도 설명한다.

디코더 동작 흐름, Inference, Training

트랜스포머 모델의 inference와 training에서 디코더가 사용되는 동작 흐름은 조금 다른 부분이 있다. (디코더 구조 자체는 동일하다.) Inference시에는 한번의 디코더 동작당 한 토큰씩 차례대로 계산하는데, training시에는 한번에 모든 토큰에 대해 계산한다.

이러한 차이는 inference시에는 다음에 어떤 토큰이 나와야 하는지 모르지만 training시에는 출력으로 나와야 될 토큰들이 무엇인지를 알고 있기 때문에서 온다. 

먼저 inference시의 동작 흐름이다. (inference가 의도한 대로 완벽하게 동작한 경우임)
([BOS], [EOS]는 각각 문장시작토큰, 문장완료토큰이다. 디코더는 항상 인코더가 준 정보를 참고하지만 그림에서는 생략하고 디코더 부분만 표현되었음. 또한 문장에서 토큰, 토큰에서 문장으로 변환되는 과정도 생략하고 표현되었음.)

Inference시에는 이처럼 한 단계씩 나아가야 한다. 다음에 무슨 토큰이 올지 모르니까 말이다. 그리고 각 단계는 해당 위치 이전의 토큰들만을 참고하여 계산한다. 이 또한 다음에 무슨 토큰이 올지 모르니까 말이다.


그런데 training시에는 나와야 될 토큰들이 이미 정해져 있고 이에 따라 입력단에 들어갈 토큰들도 정해져 있기 때문에 굳이 차례대로 할 필요 없이 미리 토큰들을 전부 넣어두고 각 단계에서 해당 단계 이전의 토큰들만 참고해 연산하게끔 하면 된다. 때문에 아래와 같이 동작하면 될 것이다.
모델이 이미 학습이 잘 되어 있다면 '?????' 에는 target과 같은 '들어본다[EOS]'가 나올 것이다. 하지만 모델이 아직 학습되어있지 않았다면 이상한 값들이 나올 것이다. 이상한 값이 나왔다면 target과의 차이로부터 loss를 계산해 모델 파라미터들에 수정을 가하는 training을 하는 것이다. (이러한 학습 방식을 teacher forcing이라 한다)
Inference와 training에서 디코더를 사용하는 방식은 위에서의 설명과 같다. 그런데 이것이 어떻게 해서 가능한지에 대해서는 아래 디코더 레이어에 대한 설명에서 추가로 설명한다.

디코더 레이어

디코더 레이어는 인코더 레이어와 구조가 거의 비슷하다. 하지만 두가지 차이가 있다. 첫번째는 인코더와 동일하게 가지고 있는 multi-head attention의 입력으로 들어가는 Key, Value의 원천이 다르다. 인코더의 최종 출력으로부터 Key, Value가 계산된다. Query는 디코더 내부에서 온다. 디코더가 인코더에서 넘겨받은 정보를 적극 참고하면서 디코딩하는 구조인 것이다. 
인코더에서 레이어를 여러번 쌓아 구성했던 것과 같이 디코더 또한 디코더 레이어를 여러번 쌓아 사용한다.

두번째 차이는 인코더 대비 레이어 가장 아래에 masked multi-head attention 연산이 추가된 것이다. 이것이 위에서 설명했었던 방식으로 inference 및 training시에 디코더를 사용하는 것을 가능하게 해 주는 요소이다. 

Masked attention연산에서는 인코더에서의 attention연산과 동일하게 q,k,v를 사용해 연산하는데, 중간에서 계산된 attention score의 일부를 매우 작은 값으로 바꾸는 동작(mask)을 하여 attention value 계산에 각 단계 이전의 토큰들만 참조하게끔 한다.
Mask하지 않은 attention연산의 경우에는 attention value들의 값들은 서로 다른 모든 위치의 토큰들을 반영한 값을 가지고 있을 것이다(모두가 v1,v2,,,vn까지 score에 기반해 가중합). 하지만 attention score matrix에 삼각형 형태의 mask를 취해(하삼각행렬만 남김) 이후 연산에 반영되지 않게 하고 v들과 연산을 진행하여 나오는 attention value들은 각 위치 이전의 v들만 참고해서 가중합 한 결과들일 것이다. 

이렇게 masked attention연산을 통해 inference시 한 토큰씩 늘려가며 연산할 때나 training시에 한번에 모두 연산할 때나 어짜피 이전 위치의 토큰들에 대해서만 참고해 계산한 결과가 나오기 때문에 두 경우 모두에 사용이 가능한 것이다.


문장이 디코더 레이어에 들어가서 연산이 되기 전 단계에는 인코더에서 하는 일과 동일하게 tokenize, embedding, positional encoding 단계를 거친다. 

그리고 여러 단계로 쌓인 디코더 레이어를 통과한 토큰들은 바로 읽을 수 있는 단어로 나타나는 것은 아니고, linear layer(fully connected layer)에 의해 단어장 크기에 해당하는 dimension으로 변환되고(예를 들어 30000개의 단어에 대해 미리 매핑을 해둔 단어장에서 150번째의 단어는 'is' 이고 (0, 0, 0, ... , 1(150번째), 0,0, .... , 0(3만번째))와 같은 형태로 표현이 됨), 이를 softmax 처리를 한번 한 결과(output probability)에 기반해서 최종적인 단어가 선택되게 된다. 결과가 보여주는 분포에서 가장 큰 값을 가진 부분의 단어를 선택하는 것을 greedy decoding이라 하고, 다른 값들의 경우 또한 고려해서 더 정교한 선택을 하려는 beam search decoding 방식 등이 단어 선택에 사용된다.

트레이닝 시의 target 문장의 단어 또한 위에서 설명한 분포의 형태로 변환되어 디코더에서 계산된 output probabilities와의 loss계산에 사용된다.

트랜스포머 기반 모델들

지금까지 설명했던 트랜스포머 모델의 인코더, 디코더 및 여러 구조들은 논문에서 소개된 가장 스탠다드한 경우이고, 다양한 방식으로 개조되어서 사용이 된다. 논문에서 소개되었던 인코더-디코더 구조에 기반하는 경우, 인코더 부분만 따로 떼서 활용하는 경우, 디코더 부분만 따로 떼서 활용하는 경우 등 다양한 모델들이 있다. 어떤 것은 생성 task에 좀 더 유리하고, 어떤 것은 번역 task에 좀더 유리한 등 각각의 특성이 있다고 한다.

대표적인 모델들 몇가지를 소개한다.

Encoder-only
BERT, RoBERTa, XLM, ALBERT, ELECTRA, DeBERTa ...

Encoder-decoder
T5, BART, M2M, BigBird ...

Decoder-only
GPT, LaMDA, PaLM ...

기타 메모

몇가지 모델 성능을 개선하는 요소들에 대해서 소개한다. 이는 PaLM논문에서 인용하였다. 
The improvements in these models have primarily come from one or more of the following approaches: 
(1) scaling the size of the models in both depth and width;
(2) increasing the number of tokens that the model was trained on;
(3) training on cleaner datasets from more diverse sources; and 
(4) increasing model capacity without increasing the computational cost through sparsely activated modules.

(1) 들어갈 수 있는 token 길이 늘리기, 레이어 더 깊게 쌓기 등을 통해 모델의 사이즈를 크게 늘리는 것
(2) 데이터 양 더 늘리기
(3) 데이터 품질 높이기
(4) sparsely activated modules를 통해서 계산비용 증가 없이도 capacity를 키움


몇몇 연구결과들에서 신기한 모습들도 보이는데 답변 문장에 "Let’s think step by step." 이라는 문장을 추가하고 시작하게 하면 답변을 더 논리적으로 하고 정확도 또한 높게 나온다고 한다.

또, 네이버 클라우드에서 클로바스튜디오 서비스를 하는데 모델이 욕설이나 폭력적인 이야기를 내뱉을 위험이 있는 것을 답변 앞쪽에 "CLOVA는 민감한 사회적 문제, 욕설, 위험, 폭력적인 발언을 하지 않습니다."를 넣고 시작하는 모습을 보인다. https://guide.ncloud-docs.com/docs/clovastudio-2-2-2

댓글

가장 많이 본 글

구글 람다(LaMDA)란? - 구글의 언어 모델

알파고 강화학습 원리

버텍스 AI란? - 구글 인공지능 플랫폼

카타고와 바둑 두어보기

뉴럴 네트워크란?

블로그 글 목록

뉴럴 네트워크를 학습시키는 방법