MountainCar Q-Learning Pipeline

MountainCar Q-Learning Pipeline

MountainCar Q-Learning Pipeline

A step-by-step guide to applying Q-learning to the classic MountainCar environment from Gymnasium.

Libraries Used

This project uses a few key Python libraries. Here is a quick overview of their roles:

  • numpy: Used for numerical operations and managing arrays.
  • gymnasium: The library that provides the classic MountainCar-v0 environment.
  • collections: Used for the `defaultdict` to store the Q-table.

1. Define the Discretization and Q-Learning Agent

  • What the code does: It defines a `Discretizer` class to convert the continuous state space of MountainCar into a discrete grid. It also defines a `QLearningAgent` class, which is a standard implementation for tabular Q-learning.
  • Behind the scenes: The MountainCar environment's state space (position and velocity) is continuous, but `Q-learning` requires a discrete state space to work with a Q-table. The `Discretizer` handles this by mapping continuous values to integer bins.
  • Abstraction: The `Discretizer` and `QLearningAgent` classes abstract the complex logic for managing the state space and the learning algorithm.
import numpy as np
from collections import defaultdict

class Discretizer:
    def __init__(self, bins):
        self.bins = bins

    def __call__(self, obs) -> tuple[int, ...]:
        obs = np.array(obs, dtype=float).ravel()
        return tuple(int(np.digitize(o, b)) for o, b in zip(obs, self.bins))

class QLearningAgent:
    def __init__(self, n_actions, alpha=0.1, gamma=0.99, epsilon=1.0, epsilon_min=0.05, epsilon_decay=0.995):
        self.n_actions = n_actions
        self.alpha = alpha
        self.gamma = gamma
        self.epsilon = epsilon
        self.epsilon_min = epsilon_min
        self.epsilon_decay = epsilon_decay
        self.Q = defaultdict(lambda: np.zeros(n_actions, dtype=np.float32))

    def act(self, state):
        if np.random.rand() < self.epsilon:
            return np.random.randint(self.n_actions)
        return int(np.argmax(self.Q[state]))

    def learn(self, s, a, r, s_next, done):
        best_next_q = 0.0 if done else np.max(self.Q[s_next])
        td_target = r + self.gamma * best_next_q
        td_error = td_target - self.Q[s][a]
        self.Q[s][a] += self.alpha * td_error
        
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.epsilon_decay

2. Create the Environment and Run the Experiment

  • What the code does: It creates the MountainCar environment, the agent, and the discretizer. It then runs a training loop for thousands of episodes, allowing the agent to learn the optimal policy.
  • Behind the scenes: In each episode, the agent interacts with the environment, using the `Discretizer` to convert the continuous state into a discrete state for the Q-table. It takes actions, receives rewards, and learns. Over time, the agent learns how to gain momentum to reach the goal.
  • Abstraction: The training loop abstracts the complex, long-term process of learning and policy improvement. The `env.step()` function abstracts the physics of the MountainCar environment.
import gymnasium as gym

env = gym.make("MountainCar-v0")
agent = QLearningAgent(n_actions=env.action_space.n)

bins = [
    np.linspace(env.observation_space.low[0], env.observation_space.high[0], 10),
    np.linspace(env.observation_space.low[1], env.observation_space.high[1], 10)
]
discretizer = Discretizer(bins)

n_episodes = 20000
for i in range(n_episodes):
    state = discretizer(env.reset()[0])
    done = False
    episode_reward = 0
    while not done:
        action = agent.act(state)
        next_obs, reward, done, _, _ = env.step(action)
        next_state = discretizer(next_obs)
        agent.learn(state, action, reward, next_state, done)
        state = next_state
        episode_reward += reward
    
    if (i + 1) % 1000 == 0:
        print(f"Episode {i + 1}, Epsilon: {agent.epsilon:.4f}, Total Reward: {episode_reward:.2f}")

print("\nTraining finished. You can now test the policy.")

Comments

Popular posts from this blog

Elevator Q-Learning Pipeline

SMS Spam Detection Pipeline