diff --git a/bot/src/dqn/burnrl/environment.rs b/bot/src/dqn/burnrl/environment.rs index 5716fa1..f8e5f21 100644 --- a/bot/src/dqn/burnrl/environment.rs +++ b/bot/src/dqn/burnrl/environment.rs @@ -179,9 +179,9 @@ impl Environment for TrictracEnvironment { // Récompense finale basée sur le résultat if let Some(winner_id) = self.game.determine_winner() { if winner_id == self.active_player_id { - reward += 50.0; // Victoire + reward += 100.0; // Victoire } else { - reward -= 25.0; // Défaite + reward -= 50.0; // Défaite } } } @@ -259,7 +259,7 @@ impl TrictracEnvironment { // } TrictracAction::Go => { // Continuer après avoir gagné un trou - reward += 0.2; + reward += 0.4; Some(GameEvent::Go { player_id: self.active_player_id, }) @@ -288,7 +288,7 @@ impl TrictracEnvironment { let checker_move1 = store::CheckerMove::new(from1, to1).unwrap_or_default(); let checker_move2 = store::CheckerMove::new(from2, to2).unwrap_or_default(); - reward += 0.2; + reward += 0.4; Some(GameEvent::Move { player_id: self.active_player_id, moves: (checker_move1, checker_move2), @@ -313,8 +313,6 @@ impl TrictracEnvironment { }; if self.game.validate(&dice_event) { self.game.consume(&dice_event); - let (points, adv_points) = self.game.dice_points; - reward += 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points } } } else { @@ -358,7 +356,7 @@ impl TrictracEnvironment { }, } } - TurnStage::MarkPoints => { + TurnStage::MarkAdvPoints | TurnStage::MarkPoints => { let opponent_color = store::Color::Black; let dice_roll_count = self .game @@ -368,31 +366,14 @@ impl TrictracEnvironment { .dice_roll_count; let points_rules = PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - let (points, adv_points) = points_rules.get_points(dice_roll_count); - reward -= 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points + let points = points_rules.get_points(dice_roll_count).0; + reward -= 0.3 * points as f32; // Récompense proportionnelle aux points GameEvent::Mark { player_id: self.opponent_id, points, } } - TurnStage::MarkAdvPoints => { - let opponent_color = store::Color::Black; - let dice_roll_count = self - .game - .players - .get(&self.opponent_id) - .unwrap() - .dice_roll_count; - let points_rules = - PointsRules::new(&opponent_color, &self.game.board, self.game.dice); - let points = points_rules.get_points(dice_roll_count).1; - // pas de reward : déjà comptabilisé lors du tour de blanc - GameEvent::Mark { - player_id: self.opponent_id, - points, - } - } TurnStage::HoldOrGoChoice => { // Stratégie simple : toujours continuer GameEvent::Go { diff --git a/bot/src/dqn/burnrl/main.rs b/bot/src/dqn/burnrl/main.rs index 9a3a16f..fdaafc6 100644 --- a/bot/src/dqn/burnrl/main.rs +++ b/bot/src/dqn/burnrl/main.rs @@ -9,15 +9,15 @@ type Backend = Autodiff>; type Env = environment::TrictracEnvironment; fn main() { - // println!("> Entraînement"); + println!("> Entraînement"); let conf = dqn_model::DqnConfig { - num_episodes: 40, + num_episodes: 50, // memory_size: 8192, // must be set in dqn_model.rs with the MEMORY_SIZE constant - // max_steps: 1000, // must be set in environment.rs with the MAX_STEPS constant + // max_steps: 700, // must be set in environment.rs with the MAX_STEPS constant dense_size: 256, // neural network complexity eps_start: 0.9, // epsilon initial value (0.9 => more exploration) eps_end: 0.05, - eps_decay: 3000.0, + eps_decay: 1000.0, }; let agent = dqn_model::run::(&conf, false); //true); diff --git a/bot/src/dqn/simple/dqn_trainer.rs b/bot/src/dqn/simple/dqn_trainer.rs index dedf382..c23b542 100644 --- a/bot/src/dqn/simple/dqn_trainer.rs +++ b/bot/src/dqn/simple/dqn_trainer.rs @@ -357,8 +357,8 @@ impl TrictracEnv { &self.game_state.board, self.game_state.dice, ); - let (points, adv_points) = points_rules.get_points(dice_roll_count); - reward -= 0.3 * (points - adv_points) as f32; // Récompense proportionnelle aux points + let points = points_rules.get_points(dice_roll_count).0; + reward -= 0.3 * points as f32; // Récompense proportionnelle aux points GameEvent::Mark { player_id: self.opponent_player_id, diff --git a/bot/src/strategy/client.rs b/bot/src/strategy/client.rs index 891f942..4f7b84f 100644 --- a/bot/src/strategy/client.rs +++ b/bot/src/strategy/client.rs @@ -46,14 +46,7 @@ impl BotStrategy for ClientStrategy { } fn calculate_adv_points(&self) -> u8 { - let dice_roll_count = self - .get_game() - .players - .get(&self.player_id) - .unwrap() - .dice_roll_count; - let points_rules = PointsRules::new(&Color::White, &self.game.board, self.game.dice); - points_rules.get_points(dice_roll_count).1 + self.calculate_points() } fn choose_go(&self) -> bool { diff --git a/devenv.nix b/devenv.nix index 1b51c9d..d41dbe8 100644 --- a/devenv.nix +++ b/devenv.nix @@ -13,7 +13,6 @@ # dev tools pkgs.samply # code profiler - pkgs.feedgnuplot # to visualize bots training results # for bevy pkgs.alsa-lib diff --git a/doc/refs/dqn-burn.md b/doc/refs/dqn-burn.md deleted file mode 100644 index 94cbf73..0000000 --- a/doc/refs/dqn-burn.md +++ /dev/null @@ -1,56 +0,0 @@ -# DQN avec burn-rl - -## Paramètre d'entraînement dans dqn/burnrl/dqn_model.rs - -Ces constantes sont des hyperparamètres, c'est-à-dire des réglages que l'on fixe avant l'entraînement et qui conditionnent la manière dont le modèle va apprendre. - -MEMORY_SIZE - -- Ce que c'est : La taille de la "mémoire de rejeu" (Replay Memory/Buffer). -- À quoi ça sert : L'agent interagit avec l'environnement (le jeu de TricTrac) et stocke ses expériences (un état, l'action prise, la récompense obtenue, et l'état suivant) dans cette mémoire. Pour s'entraîner, au - lieu d'utiliser uniquement la dernière expérience, il pioche un lot (batch) d'expériences aléatoires dans cette mémoire. -- Pourquoi c'est important : - 1. Décorrélation : Ça casse la corrélation entre les expériences successives, ce qui rend l'entraînement plus stable et efficace. - 2. Réutilisation : Une même expérience peut être utilisée plusieurs fois pour l'entraînement, ce qui améliore l'efficacité des données. -- Dans votre code : const MEMORY_SIZE: usize = 4096; signifie que l'agent gardera en mémoire les 4096 dernières transitions. - -DENSE_SIZE - -- Ce que c'est : La taille des couches cachées du réseau de neurones. "Dense" signifie que chaque neurone d'une couche est connecté à tous les neurones de la couche suivante. -- À quoi ça sert : C'est la "capacité de réflexion" de votre agent. Le réseau de neurones (ici, Net) prend l'état du jeu en entrée, le fait passer à travers des couches de calcul (de taille DENSE_SIZE), et sort une - estimation de la qualité de chaque action possible. -- Pourquoi c'est important : - - Une valeur trop petite : le modèle ne sera pas assez "intelligent" pour apprendre les stratégies complexes du TricTrac. - - Une valeur trop grande : l'entraînement sera plus lent et le modèle pourrait "sur-apprendre" (overfitting), c'est-à-dire devenir très bon sur les situations vues en entraînement mais incapable de généraliser - sur de nouvelles situations. -- Dans votre code : const DENSE_SIZE: usize = 128; définit que les couches cachées du réseau auront 128 neurones. - -EPS_START, EPS_END et EPS_DECAY - -Ces trois constantes gèrent la stratégie d'exploration de l'agent, appelée "epsilon-greedy". Le but est de trouver un équilibre entre : - -- L'Exploitation : Jouer le coup que le modèle pense être le meilleur. -- L'Exploration : Jouer un coup au hasard pour découvrir de nouvelles stratégies, potentiellement meilleures. - -epsilon (ε) est la probabilité de faire un choix aléatoire (explorer). - -- `EPS_START` (Epsilon de départ) : - - - Ce que c'est : La valeur d'epsilon au tout début de l'entraînement. - - Rôle : Au début, le modèle ne sait rien. Il est donc crucial qu'il explore beaucoup pour accumuler des expériences variées. Une valeur élevée (proche de 1.0) est typique. - - Dans votre code : const EPS_START: f64 = 0.9; signifie qu'au début, l'agent a 90% de chances de jouer un coup au hasard. - -- `EPS_END` (Epsilon final) : - - - Ce que c'est : La valeur minimale d'epsilon, atteinte après un certain nombre d'étapes. - - Rôle : Même après un long entraînement, on veut conserver une petite part d'exploration pour éviter que l'agent ne se fige dans une stratégie sous-optimale. - - Dans votre code : const EPS_END: f64 = 0.05; signifie qu'à la fin, l'agent explorera encore avec 5% de probabilité. - -- `EPS_DECAY` (Décroissance d'epsilon) : - - Ce que c'est : Contrôle la vitesse à laquelle epsilon passe de EPS_START à EPS_END. - - Rôle : C'est un facteur de "lissage" dans la formule de décroissance exponentielle. Plus cette valeur est élevée, plus la décroissance est lente, et donc plus l'agent passera de temps à explorer. - - Dans votre code : const EPS_DECAY: f64 = 1000.0; est utilisé dans la formule EPS_END + (EPS_START - EPS_END) \* f64::exp(-(step as f64) / EPS_DECAY); pour faire diminuer progressivement la valeur d'epsilon à - chaque étape (step) de l'entraînement. - -En résumé, ces constantes définissent l'architecture du "cerveau" de votre bot (DENSE*SIZE), sa mémoire à court terme (MEMORY_SIZE), et comment il apprend à équilibrer entre suivre sa stratégie et en découvrir de -nouvelles (EPS*\*). diff --git a/justfile b/justfile index d4f14c4..e7d7222 100644 --- a/justfile +++ b/justfile @@ -9,8 +9,7 @@ shell: runcli: RUST_LOG=info cargo run --bin=client_cli runclibots: - #RUST_LOG=info cargo run --bin=client_cli -- --bot dqn,dummy - RUST_LOG=info cargo run --bin=client_cli -- --bot dummy,dqn + RUST_LOG=info cargo run --bin=client_cli -- --bot dqn,dummy match: cargo build --release --bin=client_cli LD_LIBRARY_PATH=./target/release ./target/release/client_cli -- --bot dummy,dqn @@ -24,12 +23,9 @@ pythonlib: trainbot: #python ./store/python/trainModel.py # cargo run --bin=train_dqn # ok - # cargo run --bin=train_dqn_burn # utilise debug (why ?) cargo build --release --bin=train_dqn_burn - LD_LIBRARY_PATH=./target/release ./target/release/train_dqn_burn | tee /tmp/train.out -plottrainbot: - cat /tmp/train.out | awk -F '[ ,]' '{print $5}' | feedgnuplot --lines --points --unset grid - #tail -f /tmp/train.out | awk -F '[ ,]' '{print $5}' | feedgnuplot --lines --points --unset grid + LD_LIBRARY_PATH=./target/release ./target/release/train_dqn_burn + # cargo run --bin=train_dqn_burn # utilise debug (why ?) debugtrainbot: cargo build --bin=train_dqn_burn RUST_BACKTRACE=1 LD_LIBRARY_PATH=./target/debug ./target/debug/train_dqn_burn