벤포드 법칙 검정에 파일 3,619개가 걸렸다, 조작한 사람은 없다

벤포드 법칙은 여러 자연 수치 데이터에서 첫 자리가 1일 확률이 30%에 가깝다는 통계 법칙이다. 이 법칙으로 부정을 잡는 검정은 부정이 있어서 걸리는 게 아니라, 데이터가 벤포드에서 벗어난 정도에 표본 크기를 곱한 값이 커지면 걸린다.

장부 하나가 부정 판정을 받았다

두 패널에 첫 자리 막대그래프를 나란히 놓고 각각에 벤포드 이론값을 점선으로 겹친 그림. 왼쪽은 피보나치 수열로 막대가 점선에 그대로 얹히고, 오른쪽은 저장소 파일 3,619개로 자리 1이 점선 위로 솟고 자리 3과 6이 아래로 내려앉아 그 세 자리에 세로 표시가 붙어 있다. 아래 띠에 판정 배지가 둘 있는데 왼쪽은 통과, 오른쪽은 기각 p = 3.89×10⁻¹²다

회계 감사에는 장부 금액의 맨 앞 숫자만 세어 보는 검정이 있다. 1이 몇 번, 2가 몇 번, 9가 몇 번 나왔는지를 세어 그 비율을 벤포드 법칙이 말하는 이론 분포와 맞춰 본다. 어긋나는 정도가 우연으로 설명되지 않으면 그 장부에 조작 의심 표시가 붙는다.

어떤 장부에서 p값이 10⁻¹²로 나왔다고 하자. 데이터가 정말 벤포드를 따를 때 이만큼 또는 그보다 크게 어긋난 표본이 나올 확률이 1조분의 1이라는 뜻이다. 금액을 지어내는 사람은 총액과 자릿수는 맞춰도 맨 앞 숫자의 분포까지 관리하지는 않는다. 감사자는 여기서 부정을 의심한다.

같은 검정을 조작할 수 없는 데이터에 걸어 봤다. 이 블로그의 원고와 코드가 들어 있는 저장소가 추적하는 파일 가운데, 크기가 0이 아닌 3,619개의 바이트 수다. 그 목록은 이 글에 함께 싣는다.

숫자가 흔들리지 않도록 조건을 둘 걸었다. 저장소는 커밋할 때마다 자라니 2026-08-09의 커밋 하나(b38421f)에 값을 고정했다. 그리고 작업 폴더를 훑어 잰 크기가 아니라 git이 보관하고 있는 원본 바이트 수를 썼다. 그래서 윈도우에서 재든 리눅스에서 재든 같은 값이 나온다.

결과는 p = 3.89×10⁻¹²였다. 파일 크기를 조작할 사람은 없다. 에디터가 저장한 만큼, 컴파일러가 뱉은 만큼 쌓인 바이트 수다. 그런데도 검정은 장부와 같은 자릿수의 p값을 내놓고 이 데이터를 기각한다.

그러니 기각 자체는 부정의 증거가 아니다. 기각을 결정하는 것은 부정의 유무가 아니라 데이터가 벤포드에서 벗어난 정도와 표본 크기다. 이 글은 벤포드 법칙이 왜 성립하는지부터 세운다. 그다음 그 법칙을 쓰는 검정이 실제로 무엇을 재고 있는지를 단계별로 확인한다. 검정을 검사하려면 검정이 딛고 선 법칙부터 흔들리지 않아야 하기 때문이다.

벤포드 법칙은 왜 첫 자리로 1을 고를까

첫 자리 1부터 9까지가 각각 9분의 1씩 나올 것 같지만 그렇지 않다. 1이 30.1%, 9가 4.6%다. 자리 d가 나올 확률은 이렇게 적힌다.

(1) $$ P(d) = \log_{10}\left(1 + \frac{1}{d}\right), \qquad d = 1, 2, \dots, 9 $$

식 1이 이렇게 생긴 이유는 조건 하나에서 나온다. 첫 자리 분포가 단위에 좌우되지 않아야 한다는 조건이다. 금액을 원으로 적든 달러로 적든 같은 분포가 나와야 한다.

단위를 바꾸는 일은 모든 값에 같은 상수를 곱하는 일이다. 로그를 취하면 곱하기는 전체를 옆으로 미는 일이 된다. 그런데 첫 자리를 정하는 것은 그 로그의 소수부, 곧 0과 1 사이 어디에 놓이는가뿐이다. 소수부는 1을 넘으면 다시 0으로 돌아오므로, 이 구간 위에서 옆으로 밀어도 모양이 그대로인 분포는 하나뿐이다. 높낮이가 어디서나 같은 균등분포다.

그래서 값의 로그가 고르게 퍼져 있다고 놓는다. 첫 자리가 d인 값들은 로그 스케일에서 log₁₀d부터 log₁₀(d+1)까지의 구간을 차지하고, 그 구간의 폭이 곧 확률이다. 폭을 정리하면 식 1가 된다.

법칙이 얼마나 정확한지는 조건을 확실히 만족하는 데이터에 대 보면 안다. 피보나치 수열 F(1)~F(1000)의 첫 자리를 세면 1이 30.1%다. 2의 거듭제곱 2¹부터 2¹⁰⁰⁰까지도 30.1%다. 두 수열이 이론값에서 얼마나 벗어났는지는 평균 절대 편차(mean absolute deviation, MAD)로 잰다. 자리 아홉 개에서 관측 비율과 이론 비율의 차이를 절댓값으로 평균한 값이다. 각각 0.00082와 0.00068이 나온다.

피보나치·2의 거듭제곱·소수·저장소 파일 크기의 첫 자리 분포를 벤포드 이론값과 비교한 네 패널 막대그래프
그림 1. 네 데이터의 첫 자리 분포(막대)와 벤포드 이론값(점선). 피보나치와 2의 거듭제곱은 이론값에 거의 정확히 얹히고, 소수는 모양 자체가 다르다. 저장소 파일 크기는 벤포드를 닮았지만 자리 1이 크게 넘치고 자리 3과 6이 모자란다.

그림 1의 위쪽 두 패널이 그 둘이다. 막대가 점선 위에 그대로 앉는다. 벤포드 법칙은 대충 들어맞는 경험칙이 아니라, 조건이 맞으면 정확히 성립하는 수학적 사실이다. 법칙을 흔들어서 결론을 낼 글이 아니라는 뜻이기도 하다.

아래쪽 두 패널은 사정이 다르다. 100만 미만 소수 78,498개는 1이 12.2%밖에 안 되고, 모양이 벤포드보다 균등분포에 훨씬 가깝다. 저장소 파일 크기는 육안으로는 벤포드를 닮았는데 1이 35.2%로 이론값보다 5%포인트쯤 높다. 그 5%포인트가 앞 절의 p값에 가장 크게 기여했다. 자리 3과 6이 모자란 몫도 함께 들어간다. 네 데이터가 이렇게 갈리는 데에는 조건이 하나 있다.

몇 자릿수를 걸쳐야 벤포드를 따르는가

피보나치와 2의 거듭제곱은 왜 그렇게 정확한가. 둘 다 기하수열이라 로그를 취하면 일정한 간격으로 늘어선다. 항이 1,000개나 되니 그 간격이 로그 스케일을 촘촘하게 덮는다. 앞 절이 요구한 조건을 그대로 만족한다.

그럼 조건을 얼마나 만족해야 충분한지 숫자로 잡아 보자. 눈금은 값이 걸치는 자릿수 폭이다. 값에 로그를 취한 다음, 그 로그의 평균에서 표준편차 하나만큼 좌우로 벌린 구간이 십진수로 몇 자릿수를 차지하는지를 잰다. 평균도 표준편차도 값 자체가 아니라 로그의 것이다. 이 폭이 1이라는 것은 그 구간이 대략 10배 범위에 퍼져 있다는 뜻이다.

로그정규분포는 이 폭을 파라미터 하나로 조절할 수 있어서 실험대에 올리기 좋다. 그 파라미터가 σ다. σ를 키우면 값의 로그가 더 넓게 퍼지고, 따라서 값도 더 넓은 자릿수에 걸친다. 아래 표는 각 σ에서 첫 자리 분포를 해석적으로 계산한 결과다. 표본을 뽑지 않고 확률을 직접 구한 이유는 하나다 — 표본으로 재면 σ가 큰 쪽의 이탈량이 표본잡음에 통째로 잠긴다.

로그정규 σ ±1σ 구간의 자릿수 폭 MAD 판정
0.2 0.17 1.13×10⁻¹ 이탈 큼
0.5 0.43 5.37×10⁻² 이탈 큼
0.8 0.69 1.26×10⁻² 경계
1.0 0.87 3.30×10⁻³ 거의 일치
1.2 1.04 6.42×10⁻⁴ 거의 일치
1.5 1.30 3.15×10⁻⁵ 거의 일치

폭이 1자릿수를 넘어서는 언저리에서 이탈이 자릿수 단위로 곤두박질친다. σ가 0.8에서 1.0으로 갈 때 MAD가 4배 줄고, 1.0에서 1.2로 갈 때 5배, 1.2에서 1.5로 갈 때 20배 줄어든다. "데이터가 여러 자릿수에 걸쳐 있어야 벤포드를 따른다"는 통설의 정량판이며, 임계는 대략 1자릿수다.

표의 판정 칸은 MAD 값을 구간에 넣어 읽은 것이다. 구간 자체는 이 글이 유도한 값이 아니라 마크 니그리니(Mark J. Nigrini)가 부정 적발 실무의 기준으로 제시해 통용되는 인용값이다. 첫 자리 검정의 구간은 넷이다.

  • 0.006 미만 — 거의 일치(close conformity)
  • 0.012 미만 — 수용 가능(acceptable)
  • 0.015 미만 — 경계(marginal)
  • 0.015 이상 — 이탈 큼(nonconformity)

표는 이 넷을 셋으로 줄여 적었다. 0.012 미만을 거의 일치로 묶고, 0.012에서 0.015 사이를 경계, 그 위를 이탈 큼으로 표시했다. 이론에서 떨어져 나온 경계가 아니라는 점은 알고 쓰는 편이 좋다.

이제 반대쪽을 보자. 자릿수를 거의 안 걸치는 데이터는 어떻게 되는가. 성인 키를 cm로 적으면 값이 거의 전부 100대에 몰린다. 평균 170, 표준편차 10인 정규분포에서 20만 개를 뽑아 첫 자리를 세면 1이 99.85%다. MAD는 0.155로 위 표의 어느 행보다 크다. σ=0.2짜리 좁은 로그정규도 같은 계열이라 표 첫 줄에서 이미 이탈 큼 판정을 받았다.

여기서 말을 정확히 골라야 한다. 키(cm)는 벤포드 법칙을 어기는 데이터가 아니다. 벤포드 법칙이 적용될 조건을 처음부터 만족하지 않는 데이터다. 값이 한 자릿수 안에 갇혀 있으면 단위를 바꿔도 분포가 같아야 한다는 조건을 걸어 볼 여지 자체가 없다.

소수도 같은 자리에 있다. 100만 미만 소수의 87.8%가 10만에서 100만 사이 한 구간에 몰려 있고, 그 안에서는 소수가 거의 고르게 흩어져 있다. 값이 한 구간 안에 고르게 깔리면 첫 자리는 벤포드가 아니라 균등에 가까워진다.

0과 100 사이 균등분포에서 20만 개를 뽑아도 결과가 같다. 1이 11.1%로 나오고 MAD는 0.05978이다. 값의 90%가 10에서 100 사이 한 구간에 들어가 고르게 깔리기 때문이다. 그러니까 한 자릿수 구간 안에서 한쪽으로 쏠리면 키(cm)처럼 자리 하나로 몰리고, 고르게 깔리면 소수처럼 균등으로 간다. 어느 쪽도 벤포드가 아니다.

벤포드로 갈지 아닐지는 결국 자릿수 폭이 가른다. 실무에서는 그 폭을 거칠게 재도 된다. 최댓값과 최솟값의 로그 차를 그대로 쓰면 된다. 이 차이는 값이 실제로 걸치는 전체 범위여서 ±1σ 구간을 통째로 품고, 그래서 표가 쓴 폭보다 좁게 나올 수 없다. 전체 범위를 재서 1자릿수가 안 나오면 ±1σ 폭은 확실히 그 아래다. 다만 반대 방향은 성립하지 않는다 — 범위가 넉넉해도 벤포드를 따른다는 보장은 없으니, 이 눈금은 실격만 걸러 낸다.

데이터에 이 검정을 걸기 전에, 값이 몇 자릿수에 걸쳐 있는지부터 재 보자. np.log10(x.max()) - np.log10(x.min()) 한 줄이면 나온다. 이 값이 1자릿수에 못 미치면 벤포드 검정은 적용 대상이 아니다.

여기까지 이탈의 크기는 전부 MAD로 이야기했다. 다만 첫 절에서 장부와 저장소를 기각한 판정은 MAD가 아니라 카이제곱 검정이 내린 것이다. 카이제곱은 같은 이탈을 다르게 센다.

이탈량과 필요 표본 — 검정을 숫자로 옮기기

MAD는 이탈을 재기에 직관적이다. 카이제곱 검정은 다른 방식으로 센다. 자리마다 관측 개수와 기대 개수의 차이를 제곱한 뒤 기대 개수로 나눠서 아홉 개를 더한다. 기대 개수가 작은 자리에서 생긴 차이에 더 큰 벌점을 매기는 셈이다. 원래 4.6%밖에 안 나오는 자리 9에서 어긋난 1%포인트는, 30%가 나오는 자리 1에서 어긋난 1%포인트보다 훨씬 이상한 일이기 때문이다. 이 합이 카이제곱 통계량이고, 자유도 8의 카이제곱 분포에 대 보면 p값이 나온다.

여기서 성질 하나가 중요하다. 관측 개수와 기대 개수는 둘 다 표본 크기 N에 비례하므로, 비율을 고정한 채 N을 두 배로 늘리면 통계량도 정확히 두 배가 된다. 어긋남의 모양이 같아도 표본이 열 배면 통계량도 열 배라는 뜻이다. 그러니 통계량에서 N을 떼어 낸 몫을 따로 부르는 편이 편하다. 이 글에서는 이탈량이라고 부르겠다.

(2) $$ \text{effect} = \sum_{d=1}^{9} \frac{(p_{\text{obs},d} – p_{\text{bf},d})^2}{p_{\text{bf},d}} $$

식 2는 데이터가 벤포드에서 얼마나 떨어져 있는지를 검정의 언어로 요약한 숫자다. 관측 비율과 이론 비율만 있으면 정해지고 표본 크기는 들어가지 않는다. 그리고 카이제곱 통계량의 기댓값은 이 값에 N을 곱한 만큼 커진다.

(3) $$ \lambda = N \times \text{effect} $$

식 3의 λ는 비중심 카이제곱 분포의 비중심모수라고 부르는 값이다.

기각 확률은 이 λ 하나가 정한다. 데이터가 무엇이든 표본이 몇 건이든, 둘을 곱한 값이 같으면 기각 확률도 같다.

앞 절의 저장소 파일 크기로 직접 재 보자. 첫 자리를 세어 MAD와 이탈량을 구하고, 식 3의 λ까지 한 번에 찍는다. 동봉한 목록만 있으면 저장소 없이도 같은 값이 나온다.

import json
import pathlib

import numpy as np

# 이 글에 동봉한 동결 데이터셋 — 커밋 b38421f 가 추적하던 파일 3,619개의
# git blob 크기(바이트, 2026-08-09)
sizes = np.array(json.loads(
    pathlib.Path("data/repo-file-sizes.json").read_text(encoding="utf-8")
)["sizes"], dtype=float)

exp = np.floor(np.log10(sizes))
lead = np.clip(np.floor(sizes / 10.0 ** exp).astype(int), 1, 9)   # 첫 자리
obs = np.bincount(lead, minlength=10)[1:10]
benford = np.array([np.log10(1 + 1/d) for d in range(1, 10)])

p_obs = obs / obs.sum()
mad = np.mean(np.abs(p_obs - benford))
effect = np.sum((p_obs - benford) ** 2 / benford)

print(f"자리별 개수 = {obs.tolist()}")
print(f"n      = {obs.sum():,}")
print(f"MAD    = {mad:.5f}")
print(f"이탈량 = {effect:.5f}")
print(f"lambda = {obs.sum() * effect:.2f}  <- 카이제곱 통계량")
자리별 개수 = [1275, 626, 390, 382, 284, 181, 188, 157, 136]
n      = 3,619
MAD    = 0.01332
이탈량 = 0.01948
lambda = 70.51  <- 카이제곱 통계량

자유도 8에서 통계량 70.51이면 p값이 10⁻¹²대로 떨어진다. 첫 절의 판정은 이 한 줄에서 나왔다. 같은 데이터를 MAD로 읽으면 경계 구간에 걸치는 정도인데, 카이제곱은 기각으로 끝낸다.

식 3를 뒤집으면 필요 표본이 나온다. 원하는 기각 확률에 해당하는 λ를 정해 놓고 이탈량으로 나누면, 그 확률로 기각하는 데 필요한 표본 크기가 된다. 필요 표본은 이탈량에 반비례한다.

벤포드 이탈량과 99% 기각에 필요한 표본 크기의 반비례 관계를 로그-로그 축에 그린 산점도
그림 2. 가로축은 벤포드 이탈량, 세로축은 99% 확률로 기각하는 데 필요한 표본 크기(둘 다 로그축). 로그정규 σ 스윕이 그리는 직선 위에 저장소 실데이터 점과 σ=0.8 합성 대조군 점이 나란히 놓인다.

그림 2이 그 반비례를 로그-로그 축에 그린 것이다. 로그정규 σ를 0.2부터 1.5까지 훑은 여섯 점이 직선 하나에 놓인다. 이탈량이 100배 작아지면 필요 표본이 100배 커진다는 뜻이다. σ=1.5짜리 데이터는 이탈량이 9.25×10⁻⁸이라 3억 3천만 건을 모아야 99% 확률로 기각된다.

직선 위에 점 두 개를 더 찍어 두었다. 저장소 파일 크기와 로그정규 σ=0.8이다. 하나는 실측한 파일 시스템이고 하나는 난수 생성기가 뱉은 합성 데이터인데, 이탈량이 1.95×10⁻²와 1.49×10⁻²로 비슷해서 그림에서도 붙어 있다. 검정은 데이터의 정체를 보지 않고 이 축 하나만 본다.

판정 지도 — 네 줄을 나란히 놓아야 보이는 것

그림에서 붙어 있는 두 점이 실제 판정에서도 붙는지는 표로 확인해야 한다. 네 종류의 데이터에 같은 검정을 걸고, 표본 크기를 바꿔 가며 1,000번씩 반복해 기각률을 셌다. 유의수준은 0.05다. 네 줄은 각각 따로 읽을 관찰이 아니라, 기각을 설명할 후보를 하나씩 지워 나가는 순서다.

데이터 MAD 이탈량 99% 기각에 필요한 N N=500 N=1,000 N=5,000 N=10,000
저장소 파일 크기 (실데이터) 0.01332 1.95×10⁻² 1,559 0.576 0.907 1.000 1.000
로그정규 σ=0.8 (이탈량 대조군) 0.01262 1.49×10⁻² 2,041 0.454 0.784 1.000 1.000
로그정규 σ=2.0 (깨끗) 4.66×10⁻⁸ 2.03×10⁻¹³ 실무 범위 밖 0.046 0.049 0.067 0.055
정확히 벤포드 (대조) 0 0 해당 없음 0.066 0.050 0.051 0.052

첫 줄이 지울 대상을 만든다. 부정이 하나도 없는 저장소 파일 크기가 N=1,000에서 약 90% 확률로, N=5,000에서는 거의 예외 없이 기각된다. 남은 일은 무엇이 이 기각을 불렀는지 좁히는 것이다.

둘째 줄이 데이터의 정체를 지운다. 이탈량만 비슷하게 맞춘 합성 로그정규가 검정력 곡선의 같은 자리에 놓인다. 이탈량이 조금 작은 만큼 기각률도 조금씩 낮게 나올 뿐, N=5,000부터는 둘 다 예외 없이 기각된다. 파일 시스템에서 왔든 난수 생성기에서 왔든 결과는 갈리지 않는다.

셋째 줄이 표본 크기를 지운다. σ=2.0 로그정규는 이탈량이 2.03×10⁻¹³이라 N을 10,000까지 키워도 기각률이 0.055에 머문다. 표본을 키우는 것만으로는 아무 일도 일어나지 않는다.

식 3를 그대로 읽으면 이런 말도 나온다. 표본만 충분히 키우면 이탈량이 0이 아닌 어떤 데이터든 결국 기각된다는 것이다. 맞는 말이다. 다만 그 "결국"이 언제인지도 같은 식이 정한다. σ=2.0에서는 그 지점이 1조 건 너머라, 실무에서 모을 수 있는 표본으로는 영원히 안 걸린다.

지워지지 않고 남은 것은 λ, 곧 표본 크기와 이탈량을 곱한 값 하나다. 넷째 줄은 그 결론이 엉뚱한 데로 미끄러지지 않게 잡아 준다. 벤포드 분포에서 직접 뽑은 데이터, 즉 귀무가설이 문자 그대로 참인 데이터는 N이 얼마든 기각률이 0.05 근처에 머문다. 검정은 고장 나 있지 않다.

카이제곱 기각은 이 데이터가 정확히 벤포드 분포는 아니라는 뜻이다. 이 데이터에 부정이 있다는 뜻이 아니다. 넷째 줄이 그 차이를 보증한다. 검정은 자기가 답하기로 한 질문에 정확히 답하고 있고, 다만 그 질문이 감사자가 묻고 싶은 질문과 다를 뿐이다.

같은 검정은 반대쪽에서도 실패한다 — 정작 잡아야 할 것을 놓친다. 위조 모형은 사람이 무작위로 보이게 찍은 숫자로 잡았다. 1부터 9까지 균등하게 고르는 방식이다. 이렇게 만든 숫자를 1,000건짜리 장부에 일정 비율로 섞고, 비율마다 2,000번씩 검정을 돌려 검출률을 셌다.

위조가 섞인 비율 검출률
0% 0.051
5% 0.112
10% 0.263
20% 0.833
30% 0.998

100건이 위조된 장부의 검출률이 0.263이다. 네 번 중 세 번은 그냥 통과시킨다. 20%가 위조돼야 0.833으로 쓸 만해지고, 5%에서는 열에 아홉을 놓친다.

이 표가 검정에 최대한 유리하게 짜였다는 점은 밝혀 두어야 한다. 위조되지 않은 나머지를 정확히 벤포드 분포에서 뽑았기 때문이다. 실제 장부라면 그 나머지부터 이미 벤포드에서 벗어나 있어서, 위조가 0%인 줄부터 기각될 것이다.

두 실패는 서로 모순이 아니다. 결백한 파일 3,619개는 기각하고 100건이 위조된 장부 1,000건은 통과시킨다. 원인은 하나다. 검정은 이 데이터가 정확히 벤포드인지를 묻고 있고, 감사자는 부정이 있는지를 묻고 있다. 그렇다면 감사자 쪽에 남는 일도 하나다. 이 검정이 몇 건부터 기각으로 돌아설지를 미리 계산해 두는 것이다.

내 데이터의 이탈량으로 필요 표본을 미리 계산한다

먼저 같은 데이터를 자 두 개로 재 보자. MAD와 카이제곱 p값이다. 저장소 파일 크기의 첫 자리 분포를 모집단으로 두고 N개씩 다시 뽑아, 두 값을 각각 1,000번 계산했다. 데이터는 한 번도 바뀌지 않는다. 바뀌는 것은 표본 크기뿐이다.

표본 크기에 따라 MAD의 90% 구간 밴드가 좁아지며 모집단 값 0.01332로 수렴하는 그래프
그림 3. 같은 데이터에서 N개씩 재추출했을 때 MAD의 평균(중심선)과 90% 구간(밴드). N이 커질수록 모집단 값 0.01332로 좁혀지고, 판정도 한자리에서 굳는다. 가로 점선 두 개는 MAD 판정 구간의 경계다.

그림 3에서 MAD는 N이 커질수록 모집단 값 0.01332로 좁혀진다. 밴드가 줄어들 뿐 중심이 다른 데로 가지 않고, 판정도 경계 구간에서 굳는다. 카이제곱 p값은 전혀 다르게 움직인다.

N MAD 평균 MAD 판정 카이제곱 p 중앙값
100 0.02684 이탈 큼 3.6×10⁻¹
500 0.01696 이탈 큼 4.1×10⁻²
1,000 0.01523 이탈 큼 1.2×10⁻³
5,000 0.01383 경계 4.4×10⁻¹⁹
10,000 0.01358 경계 3.2×10⁻³⁹
100,000 0.01335 경계 0 (언더플로)

N=100에서 p 중앙값이 0.36이다. 기각할 근거가 전혀 없다는 뜻이다. 같은 데이터가 N=1,000에서는 0.0012로 내려가고, N=100,000에서는 배정밀도 실수로 적을 수 있는 범위 아래로 떨어져 0으로 찍힌다. 데이터는 그대로인데 판정만 뒤집힌다.

MAD도 N에서 완전히 자유롭지는 않다. 표 첫 줄을 보면 N=100에서 평균이 0.02684로 모집단 값의 두 배 넘게 부풀어 있다. 표본잡음이 절댓값 편차에 그대로 더해지기 때문이다. 작은 표본에서 MAD가 크게 나오는 것을 이탈이 크다는 뜻으로 읽으면 안 된다. MAD가 쓸 만한 이유는 N에 안 흔들려서가 아니라, 충분한 N에서 값이 수렴하고 그 수렴값이 곧 판정 기준이라서다.

두 자를 나란히 놓고 보면 계산에 무엇이 필요한지가 분명해진다. 표본 크기가 들어가지 않는 양을 하나 잡고, 거기에 표본 크기를 곱해 판정을 예측하면 된다. 식 3가 이미 그 구조였다. 그러니 재료는 둘이다. 내 데이터의 이탈량, 그리고 원하는 검정력에 해당하는 λ를 구하면 된다. 아래 코드가 검정력 세 값에 대해 λ를 풀고 필요 표본을 함께 찍는다.

from scipy import stats

def lambda_for_power(power, alpha=0.05, df=8):
    """검정력 power에 필요한 비중심모수 λ를 이분법으로 푼다."""
    crit = stats.chi2.ppf(1 - alpha, df)
    lo, hi = 0.0, 1000.0
    for _ in range(200):
        mid = (lo + hi) / 2
        if stats.ncx2.sf(crit, df, mid) < power:
            lo = mid
        else:
            hi = mid
    return hi

effect = 0.01948          # 앞에서 잰 저장소 파일 크기의 이탈량

for power in (0.50, 0.80, 0.99):
    lam = lambda_for_power(power)
    print(f"검정력 {power:.0%}: λ = {lam:6.2f}   N* = {lam/effect:9,.0f}")
검정력 50%: λ =   8.40   N* =       431
검정력 80%: λ =  15.02   N* =       771
검정력 99%: λ =  30.36   N* =     1,558

세 줄이 한꺼번에 알려주는 것이 있다. 검정력은 표본에 완만하게 붙는다. 99%에 1,558건이 필요한 데이터라도 그 절반인 779건이면 이미 검정력이 80%를 넘는다. 4분의 1을 조금 넘는 431건에서는 50%에 닿는다.

감사 표본이 흔히 잡는 1,000건 규모에서 저장소 파일 크기가 약 90%로 기각된 것도 그래서다. 필요 표본에 못 미치는데도 이미 검정력 곡선의 가파른 구간에 올라와 있다. 앞 절 표의 1,559는 이 식이 준 1,558.3을 올림한 값이다.

λ를 상수로 적어 두지 않고 매번 푸는 데는 이유가 있다. 자유도 8, 유의수준 0.05에서 카이제곱 임계값은 15.51인데 검정력 80%에 필요한 λ가 15.02라 둘이 거의 붙어 있다. 서로 다른 것을 재는 두 숫자가 눈으로는 구별되지 않는다는 뜻이다. 실제로 이 글의 초기 원고가 임계값 15.5를 필요 표본 공식의 상수로 적었다가 검산에서 걸렸다.

  1. 데이터의 첫 자리를 세어 자리 1부터 9까지의 관측 비율을 구한다. 값이 0인 항목은 빼고, 부호는 무시한다.
  2. 관측 비율과 벤포드 이론값의 차이를 제곱해 이론값으로 나눈 뒤 아홉 개를 더한다. 이탈량이다.
  3. 원하는 검정력의 λ를 이탈량으로 나눈다. 그 값이 필요 표본이다. 내 표본이 그보다 훨씬 작으면 이 검정은 웬만해선 아무 말도 하지 않고, 훨씬 크면 거의 확실하게 기각한다.

그러니 검정 결과를 받아 들 일이 있으면 p값 옆에 이탈량을 한 칸 더 적어 두자. λ를 그 한 칸으로 나누면 이 검정이 몇 건부터 기각으로 돌아서는지가 곧바로 나온다. 그 계산 어디에도 부정이 있느냐 없느냐는 들어가지 않는다.

이 사고방식은 벤포드 밖으로도 닿는다. 적합도 검정은 전부 같은 구조를 쓴다. 관측 분포와 이론 분포 사이의 거리에 표본 크기를 곱한 값이 판정을 만든다. 그래서 기각됐다는 말은 차이가 실질적으로 크다는 뜻이 아니라 차이를 볼 만큼 표본이 컸다는 뜻이다. 두 말은 표본이 작을 때만 우연히 겹친다.

더 읽기

  • Simon Newcomb, "Note on the Frequency of Use of the Different Digits in Natural Numbers", American Journal of Mathematics 4, 1881, 39–40. https://doi.org/10.2307/2369148
  • Frank Benford, "The Law of Anomalous Numbers", Proceedings of the American Philosophical Society 78(4), 1938, 551–572. https://www.jstor.org/stable/984802
  • Mark J. Nigrini, Benford’s Law: Applications for Forensic Accounting, Auditing, and Fraud Detection, Wiley, 2012 — 본문의 MAD 판정 구간이 인용된 출처로 통용되는 문헌.