야르진스키 등식: 어떤 빠르기로 바꾸든
덫을 조이는 시간을 0(한순간), 0.1, 1, 10으로 바꾸자 일의 평균은 1.500에서 0.726까지 달라졌지만, e^(−𝒲)의 평균에 −ln을 씌운 값은 네 경우 모두 0.693 근처였다. 다 조인 순간의 알갱이가 새 덫의 평형에서 뒤처진 정도는 빠르기마다 크게 달랐는데도 그렇다. 왜 이 값만 그대로이고, 0.693은 무엇일까?
역사: 부등식이 등식이 되기까지
온도가 일정한 계를 한 상태에서 다른 상태로 바꾸려면 일을 해 주어야 하고, 그 일은 자유에너지의 증가보다 작을 수 없다. 둘이 같아지는 것은 한없이 천천히 바꾸는 가역 과정뿐이고, 조금이라도 서두르면 남는 일이 열로 흩어진다. 자유에너지 차이를 알려면 한없이 천천히 바꾸거나, 아니면 평형 분포에서 뽑은 샘플로 따로 계산해야 했다. 20세기의 계산 방법들은 이 두 극단에서 나왔다. 1935년 커크우드는 매개변수를 한없이 천천히 바꾸며 평균 힘을 적분하는 방법(열역학적 적분)을, 1954년 츠반치히는 에너지를 한 번에 바꾼 차이의 지수 평균을 내는 방법을 적었다.
1996년 6월 워싱턴 대학교 핵이론연구소에 있던 크리스토퍼 야르진스키는 『피지컬 리뷰 레터스』에 짧은 논문을 보냈고, 논문은 이듬해 「자유에너지 차이에 대한 비평형 등식」이라는 제목으로 실렸다. 논문 요약의 첫 문장은 이렇다. 「계의 두 설정 사이의 평형 자유에너지 차이를, 한 설정에서 다른 설정으로 매개변수를 바꾸는 동안 해 준 일을 유한한 시간에 잰 값들을 여러 번 모은 것(앙상블)으로 나타내는 식을 유도한다.」 여기서 설정은 κ = 1인 덫과 κ = 4인 덫처럼 매개변수 값으로 정한 조건이다. 한없이 천천히 바꾸는 커크우드의 방법과 한 번에 바꾸는 츠반치히의 방법이 이 식의 두 끝이고, 그 사이의 어떤 빠르기로 바꾸어도 된다는 것이 새로운 점이었다. 평균을 내는 방법만 바꾸면 부등식이 등식이 된다.
2002년 리파르트와 부스타만테의 연구진은 RNA 분자 하나의 양 끝을 구슬 두 개에 이어 한 구슬은 광학 집게로, 다른 구슬은 가는 유리관(마이크로피펫) 끝에 붙잡고, 접힌 상태에서 펴진 상태로 잡아당기며 한 일을 쟀다. 빨리 당길수록 잰 일은 더 크게 퍼졌고 그 평균은 자유에너지 차이보다 컸다. 그러나 비가역적으로 당겨 잰 일들로 계산한 지수 평균은 가역적으로 천천히 당길 때 든 일의 평균(자유에너지 차이를 따로 어림한 가장 믿을 만한 값)과 kT의 절반 안에서 맞았다. 평형을 기다리지 않은 측정에서 평형의 양을 얻는다는 등식의 약속이 분자 하나에서 확인된 것이다.
한순간에 조이기
0.693부터 풀어 보자. 분배함수 Z에 대해 자유에너지는 F = −kT ln Z이고, 용수철 상수가 κ인 덫의 분배함수는 가우스 적분 Z(κ) = ∫e^(−κx²/2kT)dx = √(2πkT/κ)이므로, κ = 1인 덫과 κ = 4인 덫의 자유에너지 차이는 ΔF = −kT ln(Z(4)/Z(1)) = (kT/2) ln 4 = kT ln 2다. kT = 1이면 0.693이다. 조이는 빠르기와 상관없이 0.693 근처로 나온 −ln⟨e^(−𝒲)⟩는 두 덫의 자유에너지 차이였던 것이다.
한순간에 조이는 경우는 손으로 확인할 수 있다. 알갱이가 움직일 겨를이 없으므로 일은 처음 위치 하나로 정해져 𝒲 = (4 − 1)x²/2 = 1.5x²이고, x²의 평균이 1이니 일의 평균은 1.5kT다. 한편 e^(−β𝒲)의 평균은 처음 분포 위에서 에너지 차이의 지수를 평균한 것이어서, 적분 안에서 옛 에너지가 지워지고 새 에너지만 남는다.
덫에서는 Z(4)/Z(1) = 1/2이고, 한순간에 조인 실험 10만 번에서 −ln⟨e^(−𝒲)⟩가 0.6932 = −ln 0.5000으로 나온 까닭이 이것이다. 이 계산은 한 가지를 더 알려 준다. 옛 분포에서 뽑은 샘플에 e^(−β𝒲)를 곱하면 적분 안에서 옛 분포가 새 분포로 바뀌므로, 옛 덫에 머물러 있는 알갱이들도 이 가중치를 달면 새 덫의 평형 분포를 나타낸다. 실제로 한순간에 조인 알갱이들의 ⟨x²⟩는 1.000이지만 e^(−𝒲)로 가중해 평균하면 0.251로 새 평형의 0.25가 된다. 이처럼 옛 분포에서 뽑은 샘플로 에너지 차이의 지수 평균을 내어 두 상태의 자유에너지 차이를 구하는 방법을 자유에너지 섭동(섭동은 작게 건드려 본다는 뜻. 한순간에 바꾼 에너지 차이의 지수 평균으로 자유에너지 차이를 얻는 방법, free energy perturbation)이라 하고, 1954년 츠반치히가 이 식을 적었다.
한없이 천천히 조이기
한순간에 조이는 것의 반대쪽 끝은 한없이 천천히 조이는 경우다. 이때 알갱이는 매 순간 그때의 덫에서 평형을 이루므로 κ를 dκ만큼 올리는 데 드는 일은 평형 평균 ⟨x²⟩dκ/2 = (kT/κ)dκ/2이고, 1에서 4까지 더하면 (kT/2) ln 4 = kT ln 2, 곧 ΔF 자체다. 매 순간 드는 일이 평형 평균으로 정해지므로 실험마다 일이 달라지지도 않는다. 조이는 시간 10에서 일의 평균이 0.726으로 0.693에 가까웠던 것은 이 끝에 다가가고 있었기 때문이다.
그 사이의 어떤 빠르기에서도
필요한 조건은 두 가지다. 처음 위치는 λ₀의 평형 분포 p_λ₀ ∝ e^(−βU_λ₀)에서 뽑는다. 그리고 매개변수가 λ_k일 때 알갱이를 움직이는 규칙은 그때의 평형 분포 p_λk를 바꾸지 않는다. 요동과 마찰이 짝을 이룬 연속 시간의 랑주뱅 방정식이나 메트로폴리스 수락 단계(제안한 걸음을 두 위치의 확률 비에 따라 받아들이거나 물리는 단계)가 붙은 샘플러가 그런 규칙이다. 움직이는 동안 평형에 이를 필요는 없고, 이미 평형에 있는 분포를 망가뜨리지만 않으면 된다. 이 두 조건만으로 다음 등식이 성립한다.
까닭은 앞의 한순간 계산을 칸마다 되풀이해 보면 드러난다. 첫 칸에서 매개변수를 바꾸며 샘플에 가중치 e^(−β(U_λ₁ − U_λ₀))를 곱하면, 가중치를 단 샘플들은 Z_λ₁/Z_λ₀배 된 p_λ₁을 나타낸다. 그다음 움직임은 p_λ₁을 바꾸지 않으므로 가중치를 단 분포도 바꾸지 않는다. 칸마다 이것을 되풀이하면 분배함수의 비가 차례로 곱해지며 가운데 것이 모두 지워져 Z_λK/Z_λ₀만 남고, 끝에서 가중치를 단 샘플들은 끝 매개변수의 평형 분포 p_λK를 정확히 나타낸다. 오른쪽 식이 이것이고, f = 1로 두면 왼쪽 식이 된다. 샘플 자체는 평형에서 얼마든지 뒤처져 있어도 되고, 뒤처진 만큼은 가중치가 갚는다. 이 왼쪽 식을 야르진스키 등식 (평형에서 출발해 매개변수를 어떤 빠르기로 바꾸든, 일의 지수 평균이 처음과 끝 평형 상태의 자유에너지 차이를 준다는 등식, Jarzynski equality)이라 한다.
코드로 확인하기
용수철 덫 실험을 그대로 돌린다. 덫의 용수철 상수를 1에서 4로 올리는 동안 일을 재고, 일의 평균과 지수 평균, 다 조인 순간의 위치 분산을 조이는 시간별로 비교한다. 이 덫에서는 랑주뱅 방정식의 한 걸음을 정확히 풀 수 있어서 그 식을 그대로 썼다.
import numpy as np
rng = np.random.default_rng(0)
# 용수철 덫 U(x) = κx²/2에 묶인 알갱이 (kT = 1, 마찰 계수 1). 덫의 단단함 κ를 1에서 4로 조인다
kap0, kap1, n = 1.0, 4.0, 100_000
dF = 0.5 * np.log(kap1 / kap0) # ΔF = −ln(Z₁/Z₀) = ½ ln(κ₁/κ₀) = ln 2
def squeeze(t_total, dt=0.001):
K = max(1, round(t_total / dt))
kaps = np.linspace(kap0, kap1, K + 1)
x = rng.standard_normal(n) / np.sqrt(kap0) # 처음에는 평형: 분산 kT/κ₀인 정규분포
W = np.zeros(n)
for i in range(1, K + 1):
W += (kaps[i] - kaps[i - 1]) * x**2 / 2 # 일: x는 그대로 두고 κ만 바꿀 때의 에너지 변화
if t_total > 0: # 열: κ는 그대로 두고 랑주뱅 방정식으로 dt만큼 움직임
a = np.exp(-kaps[i] * dt) # (이 덫에서는 한 걸음을 정확히 풀 수 있다)
x = a * x + np.sqrt((1 - a**2) / kaps[i]) * rng.standard_normal(n)
return x, W
print(f"ΔF = ln 2 = {dF:.4f}")
for t_total in (0.0, 0.1, 1.0, 10.0):
x, W = squeeze(t_total)
w = np.exp(-W) # 경로마다의 가중치 e^(−W/kT)
print(f"조이는 시간 {t_total:4}: ⟨W⟩ = {W.mean():.3f}, Var(W)/2 = {W.var() / 2:.3f}, "
f"W < ΔF인 비율 {np.mean(W < dF):.3f}, −ln⟨e^(−W)⟩ = {-np.log(w.mean()):.4f}")
print(f"{'':16}끝의 ⟨x²⟩ = {np.mean(x**2):.3f}, e^(−W)로 가중한 ⟨x²⟩ = {(w * x**2).sum() / w.sum():.3f} (평형은 0.25)")
# ΔF = ln 2 = 0.6931
# 조이는 시간 0.0: ⟨W⟩ = 1.500, Var(W)/2 = 2.278, W < ΔF인 비율 0.504, −ln⟨e^(−W)⟩ = 0.6932
# 끝의 ⟨x²⟩ = 1.000, e^(−W)로 가중한 ⟨x²⟩ = 0.251 (평형은 0.25)
# 조이는 시간 0.1: ⟨W⟩ = 1.374, Var(W)/2 = 1.759, W < ΔF인 비율 0.513, −ln⟨e^(−W)⟩ = 0.6957
# 끝의 ⟨x²⟩ = 0.758, e^(−W)로 가중한 ⟨x²⟩ = 0.251 (평형은 0.25)
# 조이는 시간 1.0: ⟨W⟩ = 0.937, Var(W)/2 = 0.427, W < ΔF인 비율 0.540, −ln⟨e^(−W)⟩ = 0.6933
# 끝의 ⟨x²⟩ = 0.289, e^(−W)로 가중한 ⟨x²⟩ = 0.250 (평형은 0.25)
# 조이는 시간 10.0: ⟨W⟩ = 0.726, Var(W)/2 = 0.037, W < ΔF인 비율 0.535, −ln⟨e^(−W)⟩ = 0.6938
# 끝의 ⟨x²⟩ = 0.252, e^(−W)로 가중한 ⟨x²⟩ = 0.250 (평형은 0.25)
일의 평균은 조이는 시간에 따라 1.500에서 0.726까지 달라지지만 −ln⟨e^(−𝒲)⟩는 모두 ln 2 = 0.693 근처다. 천천히 조일수록 일의 분산이 작아지고 ⟨𝒲⟩ − Var(𝒲)/2가 ΔF에 다가간다. 끝의 분포가 뒤처져 있어도 e^(−𝒲)로 가중한 ⟨x²⟩는 모두 평형값 0.25다.
ML에서: 중요도 가중치
가중치 e^(−β(U₁ − U₀))는 새 분포의 정규화 전 밀도(합이 1이 되게 나누기 전의 밀도)를 옛 분포의 정규화 전 밀도로 나눈 값이다. ML에서는 이런 밀도 비를 중요도 가중치라 부르고, 한 분포에서 뽑은 샘플에 이 비를 곱해 다른 분포의 평균을 내는 방법을 중요도 샘플링이라 한다. 오프폴리시 강화학습(지금 배우는 정책이 아니라 옛 정책이 모은 기록으로 배우는 강화학습)이 옛 정책으로 모은 데이터로 새 정책을 평가할 때 두 정책의 확률 비를 곱하는 것도 같은 계산이다.
문제 3. 평형에 이르기 전에 조이면
덫에 막 넣어 아직 평형에 이르지 못한 알갱이들이 있다. 위치의 분산이 평형값 1이 아니라 0.5다. 이 알갱이들로 덫을 κ = 1에서 4로 조이면, 조이는 시간이 0(한순간), 1, 10일 때 −ln⟨e^(−𝒲)⟩는 ΔF = ln 2 = 0.693을 줄까? (풀어 본 뒤 위젯 1의 「문제 3 불러오기」로 확인해 보자.)

움직이는 동안 평형에 이를 필요는 없다고 했으니까, 처음도 꼭 평형일 필요는 없겠죠. 0.693이 나올 거예요. 한순간이면 일이 1.5x²이고 분산이 0.5니까… ⟨e^(−1.5x²)⟩ = 1/√(1 + 3 × 0.5) = 0.632, −ln을 씌우면 0.458이에요. 어?

한순간 계산에서 옛 분포가 지워진 건 처음 분포가 e^(−βU₀)/Z₀였기 때문이잖아. 처음 분포가 그게 아니면 지워지지 않아.

천천히 조이면 어떨까요? 시간 1과 10도 돌려 보세요.

시간 1이면 0.579, 10이면 0.665예요. 천천히 조일수록 다가가긴 하는데 0.693에는 못 미쳐요. 가중치를 단 끝의 ⟨x²⟩도 한순간에는 0.200이라서 새 평형의 0.25가 아니에요.

천천히 조이면 알갱이가 조이는 도중에 평형에 가까워지니까 어긋남이 줄어드는구나. 그래도 처음 몇 순간에 쌓인 몫은 남고.

그래요. 움직임이 분포를 지키는 것과 처음 위치를 평형에서 뽑는 것, 등식은 두 조건 가운데 하나만 빠져도 성립하지 않아요.

저울 영점을 안 맞추고 잰 거네요. 아무리 정밀하게 재도 처음 어긋난 만큼은 그대로 남아요.
문제 4. 옛 버전의 기록으로 새 버전 평가하기
챗봇의 옛 버전이 어떤 질문에 답 A, B, C를 각각 0.5, 0.3, 0.2의 확률로 냈고, 그 기록 10개(A 5번, B 3번, C 2번)가 남아 있다. 아직 배포하지 않은 새 버전은 세 답에 정규화 전 점수 p̃ = 2, 1, 1을 준다. 사용자가 좋아하는 답은 A뿐이라 보상은 A가 1, B와 C는 0이다. 옛 기록만으로 새 버전의 평균 보상을 어림하라. (기록 속 비율이 옛 버전의 확률과 꼭 같게 나왔다고 하자.)

기록마다 새 점수를 옛 확률로 나눈 가중치를 보상에 곱해 평균 내면 되죠. A의 가중치는 2/0.5 = 4이고 B와 C는 보상이 0이니까, 평균 보상은 5 × 4/10 = 2.0이에요.

보상이 0 아니면 1인데 평균 보상이 2라고?

가중치만 따로 평균 내 보면 얼마죠?

A는 4, B는 1/0.3 = 3.33, C는 1/0.2 = 5니까 (5 × 4 + 3 × 3.33 + 2 × 5)/10 = 4.0이에요. 1이 아니네요.

4는 새 점수를 다 더한 2 + 1 + 1이야. 정규화하지 않은 점수를 썼으니 가중치가 통째로 그만큼 부풀었어. 가중치의 합으로 나누면 20/40 = 0.5고.

정규화 전 밀도로 만든 가중치의 평균이 두 분포의 정규화 상수의 비가 된 거예요. 덫에서는 그 비가 무엇이었죠?

Z₁/Z₀요. 한순간에 조일 때 ⟨e^(−β𝒲)⟩가 그거였어요. 새 버전의 점수 합 4가 분배함수 자리네요. 조교가 기준표 점수를 100점 만점으로 바꾸지 않고 그냥 평균 낸 것과 같아요.