임베딩은 함수가 아니라 룩업입니다
토크나이저 뒤의 첫 번째 레이어
토크나이저는 모델에 정수 ID를 전달합니다: [256, 1842, 7301, ...]. 트랜스포머가 가장 먼저 하는 일은 각 ID를 d_model 크기의 실수 벡터로 변환하는 것입니다. 이 벡터는 d_model 차원의 공간에 존재합니다 (ANDREA-120M의 경우 768차원).
임베딩 레이어는 룩업 테이블이지 함수가 아닙니다. 거대한 행렬을 상상해 보세요:
shape: (V, d_model)
row 0: [e_0_0, e_0_1, ..., e_0_767]
row 1: [e_1_0, e_1_1, ..., e_1_767]
...
row 8448: [e_8448_0, e_8448_1, ..., e_8448_767]
토큰 ID i가 행 i를 선택합니다. 직접적인 배열 접근. 산술 연산 없음, 활성화 함수 없음. 단지 인덱스일 뿐입니다.
학습 가능한 실수
해당 표의 모든 항목은 작은 무작위 실수로 시작합니다(보통 d_model의 제곱근으로 스케일링된 정규 분포에서 추출). 배치에 해당 토큰 ID가 나타날 때마다 역전파가 각 행을 업데이트합니다. 학습이 끝나면 유사한 토큰(cat, dog, pet)은 유사한 벡터를 갖게 되고, 관련 없는 토큰(cat, Tuesday, xylophone)은 벡터 공간에서 멀리 떨어져 있게 됩니다.
ANDREA-120M 토큰 임베딩 비용
| 수량 | 값 |
|---|---|
| V | 8,449 |
| d_model | 768 |
| 파라미터 | 6,488,832 |
토큰 임베딩 테이블에만 대략 650만 개의 파라미터가 존재하며, 이는 ANDREA-120M 전체 파라미터의 약 5.4%에 해당합니다. 어휘집의 각 슬롯은 768개의 실수 값을 갖습니다.
임베딩 테이블 크기 계산
Dot Products Measure Similarity
벡터를 화살표로 표현하기
768차원 벡터는 인간이 시각화할 수 없는 공간에 존재하지만, 동일한 대수 연산은 모든 차원에서 동일하게 적용됩니다. 트랜스포머에서 중요한 두 가지 연산은 다음과 같습니다:
크기 (화살표의 길이):
||v|| = sqrt(v_0² + v_1² + ... + v_767²)
내적 (두 벡터 사이의 정렬 정도):
u · v = u_0 × v_0 + u_1 × v_1 + ... + u_767 × v_767
내적이 알려주는 것
어떤 차원에서도 성립하는 두 가지 사실:
- u · v = ||u|| × ||v|| × cos(theta), 여기서 theta는 두 벡터 사이의 각도입니다.
- 같은 방향을 가리키는 벡터들은 큰 양의 내적 값을 가집니다.
- 반대 방향을 가리키는 벡터들은 큰 음의 내적 값을 가집니다.
- 직각을 이루는 벡터들은 내적 값이 0이 됩니다.
내적 = 정규화되지 않은 유사도. 학습된 토큰 임베딩 cat과 dog는 높은 내적 값을 가지게 되는데, 이는 역전파가 두 임베딩을 서로 가깝게 밀어냈기 때문입니다(둘 다 애완동물 관련 문맥을 예측). 반면 cat과 Tuesday는 서로 다른 문맥을 예측하므로 거의 직교(orthogonal)하게 됩니다.
트랜스포머가 주목하는 이유
Activity 5 (grow_a_language_model_attention)는 어텐션을 내적(dot product)으로 구성합니다: 쿼리 벡터와 키 벡터의 내적은 다음 토큰을 예측할 때 어떤 과거 토큰이 중요한지를 나타내는 점수를 생성합니다. 임베딩과 내적은 트랜스포머 내부의 모든 상호작용을 담당합니다.
유사도 예측하기
ANDREA는 학습된 위치 임베딩을 사용합니다
문제
토큰 임베딩은 모델에게 이 위치에 어떤 단어가 있는지 알려줍니다. 하지만 그 단어가 어디에 위치하는지는 알려주지 않습니다. 위치 정보가 없으면 트랜스포머는 the cat sat on a mat와 mat a on sat cat the를 동일하게 처리합니다. 같은 토큰 집합이지만 순서 신호가 없습니다.
트랜스포머 문헌에는 세 가지 해결책이 존재합니다:
사인파(Sinusoidal) (Vaswani 2017). 사인과 코사인을 기반으로 한 고정된 수학 공식입니다. 위치 0은 특정 768-벡터를 받고, 위치 1은 다른 벡터를 받습니다. 학습되지 않고 업데이트되지도 않습니다. 공식을 통해 어떤 위치로도 일반화할 수 있습니다.
RoPE (Rotary Position Embedding). 위치에 따라 쿼리와 키 벡터를 회전시킵니다. LLaMA, Qwen에서 사용됩니다. 추가 파라미터가 필요 없으며, 회전 연산이 어텐션에 내장되어 있습니다.
Learned. (T, d_model) 형태의 별도 임베딩 테이블로, T는 컨텍스트 길이입니다. 각 행은 토큰 임베딩처럼 역전파를 통해 학습됩니다.
ANDREA's Choice: Learned
ANDREA는 microGPT에서 물려받은 learned-position 방식을 사용하며, microGPT는 nanoGPT, nanoGPT는 GPT-2에서 물려받았습니다. 그 이유는 다음과 같습니다:
- 단순함. 어텐션에 특별한 수학 연산이 필요하지 않습니다. 위치 테이블은 토큰 테이블과 동일하게 보입니다.
- 커스텀 CUDA와의 호환성. ANDREA의 microgpt_cuda.cu 엔진은 두 임베딩 조회를 동일하게 처리합니다. sin/cos 커널이 필요하지 않습니다.
- 고정 컨텍스트에 충분함. ANDREA는 T를 1024로 제한합니다. 학습된 테이블은 고정 길이 시퀀스에 잘 작동합니다.
ANDREA-120M 위치 임베딩 비용
| 수량 | 값 |
|---|---|
| T (context) | 1,024 |
| d_model | 768 |
| Parameters | 786,432 |
위치에 대한 0.79M 파라미터. 토큰 임베딩과 결합: 6.49M + 0.79M = 총 임베딩 파라미터 7.27M (ANDREA-120M 기준).
결합 방식
입력 시퀀스의 각 위치 t에서:
x_t = token_embedding[token_id_t] + position_embedding[t]
두 개의 768-벡터를 요소별로 더합니다. 결과인 x_t는 첫 번째 트랜스포머 블록으로 흘러갑니다. 모델은 이들을 다시 분리하지 않으며, 결합된 신호를 활용하는 방법을 학습합니다.
학습된 위치 임베딩 vs 사인 곡선 위치 임베딩
Where Embedding Parameters Live
A Full ANDREA-120M Embedding Layer
| Component | Shape | Parameters |
|---|---|---|
| 토큰 임베딩 테이블 | 8,449 × 768 | 6,488,832 |
| 위치 임베딩 테이블 | 1,024 × 768 | 786,432 |
| 총계 | 7,275,264 |
대략 730만 개의 파라미터. ANDREA-120M의 전체 파라미터 수: 약 1억 2천만. 임베딩 레이어 단독: 6%. 나머지 94%는 트랜스포머 블록(어텐션 + MLP, 활동 5-7에서 다룸)에 있습니다.
Untied vs Tied Embeddings
많은 트랜스포머 설계(GPT-2 포함)에서는 토큰 임베딩을 최종 출력 투영과 연결합니다: 입력과 출력(어휘에 대한 logits) 모두에 동일한 V × d_model 행렬을 사용합니다. 연결하면 V × d_model 파라미터를 절약하고 종종 품질도 향상됩니다.
ANDREA는 untied embeddings를 사용합니다: 입력 임베딩과 출력 투영이 별도의 행렬로 학습됩니다. Activity 7 (grow_a_language_model_transformer_block)에서 최종 레이어를 다룹니다.
지금까지의 순전파
입력: 토큰 ID [256, 1842, 7301, ...] (1024개). 각 ID는 768-벡터를 조회합니다. 각 위치도 768-벡터를 조회합니다. 요소별로 합산합니다. 결과: 토큰+위치 벡터로 구성된 (1024, 768) 행렬 x. x는 트랜스포머 블록 1로 전달됩니다.
Activity 5 (grow_a_language_model_attention)에서는 블록 1이 수행하는 작업을 다룹니다: causal mask와 softmax를 적용한 scaled dot-product attention.