LabHub
배우기 러닝패스 코스

트랜스포머 — 어텐션을 손으로 계산한다 · 온도·top-k·top-p · 실습

온도·top-k·top-p 를 손으로 만든다

LabHub 에서 이어서 보기

목표

로짓 한 벌에서 다음 토큰 하나를 고르기까지, 분포가 거치는 자리를 표준 라이브러리만으로 전부 만든다. 온도로 나눈 뒤의 안정한 소프트맥스, 엔트로피, top-k, top-p, 넷을 정해진 순서로 잇는 함수, 역누적분포 추출, greedy 와 온도 훑기까지다. 마지막에 같은 시드로 두 번 뽑아 같은 수열이 나오는지와 온도를 낮춘 쪽이 greedy 와 같아지는지를 기록으로 남긴다.

왜 중요한가

트랜스포머 블록이 하는 일은 어휘 크기만 한 실수 목록 하나를 내놓는 것까지다. 실제로 쓸 토큰을 고르는 것은 모델 바깥의 규칙이고, 같은 모델이 매번 다르게 말하는 이유도 매번 같은 말을 되풀이하는 이유도 전부 거기 있다.
이 실습은 모델을 부르지 않는다. 이 파드에는 transformers 도 torch 도 없고 numpy 는 /opt/onnx-lab/bin/python 안에만 있어 시스템 파이썬에서는 import numpy 가 되지 않는다. 대신 로짓 한 벌을 직접 적어 두고 그 뒤를 손으로 만든다. 그래서 여기 나오는 숫자는 전부 여러분이 적은 로짓에서 잰 것이다.
어려운 것은 세부다. 온도를 나누는 자리가 소프트맥스 앞인지 뒤인지, 최댓값을 왜 빼는지, top-k 의 동점을 어떻게 깨는지, top-p 가 p 에 닿는 항목을 포함하는지, 온도와 top-p 와 top-k 를 어느 순서로 먹이는지. 하나만 달라도 같은 설정이 다른 시스템이 된다.
채점기는 여러분이 적어 둔 설명을 믿지 않는다. 여러분의 모듈을 실제로 불러 매번 다른 로짓과 다른 온도로 함수를 두드려 보고, 채점기가 따로 계산한 확률 벡터와 대조한다. 무작위 추출 자체는 판정하지 않는다 — 시드를 고정한 번호 수열과 확률 벡터만 본다.

단계

1. /root/work/tf-sample/sample.pyVOCAB·LOGITSsoftmax_t(logits, temperature) 를 만드세요. 로짓을 온도로 나눈 뒤 최댓값을 빼고 소프트맥스합니다.
2. entropy_bits(probs) 를 더해 분포가 퍼진 정도를 밑이 2 인 엔트로피로 재게 하세요. 확률이 0 인 자리는 0 으로 칩니다.
3. top_k_filter(probs, k) 를 더해 확률이 큰 k 개만 남기고 나머지를 정확히 0.0 으로 두고 다시 정규화하게 하세요. 동점이면 번호가 작은 쪽이 남습니다.
4. top_p_filter(probs, p) 를 더해 내림차순 누적합이 p 에 처음 닿는 그 항목까지 남기게 하세요. 그 항목을 빼면 합이 p 에 못 미칩니다.
5. filtered_probs(logits, temperature, top_k=None, top_p=None) 를 만들어 온도 → 소프트맥스 → top-k → top-p 순서로 잇게 하세요. None 이면 그 단계를 건너뜁니다.
6. sample_index(probs, u)sample_sequence(logits, temperature, top_k, top_p, n, seed) 를 만드세요. 역누적분포로 뽑고, random.Random(seed) 에서 random() 을 n 번 불러 같은 시드면 같은 수열이 나오게 합니다.
7. greedy(logits)sweep(logits, temps, p) 를 만드세요. greedy 는 가장 큰 로짓의 번호(동점이면 작은 번호)이고, sweep 은 온도마다 (온도, 엔트로피, top-p 가 남기는 개수) 를 잽니다.
8. 정해진 설정으로 재어 /root/work/tf-sample/sample_report.json/root/work/tf-sample/sample_report.md 에 결과를 기록하세요.

참고

단계 8개

  1. 온도로 나눈 뒤 소프트맥스
  2. 퍼진 정도를 비트로 잰다
  3. 위에서 k 개만 남긴다
  4. 누적합이 p 에 닿는 그 항목까지
  5. 네 가지를 정해진 순서로 잇는다
  6. 같은 시드는 같은 수열
  7. greedy 와 온도 훑기
  8. 손잡이를 돌린 결과를 남긴다