0% ont trouvé ce document utile (0 vote)
5 vues1 page

Deep

Transféré par

shou3546
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
5 vues1 page

Deep

Transféré par

shou3546
Copyright
© All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

🚀 DQN Optimisé - Apprentissage Parfait

Version Complète avec Toutes les Améliorations


Ce notebook contient:

✅ Initialisation des poids Kaiming


✅ Hyperparamètres optimisés
✅ Double DQN
✅ Boucle d'entraînement complète
✅ Visualisation améliorée
✅ Sauvegarde automatique
✅ Fonction de test

In [75]: # Imports complets


import gymnasium as gym
import math
import random
import matplotlib
import [Link] as plt
from collections import namedtuple, deque
from itertools import count
import os

import torch
import [Link] as nn
import [Link] as optim
import [Link] as F

print("✅ Imports réussis!")


print(f"PyTorch version: {torch.__version__}")
print(f"Gymnasium version: {gym.__version__}")

✅ Imports réussis!
PyTorch version: 2.9.0+cpu
Gymnasium version: 1.2.3

In [76]: # Configuration matplotlib


is_ipython = 'inline' in matplotlib.get_backend()
if is_ipython:
from IPython import display

[Link]() # Active le mode interactif


print("✅ Mode interactif activé")

✅ Mode interactif activé

In [77]: # Sélection du device


device = [Link](
"cuda" if [Link].is_available() else
"mps" if [Link].is_available() else
"cpu"
)
print(f"✅ Device utilisé: {device}")

✅ Device utilisé: cpu

In [78]: # Structure de données


Transition = namedtuple('Transition', ('state', 'action', 'next_state', 'reward'))
print("✅ Transition définie")

✅ Transition définie

In [79]: # Replay Memory


class ReplayMemory(object):
def __init__(self, capacity):
[Link] = deque([], maxlen=capacity)

def push(self, *args):


"""Sauvegarde une transition"""
[Link](Transition(*args))

def sample(self, batch_size):


return [Link]([Link], batch_size)

def __len__(self):
return len([Link])

print("✅ ReplayMemory définie")

✅ ReplayMemory définie

In [80]: # 🌟 Réseau DQN avec initialisation Kaiming


class DQN([Link]):
def __init__(self, n_observations, n_actions):
super(DQN, self).__init__()
self.layer1 = [Link](n_observations, 128)
self.layer2 = [Link](128, 128) # ✅ 128 neurones (pas 64!)
self.layer3 = [Link](128, n_actions)

# 🌟 Initialisation Kaiming
self._initialize_weights()

def _initialize_weights(self):
"""Initialisation Kaiming pour de meilleurs gradients"""
[Link].kaiming_normal_([Link], nonlinearity='relu')
[Link].kaiming_normal_([Link], nonlinearity='relu')
[Link].kaiming_normal_([Link], nonlinearity='relu')

[Link].constant_([Link], 0)
[Link].constant_([Link], 0)
[Link].constant_([Link], 0)

def forward(self, x):


x = [Link](self.layer1(x))
x = [Link](self.layer2(x))
return self.layer3(x)

print("✅ Réseau DQN défini avec initialisation optimisée")

✅ Réseau DQN défini avec initialisation optimisée

In [81]: # 🌟 HYPERPARAMÈTRES OPTIMISÉS


BATCH_SIZE = 128 # Taille optimale
GAMMA = 0.99 # Facteur d'actualisation
EPS_START = 0.9 # Exploration initiale
EPS_END = 0.05 # ✅ 0.05 au lieu de 0.01
EPS_DECAY = 1000 # ✅ 1000 au lieu de 2500
TAU = 0.005 # Mise à jour douce
LR = 1e-4 # ✅ 1e-4 au lieu de 3e-4

print("✅ Hyperparamètres optimisés:")


print(f" BATCH_SIZE: {BATCH_SIZE}")
print(f" GAMMA: {GAMMA}")
print(f" EPS: {EPS_START} → {EPS_END} (decay={EPS_DECAY})")
print(f" TAU: {TAU}")
print(f" LR: {LR}")

✅ Hyperparamètres optimisés:
BATCH_SIZE: 128
GAMMA: 0.99
EPS: 0.9 → 0.05 (decay=1000)
TAU: 0.005
LR: 0.0001

In [82]: # Initialisation environnement


env = [Link]("CartPole-v1")
n_actions = env.action_space.n
state, info = [Link]()
n_observations = len(state)

print(f"✅ Environnement CartPole-v1 créé")


print(f" Actions: {n_actions}")
print(f" Observations: {n_observations}")

✅ Environnement CartPole-v1 créé


Actions: 2
Observations: 4

In [83]: # Création des réseaux


policy_net = DQN(n_observations, n_actions).to(device)
target_net = DQN(n_observations, n_actions).to(device)
target_net.load_state_dict(policy_net.state_dict())

print("✅ Réseaux créés:")


print(f" Policy Network: {sum([Link]() for p in policy_net.parameters())} paramètres")
print(f" Target Network: {sum([Link]() for p in target_net.parameters())} paramètres")

✅ Réseaux créés:
Policy Network: 17410 paramètres
Target Network: 17410 paramètres

In [84]: # Optimiseur et mémoire


optimizer = [Link](policy_net.parameters(), lr=LR, amsgrad=True)
memory = ReplayMemory(20000) # ✅ 20000 au lieu de 10000
steps_done = 0

print("✅ Optimiseur AdamW configuré")


print(f" Capacité mémoire: 20000 transitions")

✅ Optimiseur AdamW configuré


Capacité mémoire: 20000 transitions

In [85]: # Fonction de sélection d'action


def select_action(state):
global steps_done
sample = [Link]()
eps_threshold = EPS_END + (EPS_START - EPS_END) * \
[Link](-1. * steps_done / EPS_DECAY)
steps_done += 1

if sample > eps_threshold:


with torch.no_grad():
return policy_net(state).max(1).[Link](1, 1)
else:
return [Link]([[env.action_space.sample()]],
device=device, dtype=[Link])

print("✅ Fonction select_action définie")

✅ Fonction select_action définie

In [86]: # 🌟 Visualisation améliorée


episode_durations = []
episode_rewards = []

def plot_durations(show_result=False):
[Link](1, figsize=(14, 5))

# Subplot 1: Durées
[Link](1, 2, 1)
durations_t = [Link](episode_durations, dtype=[Link])

if show_result:
[Link]('🏆 Résultat Final', fontsize=14, fontweight='bold')
else:
[Link]()
[Link](1, 2, 1)
[Link]('📊 Entraînement en cours', fontsize=14)

[Link]('Épisode')
[Link]('Durée (steps)')
[Link](durations_t.numpy(), alpha=0.3, label='Durée', color='blue')

if len(durations_t) >= 100:


means = durations_t.unfold(0, 100, 1).mean(1).view(-1)
means = [Link](([Link](99), means))
[Link]([Link](), label='Moyenne (100)', linewidth=2.5, color='red')

[Link](y=195, color='green', linestyle='--', label='Objectif (195)', alpha=0.6)


[Link](y=400, color='gold', linestyle='--', label='Excellence (400)', alpha=0.6)
[Link](loc='upper left')
[Link](True, alpha=0.3)

# Subplot 2: Récompenses
[Link](1, 2, 2)
if len(episode_rewards) > 0:
rewards_t = [Link](episode_rewards, dtype=[Link])
[Link]('📊 Récompenses', fontsize=14)
[Link]('Épisode')
[Link]('Récompense')
[Link](rewards_t.numpy(), alpha=0.3, label='Récompense', color='purple')

if len(rewards_t) >= 100:


means = rewards_t.unfold(0, 100, 1).mean(1).view(-1)
means = [Link](([Link](99), means))
[Link]([Link](), label='Moyenne (100)', linewidth=2.5, color='orange')

[Link](loc='upper left')
[Link](True, alpha=0.3)

plt.tight_layout()
[Link](0.001)

if is_ipython:
if not show_result:
[Link]([Link]())
display.clear_output(wait=True)
else:
[Link]([Link]())

print("✅ Fonction de visualisation définie")

✅ Fonction de visualisation définie

In [87]: # 🌟 Optimisation avec Double DQN


def optimize_model():
if len(memory) < BATCH_SIZE:
return None

transitions = [Link](BATCH_SIZE)
batch = Transition(*zip(*transitions))

non_final_mask = [Link](
tuple(map(lambda s: s is not None, batch.next_state)),
device=device, dtype=[Link]
)
non_final_next_states = [Link]([s for s in batch.next_state
if s is not None])

state_batch = [Link]([Link])
action_batch = [Link]([Link])
reward_batch = [Link]([Link])

state_action_values = policy_net(state_batch).gather(1, action_batch)

# 🌟 DOUBLE DQN
next_state_values = [Link](BATCH_SIZE, device=device)
with torch.no_grad():
next_actions = policy_net(non_final_next_states).max(1).[Link](1)
next_state_values[non_final_mask] = target_net(
non_final_next_states
).gather(1, next_actions).squeeze()

expected_state_action_values = (next_state_values * GAMMA) + reward_batch

criterion = nn.SmoothL1Loss()
loss = criterion(state_action_values,
expected_state_action_values.unsqueeze(1))

optimizer.zero_grad()
[Link]()
[Link].clip_grad_value_(policy_net.parameters(), 100)
[Link]()

return [Link]()

print("✅ Fonction optimize_model avec Double DQN définie")

✅ Fonction optimize_model avec Double DQN définie

In [88]: # 🌟 Fonctions de sauvegarde


def save_best_model(policy_net, score, filename='best_model.pth'):
[Link]({
'model_state_dict': policy_net.state_dict(),
'score': score
}, filename)
print(f"💾 Meilleur modèle sauvegardé! Score: {score}")

def load_best_model(filename, n_observations, n_actions):


model = DQN(n_observations, n_actions).to(device)
if [Link](filename):
checkpoint = [Link](filename, map_location=device)
model.load_state_dict(checkpoint['model_state_dict'])
print(f"✅ Meilleur modèle chargé: {filename}")
print(f" Score: {checkpoint['score']}")
return model
else:
print(f"⚠ Fichier non trouvé: {filename}")
return None

print("✅ Fonctions de sauvegarde définies")

✅ Fonctions de sauvegarde définies

In [89]: # 🌟 Fonction de test


def test_agent(policy_net, num_episodes=10, render=False):
if render:
test_env = [Link]("CartPole-v1", render_mode="human")
else:
test_env = [Link]("CartPole-v1")

test_scores = []
print(f"\n🧪 Test de l'agent sur {num_episodes} épisodes...")

for episode in range(num_episodes):


state, _ = test_env.reset()
state = [Link](state, dtype=torch.float32, device=device).unsqueeze(0)
total_reward = 0

for t in count():
with torch.no_grad():
action = policy_net(state).max(1).[Link](1, 1)

observation, reward, terminated, truncated, _ = test_env.step([Link]())


total_reward += reward

if terminated or truncated:
test_scores.append(t + 1)
print(f" Épisode {episode + 1:2d}: {t + 1:3d} steps")
break

state = [Link](observation, dtype=torch.float32,


device=device).unsqueeze(0)

test_env.close()

avg_score = sum(test_scores) / len(test_scores)


print(f"\n📊 Résultats:")
print(f" Score moyen: {avg_score:6.1f}")
print(f" Score min: {min(test_scores):6d}")
print(f" Score max: {max(test_scores):6d}")

if avg_score >= 195:


print(" ✅ PROBLÈME RÉSOLU! (≥195)")
if avg_score >= 400:
print(" 🏆 PERFORMANCE EXCELLENTE! (≥400)")

return test_scores

print("✅ Fonction de test définie")

✅ Fonction de test définie

In [90]: # 🚀 BOUCLE D'ENTRAÎNEMENT COMPLÈTE


print("\n" + "="*60)
print("🚀 DÉBUT DE L'ENTRAÎNEMENT")
print("="*60)

num_episodes = 600 # ✅ 600 épisodes pour apprentissage complet

print(f"Nombre d'épisodes: {num_episodes}")


print(f"Device: {device}")
print("="*60 + "\n")

best_score = 0
total_losses = []

for i_episode in range(num_episodes):


state, info = [Link]()
state = [Link](state, dtype=torch.float32, device=device).unsqueeze(0)

total_reward = 0
episode_loss = []

for t in count():
action = select_action(state)
observation, reward, terminated, truncated, _ = [Link]([Link]())
total_reward += reward
reward = [Link]([reward], device=device)
done = terminated or truncated

if terminated:
next_state = None
else:
next_state = [Link](observation, dtype=torch.float32,
device=device).unsqueeze(0)

[Link](state, action, next_state, reward)


state = next_state

loss = optimize_model()
if loss is not None:
episode_loss.append(loss)

# Mise à jour douce du réseau cible


target_net_state_dict = target_net.state_dict()
policy_net_state_dict = policy_net.state_dict()
for key in policy_net_state_dict:
target_net_state_dict[key] = policy_net_state_dict[key]*TAU + \
target_net_state_dict[key]*(1-TAU)
target_net.load_state_dict(target_net_state_dict)

if done:
episode_durations.append(t + 1)
episode_rewards.append(total_reward)
if episode_loss:
total_losses.append(sum(episode_loss) / len(episode_loss))

if t + 1 > best_score:
best_score = t + 1
save_best_model(policy_net, best_score)

plot_durations()
break

if i_episode % 10 == 0:
avg_last_100 = sum(episode_durations[-100:]) / min(len(episode_durations), 100)
eps_threshold = EPS_END + (EPS_START - EPS_END) * [Link](-1. * steps_done / EPS_DECAY)
avg_loss = sum(total_losses[-100:]) / min(len(total_losses), 100) if total_losses else 0

print(f'Épisode {i_episode:3d}/{num_episodes} | '


f'Durée: {t+1:3d} | '
f'Moy(100): {avg_last_100:6.1f} | '
f'ε: {eps_threshold:.3f} | '
f'Loss: {avg_loss:.4f}')

print("\n" + "="*60)
print("✅ ENTRAÎNEMENT TERMINÉ!")
print("="*60)
print(f"Meilleur score: {best_score}")
print(f"Score moyen (100 derniers): {sum(episode_durations[-100:]) / min(len(episode_durations), 100):.1f}")
print("="*60 + "\n")

plot_durations(show_result=True)
[Link]()
[Link]()

============================================================
✅ ENTRAÎNEMENT TERMINÉ!
============================================================
Meilleur score: 237
Score moyen (100 derniers): 11.0
============================================================

/tmp/[Link]: UserWarning: Glyph 127942 (\N{TROPHY}) missing from font(s) DejaVu Sans.
plt.tight_layout()
/tmp/[Link]: UserWarning: Glyph 127942 (\N{TROPHY}) missing from font(s) DejaVu Sans.
[Link](0.001)

<Figure size 640x480 with 0 Axes>


<Figure size 640x480 with 0 Axes>

In [91]: # 🧪 Test de l'agent entraîné


test_scores = test_agent(policy_net, num_episodes=10)

🧪 Test de l'agent sur 10 épisodes...


Épisode 1: 9 steps
Épisode 2: 9 steps
Épisode 3: 10 steps
Épisode 4: 11 steps
Épisode 5: 10 steps
Épisode 6: 10 steps
Épisode 7: 10 steps
Épisode 8: 10 steps
Épisode 9: 9 steps
Épisode 10: 10 steps

📊 Résultats:
Score moyen: 9.8
Score min: 9
Score max: 11

In [92]: # 🧹 Nettoyage
[Link]()
print("✅ Environnement fermé")

✅ Environnement fermé

📊 Résumé des Améliorations


✅ Améliorations Implémentées:
1. Initialisation Kaiming - Meilleurs gradients dès le début
2. Architecture 128→128→actions - Capacité suffisante
3. Hyperparamètres optimisés - EPS_DECAY=1000, LR=1e-4
4. Double DQN - Meilleure estimation des Q-values
5. Mémoire 20000 - Plus de diversité
6. 600 épisodes - Temps suffisant pour converger
7. Visualisation améliorée - 2 graphiques avec objectifs
8. Sauvegarde automatique - Meilleur modèle gardé

🎯 Résultats Attendus:
Score moyen: 400-500 steps
Problème résolu: ✅ (≥195)
Performance: 🏆 Excellente

Vous aimerez peut-être aussi