트랜스포머 (기계 학습)

섬네일|왼쪽에는 인코더, 오른쪽에는 디코더가 있는 표준 트랜스포머 아키텍처. 참고: 원래 2017년 트랜스포머에서 사용된 Post-LN 컨벤션과는 다른 Pre-LN 컨벤션을 사용한다.
**트랜스포머**(transformer)는 멀티 헤드 어텐션 메커니즘을 기반으로 하는 딥 러닝 아키텍처이며, 텍스트가 토큰이라는 수치 표현으로 변환되고 각 토큰은 워드 임베딩 테이블에서 조회를 통해 벡터로 변환된다. 각 레이어에서 각 토큰은 병렬 멀티 헤드 어텐션 메커니즘을 통해 컨텍스트 창 범위 내에서 다른(마스크되지 않은) 토큰과 함께 컨텍스트화되며, 이를 통해 핵심 토큰에 대한 신호가 증폭되고 덜 중요한 토큰은 약화된다.

트랜스포머는 순환 유닛이 없다는 장점이 있어 장단기 메모리 (LSTM)와 같은 이전 순환 신경망 아키텍처 (RNN)보다 훈련 시간이 적게 걸린다. 이후의 변형들은 대규모 (언어) 데이터셋에서 대형 언어 모델 (LLM)을 훈련하는 데 널리 채택되었다.

트랜스포머의 현대 버전은 2017년 구글 연구원들의 논문 "어텐션 이즈 올 유 니드"에서 제안되었다. 트랜스포머는 원래 기계 번역을 위한 이전 아키텍처를 개선하기 위해 개발되었지만, 이후 많은 응용 분야에서 사용되었다. 대규모 자연어 처리, 컴퓨터 비전 (비전 트랜스포머), 강화 학습, 오디오, 멀티모덜 학습, 로봇공학, 심지어 컴퓨터 체스를 두는 데에도 사용된다. 또한 사전 훈련 시스템인 GPT (Generative Pre-trained Transformers) 및 BERT (Bidirectional Encoder Representations from Transformers)의 개발로 이어졌다.

## 역사

### 이전 모델
수년 동안 시퀀스 모델링 및 생성은 일반 순환 신경망 (RNN)을 사용하여 수행되었다. 잘 인용된 초기 예는 엘만 네트워크 (1990)였다. 이론적으로 한 토큰의 정보는 시퀀스를 따라 임의로 멀리 전파될 수 있지만, 실제로는 소실 경사 문제로 인해 긴 문장 끝에서 모델의 상태가 이전 토큰에 대한 정확하고 추출 가능한 정보 없이 남게 된다.

주요 돌파구는 LSTM (1995)이었다. LSTM은 소실 경사 문제를 극복하기 위한 다양한 혁신을 사용하여 긴 시퀀스 모델링을 효율적으로 학습할 수 있었다. 한 가지 주요 혁신은 다른 뉴런의 출력을 곱하는 뉴런, 즉 곱셈 단위를 사용하는 어텐션 메커니즘을 사용한 것이었다. 곱셈 단위를 사용하는 신경망은 나중에 시그마-파이 네트워크 또는 고차 네트워크라고 불렸다. LSTM은 2017년 트랜스포머 발표 전까지 장기 시퀀스 모델링을 위한 표준 아키텍처가 되었다.
그러나 LSTM은 대부분의 다른 RNN처럼 순차 처리를 사용했다. 특히 RNN은 한 번에 하나의 토큰을 처음부터 끝까지 처리하며, 시퀀스의 모든 토큰에 대해 병렬로 작동할 수 없다.

현대 트랜스포머는 이 문제를 극복했지만, RNN과 달리 컨텍스트 창의 크기에 대해 이차적으로 계산 시간이 필요하다. 선형적으로 스케일링되는 고속 가중치 컨트롤러 (1992)는 입력에 따라 추가 처리를 위한 가중치 행렬을 계산하는 방법을 학습한다. 두 네트워크 중 하나는 "고속 가중치" 또는 "동적 링크" (1981)를 가지고 있다. 느린 신경망은 경사 하강법을 통해 쿼리에 대한 답변을 계산하는 빠른 신경망의 가중치 변경을 계산하기 위한 키와 값을 생성하는 방법을 학습한다. 이는 나중에 비정규화된 선형 트랜스포머와 동등하다는 것이 입증되었다.

### Seq2seq와 어텐션

인코더-디코더 시퀀스 변환 개념은 2010년대 초에 개발되었다. 일반적으로 seq2seq의 원형으로 인용되는 것은 2014년에 동시에 발표된 두 개의 논문이다.

기계 번역을 위한 3억 8천만 매개변수 모델은 두 개의 장단기 메모리 (LSTM)를 사용한다. 이 아키텍처는 두 부분으로 구성된다. 인코더는 토큰 시퀀스를 입력받아 벡터로 변환하는 LSTM이다. 디코더는 벡터를 토큰 시퀀스로 변환하는 또 다른 LSTM이다. 유사하게, 또 다른 1억 3천만 매개변수 모델은 LSTM 대신 게이트 순환 유닛 (GRU)을 사용했다. 이후 연구에 따르면 GRU는 seq2seq에서 LSTM보다 성능이 더 좋지도 나쁘지도 않다.

이러한 초기 seq2seq 모델에는 어텐션 메커니즘이 없었고, 상태 벡터는 원본 텍스트의 마지막 단어가 처리된 후에만 접근할 수 있었다. 이론적으로 이러한 벡터가 전체 원본 문장에 대한 정보를 유지하지만, 실제로는 정보가 제대로 보존되지 않았다. 이는 입력이 하나의 순환 네트워크에 의해 고정된 크기의 출력 벡터로 순차적으로 처리된 다음, 다른 순환 네트워크에 의해 출력으로 처리되기 때문이다. 입력이 길면 출력 벡터가 모든 관련 정보를 포함할 수 없으므로 출력이 저하된다. 증거로, 입력 문장을 뒤집는 것이 seq2seq 번역을 개선했다.

RNNsearch 모델은 병목 현상 (고정된 크기의 출력 벡터 문제)을 해결하기 위해 기계 번역을 위한 seq2seq에 어텐션 메커니즘을 도입하여 모델이 장거리 의존성을 더 쉽게 처리할 수 있게 했다. 이 이름은 "번역 디코딩 중에 원본 문장을 검색하는 것을 에뮬레이션한다"는 의미이다.

기계 번역을 위한 전역 (RNNsearch의) 및 지역 (슬라이딩 윈도우) 어텐션 모델 아키텍처 간의 상대적 성능을 비교한 결과, 혼합 어텐션이 전역 어텐션보다 품질이 높았고, 지역 어텐션은 번역 시간을 단축했다.

2016년, 구글 번역은 구글 신경망 기계 번역으로 개편되었으며, 이는 이전 통계적 기계 번역 기반 모델을 대체했다. 새로운 모델은 인코더와 디코더 모두 8계층의 양방향 LSTM으로 구성된 seq2seq 모델이었다. 개발에 9개월이 걸렸으며, 10년이 걸린 통계적 접근 방식을 능가했다.

### 병렬화 어텐션

어텐션 (자체 어텐션 포함)이 있는 Seq2seq 모델은 여전히 순환 네트워크와 동일한 문제, 즉 병렬화하기 어렵다는 문제로 인해 GPU에서 가속화할 수 없었다. 2016년, 분해 가능한 어텐션은 순방향 네트워크에 자체 어텐션 메커니즘을 적용하여 쉽게 병렬화할 수 있었고, LSTM보다 매개변수를 10배 적게 사용하여 텍스트 추론에서 SOTA 결과를 달성했다. 저자 중 한 명인 야코프 우슈코레이트(Jakob Uszkoreit)는 순환 없이 어텐션만으로도 언어 번역에 충분할 것이라고 예상했으며, 그래서 "어텐션이 필요한 전부"라는 제목이 붙었다. 당시에는 이 가설이 통념에 반하는 것이었으며, 심지어 그의 아버지이자 유명한 전산 언어학자인 한스 우슈코레이트도 회의적이었다. 같은 해, LSTM에 자체 어텐션 (내부 어텐션 또는 문장 내부 어텐션이라 불림)이 제안되었다.

2017년, 원래 (1억 규모의) 인코더-디코더 트랜스포머 모델은 "어텐션 이즈 올 유 니드" 논문에서 제안되었다. 당시 연구의 초점은 기계 번역을 위한 Seq2seq를 개선하는 것이었다. 모든 토큰을 병렬로 처리하기 위해 순환을 제거하면서 텍스트 처리 성능을 유지하기 위해 점곱 어텐션 메커니즘을 유지했다. 이는 독립적인 헤드 사용과 순환 부족으로 인해 병렬화하기 더 쉬운 멀티 헤드 어텐션 모델의 도입으로 이어졌다. 이 모델의 병렬화 가능성은 대규모 신경망에서 널리 사용되는 중요한 요인이었다.

### AI 붐 시대
2017년 봄, "어텐션 이즈 올 유 니드" 초판이 발표되기도 전에 공동 저자 중 한 명은 아키텍처의 "디코더-온리" 변형을 사용하여 가상의 위키백과 기사를 생성했다. 트랜스포머 아키텍처는 현재 진행 중인 AI 붐에 기여하는 많은 생성 모델과 함께 사용된다.

언어 모델링에서 ELMo (2018)는 문맥화된 워드 임베딩을 생성하는 양방향 LSTM으로, 단어 가방 모형 및 Word2vec 연구를 개선했다. 그 뒤를 이어 인코더-온리 트랜스포머 모델인 BERT (2018)가 나왔다. 2019년 10월, 구글은 검색 쿼리 처리에 BERT를 사용하기 시작했다. 2020년, 구글 번역은 이전 RNN-인코더-RNN-디코더 모델을 트랜스포머-인코더-RNN-디코더 모델로 교체했다.

2018년부터 오픈AI의 GPT 시리즈는 디코더-온리 트랜스포머로서 자연어 생성 분야에서 최첨단이 되었다. 2022년, GPT-3 기반 챗봇인 챗GPT가 예상치 못하게 인기를 끌면서 대형 언어 모델에 대한 붐을 일으켰다.

2020년부터 트랜스포머는 텍스트를 넘어선 모달리티에 적용되기 시작했으며, 여기에는 비전 트랜스포머, 음성 인식, 로봇공학, 그리고 멀티모덜이 포함된다. 비전 트랜스포머는 다시 합성곱 신경망의 새로운 발전을 촉진했다. DALL-E (2021), 스테이블 디퓨전 3 (2024), 및 소라 (2024)와 같은 이미지 및 비디오 생성기는 트랜스포머를 사용하여 입력 데이터 (텍스트 프롬프트 등)를 "토큰"으로 분해한 다음 자체 어텐션을 사용하여 각 토큰 간의 관련성을 계산하여 모델이 데이터 내의 컨텍스트와 관계를 이해하도록 돕는다.

## 훈련
### 훈련 안정화 방법
일반 트랜스포머 아키텍처는 수렴에 어려움을 겪었다. 원본 논문에서 저자들은 학습률 웜업을 사용할 것을 권장했다. 즉, 학습률은 훈련의 첫 부분 (보통 총 훈련 단계의 2%로 권장됨) 동안 0에서 최대값으로 선형적으로 스케일링된 후 다시 감소해야 한다.

2020년 논문에서는 멀티헤드 어텐션 및 순방향 레이어 전 (후가 아닌) 레이어 정규화를 사용하면 학습률 웜업 없이 훈련이 안정화된다는 사실을 발견했다.

### 사전 훈련-미세 조정
트랜스포머는 일반적으로 먼저 대규모 일반 데이터셋에서 자기 지도 학습을 통해 사전 훈련된 다음, 작은 작업별 데이터셋에서 지도 미세 조정된다. 사전 훈련 데이터셋은 일반적으로 더 파일과 같은 레이블이 없는 대규모 코퍼스이다. 사전 훈련 및 미세 조정을 위한 작업은 일반적으로 다음을 포함한다.
* 언어 모델링
* 다음 문장 예측
* 질의 응답
* 독해
* 감정 분석
* 다른 말로 표현하기
T5 트랜스포머 보고서는 수많은 자연어 사전 훈련 작업을 문서화한다. 몇 가지 예는 다음과 같다.

* 불완전하거나 손상된 텍스트 복원 또는 수정. 예를 들어, 입력 "Thank youme to your partyweek"는 출력 "Thank you **for inviting** me to your party **last** week"를 생성할 수 있다.*
* 자연어 간 번역 ([[기계 번역]])
* 자연어의 실용적 허용 여부 판단. 예를 들어, 다음 문장은 문법적으로는 잘 형성되었지만 일반적인 인간의 사용에서는 가능성이 낮기 때문에 "허용되지 않음"으로 판단될 수 있다. *The course is jumping well.*

이러한 각 작업은 해당 언어의 원어민에게는 사소하거나 명백한 반면, 이전 세대의 기계 학습 아키텍처에서는 일반적으로 어려움을 겪었다는 점에 유의해야 한다.

=== 작업 ===

일반적으로 언어 모델링 작업은 "마스크드", "자기회귀", 및 "prefixLM"의 3가지 클래스로 나뉜다. 이러한 클래스는 트랜스포머와 같은 특정 모델링 아키텍처와는 독립적이지만, 트랜스포머의 맥락에서 종종 논의된다.

마스크드 작업에서, 하나 이상의 토큰이 마스킹되고 모델은 컨텍스트를 기반으로 마스킹된 토큰이 무엇인지 예측하는 확률 분포를 생성한다. 작업의 [[손실 함수]]는 일반적으로 마스킹된 토큰에 대한 [[퍼플렉시티|로그-퍼플렉시티]]의 합이다.<math display="block">\text{Loss} = -\sum_{t\in\text{masked tokens}}\ln(\text{probability of }t\text{ conditional on its context}) </math>그리고 모델은 이 손실 함수를 최소화하도록 훈련된다. [[BERT (언어 모델)|BERT 시리즈 모델]]은 마스크드 토큰 예측 및 다른 작업을 위해 훈련된다.

자기회귀 작업에서, 전체 시퀀스가 처음에는 마스킹되고 모델은 첫 번째 토큰에 대한 확률 분포를 생성한다. 그런 다음 첫 번째 토큰이 드러나고 모델은 두 번째 토큰을 예측하는 식으로 진행된다. 이 작업의 손실 함수는 여전히 일반적으로 동일하다. [[GPT (언어 모델)|GPT 시리즈 모델]]은 자기회귀 작업을 통해 훈련된다.

prefixLM 작업에서, 시퀀스는 두 부분으로 나뉜다. 첫 번째 부분은 컨텍스트로 제공되며, 모델은 두 번째 부분의 첫 번째 토큰을 예측한다. 그런 다음 해당 토큰이 드러나고, 모델은 두 번째 토큰을 예측하는 식으로 진행된다. 이 작업의 손실 함수는 여전히 일반적으로 동일하다. [[T5 (언어 모델)|T5 시리즈 모델]]은 prefixLM 작업을 통해 훈련된다.

"마스크드 언어 모델링"의 "마스크드"는 "[[#마스크드 어텐션|마스크드 어텐션]]"의 "마스크드"와 다르며, "prefixLM" (접두사 언어 모델링)은 [[#prefixLM|"prefixLM" (접두사 언어 모델)]]과 다르다는 점에 유의해야 한다.

== 아키텍처 ==
모든 트랜스포머는 동일한 주요 구성 요소를 가지고 있다.
* 토크나이저: 텍스트를 토큰으로 변환한다.
* 임베딩 레이어: 토큰과 토큰의 위치를 벡터 표현으로 변환한다.
* 트랜스포머 레이어: 벡터 표현에 반복적인 변환을 수행하여 점점 더 많은 언어 정보를 추출한다. 이들은 교대로 어텐션 및 순방향 레이어로 구성된다. 두 가지 주요 유형의 트랜스포머 레이어가 있으며, 더 많은 변형이 있다. 인코더 레이어와 디코더 레이어가 그것이다.
* 언임베딩 레이어: 최종 벡터 표현을 토큰에 대한 확률 분포로 다시 변환한다.
다음 설명은 원본 논문에 기술된 트랜스포머를 정확히 따른다. [[#후속 연구|다음 섹션]]에 설명된 변형도 있다.

관례적으로 모든 벡터를 행 벡터로 작성한다. 예를 들어, 벡터를 선형 레이어를 통해 밀어넣는 것은 <math>xW</math>와 같이 오른쪽에 가중치 행렬을 곱하는 것을 의미한다.

=== 토큰화 ===


트랜스포머 아키텍처는 기본적으로 텍스트가 아닌 숫자 데이터를 처리하므로 텍스트와 토큰 간의 변환이 필요하다. 토큰은 문자 또는 짧은 문자 세그먼트를 나타내는 정수이다. 입력 측에서 입력 텍스트는 토큰 시퀀스로 구문 분석된다. 마찬가지로 출력 측에서 출력 토큰은 다시 텍스트로 구문 분석된다. 텍스트와 토큰 시퀀스 간의 변환을 수행하는 모듈은 [[낱말 분석|토크나이저]]이다.

모든 토큰의 집합은 토크나이저의 어휘이며, 그 크기는 *어휘 크기* <math>n_{\text{vocabulary}}</math>이다. 어휘 외의 토큰에 직면했을 때는 일반적으로 "[UNK]"("알 수 없음")라는 특수 토큰이 사용된다.

일반적으로 사용되는 토크나이저로는 바이트 쌍 인코딩, WordPiece, SentencePiece 등이 있다.

=== 임베딩 ===

각 토큰은 [[순람표]]를 통해 임베딩 벡터로 변환된다. 동등하게 말하자면, 토큰의 [[원-핫]] 표현에 임베딩 행렬 <math>M</math>을 곱한다. 예를 들어, 입력 토큰이 <math>3</math>이라면 원-핫 표현은 <math>[0, 0, 0, 1, 0, 0, \dots]</math>이고, 그 임베딩 벡터는 다음과 같다.
<math display="block">\mathrm{Embed}(3) = [0, 0, 0, 1, 0, 0, \dots]M</math>
토큰 임베딩 벡터는 해당 위치 인코딩 벡터(아래 참조)에 추가되어 입력 벡터 시퀀스를 생성한다.

임베딩 벡터의 차원 수는 *은닉 크기* 또는 *임베딩 크기*라고 불리며 <math>d_{\text{emb}}</math>로 표기된다. 이 크기는 원본 트랜스포머 논문에서 <math>d_{\text{model}}</math>로 표기된다.

=== 언임베딩 ===
언임베딩 레이어는 임베딩 레이어의 거의 역이다. 임베딩 레이어가 토큰을 벡터로 변환하는 반면, 언임베딩 레이어는 벡터를 토큰에 대한 확률 분포로 변환한다.

언임베딩 레이어는 선형-[[소프트맥스 함수|소프트맥스]] 레이어이다.
<math display="block">\mathrm{UnEmbed}(x) = \mathrm{softmax}(xW + b)</math>
이 행렬의 형태는 <math>(d_{\text{emb}}, n_{\text{vocabulary}})</math>이다. 임베딩 행렬 <math>M</math>과 언임베딩 행렬 <math>W</math>는 때때로 서로의 전치 행렬이 되도록 요구되는데, 이를 가중치 연결이라고 한다.

=== 위치 인코딩 ===
[[파일:Positional encoding.png|섬네일|매개변수 <math>N=10000, d=100</math>을 사용한 [[사인파|사인파형]] 위치 인코딩 다이어그램]]

위치 인코딩은 시퀀스 내 토큰의 상대적 위치를 고정된 크기의 벡터로 표현한 것이다. 이는 트랜스포머 모델에 입력 시퀀스에서 단어가 *어디에* 있는지에 대한 정보를 제공한다. 이는 입력 시퀀스 "[[man bites dog]]"가 "dog bites man"과 다르게 처리되도록 입력 시퀀스의 순서에 대한 [[귀납적 편향|편향]]을 유도한다.

위치 인코딩은 <math>f: \R \to \R^d; d \in \mathbb{Z}, d > 0</math> 유형의 함수로 정의되며, 여기서 <math>d</math>는 양의 짝수 [[정수]]이다. 원본 논문에 정의된 전체 위치 인코딩은 다음과 같다.
<math display="block">(f(t)_{2k}, f(t)_{2k+1}) = (\sin(\theta), \cos(\theta)) \quad \forall k \in \{0, 1, \ldots, d/2 - 1\}</math>
여기서 <math>\theta = \frac{t}{r^k}, r = N^{2/d}</math>이다.

여기서 <math>N</math>은 위치 인코딩 함수에 입력될 수 있는 가장 큰 <math>k</math>보다 훨씬 커야 하는 자유 매개변수이다. 원본 논문은 <math>N=10000</math>을 사용한다.

이 함수는 <math>f: \R \to \mathbb C^{d/2}</math> 유형의 복소 함수로 작성될 때 더 간단한 형태를 가진다.
<math display="block">f(t) = \left(e^{it/r^k}\right)_{k=0, 1, \ldots, \frac d 2 - 1}</math>
여기서 <math>r = N^{2/d}</math>이다.

이 위치 인코딩 함수를 사용하는 주된 이유는 이를 사용하면 이동이 선형 변환이 되기 때문이다.
<math display="block">f(t + \Delta t) = \mathrm{diag}(f(\Delta t)) f(t)</math>
여기서 <math>\Delta t \in \R</math>는 이동하려는 거리이다. 이를 통해 트랜스포머는 인코딩된 모든 위치를 가져와 행렬 곱셈을 통해 n-단계 앞 또는 n-단계 뒤 위치의 인코딩을 찾을 수 있다.

선형 합을 취하면 모든 합성곱도 선형 변환으로 구현될 수 있다.
<math display="block">\sum_j c_j f(t + \Delta t_j) = \left(\sum_j c_j \,\mathrm{diag}(f(\Delta t_j))\right) f(t)</math>
어떤 상수 <math>c_j</math>에 대해서도 마찬가지이다. 이를 통해 트랜스포머는 인코딩된 모든 위치를 가져와 이웃의 인코딩된 위치의 선형 합을 찾을 수 있다. 인코딩된 위치의 이 합은 어텐션 메커니즘에 입력될 때, [[합성곱 신경망]] [[언어 모델]]에서 일어나는 것과 유사하게 이웃에 대한 어텐션 가중치를 생성한다. 저자의 말에 따르면, "이것은 모델이 상대적 위치에 따라 쉽게 어텐션하는 방법을 배울 수 있도록 할 것이라고 가정했다."

일반적인 구현에서는 모든 연산이 [[복소수]]가 아닌 실수에 대해 수행되지만, [[복소수#복소수의 행렬 표현|복소수 곱셈은 실수 2x2 행렬 곱셈으로 구현될 수 있기]] 때문에 이는 단순한 표기법 차이이다.

=== 인코더-디코더 (개요) ===
[[파일:Transformer,_one_encoder-decoder_block.png|섬네일|하나의 인코더-디코더 블록|220x220px]]
[[파일:Transformer,_stacked_layers_and_sublayers.png|섬네일|트랜스포머는 쌓인 인코더 레이어와 디코더 레이어로 구성된다.]]
이전 [[Seq2seq]] 모델과 마찬가지로, 원래 트랜스포머 모델은 *'인코더-디코더** 아키텍처를 사용했다. 인코더는 모든 입력 토큰을 차례로 처리하는 인코딩 레이어로 구성되는 반면, 디코더는 인코더의 출력과 디코더의 지금까지의 출력 토큰을 반복적으로 처리하는 디코딩 레이어로 구성된다.

각 인코더 레이어의 목적은 토큰의 문맥화된 표현을 생성하는 것이다. 이 표현은 자체 어텐션 메커니즘을 통해 다른 입력 토큰의 정보를 "혼합"하는 토큰에 해당한다. 각 디코더 레이어는 두 개의 어텐션 서브레이어를 포함한다: (1) 인코더의 출력 (문맥화된 입력 토큰 표현)을 통합하기 위한 교차 어텐션, (2) 디코더의 입력 토큰 (즉, 추론 시간 동안 지금까지 생성된 토큰) 사이에서 정보를 "혼합"하기 위한 자체 어텐션.

인코더 및 디코더 레이어 모두 출력의 추가 처리를 위한 [[순방향 신경망]]을 가지며, 잔차 연결 및 레이어 정규화 단계를 포함한다. 이러한 순방향 레이어는 트랜스포머 모델의 매개변수 대부분을 포함한다.

=== 순방향 네트워크 ===
[[파일:Transformer architecture - FFN module.png|섬네일|순방향 네트워크 모듈. <math>d_{\text{emb}}</math> 차원 벡터를 <math>d_{\text{emb}}</math> 차원 벡터로 매핑하는 두 계층 네트워크이다.]]
트랜스포머의 순방향 네트워크 (FFN) 모듈은 2계층 [[다층 퍼셉트론]]이다.
<math display="block">\mathrm{FFN}(x) = \phi(xW^{(1)} + b^{(1)})W^{(2)} + b^{(2)}</math>
여기서 <math>W^{(1)}</math> 및 <math>W^{(2)}</math>는 가중치 행렬이고 <math>b^{(1)}</math> 및 <math>b^{(2)}</math>는 편향 벡터이며, <math>\phi</math>는 [[활성화 함수]]이다. 원래 트랜스포머는 [[ReLU]] 활성화를 사용했다.

중간 계층의 뉴런 수는 ''중간 크기'' (GPT), ''필터 크기'' (BERT), 또는 ''순방향 크기'' (BERT)라고 불린다. 일반적으로 임베딩 크기보다 크다. 예를 들어, GPT-2 시리즈와 BERT 시리즈 모두에서 모델의 중간 크기는 임베딩 크기의 4배이다. <math>d_{\text{ffn}} = 4 d_{\text{emb}}</math>.

=== 스케일드 점곱 어텐션 ===


==== 어텐션 헤드 ====
[[파일:Transformer,_attention_block_diagram.png|섬네일|스케일드 점곱 어텐션, 블록 다이어그램]]
[[파일:Transformer architecture - Attention Head module.png|섬네일|어텐션 헤드 모듈 내의 정확한 차원 수]]
트랜스포머 아키텍처에서 사용되는 어텐션 메커니즘은 스케일드 [[스칼라곱|점곱]] [[어텐션 (기계 학습)|어텐션]] 유닛이다. 각 유닛에 대해 트랜스포머 모델은 세 가지 가중치 행렬을 학습한다: 쿼리 가중치 <math>W^Q</math>, 키 가중치 <math>W^K</math>, 값 가중치 <math>W^V</math>.

이 모듈은 쿼리 시퀀스, 키 시퀀스, 값 시퀀스 세 가지 시퀀스를 입력으로 받는다. 쿼리 시퀀스는 길이 <math>\ell_{\text{seq, query}}</math>의 시퀀스이며, 각 항목은 차원 <math>d_{\text{emb, query}}</math>의 벡터이다. 키 및 값 시퀀스도 마찬가지이다.

쿼리 시퀀스의 각 벡터 <math>x_{i, \text{query}}</math>는 행렬 <math>W^Q</math>에 곱해져 쿼리 벡터 <math>q_i = x_{i, \text{query}} W^Q</math>를 생성한다. 모든 쿼리 벡터의 행렬은 쿼리 행렬이다.
<math display="block">Q = X_{\text{query}} W^Q</math>
마찬가지로 키 행렬 <math>K = X_{\text{key}} W^K</math>와 값 행렬 <math>V = X_{\text{value}} W^V</math>를 구성한다.

일반적으로 모든 <math>W^Q, W^K, W^V </math>는 정방 행렬이며, 이는 <math>d_{\text{emb, query}}= d_{\text{query}}</math> 등을 의미한다.

어텐션 가중치는 쿼리 및 키 벡터를 사용하여 계산된다. 토큰 <math>i</math>에서 토큰 <math>j</math>까지의 어텐션 가중치 <math>a_{ij}</math>는 <math>q_i</math>와 <math>k_j</math> 사이의 [[스칼라곱]]이다. 어텐션 가중치는 키 벡터의 차원인 <math>\sqrt{d_k}</math>의 제곱근으로 나뉘어 훈련 중 [[경사 하강법|기울기]]를 안정화하고, 가중치를 정규화하는 [[소프트맥스 함수|소프트맥스]]를 통해 전달된다. <math>W^Q</math>와 <math>W^K</math>가 다른 행렬이라는 사실은 어텐션이 비대칭일 수 있도록 한다. 토큰 <math>i</math>가 토큰 <math>j</math>에 어텐션한다면 (즉, <math>q_i\cdot k_j</math>가 크다면), 토큰 <math>j</math>가 토큰 <math>i</math>에 어텐션한다는 것을 반드시 의미하지는 않는다 (즉, <math>q_j\cdot k_i</math>는 작을 수 있다). 토큰 <math>i</math>에 대한 어텐션 단위의 출력은 모든 토큰의 값 벡터를 <math>a_{ij}</math> (토큰 <math>i</math>에서 각 토큰으로의 어텐션)로 가중 평균한 값이다.

모든 토큰에 대한 어텐션 계산은 [[소프트맥스 함수]]를 사용하여 하나의 큰 행렬 계산으로 표현할 수 있으며, 이는 행렬 연산 최적화를 통해 행렬 연산을 빠르게 계산할 수 있으므로 훈련에 유용하다. 행렬 <math>Q</math>, <math>K</math>, <math>V</math>는 각각 <math>q_i</math>, <math>k_i</math>, <math>v_i</math> 벡터를 행으로 하는 행렬로 정의된다. 그러면 어텐션을 다음과 같이 표현할 수 있다.
<math display="block">\begin{align}
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\mathrm{T}}{\sqrt{d_k}}\right)V
\end{align}</math>

여기서 소프트맥스는 행렬의 각 행에 적용된다.

쿼리 벡터의 차원 수는 ''쿼리 크기'' <math>d_{\text{query}}</math>이고, 마찬가지로 ''키 크기'' <math>d_{\text{key}}</math> 및 ''값 크기'' <math>d_{\text{value}}</math>이다. 어텐션 헤드의 출력 차원은 ''헤드 차원'' <math>d_{\text{head}}</math>이다. 어텐션 메커니즘은 다음 세 가지 등식이 성립해야 한다.
<math display="block">\ell_{\text {seq, key}}=\ell_{\text {seq, value}}, \;d_{\text {query}}=d_{\text {key}}, \; d_{\text {value}}=d_{\text {head}}
</math>
그렇지 않으면 제약이 없다.

어텐션 헤드가 자체 어텐션 방식으로 사용되면 <math>X_{\text{query}} = X_{\text{key}} = X_{\text{value}} </math>이다. 어텐션 헤드가 교차 어텐션 방식으로 사용되면 일반적으로 <math>X_{\text{query}} \neq X_{\text{key}} = X_{\text{value}} </math>이다. 이론적으로는 세 가지 모두 다를 수 있지만, 실제로는 거의 그렇지 않다.

==== 멀티헤드 어텐션 ====
[[파일:Multiheaded_attention,_block_diagram.png|섬네일|멀티헤드 어텐션, 블록 다이어그램]]
[[파일:Transformer architecture - Multiheaded Attention module.png|섬네일|멀티헤드 어텐션 모듈 내의 정확한 차원 수]]
하나의 <math>\left( W^Q, W^K, W^V \right)</math> 행렬 세트를 ''어텐션 헤드''라고 하며, 트랜스포머 모델의 각 계층에는 여러 어텐션 헤드가 있다. 각 어텐션 헤드는 각 토큰과 관련된 토큰에 어텐션하는 반면, 여러 어텐션 헤드는 모델이 "관련성"에 대한 다른 정의에 대해 이를 수행할 수 있도록 한다. 특히, 어텐션 점수 계산에 관여하는 쿼리 및 키 투영 행렬인 <math>W^Q</math> 및 <math>W^K</math>는 "관련성"을 정의한다. 한편, 값 투영 행렬 <math>W^V</math>는 출력 투영 행렬 <math>W^O</math>의 부분과 결합하여 어텐션된 토큰이 후속 계층 및 궁극적으로 출력 로짓으로 전달되는 정보에 어떤 영향을 미치는지 결정한다. 또한, 어텐션의 범위, 즉 각 어텐션 헤드가 포착하는 토큰 관계의 범위는 토큰이 연속적인 계층을 통과함에 따라 확장될 수 있다. 이를 통해 모델은 더 깊은 계층에서 더 복잡하고 장거리 의존성을 포착할 수 있다. 많은 트랜스포머 어텐션 헤드는 인간에게 의미 있는 관련성 관계를 인코딩한다. 예를 들어, 일부 어텐션 헤드는 주로 다음 단어에 어텐션하는 반면, 다른 어텐션 헤드는 주로 동사에서 직접 목적어에 어텐션한다. 각 어텐션 헤드에 대한 계산은 [[병렬 컴퓨팅|병렬로]] 수행될 수 있어 빠른 처리가 가능하다. 어텐션 레이어의 출력은 [[순방향 신경망]] 레이어로 전달되기 위해 연결된다.

구체적으로, 여러 어텐션 헤드가 <math>i</math>로 인덱싱된다고 하자. 그러면 다음과 같다.
<math display="block">\text{MultiheadedAttention}(Q, K, V) = \text{Concat}_{i \in [n_{\text{heads}}]}(\text{Attention}(XW^Q_i, XW^K_i, XW^V_i)) W^O</math> 여기서 행렬 <math>X</math>는 단어 임베딩의 연결이고, 행렬 <math>W^Q_i, W^K_i, W^V_i</math>는 개별 어텐션 헤드 <math>i</math>가 소유하는 "투영 행렬"이며, <math>W^O</math>는 전체 멀티헤드 어텐션 헤드가 소유하는 최종 투영 행렬이다.

이론적으로 각 어텐션 헤드가 다른 헤드 차원 <math>d_{\text{head}}</math>를 가질 수 있지만, 실제로는 거의 그렇지 않다.

예를 들어, 가장 작은 GPT-2 모델에는 자체 어텐션 메커니즘만 있다. 이 모델은 다음과 같은 차원을 가진다.
<math display="block">d_{\text{emb}} = 768, n_{\text{head}} = 12, d_{\text{head}} = 64</math>
<math>12 \times 64 = 768</math>이므로, 출력 투영 행렬 <math>W^O \in \R^{(12 \times 64) \times 768}</math>는 정방 행렬이다.

==== 마스크드 어텐션 ====
트랜스포머 아키텍처는 출력 토큰을 반복적으로 계산하도록 구성된다. <math>t = 0</math>이 첫 번째 출력 토큰 <math>i = 0</math>의 계산을 나타낸다고 가정하면, 단계 <math>t > 0</math>에서 출력 토큰 <math>i = 0</math>은 상수로 유지되어야 한다. 이는 모델의 속성이 [[자기회귀모형|자기회귀 모델]]과 유사하도록 보장한다. 따라서 모든 시간 단계 <math>t</math>에서 모든 출력 <math>i</math>에 대한 계산은 <math>j >= i</math>인 위치 <math>j</math>의 토큰에 접근할 수 없어야 한다 (시간 단계 <math>t=i</math>의 경우 토큰 <math>j>t</math>는 아직 계산되지 않았으므로 당연하다). 이 동작은 소프트맥스 단계 전에 어텐션 링크를 끊어야 하는 항목에는 <math>-\infty</math>를, 다른 항목에는 <math>0</math>을 갖는 마스크 행렬 <math>M</math>을 추가하여 달성할 수 있다.
<math display="block">\begin{align}
\text{MaskedAttention}(Q, K, V) = \text{softmax}\left(M + \frac{QK^\mathrm{T}}{\sqrt{d_k}}\right)V
\end{align}</math> 다음 행렬은 디코더 자체 어텐션 모듈에서 일반적으로 사용되며 "인과적 마스킹"이라고 불린다.
<math display="block">M_{\text{causal}} = \begin{bmatrix}
0 & -\infty & -\infty & \dots  & -\infty \\
0 & 0 & -\infty & \dots  & -\infty \\
0 & 0 & 0 & \dots  & -\infty \\
\vdots & \vdots & \vdots & \ddots & \vdots \\
0 & 0 & 0 & \dots  & 0
\end{bmatrix}
</math>

다시 말해, 각 토큰은 자신과 그 이전의 모든 토큰에 어텐션할 수 있지만, 그 이후의 토큰에는 어텐션할 수 없다. 마스크되지 않은 어텐션 모듈은 마스크의 모든 항목이 0인 마스크드 어텐션 모듈로 생각할 수 있다. 마스크 행렬의 흔치 않은 사용 예시로, [[XLNet]]은 <math>P M_{\text{causal}} P^{-1} </math> 형태의 모든 마스크를 고려하는데, 여기서 <math>P </math>는 무작위 [[치환행렬]]이다.

=== 인코더 ===
[[파일:Transformer,_one_encoder_block.png|섬네일|하나의 인코더 레이어]]
인코더는 임베딩 레이어와 여러 인코더 레이어로 구성된다.

각 인코더 레이어는 자체 어텐션 메커니즘과 순방향 레이어의 두 가지 주요 구성 요소로 구성된다. 이 레이어는 입력 벡터 시퀀스를 입력으로 받아 자체 어텐션 메커니즘을 적용하여 중간 벡터 시퀀스를 생성한 다음, 각 벡터에 개별적으로 순방향 레이어를 적용한다. 개략적으로 다음과 같다.
<math>\begin{aligned}
\text{given input vectors } & h_0, h_1, \dots\\
\text{combine them into a matrix } H &= \begin{bmatrix} h_0 \\ h_1 \\ \vdots \end{bmatrix} \\
\text{EncoderLayer}(H) &= \begin{bmatrix} \text{FFN}(\text{MultiheadedAttention}(H, H, H)_0) \\ \text{FFN}(\text{MultiheadedAttention}(H, H, H)_1) \\ \vdots \end{bmatrix} \\

\end{aligned}</math>

여기서 <math>\text{FFN}</math>은 "순방향 네트워크"를 나타낸다. 이를 더 간결하게 다음과 같이 쓸 수 있다.
<math display="block">\text{EncoderLayer}(H) = \text{FFN}(\text{MultiheadedAttention}(H, H, H))
</math>
<math>\text{FFN}</math>은 행렬의 각 행에 개별적으로 적용된다는 암묵적인 관례가 있다.

인코더 레이어는 쌓여 있다. 첫 번째 인코더 레이어는 임베딩 레이어에서 입력 벡터 시퀀스를 받아 벡터 시퀀스를 생성한다. 이 벡터 시퀀스는 두 번째 인코더에 의해 처리되고, 이런 식으로 계속된다. 최종 인코더 레이어의 출력은 디코더에 의해 사용된다.

인코더가 전체 입력을 한 번에 처리하므로 모든 토큰은 다른 모든 토큰에 어텐션할 수 있으므로(모든 대 모든 어텐션) 인과적 마스킹이 필요 없다.

=== 디코더 ===
[[파일:Transformer,_one_decoder_block.png|섬네일|하나의 디코더 레이어]]
디코더는 임베딩 레이어, 여러 디코더 레이어, 그리고 언임베딩 레이어로 구성된다.

각 디코더는 세 가지 주요 구성 요소로 구성된다: 인과적으로 마스킹된 자체 어텐션 메커니즘, 교차 어텐션 메커니즘, 그리고 순방향 신경망이다. 디코더는 인코더와 유사하게 작동하지만, 인코더가 생성한 인코딩에서 관련 정보를 추출하는 추가적인 어텐션 메커니즘이 삽입된다. 이 메커니즘은 ''인코더-디코더 어텐션''이라고도 불린다.

첫 번째 인코더와 마찬가지로, 첫 번째 디코더는 인코딩 대신 출력 시퀀스의 위치 정보와 임베딩을 입력으로 받는다. 트랜스포머는 출력을 예측하기 위해 현재 또는 미래의 출력을 사용해서는 안 되므로, 이러한 역방향 정보 흐름을 방지하기 위해 출력 시퀀스를 부분적으로 마스킹해야 한다. 이를 통해 [[자기회귀모형|자기회귀]] 텍스트 생성이 가능하다. 디코딩의 경우, 토큰이 아직 생성되지 않았으므로 토큰이 아직 생성되지 않은 토큰에 어텐션할 수 없기 때문에 모든 대 모든 어텐션은 부적절하다. 따라서 디코더의 자체 어텐션 모듈은 인과적으로 마스킹된다.

대조적으로, 교차 어텐션 메커니즘은 디코더가 디코딩을 시작하기 전에 계산되는 인코더의 출력 벡터에 어텐션한다. 결과적으로 교차 어텐션 메커니즘에서는 마스킹이 필요 없다.

개략적으로 다음과 같다.
<math display="block">\begin{aligned}
H' &= \text{MaskedMultiheadedAttention}(H, H, H) \\
\text{DecoderLayer}(H) &=\text{FFN}(\text{MultiheadedAttention}(H', H^E, H^E))
\end{aligned}
</math>
여기서 <math>H^E</math>는 행이 인코더의 출력 벡터인 행렬이다.

마지막 디코더 뒤에는 최종 언임베딩 레이어가 이어져 어휘에 대한 출력 확률을 생성한다. 그런 다음 확률에 따라 토큰 중 하나가 샘플링되고, 디코더를 다시 실행하여 다음 토큰을 생성하는 방식으로 자기회귀적으로 출력 텍스트를 생성할 수 있다.

=== 수정된 아키텍처 ===

많은 [[대형 언어 모델]]은 입력 시퀀스로부터 완전히 새로운 시퀀스를 예측할 필요가 없으므로, 원래 트랜스포머 아키텍처의 인코더 또는 디코더만 사용한다. 초기 [[GPT (언어 모델)|GPT]] 모델은 시퀀스의 다음 토큰을 예측하도록 훈련된 디코더-온리 모델이다. 다른 언어 모델인 [[BERT (언어 모델)|BERT]]는 인코더만 사용하며, 시퀀스에서 무작위로 마스킹된 토큰을 예측하도록 훈련된다.

== 전체 트랜스포머 아키텍처 ==

=== 서브레이어 ===
[[파일:Transformer,_stacked_multilayers.png|섬네일|(a) 하나의 인코더 레이어와 하나의 디코더 레이어. (b) 두 개의 인코더 레이어와 두 개의 디코더 레이어. 서브레이어도 레이블이 지정되어 있다.]]각 인코더 레이어는 자체 어텐션과 순방향 네트워크의 2개의 서브레이어를 포함한다. 각 디코더 레이어는 인과적으로 마스킹된 자체 어텐션, 교차 어텐션, 순방향 네트워크의 3개의 서브레이어를 포함한다.
[[파일:Transformer_encoder,_with_norm-first_and_norm-last.png|섬네일|노름 우선 및 노름 마지막이 있는 트랜스포머 인코더]]
[[파일:Transformer_decoder,_with_norm-first_and_norm-last.png|섬네일|노름 우선 및 노름 마지막이 있는 트랜스포머 디코더]]
[[파일:Transformer,_full_architecture.png|섬네일|전체 트랜스포머 아키텍처의 블록 다이어그램]][[파일:Transformer,_schematic_object_hierarchy,_for_implementation_in_object-oriented_programming.png|섬네일|[[객체 지향 프로그래밍]] 스타일로 구현하기 위한 전체 트랜스포머 아키텍처의 개략적인 [[객체 계층]] 구조]]마지막 세부 사항은 [[잔차 신경망|잔차 연결]]과 [[레이어 정규화]] (LayerNorm, 또는 LN)인데, 개념적으로는 불필요하지만 수치적 안정성과 수렴을 위해 필요하다.

소실 경사 문제를 피하고 훈련 과정을 안정화하기 위해 도입된 잔차 연결은 y = F(x) + x로 표현될 수 있다. 이 표현은 출력 y가 입력 x의 변환(F(x))과 입력 자체(x)의 합임을 나타낸다. 입력 x를 추가하면 입력 정보를 보존하고 F(x)의 경사가 거의 0에 가까울 때 발생하는 문제를 피할 수 있다.

순방향 네트워크 모듈이 각 벡터에 개별적으로 적용되는 것과 유사하게, 레이어 정규화(LayerNorm)도 각 벡터에 개별적으로 적용된다.

두 가지 일반적인 컨벤션이 사용된다: ''Post-LN''과 ''Pre-LN'' 컨벤션. Post-LN 컨벤션에서 각 서브레이어의 출력은 다음과 같다.
<math display="block">\mathrm{LayerNorm}(x + \mathrm{Sublayer}(x))</math>
여기서 <math>\mathrm{Sublayer}(x)</math>는 서브레이어 자체에서 구현된 함수이다.

Pre-LN 컨벤션에서 각 서브레이어의 출력은 다음과 같다.
<math display="block">x + \mathrm{Sublayer}(\mathrm{LayerNorm}(x))</math>
원래 2017년 트랜스포머는 Post-LN 컨벤션을 사용했다. 이는 훈련하기 어려웠고 신중한 [[하이퍼파라미터 (기계 학습)|하이퍼파라미터]] 튜닝과 학습률의 "웜업"이 필요했는데, 이는 학습률이 작게 시작하여 점진적으로 증가하는 방식이었다. 2018년에 여러 차례 제안된 Pre-LN 컨벤션은 웜업이 필요 없이 훈련하기 더 쉽고 더 빠른 수렴을 이끌어낸다는 것이 밝혀졌다.

=== 의사 코드 ===
다음은 표준 Pre-LN 인코더-디코더 트랜스포머의 의사 코드이며에서 발췌했다.
 **입력:** 인코더 입력 t_e
        디코더 입력 t_d
 **출력:** 확률 분포 배열 (디코더 어휘 크기 x 디코더 출력 시퀀스 길이)

 /* 인코더 */
 z_e ← encoder.tokenizer(t_e)

 **각** t **에 대해** 1:length(z_e) **반복**
     z_e[t] ← encoder.embedding(z_e[t]) + encoder.positional_embedding(t)

 **각** l **에 대해** 1:length(encoder.layers) **반복**
     layer ← encoder.layers[l]

     /* 첫 번째 서브레이어 */
     z_e_copy ← copy(z_e)
     **각** t **에 대해** 1:length(z_e) **반복**
         z_e[t] ← layer.layer_norm(z_e[t])
     z_e ← layer.multiheaded_attention(z_e, z_e, z_e)
     **각** t **에 대해** 1:length(z_e) **반복**
         z_e[t] ← z_e[t] + z_e_copy[t]

     /* 두 번째 서브레이어 */
     z_e_copy ← copy(z_e)
     **각** t **에 대해** 1:length(z_e) **반복**
         z_e[t] ← layer.layer_norm(z_e[t])
     z_e ← layer.feedforward(z_e)
     **각** t **에 대해** 1:length(z_e) **반복**
         z_e[t] ← z_e[t] + z_e_copy[t]

 **각** t **에 대해** 1:length(z_e) **반복**
     z_e[t] ← encoder.final_layer_norm(z_e[t])

 /* 디코더 */
 z_d ← decoder.tokenizer(t_d)

 **각** t **에 대해** 1:length(z_d) **반복**
     z_d[t] ← decoder.embedding(z_d[t]) + decoder.positional_embedding(t)

 **각** l **에 대해** 1:length(decoder.layers) **반복**
         layer ← decoder.layers[l]

         /* 첫 번째 서브레이어 */
         z_d_copy ← copy(z_d)
         **각** t **에 대해** 1:length(z_d) **반복**
             z_d[t] ← layer.layer_norm(z_d[t])
         z_d ← layer.masked_multiheaded_attention(z_d, z_d, z_d)
         **각** t **에 대해** 1:length(z_d) **반복**
             z_d[t] ← z_d[t] + z_d_copy[t]

         /* 두 번째 서브레이어 */
         z_d_copy ← copy(z_d)
         **각** t **에 대해** 1:length(z_d) **반복**
             z_d[t] ← layer.layer_norm(z_d[t])
         z_d ← layer.multiheaded_attention(z_d, z_e, z_e)
         **각** i **에 대해** 1:length(z_d) **반복**
             z_d[t] ← z_d[t] + z_d_copy[t]

         /* 세 번째 서브레이어 */
         z_d_copy ← copy(z_d)
         **각** t **에 대해** 1:length(z_d) **반복**
             z_d[t] ← layer.layer_norm(z_d[t])
         z_d ← layer.feedforward(z_d)
         **각** t **에 대해** 1:length(z_d) **반복**
             z_d[t] ← z_d[t] + z_d_copy[t]

 z_d ← decoder.final_layer_norm(z_d)

 output_distributions ← []
 **각** t **에 대해** 1:length(z_d) **반복**
     output_distributions.append(decoder.unembed(z_d[t]))

 **return** output_distributions

=== 용어 ===
트랜스포머 아키텍처는 모듈화되어 다양한 변형을 허용한다. 몇 가지 일반적인 변형이 여기에 설명되어 있다.

"인코더-온리" 트랜스포머는 인코더를 적용하여 입력 텍스트를 입력 텍스트를 나타내는 벡터 시퀀스로 매핑한다. 이는 일반적으로 텍스트 임베딩 및 후속 애플리케이션을 위한 [[특징 학습|표현 학습]]에 사용된다. [[BERT (언어 모델)|BERT]]는 인코더-온리이다. 인코더-디코더 트랜스포머를 훈련한 다음 인코더만 사용하는 것보다 훨씬 좋지 않다는 것이 밝혀졌으므로 현재는 덜 사용된다.

"디코더-온리" 트랜스포머는 문자 그대로 디코더-온리가 아니다. 인코더가 없으면 교차 어텐션 메커니즘은 어텐션할 대상이 없다. 따라서 디코더-온리 트랜스포머의 디코더 레이어는 인과적으로 마스킹된 자체 어텐션과 순방향 네트워크라는 두 개의 서브레이어로만 구성된다. 이는 일반적으로 [[자연어 생성|텍스트 생성]] 및 [[대형 언어 모델#명령 튜닝|명령 따르기]]에 사용된다. [[GPT (언어 모델)|GPT 시리즈]] 및 [[친칠라 (언어 모델)|친칠라 시리즈]]의 모델은 디코더-온리이다.

"인코더-디코더" 트랜스포머는 일반적으로 원본 트랜스포머와 동일하며, 각 인코더 레이어당 2개의 서브레이어와 각 디코더 레이어당 3개의 서브레이어 등이 있다. [[#대체 활성화 함수|대체 활성화 함수]], [[#Pre-LN|정규화 위치 변경]] 등과 같은 사소한 아키텍처 개선 사항이 있을 수 있다. 이는 일반적으로 텍스트 생성 및 명령 따르기에도 사용된다. [[T5 (언어 모델)|T5 시리즈]]의 모델은 인코더-디코더이다.

"prefixLM" (접두사 언어 모델)은 디코더 전용 아키텍처이지만, 인과적 마스킹과 다른 접두사 마스킹을 사용한다.<math display="block">M_{\text{prefixLM}} = \begin{bmatrix}
\mathbf{0} &  -\infty \\
\mathbf{0} & M_{\text{causal}}
\end{bmatrix}
</math>
여기서 첫 번째 열은 "접두사"에 해당하고, 이어지는 열은 접두사를 기반으로 자기회귀적으로 생성된 텍스트에 해당한다. 이는 인코더-디코더 모델과 유사하지만 "희소성"이 적다. 이러한 모델은 이론적 가능성 및 벤치마크 비교로 인용되기는 하지만 거의 사용되지 않는다.

혼합형 seq2seq 모델도 있다. 예를 들어, 2020년 구글 번역은 RNN-디코더가 자기회귀적으로 실행될 때 트랜스포머-디코더보다 훨씬 빠르게 실행된다는 주장에 따라 이전 RNN-인코더-RNN-디코더 모델을 트랜스포머-인코더-RNN-디코더 모델로 교체했다.

== 후속 연구 ==
=== 대체 활성화 함수 ===
원래 트랜스포머는 [[ReLU]] [[활성화 함수]]를 사용한다. 다른 활성화 함수들이 개발되었다. [[LLaMA|라마 시리즈]]와 [[PaLM]]은 SwiGLU를 사용했고; GPT-1과 BERT 모두 GELU를 사용했다.

대체 활성화 함수는 순방향 모듈에서 [[게이트 선형 단위]]와 함께 사용되는 경우가 많다.

=== 대체 정규화 ===
트랜스포머에 사용되는 정규화는 레이어 정규화(LayerNorm)와 다를 수 있다. 한 가지 예는 [[LLaMA|라마 시리즈]]에서 사용되는 [[RMSNorm]]이다. 다른 예로는 CapsuleNorm ScaleNorm, 또는 FixNorm.

=== 대체 위치 인코딩 ===
트랜스포머는 사인파형 외에 다른 위치 인코딩 방법을 사용할 수 있다.

원래 트랜스포머 논문에서는 학습된 위치 인코딩을 사용했다고 보고했지만, 사인파형 인코딩보다 우수하지 않다는 것을 발견했다. 이후,는 인과적 마스킹 자체가 트랜스포머 디코더에 충분한 신호를 제공하여 위치 인코딩 모듈 없이도 절대 위치 인코딩을 암시적으로 수행할 수 있음을 발견했다.

==== RoPE ====
RoPE (회전 위치 임베딩)는 2차원 벡터 목록 <math>[(x^{(1)}_1, x^{(2)}_1), (x^{(1)}_2, x^{(2)}_2), (x^{(1)}_3, x^{(2)}_3), ...]</math>를 고려하면 가장 잘 설명된다. 이제 어떤 각도 <math>\theta</math>를 선택한다. 그러면 RoPE 인코딩은 다음과 같다.
<math display="block">\text{RoPE}\big(x^{(1)}_m, x^{(2)}_m, m\big) =
\begin{pmatrix}    \cos m \theta & - \sin m \theta \\
\sin m \theta & \cos m \theta    \end{pmatrix}
\begin{pmatrix}    x^{(1)}_m \\    x^{(2)}_m \\    \end{pmatrix}  =    \begin{pmatrix}    x^{(1)}_m \cos m\theta - x^{(2)}_m \sin m \theta \\    x^{(2)}_m \cos m\theta + x^{(1)}_m \sin m \theta \\    \end{pmatrix}
</math>
동등하게, 2차원 벡터를 복소수 <math>z_m := x^{(1)}_m + i x^{(2)}_m</math>로 작성하면, RoPE 인코딩은 단순히 각도 곱셈이다.
<math display="block">\text{RoPE}\big(z_m, m\big) = e^{i m\theta} z_m
</math>
<math>2n</math>차원 벡터 목록의 경우, RoPE 인코더는 각도 시퀀스 <math>\theta^{(1)}, ..., \theta^{(n)}</math>에 의해 정의된다. 그러면 RoPE 인코딩은 각 좌표 쌍에 적용된다.

RoPE의 이점은 두 벡터 간의 점곱이 상대적 위치에만 의존한다는 것이다.
<math display="block">
\text{RoPE}\big(x, m\big)^T\text{RoPE}\big(y, n\big)
=
\text{RoPE}\big(x, m+k\big)^T\text{RoPE}\big(y, n+k\big)
</math>
어떤 정수 <math>k</math>에 대해서도 마찬가지이다.

==== ALiBi ====
ALiBi (Attention with Linear Biases)는 원래 트랜스포머의 위치 인코더를 ''대체하는'' 것이 아니다. 대신, 어텐션 메커니즘에 직접 연결되는 ''추가적인'' 위치 인코더이다. 구체적으로, ALiBi 어텐션 메커니즘은 다음과 같다.
<math display="block">\begin{align}
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\mathrm{T}}{\sqrt{d_k}} + s B\right)V
\end{align}</math>
여기서 <math>s</math>는 실수("스칼라")이고, <math>B</math>는 다음과 같이 정의되는 ''선형 편향'' 행렬이다.
<math display="block">B = \begin{pmatrix}
0 & 1 & 2 & 3 & \cdots \\
-1 & 0 & 1 & 2 & \cdots \\
-2 & -1 & 0 & 1 & \cdots \\
-3 & -2 & -1 & 0 & \cdots \\
\vdots & \vdots & \vdots & \vdots & \ddots \\
\end{pmatrix}
</math>
다른 말로, <math>B_{i, j} = j - i</math>이다. 선형 편향 행렬은 부드러운 마스크라는 아이디어이다. <math>0</math>은 완전한 어텐션을 나타내고, <math>-\infty</math>는 어텐션을 나타내지 않는 것처럼, 선형 편향 행렬은 한 방향으로는 어텐션을 증가시키고 다른 방향으로는 어텐션을 감소시킨다.

ALiBi는 짧은 컨텍스트 창에서 사전 훈련한 다음, 더 긴 컨텍스트 창에서 미세 조정하는 것을 가능하게 한다. 어텐션 메커니즘에 직접 연결되기 때문에 전체 네트워크의 "바닥"에 연결되는 모든 위치 인코더 (원본 트랜스포머의 사인파 인코더, RoPE 및 기타 여러 가지)와 결합할 수 있다.

==== 상대 위치 인코딩 ====
상대 위치 인코딩은 ALiBi와 유사하지만 더 일반적이다.
<math display="block">\begin{align}
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\mathrm{T}}{\sqrt{d_k}} + B\right)V
\end{align}</math>
여기서 <math>B</math>는 [[퇴플리츠 행렬]]이며, 즉 <math>i-j = i'-j'</math>일 때마다 <math>B_{i, j} = B_{i', j'}</math>이다. 이는 "절대 위치 인코딩"인 원래의 사인파 위치 인코딩과 대조된다.

=== 효율적인 구현 ===
트랜스포머 모델은 [[텐서플로]] 및 [[PyTorch]]와 같은 표준 [[프레임워크 (컴퓨터 과학)|딥 러닝 프레임워크]]에 구현되었다. ''트랜스포머''는 [[허깅 페이스]]가 개발한 라이브러리로, 트랜스포머 기반 아키텍처와 사전 훈련된 모델을 제공한다.

==== KV 캐싱 ====
자기회귀 트랜스포머가 텍스트 생성과 같은 추론에 사용될 때, 쿼리 벡터는 각 단계에서 다르지만, 이미 계산된 키 및 값 벡터는 항상 동일하다. **KV 캐싱** 방법은 각 어텐션 블록에서 계산된 키 및 값 벡터를 저장하여 각 새 토큰에서 다시 계산되지 않도록 한다. **PagedAttention*'은 KV 캐싱에 [[페이징|메모리 페이징]]을 적용한다.

["당신은 고객 지원 상담원입니다..."]와 같이 내장된 프롬프트와 함께 트랜스포머가 사용되는 경우, 프롬프트에 대한 키 및 값 벡터를 계산하고 디스크에 저장할 수 있다. 모델이 온라인 챗봇과 같이 많은 짧은 상호 작용에 사용될 때 계산 절약은 상당하다.

==== FlashAttention ====
FlashAttention는 GPU에서 트랜스포머 어텐션 메커니즘을 효율적으로 구현하는 알고리즘이다. 이는 [[블록 행렬#블록 행렬 연산|블록 단위로 행렬 곱셈]]을 수행하여 각 블록이 GPU의 [[캐시]] 내에 맞도록 하고, 블록을 신중하게 관리하여 GPU 캐시 간의 데이터 복사를 최소화하는 (데이터 이동이 느리기 때문에) 통신 회피 알고리즘이다. 자세한 내용은 [[소프트맥스 함수#수치 알고리즘|소프트맥스]] 페이지를 참조한다.

개선된 버전인 FlashAttention-2는 더 긴 컨텍스트 길이를 처리할 수 있는 언어 모델에 대한 증가하는 수요를 충족시키기 위해 개발되었다. 작업 분할 및 병렬 처리 개선을 제공하여 [[Nvidia A100|A100]] GPU ([[FP16]]/[[BF16]])에서 최대 230 TFLOPs/s를 달성하여 원래 FlashAttention보다 2배 빠른 속도를 제공한다.

FlashAttention-2의 주요 발전 사항은 비-행렬 곱셈 FLOPS 감소, 시퀀스 길이 차원에 대한 병렬 처리 개선, GPU 워프 간의 더 나은 작업 분할, 그리고 최대 256의 헤드 차원과 멀티 쿼리 어텐션(MQA) 및 그룹 쿼리 어텐션(GQA)에 대한 추가 지원을 포함한다.

벤치마크 결과 FlashAttention-2는 FlashAttention보다 최대 2배 빠르고 PyTorch의 표준 어텐션 구현보다 최대 9배 빠르다. 향후 개발에는 [[Nvidia H100|H100]] GPU와 FP8과 같은 새로운 데이터 유형과 같은 새로운 하드웨어에 대한 최적화가 포함된다.

==== 멀티 쿼리 어텐션 ====

[[파일:DeepSeek KV cache comparison between MHA, GQA, MQA, MLA.svg|섬네일|몇 가지 다른 어텐션 메커니즘 형태와 각 형태에 필요한 KV 캐싱 양의 비교]]
멀티 쿼리 어텐션은 멀티헤드 어텐션 메커니즘을 변경한다. 보통은 다음과 같지만,

<math display="block">\text{MultiheadedAttention}(Q, K, V) = \text{Concat}_{i \in [n_{\text{heads}}]}\left(\text{Attention}(XW^Q_i, XW^K_i, XW^V_i)\right) W^O</math>
멀티 쿼리 어텐션에서는 <math>W^K, W^V</math>가 하나만 있으므로 다음과 같다.

<math display="block">\text{MultiQueryAttention}(Q, K, V) = \text{Concat}_{i \in [n_{\text{heads}}]}\left(\text{Attention}(XW^Q_i, XW^K, XW^V)\right) W^O</math>

이는 모델 품질과 훈련 속도에 중립적인 영향을 미치지만, 추론 속도를 향상시킨다.

더 일반적으로, 그룹 쿼리 어텐션(GQA)은 어텐션 헤드를 그룹으로 나누며, 각 그룹은 키-값 쌍을 공유한다. MQA는 그룹이 하나인 GQA이고, 표준 멀티헤드 어텐션은 그룹 수가 최대인 GQA이다.
[[파일:DeepSeek_MoE_and_MLA_(DeepSeek-V2).svg|섬네일|V2 아키텍처, MLA와 [[전문가 혼합]] 변형을 모두 보여준다.]]

멀티헤드 잠재 어텐션(MLA)은 표준 MHA의 [[저계수 근사]]이다. 구체적으로, 각 은닉 벡터는 어텐션 메커니즘에 들어가기 전에 먼저 두 개의 저차원 공간("잠재 공간")으로 투영되는데, 하나는 쿼리용이고 다른 하나는 키-값(KV 벡터)용이다. 이 설계는 KV 캐시를 최소화한다. 왜냐하면 저차원 KV 벡터만 캐시하면 되기 때문이다.

==== 추론적 디코딩 ====
추론적 디코딩은 토큰 디코딩 속도를 높이는 방법이다. [[투기적 실행|CPU의 투기적 실행]]과 유사하게, 미래 토큰은 빠르게 계산된 다음 검증된다. 빠르게 계산된 토큰이 부정확하면 폐기되고 느리게 다시 계산된다.

추론적 디코딩의 핵심은 트랜스포머 디코더가 다음과 같은 의미에서 디코딩하는 것보다 더 빠르게 검증할 수 있다는 점이다.

GPT-3 및 GPT-3-small과 같이 컨텍스트 창 크기가 512인 두 개의 트랜스포머 모델이 있다고 가정하자. GPT-3로 전체 컨텍스트 창을 탐욕적 디코딩으로 자기회귀적으로 생성하려면, 각 토큰 <math>x_1, x_2, ..., x_{512}</math>를 생성할 때마다 512번 실행되어야 하며, 총 시간은 <math>512 T_{\text{GPT-3}}</math>가 걸린다. 그러나 이러한 토큰 값에 대해 교육받은 추측이 있다면, 모델을 한 번 실행하여 모든 토큰을 병렬로 검증할 수 있다. 각 <math>x_t</math>가 실제로 <math>t</math>번째 출력에서 가장 큰 로그 우도(log-likelihood)를 가진 토큰인지 확인하는 것이다.

추론적 디코딩에서는 더 작은 모델이나 다른 간단한 휴리스틱을 사용하여 몇 개의 추론적 토큰을 생성한 다음 더 큰 모델에 의해 검증된다. 예를 들어, GPT-3-small을 사용하여 네 개의 추론적 토큰 <math>\tilde{x}_1, \tilde{x}_2, \tilde{x}_3, \tilde{x}_4</math>를 생성한다고 가정하자. 이는 <math>4 T_{\text{GPT-3-small}}</math>만 소요된다. 이 토큰들은 더 큰 GPT-3를 통해 한 번에 실행된다. <math>\tilde{x}_1</math>과 <math>\tilde{x}_2</math>가 GPT-3에 의해 선택될 것이라고 확인되면 이들은 유지되지만, <math>\tilde{x}_3</math>은 그렇지 않으므로 <math>\tilde{x}_3, \tilde{x}_4</math>는 폐기되고, GPT-3는 이들에 대해 실행된다. 이 경우 <math>4 T_{\text{GPT-3-small}} + 3 T_{\text{GPT-3}}</math>가 소요되며, 이는 <math>4 T_{\text{GPT-3}}</math>보다 짧을 수 있다.

비탐욕적 디코딩의 경우, 유사한 아이디어가 적용되지만, 추론적 토큰은 확률적으로 수용되거나 거부되며, 이는 최종 출력 분포가 추론적 디코딩을 사용하지 않은 경우와 동일하도록 보장하는 방식으로 이루어진다.
[[파일:Multi-Token Prediction (DeepSeek) 01.svg|섬네일|멀티 토큰 예측]]
멀티 토큰 예측에서 단일 순방향 패스는 최종 임베딩 벡터를 생성하며, 이 벡터는 다시 토큰 확률로 언임베딩된다. 그러나 이 벡터는 다른 트랜스포머 블록에 의해 추가로 처리되어 다음 토큰을 예측할 수 있으며, 미래의 임의의 많은 단계에 대해 이러한 방식으로 계속될 수 있다. 이는 각 새 토큰이 전체 스택이 아닌 단 하나의 트랜스포머 블록만 비용을 지불하므로 정확도를 속도와 교환하는 것이다.

=== 이차 미만 트랜스포머 ===
트랜스포머 기반 아키텍처 훈련은 특히 긴 입력의 경우 비용이 많이 들 수 있다. 이 문제를 해결하기 위해 많은 방법이 개발되었다. 이미지 도메인에서 Swin Transformer는 이동 창 내에서 어텐션을 수행하는 효율적인 아키텍처이다. 오디오 도메인에서 SepTr은 시간 및 주파수 도메인에서 어텐션을 분리한다. *Long Range Arena'' (2020)는 긴 입력에 대한 트랜스포머 아키텍처의 동작을 비교하는 표준 벤치마크이다.

#### 대체 어텐션 그래프
표준 어텐션 그래프는 모든 대 모든 또는 인과적이며, 둘 다 N이 시퀀스의 토큰 수일 때 O(N^2)로 스케일링된다.

리포머 (2020)는 지역 민감 해싱과 가역 계층을 사용하여 계산 부하를 O(N^2)에서 O(N\ln N)으로 줄인다.

희소 어텐션은 O(N^2)보다 느리게 증가하는 어텐션 그래프를 사용한다. 예를 들어, BigBird (2020)는 O(N)로 증가하는 무작위 작은 세상 네트워크를 사용한다.

일반 트랜스포머는 컨텍스트 창 크기에 대해 이차적인 메모리 크기를 필요로 한다. 어텐션이 없는 트랜스포머는 키를 값에 연결하여 이를 선형 종속성으로 줄이면서도 트랜스포머의 장점을 유지한다.

#### 랜덤 특징 어텐션
랜덤 특징 어텐션(Random Feature Attention) (2021)은 푸리에 랜덤 특징을 사용한다.
\varphi(x) = \frac{1}{\sqrt D}[\cos\langle w_1, x\rangle, \sin\langle w_1, x\rangle, \cdots \cos\langle w_D, x\rangle, \sin\langle w_D, x\rangle]^T
여기서 w_1, ..., w_D는 정규 분포 N(0, \sigma^2 I)에서 독립적으로 샘플링된 것이다. 이러한 매개변수 선택은 \mathbb E[\langle \varphi(x), \varphi(y)\rangle] = e^{-\frac{\|x-y\|^2}{2\sigma^2}} 또는 다음과 같이 만족한다.
e^{\langle x, y\rangle/\sigma^2} = \mathbb E[\langle e^{\|x\|^2/2\sigma^2} \varphi(x), e^{\|y\|^2/2\sigma^2}\varphi(y)\rangle] \approx \langle e^{\|x\|^2/2\sigma^2} \varphi(x), e^{\|y\|^2/2\sigma^2}\varphi(y)\rangle 
결과적으로, 하나의 쿼리를 가진 단일 헤드 어텐션은 다음과 같이 쓸 수 있다.

\text{Attention}(q, K, V) = \text{softmax}\left(\frac{qK^\mathrm{T}}{\sqrt{d_k}}\right)V

\approx \frac{\varphi(q)^T \sum_i e^{\|k_i\|^2/2\sigma^2}\varphi(k_i) v_i^T}{\varphi(q)^T \sum_i e^{\|k_i\|^2/2\sigma^2}\varphi(k_i)}
여기서 \sigma = d_K^{1/4}이다. 여러 쿼리 및 멀티헤드 어텐션도 마찬가지이다.

이 근사치는 선형 시간으로 계산될 수 있는데, 이는 행렬 \varphi(k_i) v_i^T를 먼저 계산한 다음 쿼리와 곱할 수 있기 때문이다. 본질적으로 다음과 같은 더 정확한 버전을 얻을 수 있었다.
\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^\mathrm{T}}{\sqrt{d_k}}\right)V \approx Q(K^TV/\sqrt{d_k})

퍼포머(Performer) (2022)는 동일한 랜덤 특징 어텐션을 사용하지만, w_1, ..., w_D는 먼저 정규 분포 N(0, \sigma^2 I)에서 독립적으로 샘플링된 다음, 그람-슈미트 처리된다.

### 멀티모달리티
트랜스포머는 텍스트를 넘어선 모달리티(입력 또는 출력)에도 사용/적용될 수 있으며, 일반적으로 모달리티를 "토큰화"하는 방법을 찾는 방식으로 이루어진다.

멀티모달 모델은 처음부터 훈련되거나 미세 조정을 통해 훈련될 수 있다. 2022년 연구에서는 자연어만으로 사전 훈련된 트랜스포머를 매개변수의 0.03%만으로 미세 조정하여 다양한 논리 및 시각 작업에서 LSTM과 경쟁할 수 있음을 발견하여 전이학습을 입증했다. LLaVA는 언어 모델(Vicuna-13B)과 비전 모델(ViT-L/14)로 구성된 시각-언어 모델이며, 선형 계층으로 연결된다. 선형 계층만 미세 조정된다.

비전 트랜스포머는 입력 이미지를 일련의 패치로 분해하고, 이를 벡터로 변환하여 표준 트랜스포머의 토큰처럼 처리함으로써 트랜스포머를 컴퓨터 비전에 적용한다.

컨포머(Conformer)와 이후의 휘스퍼는 음성 인식에 대해 동일한 패턴을 따르며, 먼저 음성 신호를 스펙트로그램으로 변환한 다음, 이를 이미지처럼 처리한다. 즉, 일련의 패치로 분해하고 벡터로 변환하여 표준 트랜스포머의 토큰처럼 처리한다.

퍼시버는 멀티모달리티를 위해 설계된 트랜스포머의 변형이다.

이미지 생성을 위한 주목할 만한 아키텍처로는 DALL-E 1 (2021), Parti (2022), Phenaki (2023), 및 Muse (2023)가 있다. 이후 모델과 달리 DALL-E는 확산 모델이 아니다. 대신, 자기회귀적으로 텍스트를 생성한 다음 이미지의 토큰 표현으로 변환하고, 이를 변분 오토인코더로 이미지로 변환하는 디코더-온리 트랜스포머를 사용한다. Parti는 인코더-디코더 트랜스포머로, 인코더는 텍스트 프롬프트를 처리하고 디코더는 이미지의 토큰 표현을 생성한다. Muse는 마스킹되지 않은 이미지 토큰으로부터 마스킹된 이미지 토큰을 예측하도록 훈련된 인코더-온리 트랜스포머이다. 생성 중에 모든 입력 토큰은 마스킹되며, 가장 높은 신뢰도의 예측은 다음 반복에 포함되어 모든 토큰이 예측될 때까지 계속된다. Phenaki는 텍스트-비디오 모델이다. 이는 사전 계산된 텍스트 토큰을 조건으로 하는 양방향 마스크드 트랜스포머이다. 생성된 토큰은 비디오로 디코딩된다.

## 응용 분야
트랜스포머는 자연어 처리 (NLP) 분야에서 큰 성공을 거두었다. GPT-2, GPT-3, GPT-4, 제미나이, AlbertAGPT, 클로드, BERT, 그록, XLNet, RoBERTa 및 챗GPT와 같은 많은 대형 언어 모델은 다양한 NLP 관련 하위 작업 및 관련 실제 응용 프로그램에서 트랜스포머의 능력을 보여주었다. 다음을 포함한다.
* 기계 번역
* 시계열 예측
* 문서 요약
* 문서 생성
* 개체명 인식 (NER)
* 자연어로 표현된 요구 사항을 기반으로 컴퓨터 코드 작성.
* 음성 인식

전통적인 NLP 외에도 트랜스포머 아키텍처는 다음과 같은 다른 응용 분야에서 성공을 거두었다.
* 생물학적 서열 분석
* 비디오 이해
* 단백질 구조 예측 (알파폴드 등)
* 체스판 위치 평가. 정적 평가만 사용했을 때 (즉, 최소극대화 탐색 없이) 트랜스포머는 엘로 2895점을 달성하여 그랜드마스터 수준에 도달했다.

## 같이 보기
* 
* 
* 
* 
* 
* 
* 

## 참고 문헌

* Alexander Rush, The Annotated transformer , Harvard NLP group, 3 April 2018
* 
* 
* 

## 각주
;내용주

;참조주

분류:인공신경망
분류:구글의 소프트웨어