「파라미터 하나당 학습 토큰 20개」는 Chinchilla 논문(arXiv 2203.15556)에서 나왔다고들 한다. 그런데 그 논문을 열어 보면 20이라는 숫자가 본문 어디에도 적혀 있지 않다. 초록이 말하는 것은 비율이 아니라 방향이다 — "for every doubling of model size the number of training tokens should also be doubled."
그러면 20은 어디서 온 것인가. 논문은 최적 배분을 세 가지 방법으로 구했고 세 방법의 답을 표로 인쇄해 두었다. 그 표를 직접 나눠 보면 답이 나온다. 이 글은 그 나눗셈의 기록이다.
먼저 결론 셋이다.
- 토큰/파라미터가 20 근처에 머무는 것은 Approach 1 열 하나뿐이다. Table 3의 아홉 행에서 20.0~22.4로 1.12배 안에 든다. 같은 자리에서 Approach 2 열은 1.52배, 파라메트릭 적합인 Approach 3 열은 6.20배로 벌어진다.
- 실제로 학습시킨 Chinchilla는 70B에 1.4조 토큰, 즉 정확히 20.0000이다. 20은 예측값이 아니라 그들이 고른 값이기도 하다.
- 논문은 세 방법의 예측이 "similar"라고 적는데, 실제로 재 보면 어느 구간에서 보느냐에 따라 다르다. 실험을 실제로 돌린 언저리에서는 세 예측이 7% 안에 모이지만, 까지 외삽하면 2.59배로 갈린다.
덤으로 하나 더 잡혔다. 논문 3절 본문이 175B 모델에 대해 적은 토큰 수와 같은 절 Table 3이 적은 토큰 수가 13.5% 어긋난다.
스케일링 법칙이 무엇을 주장하는지는 스케일링 법칙이 맡는다. 계수를 직접 넣고 최적화 문제를 푸는 쪽은 계수로 최적 배분을 직접 풀어 본 기록에 있다. 이 글은 논문이 인쇄한 표를 읽고 나누는 일만 맡는다.
논문이 한 일
Chinchilla 팀은 7천만160억 파라미터 모델 400편 이상을 5억5천억 토큰에 학습시키고, 그 결과에서 「예산 가 주어졌을 때 최적 모델 크기 와 토큰 수 」를 세 가지 방법으로 뽑았다. 컴퓨트 최적(compute-optimal)이란 학습에 쓸 연산량이 정해져 있을 때 최종 손실이 가장 낮아지는 조합을 말한다.
- Approach 1(§3.1) — 모델 크기를 고정해 두고 학습 스텝 수를 바꿔 가며 학습 곡선을 그리고, FLOPs별 최소 손실의 포락선(envelope, 여러 곡선의 아래쪽을 감싸는 선)에서 최적점을 읽는다.
- Approach 2(§3.2) — FLOPs를 아홉 개 값으로 고정하고 모델 크기만 바꿔 손실 골짜기를 그린다. 이것을 IsoFLOP 프로파일이라 부른다.
- Approach 3(§3.3) — 모든 최종 손실을 라는 함수에 적합하고, 제약 아래 그 함수를 최소화해 푼다.
세 방법이 낸 지수가 Table 2다. , 로 놓았을 때다.
| 접근법 | ||
|---|---|---|
| 1. 학습 곡선의 최소 포락선 | 0.50 (0.488, 0.502) | 0.50 (0.501, 0.512) |
| 2. IsoFLOP 프로파일 | 0.49 (0.462, 0.534) | 0.51 (0.483, 0.529) |
| 3. 손실의 파라메트릭 적합 | 0.46 (0.454, 0.455) | 0.54 (0.542, 0.543) |
| Kaplan et al. 2020 | 0.73 | 0.27 |
괄호는 10~90 백분위 구간이다. 여기서 이미 눈에 걸리는 것이 있다 — Approach 3의 구간 폭이 0.001로 위 두 줄보다 터무니없이 좁다. 그 좁기가 무엇을 뜻하는지는 이 글이 아니라 다음 글에서 다룬다.
지금 필요한 것은 다른 사실이다. 가 정확히 0.5일 때만 토큰/파라미터 비가 예산과 무관한 상수가 된다. 이기 때문이다. Approach 1은 0.50, Approach 2는 0.49, Approach 3은 0.46이다. 세 줄이 "비슷"해 보이지만 이 관점에서는 첫 줄만 상수를 준다.
재현 1 — 표를 그냥 나눠 본다
논문 Table 3은 Approach 1의 예측을 모델 크기 아홉 개에 대해 인쇄한다. 각 행은 넷을 갖는다. 토큰/파라미터를 알고 싶으면 마지막 칸을 첫 칸으로 나누면 된다.
pip install numpy scipy
python approach1.py
import numpy as np
# arXiv 2203.15556 Table 3 (Approach 1): N, FLOPs, "FLOPs (in Gopher unit)", tokens
T3 = [(4.0e8, 1.92e19, 1 / 29968, 8.0e9), (1.0e9, 1.21e20, 1 / 4761, 20.2e9),
(1.0e10, 1.23e22, 1 / 46, 205.1e9), (6.7e10, 5.76e23, 1.0, 1.5e12),
(1.75e11, 3.85e24, 6.7, 3.7e12), (2.8e11, 9.90e24, 17.2, 5.9e12),
(5.2e11, 3.43e25, 59.5, 11.0e12), (1.0e12, 1.27e26, 221.3, 21.2e12),
(1.0e13, 1.30e28, 22515.9, 216.2e12)]
GOPHER = 5.76e23
print("=== 1. Table 3 (Approach 1) 의 토큰/파라미터 ===")
print(f"{'N':>9} | {'D':>10} | {'D/N':>6} | {'6ND/인쇄 FLOPs':>14} | {'Gopher unit 대조':>16}")
for N, C, g, D in T3:
print(f"{N:9.2e} | {D:10.3e} | {D / N:6.1f} | {6 * N * D / C:14.3f} | "
f"{(C / GOPHER) / g:16.4f}")
r = [D / N for N, _, _, D in T3]
print(f"D/N 범위 {min(r):.1f} ~ {max(r):.1f} 폭(최대/최소) = {max(r) / min(r):.2f}배")
print("\n=== 2. Chinchilla 자신은 어디에 있는가 ===")
NC, DC = 70e9, 1.4e12
print(f"Chinchilla N = {NC:.2e} D = {DC:.2e} D/N = {DC / NC:.4f}")
print(f"6ND = {6 * NC * DC:.4e} Gopher 예산 {GOPHER:.4e} 비 = {6 * NC * DC / GOPHER:.4f}")
print(f"논문 본문의 하한 40B 로 같은 예산을 쓰면 D/N = {GOPHER / 6 / 40e9 / 40e9:.1f}"
f" 상한 70B 는 {GOPHER / 6 / NC / NC:.1f} 범위 폭 {70 / 40:.2f}배")
print("\n=== 3. 본문 서술과 Table 3 은 같은 값을 말하는가 ===")
# 3절 본문: 175B -> 4.41e24 FLOPs / 4.2T 토큰, 280B -> 약 1e25 FLOPs / 6.8T 토큰
BODY = [(1.75e11, 4.41e24, 4.2e12), (2.8e11, 1.0e25, 6.8e12)]
print(f"{'N':>9} | {'표 D':>8} | {'본문 D':>8} | {'본문/표':>7} | {'표 D/N':>7} | {'본문 D/N':>8}")
for (N, Cb, Db) in BODY:
Ct, Dt = next((C, D) for n, C, _, D in T3 if n == N)
print(f"{N:9.2e} | {Dt:8.2e} | {Db:8.2e} | {Db / Dt:7.3f} | {Dt / N:7.1f} | {Db / N:8.1f}")
print(f" 본문의 6ND = {6 * N * Db:.3e} 이고 본문이 적은 FLOPs = {Cb:.3e}"
f" (비 {6 * N * Db / Cb:.3f})")
print("\n=== 4. 표에서 지수를 회귀하면 ===")
C = np.array([c for _, c, _, _ in T3]); N = np.array([n for n, _, _, _ in T3])
D = np.array([d for _, _, _, d in T3])
a = np.polyfit(np.log(C), np.log(N), 1)[0]
b = np.polyfit(np.log(C), np.log(D), 1)[0]
print(f"Approach 1 표 회귀: a = {a:.4f} b = {b:.4f} -> D/N ∝ C^{b - a:+.4f}")
print(f"논문 Table 2 의 Approach 1 보고값: a = 0.50 b = 0.50 -> D/N ∝ C^+0.0000")
실제 출력이다.
=== 1. Table 3 (Approach 1) 의 토큰/파라미터 ===
N | D | D/N | 6ND/인쇄 FLOPs | Gopher unit 대조
4.00e+08 | 8.000e+09 | 20.0 | 1.000 | 0.9989
1.00e+09 | 2.020e+10 | 20.2 | 1.002 | 1.0001
1.00e+10 | 2.051e+11 | 20.5 | 1.000 | 0.9823
6.70e+10 | 1.500e+12 | 22.4 | 1.047 | 1.0000
1.75e+11 | 3.700e+12 | 21.1 | 1.009 | 0.9976
2.80e+11 | 5.900e+12 | 21.1 | 1.001 | 0.9993
5.20e+11 | 1.100e+13 | 21.2 | 1.001 | 1.0008
1.00e+12 | 2.120e+13 | 21.2 | 1.002 | 0.9963
1.00e+13 | 2.162e+14 | 21.6 | 0.998 | 1.0024
D/N 범위 20.0 ~ 22.4 폭(최대/최소) = 1.12배
=== 2. Chinchilla 자신은 어디에 있는가 ===
Chinchilla N = 7.00e+10 D = 1.40e+12 D/N = 20.0000
6ND = 5.8800e+23 Gopher 예산 5.7600e+23 비 = 1.0208
논문 본문의 하한 40B 로 같은 예산을 쓰면 D/N = 60.0 상한 70B 는 19.6 범위 폭 1.75배
=== 3. 본문 서술과 Table 3 은 같은 값을 말하는가 ===
N | 표 D | 본문 D | 본문/표 | 표 D/N | 본문 D/N
1.75e+11 | 3.70e+12 | 4.20e+12 | 1.135 | 21.1 | 24.0
본문의 6ND = 4.410e+24 이고 본문이 적은 FLOPs = 4.410e+24 (비 1.000)
2.80e+11 | 5.90e+12 | 6.80e+12 | 1.153 | 21.1 | 24.3
본문의 6ND = 1.142e+25 이고 본문이 적은 FLOPs = 1.000e+25 (비 1.142)
=== 4. 표에서 지수를 회귀하면 ===
Approach 1 표 회귀: a = 0.4981 b = 0.5019 -> D/N ∝ C^+0.0038
논문 Table 2 의 Approach 1 보고값: a = 0.50 b = 0.50 -> D/N ∝ C^+0.0000
20의 출처
첫 표의 세 번째 열이 답이다. Table 3의 아홉 행에서 토큰/파라미터는 20.0에서 22.4 사이에 있다. 가장 작은 400M 행이 정확히 20.0이고, 그다음 1B 행이 20.2다. 「20토큰/파라미터」라는 어림은 이 열을 눈으로 훑은 사람이 만들 수 있는 문장이다.
그리고 이 열은 상수에 가깝다. 폭이 1.12배이고, 표를 회귀해서 얻은 가 0.4981로 Table 2의 보고값 0.50과 소수 둘째 자리까지 맞는다. 가 0.5면 이므로 예산을 아무리 옮겨도 비가 안 움직여야 하는데, 실제로 표가 그렇게 인쇄돼 있다.
같은 표의 넷째·다섯째 열은 검산이다. 인쇄된 세 값이 서로 를 만족하는지 봤더니 아홉 행 중 여덟 행이 1.0001.009로 들어온다. 6ND 근사는 파라미터 하나를 토큰 하나에 학습시키는 데 6 FLOPs가 든다고 보는 관례적 어림이다. 유일하게 튀는 67B 행(1.047)은 토큰 수가 「1.5 Trillion」으로 두 자리까지만 인쇄된 탓이다 — 1.433조로 적혔다면 정확히 맞는다. 다섯째 열의 「Gopher 단위」도 FLOPs를 으로 나눈 값과 0.981.00으로 일치한다. 표 자체는 자기 안에서 일관돼 있다.
Chinchilla 자신
둘째 출력이 두 번째 답이다. 실제로 학습시킨 Chinchilla는 70B에 1.4조 토큰이고, 나눠 보면 20.0000이다. 우연이 아니라 그들이 고른 값이다. 그러니 20은 예측 표에서만 온 것이 아니라 논문이 실제로 만든 물건의 스펙이기도 하다.
여기에 논문 자신의 유보가 붙어 있다. §4는 이렇게 적는다 — "the optimal model size for the Gopher compute budget is somewhere between 40 and 70 billion parameters." 40B와 70B는 1.75배 차이다. 그리고 같은 예산을 40B에 쓰면 토큰/파라미터가 60.0이고 70B에 쓰면 19.6이다. 논문이 스스로 인정한 불확실성의 폭 안에서 이 어림은 20이 될 수도 60이 될 수도 있었다. 그들이 고른 쪽이 70B였고, 그래서 20이 남았다.
Chinchilla의 6ND는 으로 Gopher 예산 보다 2.1% 크다. 정확히 같은 예산은 아니었다는 뜻인데, 이 정도 차이는 비를 1% 남짓 움직일 뿐이라 위 결론에는 영향이 없다.
본문과 표가 다르다
셋째 출력이 예상 밖의 자리다. 논문 §3 본문은 이렇게 적는다 — "we find that a 175 billion parameter model should be trained with a compute budget of FLOPs and on over 4.2 trillion tokens." 그런데 바로 그 절의 Table 3은 같은 175B 행에 FLOPs와 3.7조 토큰을 인쇄한다. 토큰 수가 13.5% 어긋난다. 280B에서도 본문은 6.8조, 표는 5.9조로 15.3% 벌어진다.
우리 쪽 원인부터 지웠다. 옮겨 적는 실수라면 다른 행에도 나와야 하는데 나머지 일곱 행에는 대응하는 본문 서술이 아예 없다. 단위 착각이라면 배수가 10의 거듭제곱이어야 하는데 1.135와 1.153이다. 그리고 본문의 두 값끼리는 앞뒤가 맞는다 — 는 정확히 이다(출력의 비 1.000).
그러면 본문의 값은 무엇인가. 본문이 함의하는 토큰/파라미터는 24.0과 24.3이다. Table 3(Approach 1)의 21.1보다 크고, 뒤에서 볼 Approach 2 열의 24.6·25.4에 가깝다. 본문의 두 문장이 표와 다른 접근법의 값을 인용했을 가능성이 가장 그럴듯하지만, 인쇄된 숫자만으로는 확정할 수 없다. 여기까지가 우리가 말할 수 있는 전부이고, 나머지는 가설로만 남긴다.
재현 2 — 세 접근법을 나란히 놓는다
부록 Table A3은 Approach 2와 3의 같은 예측을 같은 모델 크기 아홉 개에 대해 싣는다. Table 3과 붙이면 같은 모델 크기에 세 방법이 각각 몇 개의 토큰을 요구하는지를 한 표로 볼 수 있다.
python three.py
import numpy as np
# arXiv 2203.15556. Table 3 = Approach 1, Table A3 = Approach 2 와 3.
# (N, A1 FLOPs, A1 토큰, A2 FLOPs, A2 토큰, A3 FLOPs, A3 토큰)
ROWS = [(4.0e8, 1.92e19, 8.0e9, 1.84e19, 7.7e9, 2.21e19, 9.2e9),
(1.0e9, 1.21e20, 20.2e9, 1.20e20, 20.0e9, 1.62e20, 27.1e9),
(1.0e10, 1.23e22, 205.1e9, 1.32e22, 219.5e9, 2.46e22, 410.1e9),
(6.7e10, 5.76e23, 1.5e12, 6.88e23, 1.7e12, 1.71e24, 4.1e12),
(1.75e11, 3.85e24, 3.7e12, 4.54e24, 4.3e12, 1.26e24, 12.0e12),
(2.8e11, 9.90e24, 5.9e12, 1.18e25, 7.1e12, 3.52e25, 20.1e12),
(5.2e11, 3.43e25, 11.0e12, 4.19e25, 13.4e12, 1.36e26, 43.5e12),
(1.0e12, 1.27e26, 21.2e12, 1.59e26, 26.5e12, 5.65e26, 94.1e12),
(1.0e13, 1.30e28, 216.2e12, 1.75e28, 292.0e12, 8.55e28, 1425.5e12)]
GOPHER = 5.76e23
BAD = 1.75e11 # 이 행의 A3 FLOPs 는 자기 행의 토큰 수와 10배 어긋나 회귀에서 뺀다
print("=== 1. 같은 모델 크기에 세 접근법이 요구하는 학습 토큰 ===")
print(f"{'N':>9} | {'A1 토큰':>9} | {'A2 토큰':>9} | {'A3 토큰':>9} | {'A2/A1':>6} | {'A3/A1':>6}")
for N, _, D1, _, D2, _, D3 in ROWS:
print(f"{N:9.2e} | {D1:9.3e} | {D2:9.3e} | {D3:9.3e} | {D2 / D1:6.2f} | {D3 / D1:6.2f}")
print("\n=== 2. 세 열의 토큰/파라미터 ===")
print(f"{'N':>9} | {'A1':>6} | {'A2':>6} | {'A3':>6}")
cols = {"A1": [], "A2": [], "A3": []}
for N, _, D1, _, D2, _, D3 in ROWS:
for k, D in zip(cols, (D1, D2, D3)):
cols[k].append(D / N)
print(f"{N:9.2e} | {D1 / N:6.1f} | {D2 / N:6.1f} | {D3 / N:6.1f}")
print(" 폭(최대/최소) |" + "".join(f"{max(v) / min(v):7.2f}" for v in cols.values()))
print("\n=== 3. 각 열을 멱법칙으로 적합해 Gopher 예산에서 다시 예측 ===")
fit = {}
for k, (ci, di) in {"A1": (1, 2), "A2": (3, 4), "A3": (5, 6)}.items():
keep = [r for r in ROWS if not (k == "A3" and r[0] == BAD)]
C = np.log([r[ci] for r in keep]); N = np.log([r[0] for r in keep])
a, c0 = np.polyfit(C, N, 1)
fit[k] = (a, c0)
Ng = np.exp(c0 + a * np.log(GOPHER))
print(f"{k}: N ∝ C^{a:.4f} Gopher 예산에서 N* = {Ng / 1e9:6.2f}B"
f" D* = {GOPHER / 6 / Ng / 1e12:5.2f}T D*/N* = {GOPHER / 6 / Ng ** 2:6.1f}")
print("\n=== 4. 예산을 옮기면 세 예측은 얼마나 벌어지는가 (N* 기준) ===")
print(f"{'C (FLOPs)':>10} | {'A1':>9} | {'A2':>9} | {'A3':>9} | {'최대/최소':>8}")
for C in [1e19, 1e21, 1e23, GOPHER, 1e25, 1e27, 1e29]:
v = [np.exp(c0 + a * np.log(C)) for a, c0 in fit.values()]
print(f"{C:10.2e} |" + "".join(f"{x / 1e9:8.2f}B |" for x in v)
+ f"{max(v) / min(v):8.2f}")
=== 1. 같은 모델 크기에 세 접근법이 요구하는 학습 토큰 ===
N | A1 토큰 | A2 토큰 | A3 토큰 | A2/A1 | A3/A1
4.00e+08 | 8.000e+09 | 7.700e+09 | 9.200e+09 | 0.96 | 1.15
1.00e+09 | 2.020e+10 | 2.000e+10 | 2.710e+10 | 0.99 | 1.34
1.00e+10 | 2.051e+11 | 2.195e+11 | 4.101e+11 | 1.07 | 2.00
6.70e+10 | 1.500e+12 | 1.700e+12 | 4.100e+12 | 1.13 | 2.73
1.75e+11 | 3.700e+12 | 4.300e+12 | 1.200e+13 | 1.16 | 3.24
2.80e+11 | 5.900e+12 | 7.100e+12 | 2.010e+13 | 1.20 | 3.41
5.20e+11 | 1.100e+13 | 1.340e+13 | 4.350e+13 | 1.22 | 3.95
1.00e+12 | 2.120e+13 | 2.650e+13 | 9.410e+13 | 1.25 | 4.44
1.00e+13 | 2.162e+14 | 2.920e+14 | 1.426e+15 | 1.35 | 6.59
=== 2. 세 열의 토큰/파라미터 ===
N | A1 | A2 | A3
4.00e+08 | 20.0 | 19.2 | 23.0
1.00e+09 | 20.2 | 20.0 | 27.1
1.00e+10 | 20.5 | 21.9 | 41.0
6.70e+10 | 22.4 | 25.4 | 61.2
1.75e+11 | 21.1 | 24.6 | 68.6
2.80e+11 | 21.1 | 25.4 | 71.8
5.20e+11 | 21.2 | 25.8 | 83.7
1.00e+12 | 21.2 | 26.5 | 94.1
1.00e+13 | 21.6 | 29.2 | 142.6
폭(최대/최소) | 1.12 1.52 6.20
=== 3. 각 열을 멱법칙으로 적합해 Gopher 예산에서 다시 예측 ===
A1: N ∝ C^0.4981 Gopher 예산에서 N* = 67.82B D* = 1.42T D*/N* = 20.9
A2: N ∝ C^0.4899 Gopher 예산에서 N* = 63.42B D* = 1.51T D*/N* = 23.9
A3: N ∝ C^0.4586 Gopher 예산에서 N* = 42.23B D* = 2.27T D*/N* = 53.8
=== 4. 예산을 옮기면 세 예측은 얼마나 벌어지는가 (N* 기준) ===
C (FLOPs) | A1 | A2 | A3 | 최대/최소
1.00e+19 | 0.29B | 0.30B | 0.28B | 1.07
1.00e+21 | 2.86B | 2.82B | 2.29B | 1.25
1.00e+23 | 28.35B | 26.89B | 18.92B | 1.50
5.76e+23 | 67.82B | 63.42B | 42.23B | 1.61
1.00e+25 | 281.06B | 256.77B | 156.37B | 1.80
1.00e+27 | 2786.10B | 2451.45B | 1292.40B | 2.16
1.00e+29 |27618.10B |23404.88B |10682.04B | 2.59
첫 표가 「세 방법이 similar하다」는 서술을 숫자로 옮긴 것이다. 400M 행에서 세 예측은 서로 15% 안에 있다. 10T 행에서는 Approach 3이 Approach 1의 6.59배를 요구한다. 두 방법이 갈라지는 것은 어느 한쪽이 틀려서가 아니라 지수가 0.03 다르기 때문이고, 지수 차이는 외삽 거리에 비례해 커진다.
둘째 표는 토큰/파라미터 열 셋이다. 폭이 각각 1.12·1.52·6.20이다. Approach 2·3 두 열의 폭은 앞의 재계산 글이 이미 낸 값이고, 여기서는 Approach 1 열을 나란히 붙이는 것이 목적이다. 셋을 함께 놓아야 20이 어느 열의 성질인지가 보인다.
셋째 출력은 방향을 뒤집은 것이다. 표는 을 주고 를 말하는데, 실무의 질문은 반대다 — 예산이 있을 때 모델을 얼마나 키우나. 각 열을 로그-로그에서 회귀해 얻은 멱법칙을 Gopher 예산에 대입하면 67.82B / 63.42B / 42.23B가 나온다. 논문이 Approach 1에 대해 인쇄한 67B, Approach 3에 대해 서술한 40B와 각각 맞는다. 회귀가 표를 제대로 요약했다는 확인이다.
넷째 출력이 「similar」의 유효 범위다. 논문이 실제로 실험을 돌린 구간은 에서 FLOPs다. 그 구간의 아래쪽인 에서 세 예측의 최대/최소 비는 1.07이다. 여기서는 정말 "similar"하다. Gopher 예산에서 1.61, 에서 2.16, 에서 2.59다. 세 방법의 일치는 데이터가 있는 자리의 성질이고, 외삽 거리에 따라 규칙적으로 무너진다. 논문 §3 역시 "there is significant uncertainty extrapolating out many orders of magnitude"라고 적어 두었다.
175B 행 하나는 회귀에서 뺐다. 그 행의 Approach 3 FLOPs가 같은 행의 토큰 수와 정확히 10배 어긋나는데, 이 어긋남은 앞의 재계산 글이 18개 칸을 전수 대조해 찾아 둔 것이다.
뒤 글로 넘기는 계수
Approach 3이 적합한 함수의 계수는 이렇다. 논문 부록 D.2 식 (10)에 인쇄된 것은 지수가 두 자리까지다.
전자리 값 , , 는 원논문 본문에 없다. arXiv에 올라온 TeX 원본의 주석에 남아 있고, 재현 논문(arXiv 2404.10102)이 그것을 표로 옮겼다. 이 두 자리 차이가 무엇을 하는지는 다음 글에서 잰다.
꺾이는 지점
논문에서 그대로 가져다 쓸 수 있는 것은 Approach 1 열의 20~22와 지수 까지다. 표 회귀와 논문 보고값이 소수 둘째 자리까지 맞고, 열의 폭도 1.12배라 상수로 취급해도 손해가 없다. 여기서부터가 손해다 — 같은 논문의 Approach 3 열을 같은 어림으로 읽으면 23에서 142까지 6.20배가 되고, 논문이 스스로 인정한 40B~70B의 불확실성 안에서만 봐도 같은 Gopher 예산의 토큰/파라미터가 19.6과 60.0으로 3배 갈린다.
실무로 옮기면 이렇다. 「20토큰/파라미터」를 쓸 때는 그것이 Approach 1의 값이라는 것을 알고 써야 한다. 그리고 예산이 논문의 실험 구간(~)에서 멀수록 세 방법의 답이 벌어지므로, 급을 계획한다면 어느 열을 따르는지가 모델 크기를 2배 이상 바꾼다.
측정 환경
| 항목 | 값 |
|---|---|
| OS | Linux 6.18.44 x86_64 (컨테이너) |
| CPU | Intel Xeon @ 2.80GHz, 4코어 |
| Python | 3.11.15 |
| numpy | 2.4.6 |
| scipy | 1.17.1 |
| 측정일 | 2026-08-25 |
두 스크립트를 각각 5회 반복 실행했다. approach1.py 0.1180.163초, 0.139초이고 다섯 번의 표준출력이 바이트 단위로 전부 동일했다. 난수를 쓰지 않으므로 시드가 없다. 위 시간은 이 컨테이너 값이고 하드웨어가 다르면 바뀐다 — 결론에 쓰는 것은 비율뿐이다.three.py 0.118
논문 원문은 ar5iv.labs.arxiv.org/html/2203.15556에서 받았다. 2022년 논문이라 arxiv.org/html/에는 HTML 전문이 없다. Table 3과 Table A3은 ar5iv가 <table> 요소로 감싸지 않고 본문 흐름 안에 풀어 놓아, 해당 구간의 태그를 걷어낸 평문에서 숫자를 읽어 옮겼다. 옮긴 값이 맞는지는 위 검산 두 줄(6ND 대조, Gopher 단위 대조)이 대신 확인해 준다 — 잘못 옮겼다면 그 비가 1에서 벗어난다.
한계
전부 나눗셈이다. 우리는 모델을 하나도 학습시키지 않았고 손실을 하나도 측정하지 않았다. 이 글이 확인한 것은 「논문이 인쇄한 표가 자기 안에서 일관되는가, 그리고 그 표에서 20이라는 어림이 어느 열에서 나오는가」뿐이다. 세 접근법 중 어느 것이 옳은지에 대해 이 글은 아무것도 말하지 않는다.
표의 아홉 행은 논문이 이미 외삽한 값이다. 실제 실험은 FLOPs까지였고, 10T 파라미터 행의 은 그보다 일곱 자릿수 위다. 4번 출력의 「에서 2.59배」는 논문의 외삽을 우리가 한 번 더 외삽한 값이므로, 실제 불확실성은 그보다 크면 컸지 작지 않다.
본문과 표의 13.5% 어긋남은 원인을 확정하지 못했다. 다른 접근법의 값을 인용했을 가능성이 가장 그럴듯하지만 인쇄된 숫자만으로는 갈리지 않는다. 가설로만 적었다.
는 근사다. 논문 부록 F는 임베딩과 어텐션 항까지 세는 자세한 회계를 따로 두고, 부록 Table A4에서 그 값이 6ND의 0.99~1.10배라고 보고한다. 위 검산의 「비 1.000」은 논문이 표를 만들 때 6ND를 썼다는 뜻이지 6ND가 정확하다는 뜻이 아니다.
읽어주셔서 감사합니다. 😊

