LabHub

트랜스포머 — 어텐션을 손으로 계산한다 · 어텐션의 안쪽 · 실습

라이브러리 없이 어텐션

LabHub 에서 이어서 보기

목표

어텐션을 라이브러리 없이 직접 구현합니다. numpy 도 torch 도 쓰지
않습니다 — 표준 라이브러리(math)만 씁니다.

느립니다. 그래서 차원을 작게(d=8~64, n=4~8) 씁니다. 목적은 속도가
아니라 안이 보이는 것입니다.

만들 것

/root/work/tf/model.py 에 다음을 정의합니다.

| 함수 | 계약 |
|---|---|
| softmax(xs) | 합이 1. 큰 입력에서도 터지지 않는다 |
| attention(Q, K, V, mask=None) | (out, weights) 를 돌려준다. √d_k 로 나눈다 |
| causal_mask(n) | mask[i][j] 가 참이면 i 가 j 를 볼 수 있다 |
| multi_head(Q, K, V, h, mask=None) | 마지막 차원을 h 등분해 각각 어텐션 후 이어 붙인다 |
| pos_encoding(n, d) | 자리마다 다른 [-1,1] 범위 벡터 |
| layer_norm(row, eps=1e-5) | 평균 0, 분산 1 |
| block(X, h, mask=None) | X + multi_head(LN(X), ...) |

행렬은 전부 파이썬 리스트의 리스트([[float]])입니다. 자리 × 차원.

확인

cd /root/work/tfpython3 -c "import model; print(model.softmax([1,2,3]))"

단계

1. softmax — 오버플로 안 남
2. attention + √d 측정 → 02-scale.txt
3. causal_mask
4. multi_head (h=1 이면 attention 과 동일)
5. pos_encoding + 순열 실험 → 05-perm.txt
6. layer_norm
7. block (pre-LN + 잔차)
8. 정리 → 08-notes.md

참고

채점기는 참조 구현과 1e-6 이내로 비교합니다. 어텐션은 구현이
달라도 같은 숫자가 나오는 연산이라, 값이 어긋나면 대개 스케일링이나
마스크 순서가 틀린 것입니다.

단계 8개

  1. 터지지 않는 소프트맥스
  2. 어텐션 세 줄과 √d
  3. 미래를 가린다
  4. 쪼개고 다시 붙인다
  5. 어텐션이 순서를 모른다는 것을 증명한다
  6. LayerNorm 은 특징 축으로
  7. 블록을 조립한다
  8. 세 가지를 숫자로 정리한다