Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Reinforcement learning fundamentals, algorithms, and research
.claude/skills/brycewang-stanford-reinforcement-learning-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-09 | ✓→✓ | = Same ✓ | 99% | 0% |
| case-18 | ✓→✓ | = Same ✓ | 95% | 0% |
| case-02 | ✓→✓ | = Same ✓ | 47% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 106% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 71% | 0% |
Understand and implement reinforcement learning algorithms from tabular methods through deep RL, including policy gradients, actor-critic, and model-based approaches.
An agent interacts with an environment to maximize cumulative reward:
Agent Environment
| |
|--- action a_t ---------->|
| |--- next state s_{t+1}
|<-- reward r_t, state s_t |--- reward r_{t+1}
| || Concept | Symbol | Definition | |---------|--------|-----------| | State | s | Observation of the environment | | Action | a | Decision made by the agent | | Reward | r | Scalar feedback signal | | Policy | pi(a\|s) | Mapping from states to actions | | Value function | V(s) | Expected cumulative reward from state s | | Q-function | Q(s, a) | Expected cumulative reward from (s, a) | | Discount factor | gamma | Weight of future vs. immediate rewards (0-1) | | Return | G_t | Sum of discounted future rewards from time t |
# Return (discounted cumulative reward)
G_t = r_t + gamma * r_{t+1} + gamma^2 * r_{t+2} + ...
# Bellman equation for V
V(s) = E[r + gamma * V(s') | s]
# Bellman equation for Q
Q(s, a) = E[r + gamma * max_a' Q(s', a') | s, a]
# Policy gradient theorem
gradient J(theta) = E[gradient log pi_theta(a|s) * Q(s, a)]| Category | Algorithm | Key Idea | On/Off Policy | |----------|-----------|----------|--------------| | Value-based | Q-Learning | Learn Q(s,a), act greedily | Off-policy | | | DQN | Q-Learning + neural net + replay buffer | Off-policy | | | Double DQN | Two networks to reduce overestimation | Off-policy | | | Dueling DQN | Separate value and advantage streams | Off-policy | | Policy gradient | REINFORCE | Monte Carlo policy gradient | On-policy | | | PPO | Clipped surrogate objective | On-policy | | | TRPO | Trust region constraint | On-policy | | Actor-Critic | A2C/A3C | Advantage actor-critic (parallel) | On-policy | | | SAC | Maximum entropy + off-policy AC | Off-policy | | | TD3 | Twin delayed DDPG | Off-policy | | Model-based | Dreamer | World model + imagination | On-policy | | | MBPO | Model-based policy optimization | Off-policy | | | MuZero | Learned model + planning (MCTS) | Off-policy |
pythonimport torch import torch.nn as nn import torch.optim as optim import numpy as np from collections import deque import random class QNetwork(nn.Module): def __init__(self, state_dim, action_dim, hidden_dim=128): super().__init__() self.net = nn.Sequential( nn.Linear(state_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, hidden_dim), nn.ReLU(), nn.Linear(hidden_dim, action_dim) ) def forward(self, x): return self.net(x) class DQNAgent: def __init__(self, state_dim, action_dim, lr=1e-3, gamma=0.99, epsilon=1.0, epsilon_decay=0.995, epsilon_min=0.01, buffer_size=10000, batch_size=64): self.action_dim = action_dim self.gamma = gamma self.epsilon = epsilon self.epsilon_decay = epsilon_decay self.epsilon_min = epsilon_min self.batch_size = batch_size self.q_network = QNetwork(state_dim, action_dim) self.target_network = QNetwork(state_dim, action_dim) self.target_network.load_state_dict(self.q_network.state_dict()) self.optimizer = optim.Adam(self.q_network.parameters(), lr=lr) self.replay_buffer = deque(maxlen=buffer_size) def select_action(self, state): if random.random() < self.epsilon: return random.randint(0, self.action_dim - 1) with torch.no_grad(): q_values = self.q_network(torch.FloatTensor(state)) return q_values.argmax().item() def store_transition(self, state, action, reward, next_state, done): self.replay_buffer.append((state, action, reward, next_state, done)) def train_step(self): if len(self.replay_buffer) < self.batch_size: return 0.0 batch = random.sample(self.replay_buffer, self.batch_size) states, actions, rewards, next_states, dones = zip(*batch) states = torch.FloatTensor(np.array(states)) actions = torch.LongTensor(actions) rewards = torch.FloatTensor(rewards) next_states = torch.FloatTensor(np.array(next_states)) dones = torch.FloatTensor(dones) # Current Q values q_values = self.q_network(states).gather(1, actions.unsqueeze(1)).squeeze() # Target Q values (Double DQN variant) with torch.no_grad(): best_actions = self.q_network(next_states).argmax(1) next_q = self.target_network(next_states).gather(1, best_actions.unsqueeze(1)).squeeze() targets = rewards + self.gamma * next_q * (1 - dones) loss = nn.MSELoss()(q_values, targets) self.optimizer.zero_grad() loss.backward() self.optimizer.step() self.epsilon = max(self.epsilon_min, self.epsilon * self.epsilon_decay) return loss.item() def update_target(self): self.target_network.load_state_dict(self.q_network.state_dict())
pythonclass PPOAgent: def __init__(self, state_dim, action_dim, lr=3e-4, gamma=0.99, lam=0.95, clip_ratio=0.2, epochs=10): self.gamma = gamma self.lam = lam self.clip_ratio = clip_ratio self.epochs = epochs self.actor = nn.Sequential( nn.Linear(state_dim, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, action_dim), nn.Softmax(dim=-1) ) self.critic = nn.Sequential( nn.Linear(state_dim, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1) ) self.optimizer = optim.Adam( list(self.actor.parameters()) + list(self.critic.parameters()), lr=lr ) def compute_gae(self, rewards, values, dones): """Generalized Advantage Estimation.""" advantages = [] gae = 0 for t in reversed(range(len(rewards))): next_value = values[t + 1] if t + 1 < len(values) else 0 delta = rewards[t] + self.gamma * next_value * (1 - dones[t]) - values[t] gae = delta + self.gamma * self.lam * (1 - dones[t]) * gae advantages.insert(0, gae) return torch.FloatTensor(advantages) def update(self, states, actions, old_log_probs, rewards, dones): values = self.critic(states).squeeze().detach().numpy() advantages = self.compute_gae(rewards, values, dones) returns = advantages + torch.FloatTensor(values[:len(advantages)]) advantages = (advantages - advantages.mean()) / (advantages.std() + 1e-8) for _ in range(self.epochs): probs = self.actor(states) dist = torch.distributions.Categorical(probs) new_log_probs = dist.log_prob(actions) entropy = dist.entropy().mean() ratio = (new_log_probs - old_log_probs).exp() clipped = torch.clamp(ratio, 1 - self.clip_ratio, 1 + self.clip_ratio) actor_loss = -torch.min(ratio * advantages, clipped * advantages).mean() critic_loss = nn.MSELoss()(self.critic(states).squeeze(), returns) loss = actor_loss + 0.5 * critic_loss - 0.01 * entropy self.optimizer.zero_grad() loss.backward() self.optimizer.step()
| Environment | Domain | Complexity | Key Paper | |-------------|--------|-----------|-----------| | Gymnasium (ex-Gym) | Classic control, Atari | Low-High | Brockman et al., 2016 | | MuJoCo | Continuous control, robotics | Medium-High | Todorov et al., 2012 | | DMControl | Continuous control from pixels | High | Tassa et al., 2018 | | ProcGen | Procedurally generated games | High (generalization) | Cobbe et al., 2020 | | Minigrid | Grid-world navigation | Low-Medium | Chevalier-Boisvert et al. | | Isaac Gym | GPU-accelerated physics sim | High | Makoviychuk et al., 2021 | | NetHack | Complex roguelike game | Very High | Kuttler et al., 2020 |
| Venue | Type | Focus | |-------|------|-------| | NeurIPS | Conference | Broad ML including RL | | ICML | Conference | Broad ML including RL | | ICLR | Conference | Representation learning, deep RL | | AAAI | Conference | Broad AI | | CoRL | Conference | Robot learning | | JMLR | Journal | Broad ML (open access) | | L4DC | Conference | Learning for dynamics and control |
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-09 | pass→pass | 15,013 | 14,992 | -0% | 1 | 1 | 0% | 2,738 | 5,442 | +99% | 0 | 0 | — |
case-18 | pass→pass | 15,327 | 13,398 | -13% | 1 | 1 | 0% | 2,599 | 5,069 | +95% | 0 | 0 | — |
case-01 | fail→fail | 23,196 | 22,143 | -5% | 1 | 1 | 0% | 4,865 | 6,787 | +40% | 0 | 0 | — |
case-02 | pass→pass | 24,308 | 21,753 | -11% | 1 | 1 | 0% | 5,029 | 7,405 | +47% | 0 | 0 | — |
case-03 | fail→fail | 22,641 | 44,417 | +96% | 1 | 1 | 0% | 3,568 | 10,940 | +207% | 0 | 0 | — |
case-04 | pass→pass | 18,869 | 21,127 | +12% | 1 | 1 | 0% | 3,093 | 6,377 | +106% | 0 | 0 | — |
case-05 | pass→pass | 19,159 | 17,998 | -6% | 1 | 1 | 0% | 3,246 | 5,544 | +71% | 0 | 0 | — |
case-06 | pass→pass | 11,915 | 13,790 | +16% | 1 | 1 | 0% | 2,295 | 5,416 | +136% | 0 | 0 | — |
case-07 | pass→pass | 13,789 | 11,818 | -14% | 1 | 1 | 0% | 2,461 | 4,895 | +99% | 0 | 0 | — |
case-08 | pass→pass | 15,168 | 13,473 | -11% | 1 | 1 | 0% | 2,968 | 5,325 | +79% | 0 | 0 | — |
case-10 | pass→pass | 15,063 | 17,241 | +14% | 1 | 1 | 0% | 2,614 | 6,010 | +130% | 0 | 0 | — |
case-11 | pass→pass | 7,002 | 4,026 | -43% | 1 | 1 | 0% | 1,169 | 3,305 | +183% | 0 | 0 | — |
case-12 | pass→pass | 28,488 | 31,355 | +10% | 1 | 1 | 0% | 4,502 | 8,051 | +79% | 0 | 0 | — |
case-13 | pass→pass | 11,640 | 13,894 | +19% | 1 | 1 | 0% | 2,264 | 5,415 | +139% | 0 | 0 | — |
case-14 | pass→pass | 7,028 | 5,808 | -17% | 1 | 1 | 0% | 1,151 | 3,640 | +216% | 0 | 0 | — |
case-15 | fail→fail | 8,412 | 8,122 | -3% | 1 | 1 | 0% | 1,484 | 4,136 | +179% | 0 | 0 | — |
case-16 | pass→pass | 9,595 | 5,888 | -39% | 1 | 1 | 0% | 1,656 | 3,680 | +122% | 0 | 0 | — |
case-17 | pass→pass | 12,587 | 4,996 | -60% | 1 | 1 | 0% | 2,070 | 3,552 | +72% | 0 | 0 | — |
case-19 | pass→pass | 8,475 | 9,119 | +8% | 1 | 1 | 0% | 1,408 | 4,130 | +193% | 0 | 0 | — |
case-20 | pass→pass | 12,237 | 12,543 | +3% | 1 | 1 | 0% | 1,861 | 5,022 | +170% | 0 | 0 | — |
case-21 | pass→pass | 27,179 | 43,284 | +59% | 1 | 1 | 0% | 5,734 | 9,832 | +71% | 0 | 0 | — |
case-22 | pass→pass | 20,263 | 23,489 | +16% | 1 | 1 | 0% | 4,072 | 7,522 | +85% | 0 | 0 | — |
case-23 | pass→pass | 20,466 | 23,352 | +14% | 1 | 1 | 0% | 3,999 | 7,579 | +90% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted. The headline lift of 0 percentage points is the difference between those two pass rates over the 23 comparable cases.
Other measured skills in the registry, with their headline benchmark lift.