Transformer 기반 인코더-디코더 모델 Hugging Face 블로그 포스트 2020

TL;DR

허깅페이스는 트랜스포머 기반 인코더-디코더 모델을 단계별로 안내하는 교육용 블로그 포스트를 출판했으며, 인코더와 디코더 구성 요소, 셀프 어텐션과 크로스 어텐션의 작동 방식, 그리고 🤗Transformers 라이브러리를 사용한 MarianMT 번역 예시를 통해 자기회귀 생성을 시연했습니다.

Background

이 블로그 포스트는 시퀀스-투-시퀀스 작업을 입력 벡터 시퀀스를 알 수 없는 길이의 목표 벡터 시퀀스로 매핑하는 것으로 프레임하며, 이는 인코더-디코더 모델 개발의 동기가 되었습니다.

"자연어 생성(NLG), NLP의 하위 분야에서의 작업은 시퀀스-투-시퀀스 문제로 가장 잘 표현됩니다."

초기의 RNN 기반 인코더-디코더는 가변 길이 출력을 처리할 수 있었지만, 소실 그래디언트 문제와 제한된 병렬화로 고통받았다고 언급합니다.

"RNN은 소실 그래디언트 문제로 인해 장기 의존성을 포착하기 매우 어렵게 만듭니다... 둘째, RNN의 내재적 반복 아키텍처는 인코딩 시 효율적인 병렬화를 방해합니다."

그 후 이 포스트는 Vaswani et al. (2017)의 트랜스포머 아키텍처를 가변 길이 시퀀스의 고도로 병렬화 가능한 처리를 가능하게 하는 솔루션으로 소개합니다.

Encoder-Decoder Architecture

트랜스포머 기반 인코더-디코더는 잔차 어텐션 블록으로 구성된 인코더 스택과 디코더 스택으로 이루어집니다.

"RNN 기반 인코더-디코더 모델과 유사하게, 트랜스포머 기반 인코더-디코더 모델은 잔차 어텐션 블록의 스택인 인코더와 디코더로 구성됩니다."

인코더는 입력 시퀀스를 컨텍스트화된 숨은 상태 시퀀스로 매핑하고, 디코더는 이러한 인코딩과 이전에 생성된 토큰을 조건으로 목표 시퀀스의 조건부 분포를 모델링합니다.

"트랜스포머 기반 인코더 부분은 입력 시퀀스를 ... 숨은 상태 시퀀스로 인코딩하고... 트랜스포머 기반 디코더 부분은 그 후 인코딩된 숨은 상태 시퀀스를 조건으로 목표 벡터 시퀀스의 조건부 확률 분포를 모델링합니다."

자기회귀 생성은 단계별로 진행되며, 디코더는 첫 번째 순전파 후 인코더의 출력을 재사용합니다.

"인코더가 첫 번째 순전파에서만 입력 시퀀스를 매핑하는 데 사용된다는 점을 이해하는 것이 중요합니다... 두 번째 순전파부터는 디코더가 이전에 계산된 인코딩을 직접 활용할 수 있습니다."

Encoder Details

각 인코더 블록은 양방향 셀프 어텐션 층 다음에 두 개의 피드포워드 층으로 구성됩니다. 셀프 어텐션 층은 입력 벡터를 쿼리, 키, 값으로 투영하고, 소프트맥스를 통해 어텐션 가중치를 계산한 후, 값의 가중 합에 원래 입력을 더한 값을 반환합니다.

"각 입력 벡터 ... 는 키 벡터, 값 벡터 및 쿼리 벡터로 투영됩니다... 출력 벡터는 모든 값 벡터의 가중 합으로 정의되며... 여기에 입력 벡터가 더해집니다."

모든 쿼리가 모든 키에 어텐션을 가지므로, 인코더는 단일 작업으로 장기 의존성을 포착하고 위치 전체에 걸쳐 완전한 병렬화를 가능하게 합니다.

"출력 ... 은 행렬 곱셈 시리즈와 소프트맥스 연산을 통해 계산되며, 이는 효과적으로 병렬화할 수 있습니다."

코드 스니펫은 입력의 마지막 단어를 변경하면 인코더의 첫 번째 토큰 표현이 바뀜을 보여 주어 문맥 의존성을 확인합니다.

Decoder Details

각 디코더 블록은 단방향 셀프 어텐션 층, 크로스 어텐션 층, 그리고 두 개의 피드포워드 층으로 구성됩니다. 단방향 셀프 어텐션은 각 쿼리가 자신의 위치와 이전 위치에만 어텐션을 가지도록 제한하여 자기회귀 동작을 보장합니다.

"단방향 셀프 어텐션에서는 각 쿼리 벡터가 해당 키 벡터와 모든 이전 키 벡터와만 비교됩니다...これにより 출력 벡터가 다음 입력 벡터에 대한 정보를 포함하는 것을 방지합니다."

크로스 어텐션은 디코더의 숨은 상태를 쿼리로, 인코더의 키와 값에 투영하여 디코더의 표현을 인코더 전체 출력에 조건화합니다.

"크로스 어텐션 층은 입력 벡터 각각을 모든 컨텍스트화된 인코딩 벡터와 관계시켜, 인코더 입력을 기준으로 다음 목표 벡터의 확률 분포를 조건화합니다."

디코더의 최종 선형 층(LM 헤드)은 숨은 상태를 어휘상의 로짓으로 매핑하며, 이는 소프트맥스를 통해 확률로 변환됩니다.

"'LM 헤드'는 인코딩된 목표 벡터 시퀀스를 로짓 벡터 시퀀스로 매핑하며... 소프트맥스 연산을 적용함으로써 전체 어휘에 대한 확률 분포를 얻을 수 있습니다."

코드 예시는 특정 위치 이후의 디코더 토큰을 변경해도 이전 토큰의 로짓에 영향을 주지 않음을 보여 주어 단방향 셀프 어텐션의 인과적 특성을 설명합니다.

Inference with 🤗Transformers

이 포스트는 🤗Transformers 라이브러리를 사용하여 사전 학습된 MarianMT 모델로 번역을 실행하는 방법을 보여 주며, generate() 메서드가 내부에서 인코딩, BOS/pad 토큰으로 디코더 초기화, 그리고 빔 서치 디코딩을 처리한다고 강조합니다.

".generate()를 호출하면 내부에서 여러 작업이 수행됩니다. 먼저, input_ids를 인코더에 전달합니다. 둘째, 사전 정의된 토큰인 <pad> 기호를... 인코딩된 input_ids와 함께 디코더에 전달합니다. 셋째, 빔 서치 디코딩 메커니즘을 적용합니다..."

제공된 예시는 'I want to buy a car'를 독일어로 번역하여 <pad> Ich will ein Auto kaufen 출력을 생성합니다.

Appendix: Code Snippets

부록에는 인코더와 디코더 호출을 수동으로 단계별로 진행하고, argmax로 다음 토큰을 선택하여 디코더 입력에 연결하는 최소한의 그리디 디코딩 루프가 포함되어 있으며, 이는 번역의 첫 몇 단어를 재현합니다.

"이 코드 예시에서는 앞서 설명한 내용을 정확히 보여 줍니다...その結果, 모델은 'Ich will ein' 단어를 생성했습니다."

이 포스트는 독자들이 이제 트랜스포머 기반 인코더-디코더 모델의 작동 방식과 🤗Transformers 라이브러리での 사용 방법을 자세히 이해했다고 결론지으며, 훈련 세부 사항은 향후 포스트에서 다룰 것이라고 언급합니다.

Sources