A duckling learns to cross a pond the way a robot learns to walk: try something, get scored, nudge the habit. Run real policy-gradient and PPO updates in your browser, drag PPO's clip, and break a reward function on purpose. From REINFORCE to PPO in about 90 minutes of play.
Reinforcement learning is one loop. The agent does something, the environment answers with a new situation and a reward, and the agent wants as much reward as possible over time. Here the agent is a duckling and the reward is breadcrumbs. Every term with a wavy red underline is tappable.
Covers HF Deep RL Course, Unit 1: the RL framework, the reward hypothesis, discounting, episodic tasks
A narrow pond of 8 spots. Crumbs sit on the far bank (+20, and the crossing ends). Every paddle costs 1 crumb of effort. The current pushes the duckling the wrong way 15% of the time, and it gets 25 paddles before the day ends.
Now there are three ways across. A hugs the reeds: about 1 crumb, every time. B passes the bread boat: 2 crumbs on average, but wildly up and down. C goes through the mud: about 0.3. The duckling's habit is three numbers turned into probabilities (a softmax). REINFORCE updates it after every crossing: make the route just taken more likely, in proportion to the crumbs it brought. This is the real algorithm, running in your browser.
Covers HF Deep RL Course, Unit 4: policy-based methods, the policy gradient, REINFORCE (Monte Carlo policy gradient)
Freeze the habit at "no preference" (⅓ each). Each dot below is what one crossing says the push toward route B should be. They're all estimates of the same true push, the dashed line.
Mama Duck has watched a thousand crossings. She knows roughly what a crossing from here usually earns: that's the value V(s). Score each crossing as crumbs − Mama's guess, the advantage, instead of raw crumbs. Subtracting a baseline doesn't change which way the push points on average. It removes the part of every haul that would have happened anyway, so the noise drops.
Covers HF Deep RL Course, Unit 6: the variance problem, advantage actor-critic (A2C) · and the value functions and TD learning from Unit 2
Mama doesn't have to wait for the far bank. After a single paddle she can compare what happened with what she expected: the reward just earned plus her (discounted) guess from the new spot, minus her guess from the old spot. That's the TD error δ, her one-step surprise. Using her own guess for the rest of the crossing is called bootstrapping.
Crossings are expensive, so you'd like to learn several lessons from each batch of them. But every lesson moves the habit, and after a few the habit is no longer the one that collected the batch, so the batch starts lying. PPO measures the drift for each crossing as a ratio, r = πnew(route) ÷ πold(route), and puts lane ropes at 1 − ε and 1 + ε. Inside the ropes, learn freely. Outside, credit for going further stops, but undoing a mistake is always allowed.
Covers HF Deep RL Course, Unit 8: the intuition behind PPO, the clipped surrogate objective, visualizing the six cases
64 crossings are collected with a no-preference habit. Then PPO takes full-batch gradient steps on that same batch, one per epoch. Watch each route's ratio. With the ropes on, ratios mostly stop near the ropes; with them off, they keep going. "Mostly" matters: the clip removes the incentive to push further, it doesn't enforce a hard bound, so the other routes' still-active crossings can drag a clipped route past its rope (try a few new batches). That's why real PPO also watches how far each update moved, as KL divergence (step 6).
Now real PPO training: each round, collect 12 crossings with the current habit, then run K epochs on them. Sixty ducklings with ropes, sixty without, same luck. It's on-policy, so a duckling that stops choosing route B stops seeing B's crumbs, and rarely learns it was the best route. Watch the rounds play out: the damage is done early.
A real robot doesn't cross a pond in one go. Microduck collects a rollout of 24 steps from each simulated duck, then stops for an update. To score step 5 of those 24, you can use just Mama's one-step surprise (steady, but only as good as her guesses), or every real reward to the end of the slice (honest, but noisy), or something in between. GAE adds up Mama's surprises along the boardwalk, fading each later one by γλ.
gae_lambda=0.98 in Unit 1's PPO settings and as an uncommented loop in Unit 8's CleanRL code. Every real PPO uses it, Microduck's included. Source: Schulman et al., High-Dimensional Continuous Control Using Generalized Advantage Estimation (2016).Fills the gap between Unit 6 (the one-step TD advantage) and Unit 8 (PPO)
200 walks along the same boardwalk, each with noisy crumbs (±0.5 per plank), scored at plank 1. Low λ leans on Mama's guesses: little noise, but her mistakes go straight in. High λ sums real rewards: honest, but the noise piles up.
The algorithm is done. What decides whether a robot walks or does something silly is the reward function, a weighted list of terms. Here a toy robot duck can learn one of five behaviours. You write the scorecard; a policy-gradient learner then settles on whatever it pays most for. Nothing more, nothing less. That's reward hacking, and it isn't a bug.
AGENTS.md playbook.Not in the course · from the reward-design rules in pollen-robotics/microduck_rl's AGENTS.md
*_penalty) already returns negative numbers, so it needs a positive weight. Get it backwards and the penalty becomes a payment. The check that always works: in the training logs, every penalty must read ≤ 0.Episode_Reward/<term> for the behaviour it chosetrack_velocity (the reward for moving forward) to 0 and train. What does it learn?action_rate_l2 (a cost, returns positive numbers) at +0.5 instead of −0.5. It still learns to walk. Is everything fine?Episode_Reward/action_rate_l2 reads +5: you're paying it to be jerky, and it will get jerkier as training goes on. That's why the playbook's check is on the logs, not the video. Try it and watch the audit turn red.Microduck is an open-source ~800 g, 25 cm bipedal robot duck whose walking, standing-up and roller-skating policies are trained with PPO in simulation, then run on the real robot. Below is its actual training config. Every line is something from the pond. Click any setting.
From pollen-robotics/microduck_rl @ d424a0c · library behaviour checked in leggedrobotics/rsl_rl @ 857de61
The simulator's floor is never exactly the real floor. Toy version: the duck picks a balance gain and how cautious to be. Train it on one exact friction, or on a range (domain randomization), then set it down on a "real" floor.
Three training runs went wrong, each a real failure from Microduck's AGENTS.md playbook, where the rules were "each learned the hard way". Read the evidence, fix the scorecard, re-train, and say why it broke. A case passes only if the robot does the right thing and the fix is the right kind of fix.
Eight questions. Answer each by operating the widget in the step named, not from memory. Six or more earns the check.
Sources: the Hugging Face Deep RL Course (Units 1, 2, 4, 6, 8) · Schulman et al., GAE (2016) and PPO (2017) · pollen-robotics/microduck_rl and its AGENTS.md · leggedrobotics/rsl_rl. Further reading: Distill's Paths Perspective on Value Learning for TD vs Monte Carlo, and Lilian Weng's Reward Hacking in RL.