한 시뮬레이션 통째 추적 (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개" 모습 — 자식들은 아직 방문되지 않은 빈 노드.
루트의 자식 4개를 PUCT로 비교. 모든 자식이 N=0이라 Q값은 동일하게 0, 차이는 prior p_0에서 옴.
제일 prior가 큰 a=2가 가장 높은 PUCT 점수를 받는다 → a=2 선택.
a=2의 자식 노드를 L이라 부르자. L은 아직 expand 안 됨 → Select 종료.
경로: path = [root, L]
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 저장.
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] 부여.
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번 완료.
위 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번의 가벼운 행렬 곱셈."
이게 한 수를 둘 때마다 일어나는 일이다. 시뮬레이션 횟수가 많을수록 결정이 더 정교하다.