6장 — 해밀토니안과 위상공간
이 장의 물음
베이즈 신경망의 사후분포(데이터를 본 뒤 가중치가 어떤 값일지를 확률로 적은 분포)처럼 수백 차원에 걸친 분포에서 표본을 뽑아야 한다고 하자. 가장 단순한 방법은 지금 위치 근처의 한 점을 무작위로 제안하고, 그곳의 확률이 더 높으면 받아들이고 낮으면 그 비율만큼의 확률로 받아들이는 무작위 걸음 메트로폴리스(random-walk Metropolis)다. 그런데 차원이 높으면 조금만 멀리 제안해도 거의 모든 제안이 거절되므로 걸음을 아주 작게 줄일 수밖에 없고, 표본은 오랫동안 제자리 근처를 맴돈다. Stan이나 PyMC 같은 확률 프로그래밍 도구가 기본으로 쓰는 표본 추출기의 뼈대인 해밀토니안 몬테카를로 (Hamiltonian Monte Carlo, HMC)는 이 문제를 뜻밖의 방법으로 푼다. 현재 위치에 무작위 「운동량」을 하나 붙여 주고, 음의 로그 확률을 땅의 높이로 삼아 그 위에서 공을 한참 굴린 뒤, 공이 멈춘 곳이 아니라 정해진 시간 뒤에 공이 있는 곳을 제안한다. 100차원 표준정규분포에서 이 장 뒤쪽에서 짜 볼 몇 줄짜리 코드로 실제로 돌려 보면, 무작위 걸음은 제안의 24%만 받아들여지는데 한참을 굴러간 HMC의 제안은 98%가 받아들여진다. 멀리 보냈는데 왜 거절되지 않을까? 그리고 공을 굴리는 계산은 왜 아무 적분법으로나 하면 안 되고 leapfrog라는 특별한 방법을 써야 할까?

멀리 굴린 공이 왜 거절되지 않는지 알려면, 굴러가는 공의 운동에 어떤 성질이 숨어 있는지부터 알아야 한다. 이 장은 그네 하나에서 출발해 다음 물음에 차례로 답한다.
- 그네의 상태를 위치 하나가 아니라 위치와 운동량의 짝으로 보면 무엇이 새로 보일까?
- 운동을 풀지 않고 에너지의 식만 보고도 상태가 어디로 움직일지 알 수 있을까?
- 조금씩 다른 상태 여럿을 함께 흘려보내면, 그 무리가 차지하는 넓이는 어떻게 변할까?
- 원자의 위치와 속도처럼 연속으로 변하는 상태는 경우의 수를 어떻게 셀까?
- 멀리 굴린 공의 제안은 왜 거의 거절되지 않을까? 같은 공을 마찰 속에서 굴리면 왜 골짜기 바닥에 멈출까?
위상공간: 그네의 상태를 점 하나로
그네를 탄 아이를 떠올려 보자. 그네는 가장 높이 올라간 순간에 잠깐 멈추고 가장 낮은 곳을 지날 때 가장 빠르다. 높이에 담긴 위치에너지와 빠르기에 담긴 운동에너지가 서로 주고받는 동안 둘의 합은 변하지 않는다. 그렇다면 어느 한 순간 그네의 상태를 빠짐없이 말하려면 무엇을 알아야 할까? 그네가 어디에 있는지만 알면 충분할까?
역사: 「위상공간」이라는 이름
운동 상태를 한 점으로 보는 생각은 기체 분자를 다루던 사람들에게서 자랐다. 기체 속 분자들의 에너지가 어떻게 나뉘는지 확률로 따지려던 볼츠만은 먼저 「분자가 어떤 상태에 있다」는 말부터 가려야 했다. 1872년 논문에서 그는 운동의 종류(앞으로 나아가는지, 도는지)와, 시시각각 바뀌는 좌표와 운동량의 값을 나눠, 뒤의 것을 운동의 「위상」(Bewegungsphase)이라 불렀다. 1879년 볼츠만의 글을 검토하던 맥스웰은 이 말을 분자 하나가 아니라 계(따로 떼어 놓고 살피는 대상, 여기서는 기체 한 상자) 전체의 좌표와 운동량을 한데 묶은 상태를 부르는 데 썼다. 깁스는 1902년의 『통계역학의 기본 원리』에서 한 걸음 더 나아가, 위상 하나를 좌표 n개와 운동량 n개로 된 2n차원 공간의 점 하나로 보면 수많은 계의 모임이 시간에 따라 바뀌는 모습은 그 공간 속의 흐름으로 나타난다고 적었다. 상태 하나를 점 하나로 만들자 기체 분자 수만큼의 궤적을 따로 좇는 대신 점들의 흐름 하나를 보면 되었다. 이 공간의 이름은 뜻밖의 우연으로 굳었다. 에렌페스트 부부는 1911년의 백과사전 항목에서 이 공간을 「Γ-공간」(Γ는 그리스 문자 감마의 대문자)이라고 새로 이름 붙이려 했지만, 독자들의 기억에 남은 것은 그 글에서 지나가듯 쓴 「위상공간」(Phasenraum)이라는 말이었다고 전해진다.
그네의 여덟 상태
그네가 크게 흔들리지 않는 동안에는 가장 낮은 점에서 옆으로 벗어난 거리를 q라 할 때 위치에너지가 q²에 비례하므로, 이 운동은 용수철에 매단 추와 같은 계산이 된다. 운동량을 p = mq̇으로 두고 에너지를 위치와 운동량의 함수로 적으면 다음과 같다.
계산을 간단히 하려고 질량과 각진동수가 모두 1이 되도록 단위를 고르면 에너지는 E = p²/2 + q²/2가 된다. 그네를 q = 1까지 끌어당겼다가 가만히 놓으면 위치는 q = cos t, 운동량은 p = −sin t로 변한다. 한 번 왕복하는 데 걸리는 시간은 2π이고, 그 8분의 1마다 상태를 기록하면 다음 표를 얻는다.
| 시각 t | 위치 q | 운동량 p | 에너지 E |
|---|---|---|---|
| 0 | 1 | 0 | 0.5 |
| π/4 | 0.707 | −0.707 | 0.5 |
| π/2 | 0 | −1 | 0.5 |
| 3π/4 | −0.707 | −0.707 | 0.5 |
| π | −1 | 0 | 0.5 |
| 5π/4 | −0.707 | 0.707 | 0.5 |
| 3π/2 | 0 | 1 | 0.5 |
| 7π/4 | 0.707 | 0.707 | 0.5 |
이제 가로축을 위치 q, 세로축을 운동량 p로 하는 평면을 그리고 표의 여덟 상태를 점으로 찍어 보자. 여덟 점은 모두 반지름 1인 원 위에 있고, 시간이 흐르면 원을 시계 방향으로 한 바퀴 돈다. 그네의 한 번 왕복이 이 평면에서는 원 한 바퀴가 되는 것이다. 위치만 보면 그네가 q = 0.707을 지나는 순간은 한 번 왕복에 두 번 있지만, 운동량까지 함께 보면 둘은 (0.707, −0.707)과 (0.707, 0.707)이라는 다른 점이다. 위치와 운동량을 함께 알면 그네의 상태가 빠짐없이 정해지고, 그다음 움직임도 하나로 정해진다.

그네는 위치 하나와 운동량 하나로 상태가 정해졌으므로 평면 한 장이면 충분했다. 그렇다면 공중을 나는 공이나 원자 여러 개처럼 위치 좌표가 여럿인 계의 상태는 어디에 찍어야 할까? 그네에서 한 일을 그대로 늘리면 된다. 계의 위치와 운동량을 모두 좌표로 갖는 공간을 위상공간 (상태 전체를 좌표로 갖는 공간, phase space)이라 한다. 여기서 위상(phase)은 「운동의 국면」이라는 뜻이고, 수학의 위상공간(topological space)과는 이름만 같다. 그네의 평면은 가장 작은 위상공간이었던 셈이다.
위치 좌표가 몇 개 필요한지는 계마다 다르다. 계를 이루는 것 하나하나가 어디에 어떻게 놓였는지를 빠짐없이 적은 목록을 배치(configuration)라 하고, 배치를 정하는 데 필요한 숫자의 개수를 자유도(degrees of freedom)라 한다. 배치만 모은 공간(배치 공간, configuration space)에 좌표마다 운동량 축을 하나씩 붙인 것이 위상공간이므로, 위상공간의 차원은 늘 자유도의 두 배다.
| 계 | 배치를 정하는 숫자 | 자유도 | 위상공간의 차원 |
|---|---|---|---|
| 진자, 작게 흔드는 그네 | 각도(또는 옆으로 벗어난 거리) 1 | 1 | 2 |
| 공중을 나는 공 | 위치 3 | 3 | 6 |
| 책상 위에서 움직이는 컵 | 위치 3 + 기울기 각도 3 | 6 | 12 |
| 자유도가 n인 계 | 좌표 n개 | n | 2n |
어느 계든 위상공간의 점 하나가 한 순간의 상태 전부를 나타낸다.
ML에서: 모멘텀 버퍼도 상태의 일부
모멘텀 SGD(모멘텀은 영어로 운동량 momentum과 같은 낱말이다)로 학습하는 모델은 갱신할 때마다 매개변수와 함께, 지난 기울기를 쌓아 둔 모멘텀 버퍼도 바꾼다. 다음 걸음은 둘을 함께 알아야 정해지므로, 이 학습의 「상태」는 매개변수 하나가 아니라 매개변수와 버퍼의 짝이다. 이 짝을 반쪽만 들고 있으면 무슨 일이 생기는지는 아래 문제 3에서 직접 셈해 본다.
문제 1. 사진 한 장으로 보는 공
공중에 던진 공을 찍은 사진 한 장이 있다. 사진 속 공은 땅에서 5m 높이에 있다. 이 사진만 보고 0.5초 뒤 공의 높이를 맞힐 수 있는가? 공이 그 순간 초속 5m로 올라가고 있었을 때와 초속 5m로 내려오고 있었을 때를 각각 셈해 보라(중력가속도 9.8m/s², 공기 저항 무시).

사진에 5m라고 나와 있으니까 0.5초 동안 떨어지는 거리만 빼면 돼요. ½ × 9.8 × 0.25 = 1.225m, 그러니까 3.775m요.

민준 학생 셈에서 공은 그 순간 얼마나 빨리 움직이고 있었죠?

아… 속도를 0으로 놓고 셈했네요. 사진에는 속도가 안 찍혀 있는데.

올라가는 중이었다면 5 + 5 × 0.5 − 1.225 = 6.275m, 내려오는 중이었다면 5 − 2.5 − 1.225 = 1.275m야. 같은 사진인데 5m나 차이가 나.

그럼 무엇이 더 있어야 다음 위치가 하나로 정해질까요?

속도요. 사진을 한 장 더 찍어서 두 장의 차이를 보면 되겠네요. 그네 표에서 위치만으로는 두 점을 못 가르던 거랑 같아요.

위치와 속도, 그러니까 위치와 운동량이 한 쌍이어야 한 순간의 상태가 되는 거네.
문제 2. 위치 그래프에서는 만나는 두 그네
똑같은 그네 두 개(E = p²/2 + q²/2)가 있다. 그네 A는 q = 1에서, 그네 B는 q = 0.5에서 가만히 놓았다. 시간에 따른 위치 그래프를 그리면 두 곡선은 반 번 왕복할 때마다 한 번씩 만난다. (가) 두 곡선이 만나는 순간, 두 그네는 위상공간의 어느 점에 있는가? (나) 위상공간에서 두 그네의 궤적은 만날 수 있는가?

위치 그래프에서 만나면 같은 자리에 있는 거니까, 위상공간에서도 같은 점이겠죠. 만나는 순간은 둘 다 가장 낮은 곳 q = 0이니까요.

운동량도 봐야지. 그네 A는 에너지가 0.5니까 q = 0에서 p²/2 = 0.5, p = ±1이야. 그네 B는 에너지가 0.125라서 p = ±0.5고. 같은 자리를 지나가도 빠르기가 두 배 차이 나.

그럼 두 궤적을 위상공간에 그리면 어떤 모양이죠?

A는 반지름 1인 원, B는 반지름 0.5인 원이요. 가운데가 같은 원 두 개라 절대 안 만나네요. 위치 그래프에서 만난 건 위치만 같고 운동량이 달랐던 거고요.

만약 두 궤적이 위상공간의 한 점에서 만난다면 어떻게 될까요?

그 점에서 출발한 다음 움직임이 두 가지가 되는데, 위치와 운동량을 알면 다음 움직임은 하나로 정해진다고 했으니까 그럴 수 없어요. 만난다면 처음부터 같은 궤적인 거예요.
문제 3. 체크포인트에서 버퍼를 빼면
손실 U(θ) = θ²/2를 모멘텀 SGD(p ← 0.9p − 0.1∇U(θ), θ ← θ + p)로 줄이고 있다. θ = 1, 버퍼 p = 0에서 출발해 다섯 번 갱신한 뒤 체크포인트를 저장했더니 θ = −0.0292, p = −0.2560이었다. 학습을 이어 갈 때 (가) 매개변수와 버퍼를 모두 불러온 경우와 (나) 매개변수만 불러오고 버퍼를 0으로 둔 경우, 네 번 더 갱신한 뒤의 θ를 각각 구하라.

θ가 −0.03이면 이미 바닥이잖아요. 버퍼가 있든 없든 바닥 근처에 있을 테니 버퍼는 안 불러와도 될 것 같은데요.

한번 돌려 볼까요? 두 경우를 나란히요.

(나)는 −0.0263, −0.0210, −0.0142, −0.0066이에요. 바닥 근처 그대로네요. 그런데 (가)는 −0.2567, −0.4357, −0.5533, −0.6038… 바닥을 한참 지나쳐 가요. 같은 θ에서 출발했는데요?

저장한 순간 버퍼가 −0.256이었잖아. 공이 바닥을 빠르게 지나가던 순간을 찍은 거야. 버퍼를 0으로 두면 그 공을 바닥에 세워 놓고 다시 시작하는 셈이고.

그래요. 이 손실에서는 (나)가 오히려 빨리 멈춘 것처럼 보이지만, 원래 학습과는 다른 궤적이에요. 학습을 멈췄다 이어 갈 때 무엇을 함께 저장해야 할까요?

옵티마이저 상태까지요. 그래서 PyTorch 체크포인트에 optimizer의 state_dict를 따로 넣는 거였네요. 과제 때는 모델만 저장해도 이어서 돌아가길래 괜찮은 줄 알았어요.

아까 사진 한 장 문제랑 같네. 매개변수가 사진 속 위치고, 버퍼가 빠진 속도야.