요동-소산 정리: 마찰이 있으면 잡음이 있다
지금까지는 관성을 뺐다. 물속의 작은 알갱이에서는 옳은 근사지만, HMC(Hamiltonian Monte Carlo, 해밀토니안 몬테카를로: 샘플에 무작위 운동량을 붙여 멀리 옮기는 샘플러)나 모멘텀 SGD처럼 운동량을 가진 계에서는 어떨까?
역사: 저항기의 잡음
흔드는 것과 막는 것의 관계는 아인슈타인의 브라운 운동 논문이 나오고 20여 년 뒤 전기 회로에서 다시 나타났다. 1928년 벨 연구소의 존 존슨은 전류가 흐르지 않는 저항기의 양 끝에서도 전압이 쉬지 않고 흔들리며, 그 제곱 평균이 저항값과 절대온도에 비례함을 측정했다. 같은 연구소의 해리 나이퀴스트는 같은 해 이 잡음을 열역학으로 설명했다. 전하의 흐름을 막아 열을 내는 저항기가 곧 전하를 흔드는 원인이라는 것이다. 1951년 캘런과 웰턴은 에너지를 잃는 선형 계라면 어디서나 마찰의 크기와 온도가 잡음의 크기를 정한다는 일반적인 관계를 증명했다.
조화 진동자에 마찰과 잡음 넣기
운동량을 다루려면 관성을 되살려야 한다. 랑주뱅이 1908년에 처음 쓴 것도 질량이 있는 뉴턴 방정식이었고, 1930년 울렌벡과 오른스타인은 이 식으로 속도까지 넣은 브라운 운동을 풀었다. 먼저 숫자로 보자. 용수철에 매달린 추처럼 위치에너지가 U = q²/2인 조화 진동자(m = 1)를 q = 3에서 놓고, 운동량을 짧은 시간마다 세 가지로 바꾼다. 용수철의 힘으로 바뀌고, 마찰로 일정한 비율만큼 깎이고, 잡음으로 흔들린다. 시간 40 동안 돌린 뒤 운동량 제곱의 평균 ⟨p²⟩를 재면, 마찰(계수 0.5)만 있을 때는 0.000으로 멈추고, 단위 시간당 분산 1인 잡음만 있을 때는 24.7로 불어나며, 둘을 함께 두면 1.000이 된다. 마찰은 그대로 두고 잡음의 분산만 2로 키우면 1.99다. 잡음의 분산이 마찰 계수의 두 배일 때만 온도 1의 볼츠만 분포가 주는 ⟨p²⟩ = 1에 이르는 듯하다. 이 관계를 식으로 적어 보자.
해밀턴 흐름 + 마찰 + 잡음
위치 q와 운동량 p로 적으면 다음과 같다.
이 식을 언더댐프드 랑주뱅 방정식(관성을 남겨 둔 채 해밀턴 흐름에 마찰과 잡음을 더한 식, underdamped Langevin equation)이라 한다. 마찰과 잡음을 지우면 dq = (p/m)dt, dp = −∇U dt로 해밀턴 방정식 그대로여서, 이 식은 해밀턴 역학 + 마찰 + 잡음이다. 이 식을 따르는 (q, p)의 분포는 위상공간(위치와 운동량을 두 축으로 한 공간, phase space. 수학의 위상공간과 이름만 같다)의 볼츠만 분포 e^(−ℋ/kT)에 이른다.
그런데 잡음 앞의 √(2ζkT)는 왜 하필 이 크기일까? 마찰과 잡음이 서로 다른 크기이면 무슨 일이 생길까?
운동에너지가 들고 나는 셈
앞의 네 숫자는 운동에너지가 들어오고 나가는 셈으로 읽을 수 있다. 해밀턴 흐름은 운동에너지와 위치에너지를 서로 바꿀 뿐 전체 에너지를 바꾸지 않으므로, 전체 에너지를 바꾸는 것은 마찰과 잡음뿐이다. 마찰은 운동량을 깎아 운동에너지를 빼내는데, 빼내는 빠르기는 마찰 계수와 지금의 운동에너지에 비례한다. 잡음은 운동량을 흔들어 운동에너지를 넣는데, 넣는 빠르기는 잡음 분산에 비례하고 지금의 운동에너지와는 상관없다. 둘이 비기는 곳을 계산하면 다음과 같다.
마찰 계수가 빼내는 쪽과 넣는 쪽에 똑같이 곱해져 있으므로, 비기는 곳의 운동에너지는 ζ와 상관없이 kT/2다. 마찰을 키우면 잡음도 같은 비율로 키워야 온도가 유지된다. 반대로 마찰만 있고 잡음이 없으면 운동에너지가 0으로 빠져나가 계가 식고, 잡음만 있고 마찰이 없으면 에너지가 들어오기만 해서 계가 한없이 뜨거워진다. 조화 진동자에서 잰 네 숫자(마찰만 0.000, 잡음만 24.7, 짝이 맞으면 1.000, 잡음 분산이 두 배면 1.99)가 바로 이 셈을 따른다. 에너지를 잃게 하는 마찰이 있는 계는 반드시 그 마찰과 온도로 크기가 정해진 잡음을 받는다는 이 관계를 요동-소산 정리 (마찰로 에너지를 잃는 계가 받는 잡음의 크기가 마찰 계수 × 온도로 정해진다는 관계, fluctuation-dissipation theorem)라 한다. 아인슈타인 관계 D = kT/ζ는 관성을 뺀 경우의 요동-소산 정리다.

일상 사례: 앰프의 「쉬」 소리
오디오 앰프의 볼륨을 끝까지 올리면 음악을 틀지 않아도 「쉬」 하는 소리가 난다. 그 소리의 한 몫은 회로 속 저항기에서 온다. 저항기는 전하의 흐름을 막아 전기 에너지를 열로 바꾸는 마찰이므로, 전류가 흐르지 않아도 저항기 양 끝에는 그 저항값과 온도로 크기가 정해진 잡음 전압이 생긴다.
이것이 존슨–나이퀴스트 잡음이다. 실온(300 K)의 1 MΩ(메가옴, Ω는 그리스 문자 오메가) 저항기를 주파수 폭 10 kHz로 재면 잡음 전압의 제곱평균제곱근은 약 12.9 μV다. 마찰(저항값)이 클수록, 온도가 높을수록 잡음이 크다. 아주 약한 신호를 재는 전파 망원경의 수신기를 극저온으로 식히는 까닭도 여기에 있다.
코드로 확인하기
조화 진동자에 언더댐프드 랑주뱅 방정식을 쓰고, 마찰만, 잡음만, 짝이 맞는 둘, 짝이 어긋난 둘을 비교하는 코드다. 이어서 위치에너지 없이 마찰을 키워 가며 위치의 확산 계수가 kT/ζ로 가는지 본다.
import numpy as np
rng = np.random.default_rng(1)
# 언더댐프드 랑주뱅: 해밀턴 흐름 + 마찰 + 잡음. U(q) = q²/2, 질량 m = 1, kT = 1
def run(zeta, noise, T=40.0, dt=0.01, n=20000, q0=3.0, p0=0.0):
q = np.full(n, q0); p = np.full(n, p0)
for _ in range(int(T / dt)):
p = p - q * dt - zeta * p * dt + noise * np.sqrt(dt) * rng.standard_normal(n) # 힘, 마찰, 잡음
q = q + p * dt # 위치는 운동량으로
return q, p
kT = 1.0
for label, zeta, noise in (("마찰만 (모멘텀 SGD)", 0.5, 0.0),
("잡음만", 0.0, np.sqrt(2 * 0.5 * kT)),
("마찰 + 짝이 맞는 잡음", 0.5, np.sqrt(2 * 0.5 * kT)),
("마찰 0.5 + 마찰 1에 맞춘 잡음", 0.5, np.sqrt(2 * 1.0 * kT))):
q, p = run(zeta, noise)
print(f"{label:22s}: ⟨p²⟩ = {np.mean(p**2):7.3f}, ⟨q²⟩ = {np.mean(q**2):7.3f}, 잡음²/(2ζ) = "
f"{(noise**2 / (2 * zeta) if zeta > 0 else float('inf')):.2f}")
# 마찰이 크면: 운동량은 금방 열평형이 되고, 위치만 보면 확산 계수 kT/ζ인 브라운 운동 (위치에너지 없이)
for zeta in (0.5, 5.0, 50.0):
q = np.zeros(20000); p = np.sqrt(kT) * rng.standard_normal(20000); dt = min(0.01, 0.1 / zeta)
T = 20.0
for _ in range(int(T / dt)):
p = p - zeta * p * dt + np.sqrt(2 * zeta * kT * dt) * rng.standard_normal(q.size)
q = q + p * dt
print(f"ζ = {zeta:4}: 시간 {T:.0f} 뒤 ⟨q²⟩/(2T) = {np.mean(q**2) / (2 * T):.4f}, kT/ζ = {kT / zeta:.4f}")
# 마찰만 (모멘텀 SGD) : ⟨p²⟩ = 0.000, ⟨q²⟩ = 0.000, 잡음²/(2ζ) = 0.00
# 잡음만 : ⟨p²⟩ = 24.714, ⟨q²⟩ = 24.398, 잡음²/(2ζ) = inf
# 마찰 + 짝이 맞는 잡음 : ⟨p²⟩ = 1.000, ⟨q²⟩ = 1.001, 잡음²/(2ζ) = 1.00
# 마찰 0.5 + 마찰 1에 맞춘 잡음 : ⟨p²⟩ = 1.989, ⟨q²⟩ = 2.023, 잡음²/(2ζ) = 2.00
# ζ = 0.5: 시간 20 뒤 ⟨q²⟩/(2T) = 1.8120, kT/ζ = 2.0000
# ζ = 5.0: 시간 20 뒤 ⟨q²⟩/(2T) = 0.1963, kT/ζ = 0.2000
# ζ = 50.0: 시간 20 뒤 ⟨q²⟩/(2T) = 0.0201, kT/ζ = 0.0200
마찰만 있으면 식어서 멈추고, 잡음만 있으면 한없이 뜨거워지며, 잡음의 분산이 2ζkT일 때만 ⟨p²⟩ = ⟨q²⟩ = kT에 이른다. 짝이 어긋나면 잡음²/(2ζ)가 새 온도가 된다. 마찰이 크면 위치의 확산 계수가 아인슈타인 관계 kT/ζ로 간다.
마찰 계수의 양 끝
마찰과 잡음의 짝을 지키면서 마찰 계수를 0이나 아주 큰 값으로 보내면 어떻게 될까? 양 끝에서 익숙한 두 방정식이 나온다. ζ = 0이면 마찰도 잡음도 사라져 해밀턴 방정식만 남는다. 에너지를 지키며 등고선을 따라 도는 이 흐름에 HMC는 궤적 사이마다 운동량을 새로 뽑아 무작위성을 넣는데, 운동량을 통째로 새로 뽑는 것은 아주 큰 마찰과 짝이 맞는 잡음이 한순간에 작용해 운동량을 열평형으로 되돌리는 것과 같다. 반대로 ζ가 크면 운동량은 m/ζ의 시간 안에 열평형에 이르고, 그보다 긴 시간 동안 위치만 보면 확산 계수가 kT/ζ인 오버댐프드 랑주뱅 방정식이 된다. 위치에너지 없이 돌려 보면 ζ = 5, 50에서 ⟨q²⟩/(2t)가 0.1963, 0.0201로 kT/ζ = 0.2, 0.02에 가깝다. ζ = 0.5에서는 1.812로 kT/ζ = 2보다 작은데, 운동량을 잊는 시간 1/ζ = 2가 재는 시간 20에 비해 짧지 않아서다. 그리고 잡음을 0으로 두고 마찰만 남기면 계는 에너지 바닥 한 점에 멈추는데, 이것이 모멘텀 SGD다. HMC, SGLD, 모멘텀 SGD는 한 방정식에서 마찰과 잡음을 어떻게 두느냐가 다를 뿐이다.

ML에서: SGHMC
모멘텀 SGD에 잡음을 더하면 언더댐프드 랑주뱅 방정식이 된다. 첸·폭스·게스트린(2014)은 HMC의 기울기를 미니배치로 어림하는 자연스러운 구현이 「제멋대로 나빠질 수 있다」고 보였다. 미니배치 기울기의 오차가 운동량에 잡음으로 들어가는데 그 잡음과 짝을 이루는 마찰이 없으니, 에너지가 들어오기만 해서 계가 뜨거워지는 것이다. 그들의 처방이 논문 요약의 「잡음 섞인 기울기의 효과를 상쇄하는 마찰 항을 넣은 2차 랑주뱅 동역학」이고, 이 방법을 SGHMC(stochastic gradient Hamiltonian Monte Carlo)라 부른다. 잡음이 있는 곳에는 짝이 되는 마찰이 있어야 한다는 요동-소산 정리를 알고리즘 설계에 그대로 쓴 것이다.
문제 16. 헬스장 회원은 몇 명에서 멈추나
헬스장 회원을 30명 안팎으로 두고 싶다. 이 헬스장은 매달 회원의 10%가 그만둔다. 한 달권만 파는 옆 헬스장(매달 모두 그만둠)은 매달 30명씩 새로 받아 30명을 유지한다. (가) 옆 헬스장 규칙대로 매달 30명씩 받으면 회원 수는 어디서 멈추는가? (나) 30명을 유지하려면 매달 몇 명을 받아야 하는가?

옆 헬스장이 30명씩 받아서 30명이니까 우리도 30명씩 받으면 30명이죠.

옆은 매달 전부 나가니까 들어온 30명이 곧 회원 수지. 여긴 10%만 나가. 나가는 수 0.1M이 들어오는 30명과 같아야 멈추니까 M = 300이야.

돌려 보니 1년 뒤 215명, 2년 뒤 276명… 300명으로 가네요. 10배예요.

멈추는 곳은 들어오는 수와 나가는 비율로 정해지네요. 그럼 30명을 지키려면 매달 몇 명을 받아야 할까요?

나가는 수 0.1 × 30 = 3명이 들어오는 수와 같아야 하니까 매달 3명이에요. 멈추는 곳은 들어오는 수 ÷ 나가는 비율이고, 나가는 비율이 10분의 1이 되면 들어오는 수도 10분의 1이어야 해요.

선배 과제 코드를 조건이 다른 줄도 모르고 그대로 돌린 셈이네요.
문제 17. 마찰과 잡음의 짝
손실 U(θ) = θ²/2에 모멘텀 SGD p ← μp − η∇U + (잡음), θ ← θ + p를 쓴다. μ = 0.9, η = 0.01이다. (가) 표준정규분포에서 샘플을 얻으려고 SGLD처럼 운동량에 √(2η)z를 더하면 θ의 분산은? (나) 맞는 잡음의 크기는? (다) 미니배치로 어림한 기울기에 표준편차 3인 오차가 걸음마다 독립으로 섞여 있다면, 운동량에 더할 잡음은 얼마여야 하는가? (라) 마찰이 0인 HMC는 어떻게 온도를 맞추는가? (마) 연속 시간의 언더댐프드 랑주뱅 방정식에서 마찰 계수를 ζ = 20(m = kT = 1)으로 키우면, 위치만 보았을 때 확산 계수는 얼마이고 무엇이 되는가?

SGLD에서 √(2η)였으니까 모멘텀 버퍼에 √(2η)z를 더했어요. 목표 분산이 1인데… 10.0이 나왔어요. 온도가 10배예요!

모멘텀이 있으면 마찰이 달라지잖아. μ = 0.9면 한 걸음마다 운동량의 10%만 깎이니까 마찰이 0.1이야. SGLD는 한 걸음마다 운동량이 통째로 사라지는, 마찰이 1인 경우고.

헬스장이랑 같네. 한 걸음에 10%만 빠지는데 전부 빠지는 SGLD 규칙대로 넣었으니 10배가 된 거야.

운동에너지가 들고 나는 셈으로 따져 보세요.

마찰이 빼내는 양은 마찰에 비례하고 잡음이 넣는 양은 잡음의 분산에 비례하니까, 온도는 잡음 분산 ÷ (2 × 마찰 × η)예요. 2η ÷ (2 × 0.1 × η) = 10, 딱 맞아요. 마찰에 맞추려면 잡음의 분산이 2 × 0.1 × η, 곧 표준편차가 √(2(1 − μ)η) = 0.0447이어야 해요.

0.0447로 바꾸면… 1.008이에요! 모멘텀을 쓰면서도 샘플러가 되네요. 모멘텀 SGD에서 한 걸음마다 넓이가 0.9배로 줄던 게 수렴하는 이유였는데, 이번엔 그만큼을 잡음으로 채워 줘야 하는 거네요.

(다)로 가 볼까요? 미니배치 기울기의 오차도 η배 되어 운동량에 들어가요.

오차 표준편차 3에 η를 곱하면 0.03, 분산 9 × 10⁻⁴가 걸음마다 운동량에 이미 들어가요. 짝이 맞는 잡음의 분산은 2 × 0.1 × 0.01 = 0.002니까, 더 넣을 것은 0.002 − 0.0009 = 0.0011, 표준편차 0.0332예요.

미니배치 잡음을 빼지 않고 0.0447을 그대로 넣었더니 분산이 1.45예요. 0.0332로 바꾸니 1.002고요. 들어오는 잡음은 어디서 오든 다 세어야 하네요. 첸·폭스·게스트린이 SGHMC에서 맞춘 게 바로 이거였구나.

물탱크 같네요. 수도꼭지로 물이 일정하게 들어오고, 바닥 구멍으로는 물 높이에 비례해서 빠지는 거요. 구멍을 키우면 수도꼭지도 같은 비율로 더 열어야 물 높이가 그대로고요.

그래요. 물 높이가 온도, 구멍이 마찰, 수도꼭지가 잡음이에요. 저항기의 열잡음도 같아요. 저항값이 크면 전하의 흐름을 더 많이 막고, 그만큼 잡음 전압의 분산도 커요. (라)로 가 볼까요? HMC는 궤적을 따라가는 동안 마찰이 0이에요.

운동량을 새로 뽑잖아요. 아, 볼츠만 분포 배울 때 운동량을 온도 4짜리 정규분포에서 뽑았더니 위치 분산이 3.95로 운동량 쪽 온도를 따라갔던 거!

운동량을 새로 뽑는 건 마찰이 무한대인 한순간이야. 옛 운동량은 통째로 사라지고 짝이 맞는 잡음으로 새 운동량이 채워지는 거지. 그러니까 새로 뽑는 분포의 온도가 곧 잡음의 온도고, 위치는 그 온도를 따라가.

HMC는 궤적 사이에서만 마찰과 잡음이 한꺼번에 작용하는 언더댐프드 랑주뱅인 셈이에요. 궤적 동안에는 마찰이 없으니 에너지를 지키며 멀리 가고요. (마)는요?

마찰이 크면 운동량은 m/ζ = 0.05 만에 열평형이 되고, 그보다 긴 시간 동안 위치는 확산 계수 kT/ζ = 0.05로 퍼져요. 돌려 보니 0.0495예요. 오버댐프드 랑주뱅, 곧 SGLD가 이 극한이네요. 문제 7의 알갱이도 m/ζ가 58나노초라 이쪽 끝에 있었고요.

그럼 마찰 하나로 전부 줄 세울 수 있겠네요. 마찰 0에 가끔 운동량을 새로 뽑으면 HMC, 적당하면 SGHMC, 크면 SGLD, 잡음을 0으로 두면 모멘텀 SGD랑 경사하강이요.

모두 한 방정식이에요. 그리고 어느 자리에 있든, 잡음을 넣으면 그에 맞는 마찰이, 마찰이 있으면 그에 맞는 잡음이 있어야 원하는 온도가 나와요.