λͺ©ν: μ¬κ³Όκ²μ(FruitBox) 170κ° μ μ λΆ μ κ±° (100% ν΄λ¦¬μ΄)
κ°ννμ΅μΌλ‘ μΈκ°μ λμ΄μλ μ±λ₯ λ¬μ±μ λͺ©νλ‘ νλ νλ‘μ νΈμ λλ€.
- DQN λ² μ΄μ€λΌμΈ κ΅¬μΆ μλ£: CNN κΈ°λ°μ DQN λͺ¨λΈκ³Ό 컀리νλΌ νμ΅μ ν΅ν΄ μμ μ μΈ νμ΅ κΈ°λ°μ λ§λ ¨νμ΅λλ€.
- μ±λ₯ κΈ°λ‘: μ½ 10,000 μνΌμλ νμ΅ κ²°κ³Ό, νκ· **96% (163.4κ°)**μ μ¬κ³Όλ₯Ό μ κ±°νλ μ±κ³Όλ₯Ό λ¬μ±νμ΅λλ€.
- μ루μ
보μ₯ν νκ²½:
BackwardBoardGeneratorλ₯Ό λμ νμ¬ νμ ν΄λ΅μ΄ μ‘΄μ¬νλ 보λμμ νμ΅ν μ μλλ‘ νκ²½μ κ°μ νμ΅λλ€.
κΈ°μ‘΄ DQNμ Q-value νλ° λ¬Έμ λ₯Ό ν΄κ²°ν μλ‘μ΄ μν€ν μ²μ λλ€.
| λ¬Έμ | κΈ°μ‘΄ | v2 |
|---|---|---|
| Q-value λ²μ | [-10μ΅, +1μ΅] | [-10, 200] |
| μκ³ λ¦¬μ¦ | Vanilla DQN | Dueling Double DQN |
| Target μ λ°μ΄νΈ | Hard (1000 steps) | Soft (tau=0.005) |
| κ²½ν μ¬μ | Uniform | PER (Prioritized) |
| 보λ μμ± | μμ μ«μ νΈν₯ | κ· λ± λΆν¬ |
src/
βββ models_v2.py # Dueling DQN + Residual + Q-value clipping
βββ agent_v2.py # Double DQN + Soft Update + PER
βββ replay_buffer.py # Prioritized Experience Replay
βββ reward_normalizer.py # 보μ μ κ·ν
envs/
βββ board_generator_v2.py # κ· λ± λΆν¬ + μ ν¨μ± κ²μ¦
experiments/
βββ train_v2.py # Colabμ© ν΅ν© νμ΅ μ€ν¬λ¦½νΈ
# Colabμμ μ§μ μ€ννκ±°λ
uv run python experiments/train_v2.py- λͺ¨λΈ μμ ν:
src/models.pyμ BatchNormμ μΆκ°νμ¬ activation νλ°κ³Ό λΉνμ€μ Q-value μ€μΌμΌ λ¬Έμ λ₯Ό μννμ΅λλ€. - νκ²½ μΌλ°ν: 보λ μμ±μ backward/random νΌν© λΉμ¨(
backward_generator_ratio)μ λμ ν΄ λΆν¬ μ΄λμ μ€μμ΅λλ€. - 보μ μ€κ³: λ―Έλ κ°λ₯μ±(μ ν¨ μ‘μ μ λ³ν), ν° μμ μ κ±°, μμ ν΄λ¦¬μ΄ 보λμ€λ₯Ό μ΅μ μΌλ‘ μΆκ°νμ΅λλ€.
- Colab + Drive νμ΅: Google Driveμ 체ν¬ν¬μΈνΈλ₯Ό μ μ₯νλ μ€ν¬λ¦½νΈ
experiments/train_colab_drive.pyλ₯Ό μΆκ°νμ΅λλ€. - νκ²½ λ¨μΌ μμ€: νκ²½ μ½λλ
envs/fruitbox_env_improved.pyκ° κΈ°μ€μ΄λ©°,envs/fruitbox_env.pyλ νΈνμ© λνΌμ λλ€.
- κ³ μ±λ₯ νκ²½ (
envs/fruitbox_env_improved.py): Prefix Sum λ° Incremental Action Maskingμ μ μ©νμ¬ μ°μ° μλλ₯Ό κ·Ήλννμ΅λλ€. - DQN μμ΄μ νΈ (
src/agent.py,src/models.py): 10μ±λ One-hot μΈμ½λ© μ λ ₯κ³Ό μ‘μ λ§μ€νΉμ μ§μνλ CNN λͺ¨λΈμ λλ€. - Colab μ΅μ ν: GPU λ° TPU κ°μμ μ§μνλ νμ΅ μ€ν¬λ¦½νΈ/λ
ΈνΈλΆ(
experiments/train_colab_drive.py,experiments/train_colab_integrated.ipynb)μ μ 곡ν©λλ€. - μκ°ν λꡬ: μμ΄μ νΈμ νλ μ΄λ₯Ό λ¨κ³λ³ ASCII κ·Έλν½μΌλ‘ λ λλ§νκ³ μ λ΅μ λΆμν μ μλ κΈ°λ₯μ ν¬ν¨νκ³ μμ΅λλ€.
envs/: μ¬κ³Όκ²μ νκ²½ λ° λ³΄λ μμ±κΈ°src/: DQN λͺ¨λΈ μν€ν μ² λ° μμ΄μ νΈ λ‘μ§experiments/: λ‘컬 λ° Colabμ© νμ΅ μ€ν¬λ¦½νΈ/λ ΈνΈλΆcheckpoints/: νμ΅λ λͺ¨λΈ μ μ₯ ν΄λ
- ONNX λ³ν: λΈλΌμ°μ μμ μ€ν κ°λ₯νλλ‘ λͺ¨λΈμ λ³νν©λλ€.
uv run python src/export_onnx.py --model_path checkpoints/model.pth --output_path extension/model.onnx
- Hugging Face μ
λ‘λ: νμ΅λ κ°μ€μΉμ ONNX λͺ¨λΈμ νλΈμ 곡μ ν©λλ€.
uv run python src/upload_hf.py --repo_id "μ¬μ©μ/리ν¬μ§ν 리" --model_path checkpoints/model.pth --onnx_path extension/model.onnx
μ€μ Gamesaien Fruit Box μ¬μ΄νΈμμ λͺ¨λΈμ μ€ννμ¬ ν΄λ΅μ μ°Ύμμ£Όλ νμ₯ νλ‘κ·Έλ¨μ λλ€.
- λΈλΌμ°μ μ£Όμμ°½μ
chrome://extensions/μ λ ₯ - 'κ°λ°μ λͺ¨λ' νμ±ν
- 'μμΆν΄μ λ νμ₯ νλ‘κ·Έλ¨μ λ‘λν©λλ€' ν΄λ¦ ν νλ‘μ νΈμ
extension/ν΄λ μ ν - μ€μ: νμ₯ νλ‘κ·Έλ¨ ν΄λ μμ
model.onnxνμΌκ³Ό onnxruntime-web λΌμ΄λΈλ¬λ¦¬κ° ν¬ν¨λμ΄μΌ ν©λλ€.
- κ²μ μ¬μ΄νΈ μ μ ν νμ₯ νλ‘κ·Έλ¨ νμ μμ "Find Best Move" λ²νΌ ν΄λ¦
- νλ©΄μ μ΅μ μ μ¬κ³Ό λ°μ€κ° λΉ¨κ°μμΌλ‘ νμλ©λλ€.
- 100% ν΄λ¦¬μ΄ λμ : νμ¬μ 96% μ±κ³Όλ₯Ό λμ΄ 100% ν΄λ¦¬μ΄λ₯Ό μν΄ λ κΉμ μ κ²½λ§(ResNet λ±)κ³Ό PPO μκ³ λ¦¬μ¦ λμ μ κ²ν μ€οΏ½οΏ½οΏ½λλ€.
- JAX/TPU κ°μ νλ: λ λΉ λ₯Έ μ€νμ μν΄ JAX κΈ°λ°μ λΆμ° νμ΅ νκ²½μ κ³ λνν μμ μ λλ€.