Files
coorl-lost-cities/docs/archive/deep-cfr-opponent-policy-network-divergence-2026-05-07.md
T
2026-05-07 15:39:24 +09:00

12 KiB
Raw Blame History

Deep CFR opponent_policy: network 발산 (Policy Collapse) 분석

Date: 2026-05-07 Author: Claude Code 세션 기록 Status: Definitive — opponent_policy: network는 안정적인 학습을 보장하지 않음

TL;DR

traversal.opponent_policy: network 옵션은 자기 자신의 현재 네트워크를 opponent로 사용한다. 이 설정으로 1000-iteration 실험을 두 번 (512x3 / 1024x4) 돌린 결과, 두 실험 모두 학습 초기 (peak) 이후 명백한 policy collapse가 발생했다. 큰 네트워크는 발산을 늦추기는 하지만 막지는 못한다.

권고: 향후 학습은 opponent_policy: self_play_league를 기본값으로 유지할 것.

실험 설정

두 실험 모두 동일한 구조:

항목
traversal.opponent_policy network
traversal.traversals_per_iteration 2
traversal.traversals_per_player 70
optimization.advantage_updates_per_iteration 512
optimization.strategy_updates_per_iteration 512
optimization.learning_rate 3e-5
regret_matching.all_negative_fallback argmax_tiebreak
self_play.max_snapshots 0 (snapshot pool 비활성)
Eval 매 5 iter, 6 opponents × 100 games
Max iterations 1000

차이점:

  • 512x3: network.hidden_size=512, num_layers=3 config: configs/deep_cfr/deep_cfr_opponent_network_512x3_1000iter.yaml
  • 1024x4: network.hidden_size=1024, num_layers=4 config: configs/deep_cfr/deep_cfr_opponent_network_1024x4_1000iter.yaml

두 실험 모두 동일 머신 (AMD Ryzen 5 5600X, 12 threads, CUDA GPU)에서 약간의 시간차 (4분)를 두고 병렬 실행. 병렬 실행으로 iteration time이 평균 ~2배 느려졌으나 결과 패턴(발산)에는 영향 없음.

결과

512x3 (iteration 363까지 관찰 후 중단)

Phase Iter Random WR Random Δ Safe Heur WR Safe Heur Δ
초기 5 53.0% -0.7 4.0% -78.1
Peak 15 85.0% +32.2 5.0% -47.2
발산 시작 20 67.0% +14.4 2.0% -62.3
발산 진행 30 36.0% -14.3 3.0% -106.2
수렴 (망함) 100 41.0% -12.9 0.0% -111.6
수렴 (망함) 200 33.0% -17.1 1.0% -114.1
마지막 360 34.0% -12.7 2.0% -101.3
  • Peak는 iter 15 — Random 상대 85% win rate.
  • iter 20부터 급격히 무너짐.
  • iter 30 이후 Random WR이 Random 자신(50%)보다 낮음 → 모델이 random보다 못 한 상태로 수렴.
  • Safe Heuristic 상대로는 처음부터 끝까지 ~0–8% (전혀 학습 안 됨).

1024x4 (iteration 231까지 관찰 후 중단)

Phase Iter Random WR Random Δ Safe Heur WR Safe Heur Δ
초기 5 35.0% -14.9 1.0% -91.8
Plateau 30 62.0% +15.0 3.0% -82.2
Plateau 55 63.0% +16.0 5.0% -69.2
Best Random 70 70.0% +17.6 6.0% -74.1
Best Safe Heur 85 63.0% +11.4 13.0% -52.3
발산 시작 100 49.0% +3.8 3.0% -89.7
발산 진행 150 35.0% -17.4 5.0% -78.1
수렴 (망함) 200 24.0% -24.6 9.0% -71.3
마지막 230 36.0% -19.9 4.0% -95.6
  • Plateau가 iter 3095 (60+ iter)로 길게 유지됨.
  • Best Safe Heuristic WR = 13% (iter 85) — 512x3의 best (8%, iter 10) 보다 명확히 우수. 큰 capacity가 다양성 표현에 도움.
  • iter 100 이후부터 발산 시작, iter 150 이후 망가짐.

두 실험 비교

항목 512x3 1024x4
Best Random WR 85% (iter 15) 70% (iter 70)
Best Safe Heur WR 8% (iter 10) 13% (iter 85)
Plateau 길이 ~10 iter ~65 iter
발산 시작 시점 iter 20 iter 100
수렴 시 Random WR ~3040% ~3040%

관찰:

  • 큰 네트워크는 plateau를 5x 이상 길게 유지함.
  • 큰 네트워크는 Safe Heuristic 상대로도 plateau 구간에 학습 가능 (13%).
  • 그러나 두 실험 모두 결국 발산. capacity로 발산을 막지 못함.

원인 분석

1. Moving Target (가장 큰 원인)

정상적인 외부 샘플링 CFR은 traversal 동안 opponent가 고정된 policy를 사용한다고 가정한다. opponent_policy: network학습 중인 네트워크를 opponent로 사용하기 때문에:

  • 매 iteration마다 opponent의 policy가 바뀜.
  • 이전 iteration에서 추정한 advantage가 outdated 됨.
  • advantage memory의 (state, action, regret) 샘플들이 서로 다른 opponent policy 하에서 측정됨 → 일관성 없음.
  • 결과: 학습이 자기 자신을 쫓는 무한 루프.

2. Echo Chamber (다양성 부재)

traverser와 opponent가 같은 네트워크를 공유하므로:

  • 같은 약점 공유. 예를 들어 모델이 Safe Heuristic 스타일의 조심스러운 상대를 처리하지 못하면, 그 상대를 self-play에서 만날 일이 없음.
  • 약점이 advantage estimation에 표현되지 않음 → regret 신호로 학습되지 않음.
  • 결과: 모델이 "자기 자신을 이기는 데 특화된" 좁은 strategy로 수렴. Random 같은 다른 distribution을 만나면 처참히 패배.

3. CFR 수렴 보장 깨짐

Deep CFR의 이론적 수렴은 average strategy가 Nash에 가까워진다는 보장이며, opponent가 fixed 또는 average policy일 때 성립한다. network policy를 매번 바뀌는 traversal opponent로 사용하면:

  • external sampling의 unbiased estimate 가정 위반.
  • no-regret 보장 사라짐.
  • 수렴이 이론적으로 보장되지 않음 → 실제로 발산 관찰됨.

4. Non-stationary Regret 추정

같은 (state, action) 샘플에서 측정한 regret이 시간에 따라 다름 (opponent 가 변하니까). advantage 네트워크는:

  • 새 데이터와 옛 데이터가 다른 distribution.
  • 학습이 진동.
  • advantage_loss가 안정적으로 줄지 않고 plateau 또는 증가.

5. Strategy Mode Collapse

같은 네트워크끼리 self-play하면 mixed strategy가 deterministic-like한 하나의 mode로 수렴하기 쉽다 (game-theoretic 의미에서 Nash가 mixed인 경우 에도). 이는 imperfect information game (Lost Cities 포함) 에서 본질적으로 suboptimal — exploitable.

왜 self_play_league는 안정적인가

opponent_network self_play_league
Opponent policy moving (현재 네트워크) fixed (snapshot pool)
Diversity 없음 (echo) 다수 snapshot에서 sampling
Regret estimation non-stationary quasi-stationary
이론적 수렴 보장 없음 average strategy → Nash

self_play.max_snapshots > 0 으로 과거 정책의 스냅샷을 pool에 저장하고 weighted sampling으로 opponent를 선택하면, 위 문제 4개 (1, 2, 3, 4) 모두 완화되거나 해결된다.

직접 비교: 동일 조건의 self_play_league run

runs/deep_cfr/2026-05-07_512x3_argmax_tiebreak_2x_updates_10000iter는 512x3 opponent_network 실험과 거의 동일한 hyperparameter에 단지 opponent_policyself_play_league로 바꾼 run이다 (10000-iter cap이라 iter 579에서 멈춰있음).

항목 opponent_network 512x3 self_play_league 512x3
opponent_policy network self_play_league
self_play.max_snapshots 0 20
self_play.current_weight 1.0 0.5
self_play.recent_weight 0.0 0.3
self_play.older_weight 0.0 0.2
network / traversal / optimization 나머지 동일 동일
regret_matching.all_negative_fallback argmax_tiebreak argmax_tiebreak
traversals_per_iteration 2 2

iteration별 비교

iter NETWORK Random WR NETWORK Safe WR LEAGUE Random WR LEAGUE Safe WR
10 78% Δ+28.6 8% Δ-40.8 86% Δ+32.0 5% Δ-52.7
15 85% Δ+32.2 5% Δ-47.2 70% Δ+14.4 7% Δ-53.6
30 36% Δ-14.3 3% Δ-106 53% Δ+3.9 10% Δ-75.5
100 41% Δ-12.9 0% Δ-111.6 68% Δ+19.9 1% Δ-88.5
200 33% Δ-17.1 1% Δ-114.1 63% Δ+18.9 0% Δ-90.7
300 38% Δ-16.2 0% Δ-106.4 78% Δ+35.6 1% Δ-74.1
350 34% Δ-21.0 8% Δ-91.9 72% Δ+31.7 4% Δ-68.6

Best 비교

메트릭 NETWORK LEAGUE
Best Random WR 85% (iter 15) 86% (iter 10)
iter 350 시점 Random WR 34% 72%
Best Safe Heuristic WR 8% (iter 10) 11% (iter 555)
발산 여부 발산 (iter 30~) 발산 없음, plateau 유지

해석

  • 두 run 모두 iter 1015 근처에서 비슷한 peak (~85%) 도달. → opponent_policy는 학습 초기 신호에는 영향 없음.
  • 그 이후가 갈림길:
    • network: iter 30부터 발산, iter 100+에서 Random WR ~3040%로 collapse.
    • league: 같은 시점에 plateau 유지, iter 200350 사이에 오히려 Random WR이 6078%로 천천히 상승. Safe Heuristic도 매우 느리지만 학습 (iter 555에 11%로 best).
  • iter 350 시점의 Random WR 격차 = 38%p (72% vs 34%). 같은 hyperparameter, 같은 seed, 같은 traversal/optimization 설정에서 opponent policy 하나의 차이가 이런 정도의 격차를 만든다.

이 결과는 본 문서의 "moving target → 발산" 가설을 거의 완벽히 실증한다. network는 echo chamber로 무너지고, league는 다양한 fixed snapshot 덕에 안정적으로 학습을 이어간다.

왜 큰 네트워크가 plateau를 늘렸나

가설: 큰 capacity는 더 다양한 strategy mode를 표현할 수 있음. echo chamber가 단일 mode로 collapse되는 데 더 오래 걸림. 하지만 일단 collapse가 시작되면 큰 네트워크도 동일하게 발산. 근본 원인 (moving target) 은 capacity로 해결 불가.

부수 효과: 큰 네트워크 + plateau 동안 Safe Heuristic 상대 13% WR은 다른 어떤 self-play 실험에서도 보지 못한 수치. 이 단계의 checkpoint는 별도로 보존할 가치가 있을 수 있음 (단, 1024x4 실험은 발산 후 last 만 저장 되어 iter 85 checkpoint가 archive되지 않았다면 복구 불가).

결론 및 권고

  1. traversal.opponent_policy: network단독으로 사용하지 말 것. 학습 초기에 잘 되는 것처럼 보이다가 발산하므로 짧은 실험으로 위험성을 놓치기 쉽다.

  2. 기본값은 self_play_league 유지. snapshot pool로 fixed/diverse opponent를 제공해야 안정적.

  3. 그래도 network를 시도하고 싶다면:

    • early stopping 필수 (eval WR 기준 best checkpoint 보존).
    • save_iteration_interval을 짧게 (예: 5 iter) 설정해서 plateau 시점을 archive.
    • peak 이후 곧바로 중단.
  4. 연구 가치 있는 후속 실험:

    • opponent_policy: average_strategy (학습 중인 average 정책 사용). CFR 이론과 더 잘 부합할 가능성.
    • opponent_policy: hybrid (probabilistic mix of network + snapshot). diversity와 simplicity 절충.
    • 1024x4의 iter 85 plateau 패턴을 self_play_league에서 재현 가능한지.

사용된 Config 파일

  • configs/deep_cfr/deep_cfr_opponent_network_512x3_1000iter.yaml
  • configs/deep_cfr/deep_cfr_opponent_network_1024x4_1000iter.yaml

Run 디렉토리

  • runs/deep_cfr/deep_cfr_opponent_network_512x3_1000iter/ (363 iter에서 중단)
  • runs/deep_cfr/deep_cfr_opponent_network_1024x4_1000iter/ (231 iter에서 중단)

각 디렉토리의 metrics.jsonl이 본 분석의 raw source.