시즌 2 · 알파폴드편 / PART 8 · PART 8 · MuZero (2019) / Ch 4 · 잠재 공간에서의 MCTS

한 시뮬레이션 통째 추적 (6 단계)

이제 네 단계가 어떻게 한 묶음으로 도는지 한 번에 보자. 한 번의 MCTS 시뮬레이션이 정확히 어떤 모습인지 단계별로 추적한다.

🎬 출발 상황

관측 o가 주어졌다 (예: 아타리 화면). 우리는 이 상황에서 어떤 행동을 할지 결정해야 한다.

가능한 행동: 4가지 (a=0, 1, 2, 3).

MCTS 시뮬레이션을 N=50번 돌릴 거다. 그 중 첫 시뮬레이션 한 번을 자세히 본다.

📍 시뮬레이션 시작 전 — 루트 준비

먼저 h(o) → s_0 호출 (이건 시뮬레이션 전 단 한 번만).

루트 노드의 잠재 상태를 s_0로 둔다.

다음 f(s_0) → (p_0, v_0) 호출. 루트 노드의 자식 4개를 만들고 각 prior에 p_0[a] 부여.

이제 트리는 "루트 + 자식 4개" 모습 — 자식들은 아직 방문되지 않은 빈 노드.

📍 1단계 — Select

루트의 자식 4개를 PUCT로 비교. 모든 자식이 N=0이라 Q값은 동일하게 0, 차이는 prior p_0에서 옴.

제일 prior가 큰 a=2가 가장 높은 PUCT 점수를 받는다 → a=2 선택.

a=2의 자식 노드를 L이라 부르자. L은 아직 expand 안 됨 → Select 종료.

경로: path = [root, L]

📍 2단계 — Expand (g 호출)

g(s_0, a=2) → (s_L, r_L) 계산.

예를 들면 s_L = [0.06, 0.01, ..., 0.00] (8차원 잠재 벡터), r_L = -0.05.

L의 state에 s_L, reward에 r_L 저장.

📍 3단계 — Evaluate (f 호출)

f(s_L) → (p_L, v_L) 계산.

예: p_L = [0.24, 0.25, 0.25, 0.26], v_L = -0.06.

L 아래에 자식 4개 만들고 각각의 prior에 p_L[a] 부여.

📍 4단계 — Backup

L에서 시작해서 루트까지 거꾸로 올라가며 갱신:

  • L에서: N=1, W += v_L = -0.06, value = r_L + γ·v_L ≈ -0.05 + 0.997·(-0.06) ≈ -0.11
  • root에서: N=2 (이미 1이었음), W += -0.11

시뮬레이션 1번 완료.

📍 49번 더 반복

위 4단계를 49번 더 반복. 두 번째 시뮬레이션에서는 a=2가 이미 방문 1회라 Select가 다른 자식(a=1 또는 a=0)을 시도할 수 있다 — PUCT의 탐험 항이 다른 자식의 점수를 더 올려주기 때문.

시뮬레이션 50번이 끝나면 루트의 자식들 방문 횟수가 어떤 분포를 이룬다. 예:

  • a=0: 5번
  • a=1: 7번
  • a=2: 33번 ← 제일 많이 방문 (사전 확률 + 결과적으로 좋은 가치)
  • a=3: 5번

실제로 둘 행동 = a=2. 그리고 이 방문 횟수 분포 [5, 7, 33, 5]가 학습 타겟이 된다 (정규화해서 정책 손실에 사용).

💡 한 줄 정리

"MCTS 한 번의 결정 = 시뮬레이션 N번 × (Select → Expand → Evaluate → Backup) = 신경망 (g, f) 호출 N번 ≈ 2N번의 가벼운 행렬 곱셈."

이게 한 수를 둘 때마다 일어나는 일이다. 시뮬레이션 횟수가 많을수록 결정이 더 정교하다.