LabHub
배우기 러닝패스 코스

트랜스포머 — 어텐션을 손으로 계산한다 · 임베딩·가중치 묶기·로짓 · 실습

임베딩 표에서 로짓까지

LabHub 에서 이어서 보기

목표

토큰 번호가 벡터가 되고 그 벡터가 다시 어휘 전체의 점수가 되기까지를 표준 라이브러리만으로 만든다. 조회가 원-핫 벡터와 행렬의 곱과 같은 값을 낸다는 것을 두 방법으로 계산해 확인하고, 파라미터 수를 세고, 같은 표를 출력 쪽에서 한 번 더 쓰는 가중치 묶기를 만들고, 코사인과 내적이 갈리는 자리를 숫자로 본다. 마지막으로 임베딩에 √d 를 곱하면 크기만 바뀌고 방향은 그대로라는 것을 잰다.

왜 중요한가

모델을 이야기할 때 사람들이 가장 자주 틀리는 자리가 여기다. "임베딩은 조회고 출력은 행렬 곱" 이라고 나눠 생각하면 둘이 같은 표라는 것이 안 보이고, 파라미터 수가 왜 어긋나는지도 설명이 안 된다. 어휘를 키우자는 제안이 왜 메모리 회의로 끝나는지도 V 곱하기 d 를 세어 보기 전에는 감이 오지 않는다.
이 실습은 실제 모델을 부르지 않는다. 이 파드의 시스템 파이썬에는 numpy·torch·transformers 가 없다(numpy 는 /opt/onnx-lab/bin/python 안에만 있다). 그래서 실제 모델의 어휘 크기나 파라미터 수 같은 숫자는 여기서 쓰지 않는다 — 여러분이 만든 표에서 잰 값만 쓴다.
판정은 실수 비교가 많다. 채점기는 abs(a-b) <= atol + rtol*abs(b) 로 보되, 모양·파라미터 수·이웃 목록 같은 정수 판정도 함께 본다. 그래서 더하는 순서가 달라 마지막 자리가 흔들리는 것은 받아들이고, 실제로 틀린 구현은 거른다.
채점기는 여러분이 적어 둔 설명을 믿지 않는다. 여러분의 모듈을 실제로 불러 매번 다른 표와 다른 번호로 함수를 두드려 보고, 채점기가 따로 계산한 값과 대조한다.

단계

1. /root/work/tf-embed/embed.pyVOCAB = 512·DIM = 64·SEED = 20260917make_table(vocab, dim, seed)·shape(matrix)·param_count(vocab, dim) 을 만드세요. 같은 씨앗이면 언제나 같은 표가 나와야 합니다.
2. lookup(table, ids) 를 더해 번호 목록을 벡터 목록으로 바꾸게 하세요. 같은 번호는 같은 벡터를 주고, 어휘 밖의 번호는 IndexError 입니다.
3. one_hot(token_id, vocab)·row_times_matrix(vec, matrix)·lookup_via_one_hot(table, ids)·one_hot_mults(vocab, dim, count) 를 더해 조회와 원-핫 곱이 같은 값을 내는지 보세요.
4. logits(table, hidden) 을 만들어 입력에 쓴 그 표로 어휘 전체의 점수를 내게 하세요. 새 행렬을 만들면 안 됩니다.
5. tied_params(vocab, dim)·untied_params(vocab, dim)·vocab_growth(vocab, dim, factor) 로 묶었을 때와 따로 둘 때의 수 개수를 세게 하세요.
6. dot·norm·cosine·stretch·nearest_by_cosine·nearest_by_dot 을 만들어 한 줄만 늘였을 때 두 목록이 어떻게 갈리는지 보세요.
7. rms(vec)scaled_lookup(table, ids, dim) 을 만들어 √d 를 곱하면 크기가 √d 배가 되는 것을 재게 하세요.
8. 정한 상수로 전부 재어 /root/work/tf-embed/embed_report.json/root/work/tf-embed/embed_report.md 에 기록하세요.

참고

단계 8개

  1. 표의 모양과 파라미터 수
  2. 번호로 줄을 꺼낸다
  3. 조회는 원-핫 곱과 같은 값이다
  4. 같은 표로 점수를 낸다
  5. 묶으면 얼마나 줄어드는가
  6. 길이가 순서를 바꾼다
  7. √d 를 곱하면 크기만 바뀐다
  8. 재어 본 것을 기록으로 남긴다