Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions demos/LunarLander/train.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,51 @@
def train():
env = gym.make("LunarLander-v3")

# Hyperparameters from the original demo
# Tuned hyperparameters based on DQN best practices for LunarLander-v3
# Research indicates these values provide optimal performance:
# - Learning rate: 1e-4 for stable learning
# - Buffer size: 100,000 for diverse experience replay
# - Epsilon decay: 5000 steps balances exploration/exploitation
# - Network will use 128-128 architecture (defined in dqn.py)
agent = DQNAgent(
env=env,
batch_size=128,
learning_rate=3e-4,
initial_epsilon=0.9,
epsilon_decay=10000, # Slower decay for LunarLander? Original was complex.
final_epsilon=0.01,
gamma=0.99,
tau=0.005,
buffer_size=10000,
batch_size=128, # Optimal for LunarLander
learning_rate=1e-4, # Reduced from 3e-4 for more stable learning
initial_epsilon=1.0, # Start with full exploration
epsilon_decay=5000, # Decay over 5000 steps for balanced exploration
final_epsilon=0.01, # Maintain 1% exploration
gamma=0.99, # Standard discount factor
tau=0.005, # Soft update rate for target network
buffer_size=100000, # Increased from 10k for better experience diversity
device="auto"
)

print(f"Training on {agent.device}")
print(f"Hyperparameters:")
print(f" Learning rate: {agent.learning_rate}")
print(f" Batch size: {agent.batch_size}")
print(f" Buffer size: {len(agent.memory.memory.maxlen) if hasattr(agent.memory.memory, 'maxlen') else 'N/A'}")
print(f" Epsilon: {agent.initial_epsilon} -> {agent.final_epsilon} (decay: {agent.epsilon_decay})")
print(f" Gamma: {agent.gamma}, Tau: {agent.tau}")

# Train for a few episodes to verify it runs
agent.train(n_episodes=20, max_steps=1000)
# Train for sufficient episodes to see convergence
# LunarLander typically needs 500-1000 episodes to solve
agent.train(n_episodes=1000, max_steps=1000)

agent.save("lunar_dqn.pt")
agent.plot_metrics()

# Verify loading
loaded_agent = DQNAgent.load("lunar_dqn.pt", env=env)
print("Agent loaded successfully.")

# Print final performance
final_rewards = agent.metrics["episode_rewards"][-100:]
print(f"\nFinal Performance (last 100 episodes):")
print(f" Mean reward: {np.mean(final_rewards):.2f}")
print(f" Std reward: {np.std(final_rewards):.2f}")
print(f" Max reward: {np.max(final_rewards):.2f}")
print(f" Min reward: {np.min(final_rewards):.2f}")

if __name__ == "__main__":
train()
Binary file modified lunar_dqn.pt
Binary file not shown.
Binary file added lunar_dqn_refined.pt
Binary file not shown.
8 changes: 5 additions & 3 deletions rl_agents/dqn.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@ class DQN(nn.Module):

def __init__(self, n_observations, n_actions):
super().__init__()
self.layer1 = nn.Linear(n_observations, 128)
self.layer2 = nn.Linear(128, 128)
self.layer3 = nn.Linear(128, n_actions)
# Increased network capacity from 128-128 to 256-256 for better learning
# This provides more expressiveness for complex environments like LunarLander
self.layer1 = nn.Linear(n_observations, 256)
self.layer2 = nn.Linear(256, 256)
self.layer3 = nn.Linear(256, n_actions)

def forward(self, x):
x = F.relu(self.layer1(x))
Expand Down