점

고차원 심플렉스: 5만 면 주사위의 세계

삼각형 위에서는 어느 점이 가운데이고 어느 점이 가장자리인지 눈으로 보이는데, 칸이 5만 개로 늘어나도 그 감각이 통할까?

실제 언어 모델의 “다음 토큰” 분포는 면이 수만~수십만 개인 주사위다. 어휘가 5만 개라면 그 심플렉스는 49,999차원의 초삼각형인데, 합이 1이라는 약속 하나가 차원 하나를 가져가기 때문이다.

안쪽은 얼마나 넓은가

눈에 보이는 세 칸짜리 삼각형에서 먼저 재 보자. 모든 칸이 균등값 1/3의 절반, 곧 1/6 이상인 점들을 "안쪽"이라고 부르자. 어느 칸도 유난히 작지 않은, 한가운데 근처의 분포들이다. 이 영역은 한가운데에 거꾸로 놓인 작은 삼각형이고 넓이가 전체의 4분의 1이어서, 삼각형 위에 점을 고르게 뿌리면 넷 가운데 하나꼴로 안쪽에 떨어진다.

세 칸 심플렉스 안에 모든 칸이 1/6 이상인 안쪽 삼각형을 칠하고, 고르게 찍은 점 160개 가운데 38개가 안쪽에 든 모습
세 칸 심플렉스 안에 모든 칸이 1/6 이상인 안쪽 삼각형을 칠하고, 고르게 찍은 점 160개 가운데 38개가 안쪽에 든 모습

칸이 n개일 때도 안쪽의 부피 비율을 계산할 수 있다.

안쪽={p∈Δ:pi≥12n (모든 i)},안쪽의 부피심플렉스 전체의 부피=(12)n−1\text{안쪽} = \left\{ \textcolor{#d6479f}{p} \in \textcolor{#407050}{\Delta} : \textcolor{#d6479f}{p}_i \ge \frac{1}{2\textcolor{#a05000}{n}} \ \text{(모든 } i\text{)} \right\}, \qquad \frac{\text{안쪽의 부피}}{\text{심플렉스 전체의 부피}} = \left(\frac{1}{2}\right)^{\textcolor{#a05000}{n}-1}
p결과가 n 개인 분포 하나 (심플렉스의 점)Δ결과가 n 개인 분포 전체의 모임 (심플렉스)n결과(칸)의 개수i칸의 번호\begin{array}{ll} \textcolor{#d6479f}{p} & \text{결과가 } n \text{ 개인 분포 하나 (심플렉스의 점)} \\ \textcolor{#407050}{\Delta} & \text{결과가 } n \text{ 개인 분포 전체의 모임 (심플렉스)} \\ \textcolor{#a05000}{n} & \text{결과(칸)의 개수} \\ i & \text{칸의 번호} \end{array}

모든 칸에서 1/(2n)을 덜어 내면 남은 확률의 합이 1/2이 되므로, 안쪽은 심플렉스를 가로세로 절반으로 줄인 모양이다. (n − 1)차원 도형을 절반으로 줄였으니 부피는 (1/2)n−1배이고, 칸이 하나 늘 때마다 안쪽이 차지하는 부피 비율이 절반으로 준다. 칸이 넷이면 8분의 1, 다섯이면 16분의 1이고, 5만 칸이면 10−15051 정도다. 고르게 찍은 점은 거의 틀림없이 안쪽 밖, 곧 어느 한 칸이 유난히 작은 쪽에 떨어진다. 부피가 이렇게 한쪽 얇은 층에 쏠리는 현상을 측도(여기서는 부피)의 집중이라 부른다.

서울역 대합실을 떠올려 보면, 사람들은 대개 한가운데를 비워 두고 벽을 따라, 기둥 옆에 서 있다. 그렇다면 사람들이 구석에 몰려 있다는 뜻일까, 다시 말해 벽 가까이 있는 것과 구석에 있는 것은 같은 일일까? 고차원 심플렉스에서 「벽 가까이인가, 구석인가」라는 물음은 생각보다 까다롭다. 아래 문제에서 직접 재 본다.

파이썬

import numpy as np

rng = np.random.default_rng(0)
xy = rng.random((400_000, 2))                 # 정사각형에 고르게 뿌린 뒤
xy = xy[xy.sum(axis=1) <= 1]                  # 대각선 아래 반쪽만 남기면 삼각형 위에 고르다
p = np.column_stack([xy, 1 - xy.sum(axis=1)]) # (p1, p2, p3), 합 1

inner = (p >= 0.5 / 3).all(axis=1)            # 모든 칸이 균등값 1/3 의 절반 이상
print("점의 개수        :", len(p))
print("안쪽 영역의 비율 :", round(inner.mean(), 4), "  (1/2)^(n-1) =", 0.5 ** 2)
print("5만 칸이면       : 10 의", round((50_000 - 1) * np.log10(0.5), 1), "제곱")
# 점의 개수        : 199935
# 안쪽 영역의 비율 : 0.2496   (1/2)^(n-1) = 0.25
# 5만 칸이면       : 10 의 -15051.2 제곱

세 칸에서는 정사각형의 반쪽을 삼각형으로 옮기는 간단한 방법으로 점을 고르게 뿌릴 수 있었고, 안쪽 영역의 비율이 식대로 4분의 1이 나왔다. 칸이 많아지면 이 방법을 그대로 쓸 수 없는데, 많은 칸에서 점을 고르게 뽑는 법은 아래 문제에서 따진다.

이 절의 결론

“칸이 많아질수록 심플렉스의 부피는 거의 다 한가운데에서 멀리, 어느 한 칸이 유난히 작은 쪽에 있다.” 어느 한 칸이 작은 그 영역이 꼭짓점 근처인지 면 근처인지는 따로 물어야 한다.

5만 차원의 삼각형 위에 점 하나를 찍었다. 그런데 두 점이 “가깝다” 또는 "멀다"는 것은 어떻게 아는가? 삼각형 위에서 거리를 재야 한다. 어떤 거리로?

문제 9. 고르게 찍은 점의 가장 작은 칸 (킬러)

결과가 n개인 심플렉스 위에서 점을 고르게(균등하게) 하나 뽑는다. (가) 가장 작은 칸의 확률 min pᵢ의 기댓값이 결과의 개수 n에 따라 어떻게 줄어드는지 구하라. (나) (가)에서 구한 기댓값을 "고차원 심플렉스의 점은 대부분 꼭짓점 근처에 있다"는 말과 비교하라. (다) numpy로 확인할 때 샘플을 어떻게 뽑아야 하는가?

칸이 10개인 심플렉스에서 고르게 뽑은 점 하나의 열 칸 확률과 균등값 1/n. 가장 작은 칸을 진하게 칠했다
칸이 10개인 심플렉스에서 고르게 뽑은 점 하나의 열 칸 확률과 균등값 1/n. 가장 작은 칸을 진하게 칠했다

함께 풀기

김민준 M01
김민준

바로 돌렸어요. p = rng.random(n) 뽑아서 합으로 나누고 min을 평균냈어요. n = 3이면 0.153이고, n = 1000이면 2.0 × 10⁻⁶이에요. n² 곱하면 2쯤 되니까 1/n²에 비례하는 것 같아요. 답은 2/n²?

이서연 S01
이서연

나는 손으로 했는데 1/n²이 나왔어. 계수가 달라.

선생님 T01
선생님

둘 중 하나는 “고르게” 뽑지 않았어요. 민준 학생, n = 3에서 칸 세 개를 따로 0과 1 사이에서 뽑고 합으로 나누면, 삼각형 위에 점이 고르게 뿌려질까요?

김민준 M05
김민준

음… 정육면체 안의 점을 원점에서 대각선 쪽으로 쏘아서 삼각형에 찍는 거니까, 그 방향으로 정육면체가 얼마나 긴지에 따라 밀도가 달라지겠네요. 가운데 방향이 제일 길어요.

김민준 M01
김민준

그래서 가운데가 진하고 변 근처가 옅어요. min이 부풀려진 거예요.

김민준 M07
김민준

심플렉스 위에 점을 뿌리는 디리클레 분포, rng.dirichlet(np.ones(n))로 다시 뽑으니까 n = 3에서 0.111, n = 1000에서 n² 곱한 값이 1.00이에요. 정확히 1/n²이네요.

김민준 M01
김민준

설문 응답을 역 앞에서만 받아 놓고 "국민 여론"이라고 보고서 쓴 거랑 같은 실수였어요. 뽑는 방법이 이미 답을 기울여 놨어요.

선생님 T01
선생님

서연 학생은 어떻게 1/n²을 얻었어요?

이서연 S01
이서연

처음엔 저도 칸마다 0과 1 사이에서 뽑을 생각이었어요. 그러다 확률 수업에서 서로 독립인 지수분포 n개를 뽑아서 합으로 나누면 심플렉스에서 균등한 점이 된다고 배운 게 떠올랐어요. 지수분포는 기다리는 시간처럼 밀도가 e−x 꼴로 줄어드는 분포예요.

선생님 T01
선생님

그렇게 뽑으면 가장 작은 칸은 무엇을 무엇으로 나눈 거예요?

이서연 S01
이서연

뽑은 값들의 최솟값을 합으로 나눈 거요. 지수분포 n개의 최솟값은 평균이 1/n인 지수분포라고 배웠어요.

김민준 M01
김민준

합은 쉽네. 하나 평균이 1이니까 n개 더하면 평균 n이지.

이서연 S01
이서연

그래서 평균끼리 나누면 대략 (1/n)/n = 1/n²이에요.

선생님 T01
선생님

"대략"이라고 했는데, 정확히는요?

이서연 S04
이서연

나눗셈의 기댓값을 기댓값끼리 나누면 보통은 안 되는데… 여기서 그래도 되는지는 모르겠어요.

선생님 T01
선생님

지수분포로 뽑을 때는 합으로 나눈 벡터 p와 합 자체가 서로 독립이라는 성질이 있어요. 나눗셈을 곱셈으로 바꿔 써 보면요?

이서연 S01
이서연

뽑은 값의 최솟값 = min pᵢ × 합이에요. 곱셈이 됐네요.

선생님 T01
선생님

곱한 두 값이 독립이면 그 곱의 기댓값은요?

이서연 S07
이서연

기댓값끼리 곱하면 돼요. 그러니까 E[뽑은 값의 최솟값] = E[min pᵢ] × E[합]이 정확히 성립해요. 1/n = E[min pᵢ] × n이니까 정확히 1/n²이에요. 민준이 디리클레 결과랑도 맞고요.

선생님 T01
선생님

좋아요. 그럼 (나)는요?

이서연 S01
이서연

가장 작은 칸이 1/n²으로 0에 붙으니까, 점이 거의 늘 가장자리에 있다는 뜻이에요. 그러니까 "꼭짓점 근처"라는 말이 맞아요.

선생님 T01
선생님

꼭짓점에 가깝다는 건 어떤 분포예요?

이서연 S01
이서연

한 칸이 거의 1인 분포요.

선생님 T01
선생님

민준 학생, 가장 큰 칸의 평균도 찍어 봐요.

김민준 M01
김민준

n = 1000에서 0.0075예요. 1000분의 7.5요. 1과는 한참 멀어요.

이서연 S06
이서연

가장 큰 칸도 1/n의 몇 배 수준이에요. 꼭짓점 근처가 전혀 아니에요.

이서연 S08
이서연

가장자리가 두 종류였어요. 한 칸이 0에 가까우면 “면” 근처고, 한 칸만 빼고 다 0이어야 “꼭짓점” 근처예요. 고르게 뽑은 점은 모든 칸이 1/n 정도인데 그중 몇 칸이 아주 작아서, 면에는 붙어 있지만 꼭짓점과는 멀어요.

선생님 T01
선생님

그래요. 안쪽 영역의 부피 비율이 (1/2)n−1이라고 했죠. 디리클레로 뽑아서 확인해 봐요.

김민준 M01
김민준

n = 10이면 0.00195예요. 디리클레로 백만 개 뽑아 세어 보니 0.00201이고요. 열 칸만 돼도 안쪽은 거의 비어 있어요.

이서연 S09
이서연

그래서 서울역 사람들이 벽을 따라 서 있어도 구석에 몰린 건 아니었군요. 수업에서 고차원 공의 부피가 거의 다 껍질에 있다는 걸 배웠을 때도, 그게 "북극점 근처"라는 뜻은 아니었어요. 껍질은 넓고 북극점은 좁으니까요.

선생님 T13
선생님

두 사람이 다른 곳에서 넘어졌어요. 민준 학생은 "고르게"를 코드로 옮기다가, 서연 학생은 "가장자리"를 말로 옮기다가요. 고차원에서는 이 두 옮김이 모두 위험해요. 그래서 우리는 자가 필요해요. 가깝다, 멀다를 말로 하지 않고 재기 위해서요.

문제 10. 첫 loss로 보는 출발점

어휘가 5만 개인 언어 모델의 출력은 n = 50,000칸 심플렉스의 점이다. (가) 학습 전 모델의 로짓이 모두 0이면 출력은 심플렉스의 어디이고, 첫 loss(정답 토큰에 준 확률의 −ln)는 몇 nat인가? (나) 마지막 층을 잘못 초기화해 로짓이 표준편차 5인 정규분포처럼 흩어졌더니, 첫 loss가 평균 22 nat쯤으로 나왔다. 이 출발점은 심플렉스의 어디쯤인가? (다) 로짓 0, 표준편차 5, 문제 9처럼 고르게 뽑은 점, 이 세 출발점을 한가운데·면 근처·한 꼭짓점 쪽으로 가르고, 가장 큰 칸으로 확인하라.

어휘 5만 개 가운데 앞 40개 토큰의 로짓. (가)는 모두 0, (나)는 표준편차 5인 정규분포에서 뽑은 값
어휘 5만 개 가운데 앞 40개 토큰의 로짓. (가)는 모두 0, (나)는 표준편차 5인 정규분포에서 뽑은 값

함께 풀기

김민준 M01
김민준

(가)는 소프트맥스에 0을 넣으면 모든 칸이 1/50,000이니까 한가운데예요. loss는 ln 50,000 ≈ 10.82 nat이고요.

선생님 T01
선생님

(나)는요?

김민준 M01
김민준

로짓을 무작위로 뽑았으니까 문제 9에서 고르게 뽑은 점이랑 같겠죠. 면 근처요.

선생님 T01
선생님

고르게 뽑은 점이면 첫 loss가 몇이 나와요? 문제 9에서 쓴 방법으로 뽑아 봐요.

김민준 M04
김민준

디리클레로 뽑아서 재 보니 11.4쯤이에요. 22가 아니네요. 로짓을 무작위로 뽑는 것과 심플렉스에서 고르게 뽑는 건 다른 일이었어요.

선생님 T01
선생님

그러면 표준편차 5인 로짓은 점을 어디에 찍죠? 가장 큰 칸을 봐요.

김민준 M01
김민준

여러 번 뽑아 평균을 내니 가장 큰 칸이 0.38쯤이에요. 5만 칸 가운데 한 칸이 38%를 가져가요.

이서연 S08
이서연

지수를 씌우니까 로짓 차이가 조금만 벌어져도 확률은 한 칸으로 몰려요. 로짓이 5만 개면 가장 큰 것은 표준편차의 네 배쯤 위에 있고, e를 씌우면 가장 큰 로짓의 칸 하나가 나머지를 압도해요. 한가운데도 면 근처도 아니고, 아무 토큰 하나의 꼭짓점 쪽으로 기울어진 점이에요. 정답이 하필 그 토큰일 리가 거의 없으니 loss가 커요.

선생님 T01
선생님

(다)로 정리해 봐요.

이서연 S01
이서연

로짓 0은 가장 큰 칸이 1/n = 0.00002라서 한가운데, 고르게 뽑은 점은 0.00023쯤이라서 면 근처, 표준편차 5는 0.38쯤이라서 한 꼭짓점 쪽이에요.

선생님 T01
선생님

그래요. 그래서 학습을 돌리기 전에 첫 loss가 ln(부류 수) 근처인지부터 보라는 조언이 널리 쓰여요(카파시(Andrej Karpathy)가 2019년 글에 적은 조언이 잘 알려져 있어요). 출발점이 한가운데에 있는지 확인하는 거예요.

김민준 M01
김민준

조교님이 채점 스크립트를 돌리기 전에 빈 답안지부터 넣어서 0점이 나오는지 확인하던 거랑 같네요.