<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tony Yum</title>
    <description>The latest articles on DEV Community by Tony Yum (@kakuto-io).</description>
    <link>https://dev.to/kakuto-io</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1754352%2F38f687ee-f507-49f0-9a71-e7e97fafa390.png</url>
      <title>DEV Community: Tony Yum</title>
      <link>https://dev.to/kakuto-io</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kakuto-io"/>
    <language>en</language>
    <item>
      <title>How full is a fighter's brain? A network-size experiment</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Sat, 31 Oct 2026 04:15:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/how-full-is-a-fighters-brain-a-network-size-experiment-c7o</link>
      <guid>https://dev.to/kakuto-io/how-full-is-a-fighters-brain-a-network-size-experiment-c7o</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=RvK7Um3wfwk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8oqlhdhher24aokccl3s.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=RvK7Um3wfwk" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short.&lt;/strong&gt; The AI fighter’s whole repertoire, eighteen techniques plus walking, blocking and the dash, is one &lt;a href="https://ai.kakuto.io/en/glossary/neural-network/" rel="noopener noreferrer"&gt;neural network&lt;/a&gt; with two &lt;a href="https://ai.kakuto.io/en/glossary/hidden-layer/" rel="noopener noreferrer"&gt;hidden layers&lt;/a&gt; of 512 neurons: about half a million weights. Lately every new skill had cost an old one, which is what a full network looks like, but it is also what teachers pulling against each other look like. To tell the two apart I grew the network three ways, wider (1024 × 2), deeper (512 × 3) and both (1024 × 3), in a way that leaves its behaviour exactly as it was, and trained each for the same 200 million steps beside an unchanged 512 × 2 control. &lt;strong&gt;Closeness to the teachers:&lt;/strong&gt; the control improved by 7 % and flattened; the grown networks improved by 20 %, 24 % and 41 %, on every one of the sixteen teachers, and the largest was still improving at the end. By that measure the small network is at its &lt;a href="https://ai.kakuto.io/en/glossary/model-capacity/" rel="noopener noreferrer"&gt;capacity&lt;/a&gt;. &lt;strong&gt;Fight tests:&lt;/strong&gt; across 21 tests, none of the three bigger networks was clearly better or worse than the control on any of them. Closer to the teachers has not yet meant a better fighter. I kept the largest anyway, for the work that comes next.&lt;/p&gt;

&lt;h2&gt;
  
  
  A network that trades skills
&lt;/h2&gt;

&lt;p&gt;The fighter is a &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt;: fifty times a second it reads 465 numbers about its body, its balance and which technique button is pressed, and outputs 48, a target angle for every joint motor. One network, the &lt;em&gt;student&lt;/em&gt;, does everything on the &lt;a href="https://ai.kakuto.io/en/try/" rel="noopener noreferrer"&gt;try page&lt;/a&gt;. It learns by &lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;: for each technique there is a &lt;em&gt;teacher&lt;/em&gt;, a separate network trained on that one technique, and the student is trained to act like the right teacher whenever that technique runs, and like the base teacher (guard18, the stance, punches, walking and blocks) the rest of the time. In October that meant sixteen teachers poured into one student.&lt;/p&gt;

&lt;p&gt;The last few distillations had a pattern. distill12, the student before this experiment, came out with better blocks and kicks than the one before it, and worse knees (their gate score down from 11 to 8) and a worse left elbow (52 down to 49). Earlier students had shown the same kind of trade. A network that can only learn one thing by forgetting another is the textbook sign of a full one (&lt;a href="https://ai.kakuto.io/en/glossary/catastrophic-forgetting/" rel="noopener noreferrer"&gt;catastrophic forgetting&lt;/a&gt; is the extreme case). But there are at least two other explanations: the training budget (each run is a few hours; maybe the student just needed longer), and the teachers themselves, which were trained separately and can ask for incompatible things in similar situations.&lt;/p&gt;

&lt;p&gt;Neural networks don’t come with a gauge. There is no reading that says “83 % full”. So the question has to be answered by experiment: give the same student more room, change nothing else, and see whether it does better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Four networks, one starting point.&lt;/strong&gt; The obvious experiment, training a bigger network from scratch, would change two things at once: the size and everything the student had already learnt. Instead, every network started as &lt;em&gt;the same function&lt;/em&gt;: the kept student distill12-196.6M, grown by &lt;a href="https://ai.kakuto.io/en/glossary/function-preserving-growth/" rel="noopener noreferrer"&gt;function-preserving growth&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wider.&lt;/strong&gt; Each hidden layer gets 512 new neurons. Their incoming weights are random, like any new neuron’s; their outgoing weights are all zero. Whatever the new neurons compute, nothing downstream reads it yet, so the network’s outputs are exactly the old ones. Training then gives the new neurons a use. This is the widening of Net2Net (Chen et al., 2016), with zeros instead of a copy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deeper.&lt;/strong&gt; A new hidden layer is added just before the output. Its weights are the identity matrix and its bias is +1. The network’s &lt;a href="https://ai.kakuto.io/en/glossary/activation-function/" rel="noopener noreferrer"&gt;activation function&lt;/a&gt;, the ELU, is the identity for positive inputs, and the layer before always outputs more than −1, so after the +1 every input to the new layer is positive and passes through unchanged. The output layer’s bias subtracts the extra 1 again:
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-1.svg" alt="Two diagrams of weight matrices: on the left, three layers each with a trained block, new random rows below and new zero columns beside; on the right, a new identity layer inserted before the output" width="640" height="250"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. How the networks were grown, as weight matrices (rows are a layer's neurons, columns its inputs). Widening adds rows of random weights for the new neurons and columns of zeros where later layers would read them, so no output changes. Deepening inserts an identity layer with a bias of +1, and the output layer's bias takes the 1 back.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before launching, I checked this on the real student with 4096 random inputs: the widened policy’s outputs were identical to the original’s (largest difference 0.0), and the deepened one’s differed by 4 × 10⁻⁵, the size of floating-point rounding. Any difference between the four after training is therefore due to their size and nothing else.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fejh2lypyjy66jpepwhnn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fejh2lypyjy66jpepwhnn.webp" alt="A large dark glass panel in the white lab, a grid of neurons in two blocks lit blue and orange with dark unlit neurons around them, and a pale grey column between the blocks" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. A rendering of the grown brain at the moment it starts training. The left and right blocks are the two original layers, their 512 trained neurons recording the student's real activity; the new neurons around them are silent (dark). The pale column in the middle is a new layer that only mirrors what reaches it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A 2 × 2 design.&lt;/strong&gt; Width and depth were varied separately and together, so their effects can be told apart:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;network&lt;/th&gt;
&lt;th&gt;hidden layers&lt;/th&gt;
&lt;th&gt;policy parameters&lt;/th&gt;
&lt;th&gt;relative size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;512 × 2 (control, the original)&lt;/td&gt;
&lt;td&gt;2 of 512&lt;/td&gt;
&lt;td&gt;525,872&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 2 (wider)&lt;/td&gt;
&lt;td&gt;2 of 1024&lt;/td&gt;
&lt;td&gt;1,575,984&lt;/td&gt;
&lt;td&gt;3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;512 × 3 (deeper)&lt;/td&gt;
&lt;td&gt;3 of 512&lt;/td&gt;
&lt;td&gt;788,528&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 3 (both)&lt;/td&gt;
&lt;td&gt;3 of 1024&lt;/td&gt;
&lt;td&gt;2,625,584&lt;/td&gt;
&lt;td&gt;5.0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;(The critic, a second network of the same shape that estimates how well things are going, grows the same way and isn’t counted here.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The control&lt;/strong&gt; is the original network trained exactly like the others. It separates “more training helps” from “more room helps”: if the control improves as much as the grown networks, the student simply needed more steps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Equal steps.&lt;/strong&gt; Every network trained for exactly 200 million &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;environment steps&lt;/a&gt; with distill12’s settings unchanged: the same environments, the same sixteen teachers with the same weight, the same learning rate and the same mix of practice. A bigger network is slower per step, so equal steps means unequal hours; the cost is reported below rather than levelled out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two measures.&lt;/strong&gt; The first is how close the student gets to its teachers, logged throughout training for each teacher separately. The second is the &lt;a href="https://ai.kakuto.io/en/glossary/evaluation-gate/" rel="noopener noreferrer"&gt;gate&lt;/a&gt;, the same fight tests every candidate student goes through, on each network’s final checkpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Distance to the teachers
&lt;/h3&gt;

&lt;p&gt;During training, before every update, the trainer takes the states the student actually visited in its last &lt;a href="https://ai.kakuto.io/en/glossary/rollout/" rel="noopener noreferrer"&gt;rollouts&lt;/a&gt; and asks the teacher in charge of each state what it would have done. The distance is the &lt;a href="https://ai.kakuto.io/en/glossary/mean-squared-error/" rel="noopener noreferrer"&gt;mean squared difference&lt;/a&gt; between the student’s action and the teacher’s, averaged over the 48 joint commands, and kept separately per teacher:&lt;/p&gt;

&lt;p&gt;where  is the set of visited states in which teacher  is in charge,  the student’s action (the mean of its &lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;action distribution&lt;/a&gt;) and  the teacher’s. Measuring on the student’s own states matters: a student that drifts into situations its teachers never saw is judged there, not on the teachers’ home ground. Below, distances are multiplied by 1000.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result 1: bigger networks get closer to their teachers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-2.svg" alt="Line chart of the distance to the teachers against training steps for four networks: the 512 by 2 control flattens near 4.3, 1024 by 2 and 512 by 3 fall to about 3.7, 1024 by 3 falls to about 2.8" width="640" height="346"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. The mean distance to all sixteen teachers over training, each point averaged over 6.5 M steps. The 512 × 2 control (dashed) improves by 7 % and flattens. Wider (1024 × 2) and deeper (512 × 3) improve by 20 % and 24 %, close to each other. Both together (1024 × 3) improves by 41 % and is still falling at 200 M. Hover for the values.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;steps&lt;/th&gt;
&lt;th&gt;512 × 2&lt;/th&gt;
&lt;th&gt;1024 × 2&lt;/th&gt;
&lt;th&gt;512 × 3&lt;/th&gt;
&lt;th&gt;1024 × 3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0–25 M&lt;/td&gt;
&lt;td&gt;4.60&lt;/td&gt;
&lt;td&gt;4.66&lt;/td&gt;
&lt;td&gt;4.87&lt;/td&gt;
&lt;td&gt;4.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50–75 M&lt;/td&gt;
&lt;td&gt;4.48&lt;/td&gt;
&lt;td&gt;4.37&lt;/td&gt;
&lt;td&gt;4.42&lt;/td&gt;
&lt;td&gt;3.98&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100–125 M&lt;/td&gt;
&lt;td&gt;4.43&lt;/td&gt;
&lt;td&gt;4.03&lt;/td&gt;
&lt;td&gt;4.03&lt;/td&gt;
&lt;td&gt;3.33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;175–200 M&lt;/td&gt;
&lt;td&gt;4.28&lt;/td&gt;
&lt;td&gt;3.75&lt;/td&gt;
&lt;td&gt;3.71&lt;/td&gt;
&lt;td&gt;2.88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;−7 %&lt;/td&gt;
&lt;td&gt;−20 %&lt;/td&gt;
&lt;td&gt;−24 %&lt;/td&gt;
&lt;td&gt;−41 %&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Three things stand out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The control is near its limit.&lt;/strong&gt; With another 200 M steps of the same training, the original network improved by only 7 %, and its curve is close to flat by the end. More training alone would not have closed the gap.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Width and depth helped about equally, and together most.&lt;/strong&gt; 1024 × 2 has twice the parameters of 512 × 3 and ended in the same place (3.75 against 3.71). Per parameter, the extra layer was the better buy. The two together did better than either: 1024 × 3’s improvement (41 %) is close to the sum of the other two (20 % + 24 %).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The grown networks start slightly behind.&lt;/strong&gt; In the first 25 M steps the bigger networks are a little further from their teachers than the control (4.87–4.91 against 4.60), although they started as exactly the same function. The new weights are trained from their first update, and with the Adam optimiser, which scales each weight’s step to its own gradient history, the new ones move as fast as the old. That disturbs the inherited behaviour for a while before it pays off. This is my reading, not something I measured separately; it costs about 10–20 M steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-3.svg" alt="Dot plot of sixteen teacher groups, each with four dots for the four networks; the 1024 by 3 dot is to the left of the control's on every row, by 20 to 35 percent" width="640" height="394"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. Each teacher's distance over the last 25 M steps, for the four networks, sorted by the control's distance. The bar runs from the control to 1024 × 3; the right column is 1024 × 3's change against the control. Every teacher shows the same gap: 30–35 % for almost all of them, 20 % for the dash and 30 % for the base.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gap is everywhere.&lt;/strong&gt; If one or two teachers had been in conflict, the extra room would have helped those techniques and left the rest alone. Instead, 1024 × 3 is 30–35 % closer than the control on fifteen of the sixteen teachers, from the kicks, the hardest to imitate (distance 5–7), to the knees and the body straight (2–4). That includes the base, the stance, punches, walking and blocks that were in the network first (0.30 to 0.21). The dash, already the easiest after the base, improves the least (20 %). An even gap across every teacher is what a shortage of room looks like, not a quarrel between two teachers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Result 2: in the fight tests, no clear difference
&lt;/h2&gt;

&lt;p&gt;Distance to a teacher is a training measure. What matters is whether the fighter fights better, and that is what the gate tests: every technique at aim points in the air and at a heavy bag, with six random seeds; 120 punches; 40 walking goals; 32 blocks; 160 punches from the opponent to defend; punches at 60 set distances; the body straight. Each row counts successes out of a fixed number of tries, played without exploration noise.&lt;/p&gt;

&lt;p&gt;For each row I took the difference between a network’s success rate and the control’s, with a 95 % &lt;a href="https://ai.kakuto.io/en/glossary/confidence-interval/" rel="noopener noreferrer"&gt;confidence interval&lt;/a&gt; (the Agresti–Caffo interval, which behaves sensibly when a row is at 0 or at every try). Rows where all four networks scored the same, such as every kick in the air at 30 of 30, are left out: 21 rows remain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-4.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fnetwork-capacity%2Fchart-4.svg" alt="Forest plot of 21 gate rows, each a dot with a horizontal interval for the difference between 1024 by 3 and the control; all intervals cross the zero line" width="640" height="481"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The gate at 200 M steps: 1024 × 3's success rate minus the control's on each row, with its 95 % interval. Every interval crosses zero. The counts on the right are the control's and 1024 × 3's successes. A row with only 6 tries has an interval more than 60 points wide.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;against 512 × 2&lt;/th&gt;
&lt;th&gt;better&lt;/th&gt;
&lt;th&gt;worse&lt;/th&gt;
&lt;th&gt;tied&lt;/th&gt;
&lt;th&gt;clearly different&lt;/th&gt;
&lt;th&gt;sign test&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 2&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;1 (right uppercut at the bag, 3 → 11 of 54)&lt;/td&gt;
&lt;td&gt;p = 1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;512 × 3&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;p = 1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 3&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;p = 0.82&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Not one of the 1024 × 3 rows is clearly different from the control. It is ahead on the punches (61 against 56 of 120), the pull counter in the air (6 against 3 of 6) and the mid kicks and left low kick at the bag; it is behind on the blocks (24 against 26 of 32), the knees in the air, the right elbow and the left high kick in the air (23 against 30 of 36). Counting rows instead of looking at each, it is better on 8 and worse on 10: a &lt;a href="https://ai.kakuto.io/en/glossary/sign-test/" rel="noopener noreferrer"&gt;sign test&lt;/a&gt; gives p = 0.82, no evidence either way. The one “clear” row for 1024 × 2 is what chance alone would produce: with 21 rows and 95 % intervals, about one should fall outside by luck.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the two measures disagree
&lt;/h2&gt;

&lt;p&gt;A network 41 % closer to its teachers that fights no better needs explaining. Four reasons, from the most to the least certain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The gate can’t see differences this size.&lt;/strong&gt; Its rows have 6 to 160 tries. With 30 tries at a success rate near 70 %, a 95 % interval on a difference is about ±23 points wide; with 6 tries, more than ±50. To detect a real 10-point improvement on a single row with the usual 80 % &lt;a href="https://ai.kakuto.io/en/glossary/statistical-power/" rel="noopener noreferrer"&gt;power&lt;/a&gt; would take about 330 tries per network. The gate is built to catch a student that has broken something, which it does well, not to rank four students that are all good.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Squared distances exaggerate.&lt;/strong&gt; The distance is a mean of squares. Its square root, a typical size of the difference in one joint command, falls from 0.065 to 0.054, 18 %, not 41 %. Most of the gain is the bigger network matching the teachers’ larger, rarer actions better, and those may matter less to a hit than to the distance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The teachers are not perfect either.&lt;/strong&gt; The fight tests score the student’s &lt;em&gt;outcome&lt;/em&gt;: did the knee land within 5 cm at speed? A student that copies its teacher more closely inherits the teacher’s misses too. Once the student is close enough to land what its teacher lands, getting closer still adds little.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;200 M steps may be early.&lt;/strong&gt; 1024 × 3’s distance was still falling steeply when the run stopped. A capacity advantage might show in the fight tests only once the gap in closeness is larger still.&lt;/p&gt;

&lt;p&gt;So the honest summary is two-sided. The small network &lt;em&gt;is&lt;/em&gt; at its capacity: by the measure it is trained on, more training stopped helping and more room helped on every skill. Whether that capacity is what limits the fighter’s techniques today, the experiment cannot say. Within what the gate can resolve, it isn’t.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it cost and which machine
&lt;/h2&gt;

&lt;p&gt;Each network trained on its own rented RTX 5090 on vast.ai, all four at once. The bigger networks were slower per step, but much less than their size: the simulation of the body, not the network, takes most of each step.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;network&lt;/th&gt;
&lt;th&gt;steps per second&lt;/th&gt;
&lt;th&gt;hours for 200 M steps&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;512 × 2&lt;/td&gt;
&lt;td&gt;25,400&lt;/td&gt;
&lt;td&gt;2.19&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 2&lt;/td&gt;
&lt;td&gt;23,900&lt;/td&gt;
&lt;td&gt;2.33&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;512 × 3&lt;/td&gt;
&lt;td&gt;24,100&lt;/td&gt;
&lt;td&gt;2.30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1024 × 3&lt;/td&gt;
&lt;td&gt;21,900 (−14 %)&lt;/td&gt;
&lt;td&gt;2.54&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Five times the parameters cost 14 % in training speed. The gate is where the size shows: it runs the policy on ordinary CPUs, and 1024 × 3’s gate took 49 minutes on 12 cores, against 30–45 minutes for the others on 16–32. Seven more boxes were rented and never came up (no connection after 4 minutes, or still loading after 10); they were destroyed within minutes and are counted in the cost at the top. Every machine is listed in the work log below.&lt;/p&gt;

&lt;h2&gt;
  
  
  The decision
&lt;/h2&gt;

&lt;p&gt;I kept 1024 × 3, &lt;code&gt;cap1024x3-200.0M&lt;/code&gt;, as the parent of everything that follows. The rule I set before seeing the gate was simple: if nothing in it is clearly against the biggest network, take it. Nothing was. The reason is what comes next. The plan for the coming weeks adds to what this one network has to hold: aiming at a moving opponent, a queue for the next technique so strikes can be joined into combinations, and seeing where the opponent is. Each of those is new behaviour in the same weights. A network that has already shown it has room to spare on every current skill is the better place to put them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvsminq50hxgnnudwab01.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvsminq50hxgnnudwab01.webp" alt="The chrome robot fighter driving a rear knee in the white lab, a large panel on the wall with three columns of lit neurons" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6. The kept network, 1024 × 3, throwing a rear knee. Its brain panel is wider and has three columns, one per hidden layer, each neuron showing its real activity in this knee.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There were bigger changes on the table if size alone hadn’t been enough: a &lt;a href="https://ai.kakuto.io/en/glossary/mixture-of-experts/" rel="noopener noreferrer"&gt;mixture of experts&lt;/a&gt;, where a small network learns to blend several specialised ones (Peng et al., 2019), or a learned space of skills that a higher-level controller picks from (Peng et al., 2022). Both are much larger changes than adding neurons. This experiment says they aren’t needed yet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3iunxk6jhkqrvsm491el.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3iunxk6jhkqrvsm491el.webp" alt="Four chrome robot fighters standing in a row in the white lab, each with a neuron panel on the wall above it, the panels growing from a small square to a wide three-column grid" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7. The four networks side by side, each panel drawn to its network's size and showing that network's real activity while standing. (The four bodies all replay 1024 × 3's motion; standing, the four are hard to tell apart.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One run per network.&lt;/strong&gt; Each size was trained once. The curves are smooth and the gaps large compared to their wobble, so I trust the ordering of the distances; I can’t put an error bar on them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different machines.&lt;/strong&gt; The four runs were on four hosts (France, Norway, Vietnam, Canada). The steps-per-second figures mix network size with hardware.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Equal steps, not equal compute.&lt;/strong&gt; A fair comparison per hour would give the small network about 16 % more steps. Given how flat its curve was, that would not have closed a 33 % gap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Growth, not training from scratch.&lt;/strong&gt; The result says how much extra room helps a student that has already learnt. A network trained at 1024 × 3 from the beginning might end up elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I think, as a coach
&lt;/h2&gt;

&lt;p&gt;This experiment was one of several I asked to run in parallel on 31 October, before the bigger job of the week, the combo-aiming plan: “launch a bunch of steps that can run in parallel, for example … whether we need to increase the network size or more layers”. Before the fight tests came back I had already said “if nothing obviously against it, let’s go 1024x3”, and that is what happened.&lt;/p&gt;

&lt;p&gt;When I made the short film at the top of this page, I wanted it to open on the question I care about, “how do we know when the AI’s brain is full”, and to end on what the answer is for: now that the brain is ready for more training, more Muay Thai techniques are coming.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Agresti, A. and Caffo, B. (2000). Simple and effective confidence intervals for proportions and differences of proportions result from adding two successes and two failures. &lt;em&gt;The American Statistician&lt;/em&gt; 54(4).&lt;/li&gt;
&lt;li&gt;Chen, T., Goodfellow, I. and Shlens, J. (2016). Net2Net: accelerating learning via knowledge transfer. &lt;em&gt;ICLR&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Peng, X. B., Chang, M., Zhang, G., Abbeel, P. and Levine, S. (2019). MCP: learning composable hierarchical control with multiplicative compositional policies. &lt;em&gt;NeurIPS&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Peng, X. B., Guo, Y., Halper, L., Levine, S. and Fidler, S. (2022). ASE: large-scale reusable adversarial skill embeddings for physically simulated characters. &lt;em&gt;ACM Transactions on Graphics&lt;/em&gt; 41(4).&lt;/li&gt;
&lt;li&gt;Rusu, A. A. et al. (2016). Policy distillation. &lt;em&gt;ICLR&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The work logs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Work log&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;th&gt;Hours&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/network-size/" rel="noopener noreferrer"&gt;Students: the network-size experiment&lt;/a&gt;31 October 2026 · The student grown from 2 × 512 to 1024 × 2, 512 × 3 and 1024 × 3 without changing what it does, and trained beside a 512 × 2 control for 200 M steps each: the distances to the teachers, the gate, and the four boxes.&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;$7.65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;$7.65&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/network-capacity/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>neuralnetworks</category>
      <category>modelcapacity</category>
      <category>distillation</category>
      <category>student</category>
    </item>
    <item>
      <title>Torque and neural visualisation of Muay Thai techniques</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Thu, 29 Oct 2026 11:21:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/torque-and-neural-visualisation-of-muay-thai-techniques-22pg</link>
      <guid>https://dev.to/kakuto-io/torque-and-neural-visualisation-of-muay-thai-techniques-22pg</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=zlFXbthpXyg" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvri3miu951jcwtdl4zaj.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=zlFXbthpXyg" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz54stbbzievm7c2xhbv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwz54stbbzievm7c2xhbv.webp" alt="The chrome robot fighter in a right high kick, his kicking ankle and both toes glowing yellow at full torque, beside a telemetry panel: a heatmap of joint force over time and a raster of 512 neurons sorted by when they fire" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short.&lt;/strong&gt; The AI fighter’s brain is a small &lt;a href="https://ai.kakuto.io/en/glossary/neural-network/" rel="noopener noreferrer"&gt;neural network&lt;/a&gt;: 465 numbers in, two layers of 512 neurons, 48 joint commands out, 50 times a second. I recorded everything inside it, and every joint’s &lt;a href="https://ai.kakuto.io/en/glossary/torque/" rel="noopener noreferrer"&gt;torque&lt;/a&gt;, while it stood, took a 260 N shove from four directions, was knocked over by a 900 N one, and threw fourteen techniques. Then I drew the two side by side: the joints glow yellow with how hard their motor pushes, and a panel shows the neurons fire. &lt;strong&gt;Standing&lt;/strong&gt; , no neuron is far from its resting level. &lt;strong&gt;A shove&lt;/strong&gt; wakes 98–146 neurons within 0.16 s, and the fighter steps back into balance every time. &lt;strong&gt;The knockdown&lt;/strong&gt; : the network’s own forecast of how things will go halves 40 ms after the push; the body hits the floor 1.94 s later. &lt;strong&gt;A press&lt;/strong&gt; of a technique’s button lights 108–140 neurons on the very next tick, before the body has moved. &lt;strong&gt;Fingerprints&lt;/strong&gt; : a cross and a rear hook share 28 of their 40 most responsive neurons, a jab and a left high kick share 2. &lt;strong&gt;Force&lt;/strong&gt; : in almost every punch the busiest joints are the hips, not the arms; in the knees and kicks the feet take over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why look inside
&lt;/h2&gt;

&lt;p&gt;Every other post judges the fighter from the outside: did the punch land, did it fall, does it look like Muay Thai. On 29 October I asked for something different: a film that shows “how these neural networks are interpreted in terms of what techniques being used, which neurons activated”, because “seeing through the brain of the fighter actually helps our understanding of techniques”. I wanted the torques of the joints too, and to watch the brain react as the fighter goes from balance to being knocked over, gets hit from various directions and has to rebalance.&lt;/p&gt;

&lt;p&gt;Looking inside a trained network to see what its parts do is called &lt;a href="https://ai.kakuto.io/en/glossary/interpretability/" rel="noopener noreferrer"&gt;interpretability&lt;/a&gt;. This post is a first, simple pass at it: no new training, just one fighter, recorded carefully, and a way to draw what it does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The brain being looked at
&lt;/h2&gt;

&lt;p&gt;The fighter is the current student, distill9-196.6M: one &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; that has every technique on the &lt;a href="https://ai.kakuto.io/en/try/" rel="noopener noreferrer"&gt;try page&lt;/a&gt;, &lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;distilled&lt;/a&gt; from the teachers in earlier posts. Fifty times a second it reads its &lt;a href="https://ai.kakuto.io/en/glossary/observation/" rel="noopener noreferrer"&gt;observation&lt;/a&gt;, 465 numbers: the angles and speeds of its joints, how its body is moving, where its feet are, the phase of the stance’s rhythm, and which technique button is pressed. Those pass through two &lt;a href="https://ai.kakuto.io/en/glossary/hidden-layer/" rel="noopener noreferrer"&gt;hidden layers&lt;/a&gt; of 512 neurons each (an &lt;a href="https://ai.kakuto.io/en/glossary/mlp/" rel="noopener noreferrer"&gt;MLP&lt;/a&gt; with ELU activations) and come out as 48 numbers: a target angle for every joint’s &lt;a href="https://ai.kakuto.io/en/glossary/position-servo/" rel="noopener noreferrer"&gt;servo&lt;/a&gt;. A second network, the critic, reads the same 465 numbers and gives one: its &lt;a href="https://ai.kakuto.io/en/glossary/value-function/" rel="noopener noreferrer"&gt;estimate&lt;/a&gt; of how much reward the next few seconds will bring. In the pictures that is the &lt;strong&gt;forecast&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffzadyfkx0dmdukmlu0on.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffzadyfkx0dmdukmlu0on.webp" alt="A diagram of four columns of dots: 465 inputs, layer 1 with 512 neurons, layer 2 with 512 neurons and 48 commands, with some dots lit orange and blue" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The fighter's brain: 465 inputs, two layers of 512 neurons, 48 commands, one per joint motor, 50 times a second. The dots light up as a signal passes through; the lines are a sample of the connections (each layer has 512 × 512 of them).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two ways to look
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Joint force.&lt;/strong&gt; Each joint motor has a maximum torque, set so the fighter is no stronger than a person. Every physics step I recorded how hard each one pushed, as a percentage of its own maximum. A joint with several motors (the hip turns three ways) shows its strongest. On the body, each joint glows yellow with that percentage; in the panel’s heatmap each row is a joint and time runs left to right. A percentage of each motor’s own maximum is how close the joint is to its limit, not how much force it makes: the hip’s strongest motor has a maximum of 220 N·m, the elbow’s 90 and the toes’ 30.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Neurons.&lt;/strong&gt; For the second layer’s 512 neurons I first recorded three seconds of quiet standing, to learn each neuron’s resting level and how much it wanders. A neuron’s response at any moment is how far it is from rest, in units of its own wandering, a &lt;a href="https://ai.kakuto.io/en/glossary/z-score/" rel="noopener noreferrer"&gt;z-score&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;where  is the neuron’s output,  and  its mean and spread while standing (0.05 keeps a neuron that never moves from dividing by nearly zero). Over 3, I call it &lt;strong&gt;lit&lt;/strong&gt;. In the panel each neuron is a row, sorted by when it peaks, so a wave of activity reads as a diagonal sweep. Bright means far from rest.&lt;/p&gt;

&lt;p&gt;Every segment below started from the same reset, in the same stance, and was recorded once at 60 frames a second on the &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; simulation. The robot body is drawn in Blender over the simulated one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standing: never still
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkdtgc3xopwdv58fcflw4.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkdtgc3xopwdv58fcflw4.webp" alt="The fighter in his stance, hips glowing faintly, beside a calm joint heatmap and a neuron raster with no lit rows" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. The stance. The hips hold about a third of their strength (left 34 %, right 26 %) and the right knee 22 %. In the second layer, nothing is lit: the raster is the neurons' quiet wandering.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Standing is never still. The stance has a rhythm, a gentle bounce on the lead foot, and the legs carry the body’s weight through it, so the hips and knees are always working. The neurons hum but never stray: in the quiet seconds not one is lit.&lt;/p&gt;

&lt;h2&gt;
  
  
  A push from four sides
&lt;/h2&gt;

&lt;p&gt;Then a steel block hits the chest: 260 N for 0.16 s, from in front, from behind, from the left and from the right, each from a fresh start.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzxe63ilodlg5tfbrci9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnzxe63ilodlg5tfbrci9.webp" alt="The fighter stepping back after a steel block hit his chest, both hips glowing, with the neuron raster lighting up in a diagonal sweep after the push" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Shoved from the front, 1 s after the push. The left hip is at 85 % of its maximum, the right hip at 76 %. In the raster, a sweep of neurons lights up after the push line.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Within 0.16 s of the block landing, 98–146 neurons are lit, depending on the direction (front 98, behind 130, left 146, right 144); at their peak 161–174. Over the second after the push, both hips average 60–64 % of their maximum when pushed from the front, and three to five joints touch 95 % or more. The fighter steps and is balanced again every time.&lt;/p&gt;

&lt;p&gt;In all four the environment switched on &lt;strong&gt;survive mode&lt;/strong&gt;. It comes on when the body’s &lt;a href="https://ai.kakuto.io/en/glossary/capture-point/" rel="noopener noreferrer"&gt;capture point&lt;/a&gt;, where its momentum is carrying it, heads past the edge of its feet, and goes off once it is calm again. In survive mode the legs may move further from the stance and the only reward is staying up. The network sees the mode as one of its inputs; the &lt;a href="https://ai.kakuto.io/en/glossary/push-recovery/" rel="noopener noreferrer"&gt;recovery&lt;/a&gt; itself is learnt.&lt;/p&gt;

&lt;p&gt;Do different pushes use different neurons? For each direction I took the 40 neurons that responded most in the second after the push and counted how many each pair of directions share:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;behind&lt;/th&gt;
&lt;th&gt;left&lt;/th&gt;
&lt;th&gt;right&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;front&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;behind&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;left&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd926f0rvbe3f2rri96zo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd926f0rvbe3f2rri96zo.webp" alt="Four horizontal bands, one per push direction, each showing the 512 neurons' response; the bands for behind and left are lit in the same places" width="800" height="444"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The 512 second-layer neurons, grouped by the push they answer most; bright = strong. Pushes from the left and the right share only 16 of their 40 strongest neurons; from behind and from the left, 30.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Left and right are told apart most clearly, which makes sense: they need opposite answers. The surprise is that a push from behind and one from the left look almost the same to it. My guess, not something I measured: in its side-on stance, both tip it the same way, over its lead side. Nobody designed this map; it grew out of the millions of shoves in its training.&lt;/p&gt;

&lt;h2&gt;
  
  
  Knocked over
&lt;/h2&gt;

&lt;p&gt;The same push at 900 N is too big to hold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fay8id1yiqysbijpkxy1l.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fay8id1yiqysbijpkxy1l.webp" alt="The fighter falling backwards with his ankle and toes glowing, the forecast line in the panel already low" width="800" height="450"&gt;&lt;/a&gt; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmc5vvkiq78ypg58kboon.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmc5vvkiq78ypg58kboon.webp" alt="The fighter lying on the floor, toes still glowing, the forecast line at the bottom of its range" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 5. The 900 N push. Top: 0.45 s after it, falling, with the left ankle and toes at 100 %; the red forecast line at the bottom of the panel has already dropped. Below: on the floor 2.4 s after the push, still pushing with its toes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The forecast before the push is 555 (the reward it expects over its horizon). Two ticks after the push, 40 ms, it is already below half. It bottoms out at −92 a second later. The body hits the floor at 1.94 s. The network knew it would fall long before it did, and kept fighting anyway: 187 neurons lit at 0.16 s, nine joints at 95 % or more of their maximum. On the ground, it keeps trying.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pressing a technique
&lt;/h2&gt;

&lt;p&gt;A technique starts with a button: one of the 465 inputs flips from 0 to 1.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21277heh34xht4xtea1r.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F21277heh34xht4xtea1r.webp" alt="The fighter jabbing, hips glowing, with a burst of activity in the joint heatmap and neuron raster just after the press line" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6. A jab, 0.75 s after the press. The busiest joint is the left hip (44 % at this moment); 161 neurons are lit. The vertical line in both panels is the press.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the very next tick, 20 ms later, 108–140 neurons are lit, across all fourteen techniques, before the body has moved at all: the press itself is the cause, not anything the body felt. Then the wave spreads, peaking at 179–232 neurons: up to 45 % of the layer for one technique.&lt;/p&gt;

&lt;p&gt;Three techniques switched survive mode on for a moment: the rear hook, the switch knee and the pull counter. For a short time each of them put the capture point past the edge of the feet, so close to falling that the balance rules took over.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnelu92rz0y66kj4ezifd.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnelu92rz0y66kj4ezifd.webp" alt="The fighter coming forward out of a lean back, his right toes and ankle glowing, with a long diagonal sweep in the neuron raster" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7. The pull counter, 0.88 s after the press: lean back, then come forward with the counter. The right toes are at 97 %, the right ankle at 92 %.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Neural fingerprints
&lt;/h2&gt;

&lt;p&gt;Each push and technique leaves a pattern: every neuron’s average response over the second after it. I scaled each pattern to the same size (otherwise the loud techniques all look alike just for being loud), took away the average pattern, and compared each pair with &lt;a href="https://ai.kakuto.io/en/glossary/cosine-similarity/" rel="noopener noreferrer"&gt;cosine similarity&lt;/a&gt;: 1 for the same neurons in the same proportions, 0 for unrelated, negative for opposite.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitnfu2d40aqvtepcpdqx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fitnfu2d40aqvtepcpdqx.webp" alt="A 19 by 19 grid coloured red to blue, with a red block for the four pushes and another for jab, cross and the two hooks" width="800" height="673"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 8. How alike each pair of moves' neuron responses are: red = the same neurons, blue = different. The pushes form one block, the straight punches and hooks another; the uppercuts, elbows, knees and kicks each mostly stand alone.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The straight punches and hooks share much of their brain.&lt;/strong&gt; A cross and a rear hook: similarity 0.75, and 28 of their 40 most responsive neurons in common. Jab and cross 0.69 (23 of 40), the two hooks 26 of 40.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The pushes are a family of their own.&lt;/strong&gt; Behind and left are the most alike pair of anything: 0.93.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The rest are individuals.&lt;/strong&gt; A jab and a left high kick share 2 of 40. The two high kicks share 9, the rear and switch knees 11. Each knee and kick has neurons of its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A shared core.&lt;/strong&gt; Eleven neurons are in the top 60 of at least 70 % of the techniques: something every technique uses, whatever it is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The uppercuts don’t join the punches’ block: in the grid they sit with the elbows, knees and kicks, each mostly on its own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the force comes from
&lt;/h2&gt;

&lt;p&gt;The joints tell what each technique asks of the body. For each, the three joints that worked hardest on average in the second after the press:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxa522h9j60bzkurtz10r.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxa522h9j60bzkurtz10r.webp" alt="A table of fourteen techniques, each with its three hardest-working joints as labelled tags; left and right hips appear in most rows, toes and ankles in the knees and kicks" width="800" height="616"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 9. Each technique's three hardest-working joints: mean torque as a percentage of the joint's maximum, in the second after the press. Hips (and in the kicks, ankles and toes) dominate.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Punches:&lt;/strong&gt; the hips are the top two joints in every punch: the jab (left hip 56 %, right 54 %), the cross (61 %, 49 %), both hooks and both uppercuts. In the rear hook, the rear uppercut and the cross to the body the lower back is next (38–43 %). The arm joints never make the top three, apart from the lead hook’s shoulder girdle (29 %).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Knees and kicks:&lt;/strong&gt; the feet take over. The switch knee’s left toes 82 %; the right high kick’s toes 65–66 % on both feet and its right ankle 64 %; the left high kick’s left ankle 69 % and right hip 68 %. The standing foot works as hard as the kicking one: it is the only thing holding the body up.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What this does and doesn’t show
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;It shows what goes together, not what causes what.&lt;/strong&gt; A neuron that lights up during a hook might drive the hook, or only notice it. The next step is to switch neurons off, or hold them at rest, and see which techniques break.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One take each.&lt;/strong&gt; Every push and technique is one recording from one start. The counts would shift a little with another start, and with the threshold (3) I chose for “lit”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The second layer only.&lt;/strong&gt; The first layer and the critic’s own neurons aren’t drawn.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Percent of each motor’s own maximum.&lt;/strong&gt; Hips and ankles have far stronger motors than elbows, so the same percentage is not the same force.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No one told these neurons what to mean, or the fighter where a punch’s force should come from. Both were found by trial and error in training, and looking inside is a way to read them back out.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/torque-and-neural-visualisation/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>interpretability</category>
      <category>neurons</category>
      <category>torque</category>
      <category>balance</category>
    </item>
    <item>
      <title>Muscles instead of motors</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Wed, 28 Oct 2026 05:04:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/muscles-instead-of-motors-2fi7</link>
      <guid>https://dev.to/kakuto-io/muscles-instead-of-motors-2fi7</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=XC-ySXbsX_0" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqm62062s4p73gwm6pbey.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=XC-ySXbsX_0" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short.&lt;/strong&gt; Every fighter so far moves with a motor in each joint that drives it to a target angle. I asked what happens with muscles instead: pull-only, slow to switch on, weaker away from their best length, and stiff only when opposing muscles both work. Three stages, each learning the Muay Thai stance from scratch on a rented GPU, against the motor body on the same settings. &lt;strong&gt;Joint muscles&lt;/strong&gt; (86, one pair per joint): solved in 2.1–2.9 times the training steps. &lt;strong&gt;Real leg muscles&lt;/strong&gt; from MyoSuite on their anatomical paths (26 of them, then all 80): 2.6–3.9 and 4.9–5.8 times, once three fixes were in. The GPU simulation was no slower; all the extra is learning. Then &lt;strong&gt;the punches&lt;/strong&gt; : the motor body learnt them on its own (hits 4 % → 9 %), the muscle body never punched fast enough to score. Its arm muscles braked every punch: forced on, the jab reaches 8.6 m/s with the opposing muscles off and 3.0 m/s with them half on (a hit needs 3.5). Relaxing the arms fixed the braking, and the fighter landed its first muscle punch, then settled on slow punches that keep it on its feet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Motors in the joints
&lt;/h2&gt;

&lt;p&gt;The fighter in every other post is a &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; body with 43 moving joints, each with a motor. The motors are &lt;a href="https://ai.kakuto.io/en/glossary/position-servo/" rel="noopener noreferrer"&gt;position servos&lt;/a&gt;: the &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; gives each joint a target angle, as a correction to the &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt;, and the servo pushes the joint there. An action of zero already follows the reference. Holding a pose is the default; the policy only has to learn what to change.&lt;/p&gt;

&lt;p&gt;A real body works differently. A muscle can only pull, so every joint needs at least two working against each other. It doesn’t respond instantly: the nerve signal (the excitation) takes about 10 ms to switch it on and 40 ms to let it go. Its force depends on how stretched it is and how fast it is moving. And a joint is stiff only when the muscles on both sides of it pull at once. On 27 October I asked: if the fighter were driven by muscles, how much longer would training take, is it possible at all, and how much of the existing work could be reused?&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 1: a pair of muscles on every joint
&lt;/h2&gt;

&lt;p&gt;The cleanest first test changes only the drive. Same skeleton, masses, contacts, reference motions and rewards; each joint’s motor is replaced by two MuJoCo muscles, one pulling each way, as strong as the motor at their best length. That’s 86 muscles. MuJoCo’s muscles have the three properties that make muscle control hard: &lt;a href="https://ai.kakuto.io/en/glossary/muscle-activation/" rel="noopener noreferrer"&gt;activation&lt;/a&gt; that lags the command, a &lt;a href="https://ai.kakuto.io/en/glossary/force-length-velocity/" rel="noopener noreferrer"&gt;force that depends on length and speed&lt;/a&gt;, and pulling only. What this stage leaves out is anatomy: each muscle acts on one joint with a fixed lever.&lt;/p&gt;

&lt;p&gt;The policy now outputs one excitation per muscle (86 numbers instead of 43), and gets nothing for free: at zero, every muscle is at half excitation, which turns no joint and holds no posture. Left alone, the servo body stands for about 2 s on its servos; the muscle body folds in 0.6 s.&lt;/p&gt;

&lt;p&gt;Every run learnt the stance env from scratch: hold the stance, then sway with its rhythm, then take shoves, until it passes the trainer’s test (falls at most 5 % and nearly full-length episodes, over 20 iterations at the full rhythm). Each ran on one rented &lt;a href="https://ai.kakuto.io/en/glossary/gpu/" rel="noopener noreferrer"&gt;GPU&lt;/a&gt; (RunPod, RTX 4090 or 5090), simulating 1,024 fighters at once with &lt;a href="https://ai.kakuto.io/en/glossary/mujoco-warp/" rel="noopener noreferrer"&gt;MuJoCo Warp&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The muscles cost nothing on the GPU.&lt;/strong&gt; The muscle body simulated at 45.5k &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt; a second against the servo body’s 36.6k; the contacts dominate the cost, not the muscles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;On the servo body’s settings it never solved.&lt;/strong&gt; Two seeds plateaued at 7–9 % falls; one ran on and &lt;a href="https://ai.kakuto.io/en/glossary/training-divergence/" rel="noopener noreferrer"&gt;collapsed&lt;/a&gt; to 100 % falls at 185 M steps. No muscle was at full strength before any fall. The problem was timing: the policy’s actions pass through a &lt;a href="https://ai.kakuto.io/en/glossary/low-pass-filter/" rel="noopener noreferrer"&gt;smoothing filter&lt;/a&gt; that adds about 80 ms of lag, on top of the muscles’ own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With a lighter filter (about 20 ms) it solved&lt;/strong&gt;: 37.8 M and 26.6 M steps on two &lt;a href="https://ai.kakuto.io/en/glossary/random-seed/" rel="noopener noreferrer"&gt;seeds&lt;/a&gt;. The servo body on the same filter: 12.9 M and 12.7 M. &lt;strong&gt;2.1–2.9 times the steps&lt;/strong&gt; , seed for seed, and 1.8–2.6 times the time (10–15 minutes against 5–6).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A servo policy as a teacher&lt;/strong&gt; (its joint torques turned into target excitations) made the start 3–4 times faster, but once the teacher faded the run went back to the same plateau. It isn’t a substitute for learning on the muscle body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything except the trained models carried over unchanged: body, references, rewards, the GPU trainer, the cloud tooling, the evaluation tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 2: real leg muscles
&lt;/h2&gt;

&lt;p&gt;Joint muscles are a simplification. Real leg muscles run along paths over the bones, so their &lt;a href="https://ai.kakuto.io/en/glossary/moment-arm/" rel="noopener noreferrer"&gt;lever&lt;/a&gt; on a joint changes with the angle, and several cross two joints (the hamstrings bend the knee and extend the hip). I took the leg muscles of &lt;a href="https://ai.kakuto.io/en/glossary/myosuite/" rel="noopener noreferrer"&gt;MyoSuite&lt;/a&gt;, an open-source musculoskeletal model built for this kind of research, and mapped their &lt;a href="https://ai.kakuto.io/en/glossary/tendon-path/" rel="noopener noreferrer"&gt;paths&lt;/a&gt; onto the fighter’s legs, scaled to his bones. Stage 2a used MyoLeg26 (13 muscles a leg, 26 paths in all); 2b the full MyoLeg (40 a leg, wrapping round the bones). Everything above the hips kept stage 1’s joint pairs, so the full body was 96 and then 142 muscles. I checked every muscle’s lever arm against MyoSuite’s own model at every joint it crosses: within 2.2 cm everywhere, most within 1 cm.&lt;/p&gt;

&lt;p&gt;It took three fixes before the 2a body learnt the stance, and none of them was needed by the servo body.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A neutral zero action.&lt;/strong&gt; At half excitation, real leg muscles don’t cancel: the hip extensors, for one, are much stronger than the flexors, and the leg was pushed up to about 180 N m off the stance. From there the policy never found the stance at all: it stood tall and straight-legged with its arms out. I set each leg muscle’s resting excitation to the values that hold the still stance, so a zero action means “stand”, as it does for the servo body.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A cost for resting on joint limits.&lt;/strong&gt; With that, both seeds passed the trainer’s test, but in the wrong posture: the rear leg straight and swung back, the trunk bent to make up for it (Figure 1, middle). My first guess was a weak muscle: the stance turns the rear hip out 45°, where the hip abductors lose half their lever, in MyoSuite’s own models too. Making them 1.5 and 2 times stronger changed nothing, to the degree. The real cause: the rear leg was pressed against its hip and knee &lt;a href="https://ai.kakuto.io/en/glossary/range-of-motion/" rel="noopener noreferrer"&gt;joint limits&lt;/a&gt;, with its muscles idle. A straight leg on its limits is held up by the simulated bone, for free. The policy found that and kept it. A small cost for resting within 10° of a limit took the free support away: the rear knee went to 33–35° (the reference: 43°), and the servo body didn’t notice the cost at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Smaller policy updates.&lt;/strong&gt; In the right posture, the balance plateaued at 7–15 % falls and then collapsed. With a third of the &lt;a href="https://ai.kakuto.io/en/glossary/learning-rate/" rel="noopener noreferrer"&gt;learning rate&lt;/a&gt; and half the &lt;a href="https://ai.kakuto.io/en/glossary/ppo/" rel="noopener noreferrer"&gt;PPO&lt;/a&gt; passes over each batch, it solved within 6.6 M more steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsryba1o0ell0ogujhh3q.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsryba1o0ell0ogujhh3q.webp" alt="Five MuJoCo frames of the fighter in his Muay Thai stance: servo body, stage 1, stage 2a with a straight rear leg, stage 2a corrected, stage 2b" width="800" height="258"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The still stance after 3 s, deterministic policy, no shoves, seen from the fighter's left: the servo body (mbase-s0-11.7M), stage 1 (muscle1f-37.8M), stage 2a with its rear leg on its hip and knee limits (muscle2n-46.2M), stage 2a with the joint-limit cost (muscle2S-33.1M) and stage 2b (muscle2b-63.3M). The red lines on the legs of the last three are the muscle paths. Rendered in MuJoCo from the checkpoints.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With all three from the start, the 2a body solved from scratch in 33.1 M and 49.6 M steps, and the full 2b body in 63.3 M and 73.5 M, first time, with nothing body-specific added. Figure 2 puts the four bodies side by side.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-1.svg" alt="Bar chart: training steps to learn the stance and the multiple of the servo body, for the servo body, joint muscles, MyoLeg26 legs and the full MyoLeg" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Steps to pass the trainer's test, learning the stance from scratch; mean of two seeds, the range above each bar. All on the same action filter and reward; stages 2a and 2b also have the joint-limit cost and smaller PPO updates, which leave the servo body's result unchanged (12.3 M and 12.1 M steps). RunPod RTX 4090, 5090 and RTX PRO 6000 GPUs, 1,024 fighters at once.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So: &lt;strong&gt;possible, yes, at 2–6 times the training&lt;/strong&gt; , and the more anatomy, the more training. On wall time the muscle bodies took 10 to 37 minutes on one GPU against about 6 for the servos. The muscle stances are a little looser (pose score 0.86–0.89 against the servos’ 0.95), and stage 1’s held still more smoothly than the servos (0.04 joint reversals a second against 0.15).&lt;/p&gt;

&lt;h2&gt;
  
  
  Stage 3: the punches
&lt;/h2&gt;

&lt;p&gt;Standing is one thing; the point of the fighter is to fight. The punch env is the one the five punches (jab, cross, both hooks, the uppercut) were learnt in: punches pressed on command at targets in the air and at a heavy bag, with shoves in between. A punch counts as a hit when the fist passes within 5 cm of the target at 3.5 m/s or faster. Each body started from its own stance, on the same settings.&lt;/p&gt;

&lt;p&gt;The servo body learnt the punches without help: within 10 M steps the punch left the guard, and over 145 M steps its hits rose from 4 % to 9 % and its misses shrank from 25 to 10 cm, with under 3 % falls. The 2a muscle body never landed one. In the first runs its arm barely left the guard (misses of 51–68 cm), and the shoves took up the whole run.&lt;/p&gt;

&lt;h3&gt;
  
  
  A stretch reflex
&lt;/h3&gt;

&lt;p&gt;The servo body gets a rough punch for free: its targets follow the punch’s reference, so the arm goes out even before the policy has learnt anything. The muscle body has to find the punch from 96 excitations and the reward alone. In a person, the spinal cord does some of this work: a &lt;a href="https://ai.kakuto.io/en/glossary/stretch-reflex/" rel="noopener noreferrer"&gt;stretch reflex&lt;/a&gt; excites a muscle when it is stretched, which pulls a limb back toward where it was going. I gave each muscle one: extra excitation in proportion to how far it is stretched past its length at the target pose, plus a little for how fast. The arm came out at once (misses 28–31 cm, where the servo body started).&lt;/p&gt;

&lt;p&gt;It had to be there from the start, though. Switched on under a stance trained without it, the body fell in 97 % of episodes at first and 25–30 % after 30 M steps. A stance trained with the reflex from scratch solved in 56.0 M steps, with the tidiest pose of all (0.93), but three times the &lt;a href="https://ai.kakuto.io/en/glossary/jitter/" rel="noopener noreferrer"&gt;jitter&lt;/a&gt; (0.30 joint reversals a second against 0.10). The punches from that stance: still no hits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why it didn’t score
&lt;/h3&gt;

&lt;p&gt;Tested without exploration noise, the muscle fighter didn’t fall at all, and some punches came close: uppercuts 3–10 cm from the target, left hooks 10–16 cm. But its fist moved at 0.5–2.9 m/s. The servo body’s: 3 to 11. The punches weren’t short so much as slow.&lt;/p&gt;

&lt;p&gt;Recording the arm muscles through a jab showed why. Both muscles of the shoulder’s and the elbow’s pairs sat between 0.3 and 0.7 excitation the whole time: a lot of &lt;a href="https://ai.kakuto.io/en/glossary/co-contraction/" rel="noopener noreferrer"&gt;co-contraction&lt;/a&gt;. A muscle that is switched on while being stretched resists more than it can pull, so the opposing muscles were braking every punch. To check it was that and not a lack of strength, I forced the jab’s muscles (the shoulder’s forward muscle and the elbow’s straightener) fully on from the stance, &lt;a href="https://ai.kakuto.io/en/glossary/open-loop-control/" rel="noopener noreferrer"&gt;open loop&lt;/a&gt;, with everything else the same:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-2.svg" alt="Bar chart: peak fist speed with the opposing muscles off, 8.6 m/s, and at half, 3.0 m/s, against the 3.5 m/s a hit needs" width="640" height="144"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Peak fist speed when the jab's muscles are forced fully on from the stance, with the opposing muscles (shoulder back, elbow bend) switched off or held at half excitation, where the trained policy kept them. Stage 2a body with the reflex (jab3R at 19 M steps), CPU MuJoCo, 0.5 s. The dashed line is the speed a hit needs.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The body is strong enough: 8.6 m/s with the brakes off. With them at half, as the policy held them, 3.0 m/s, under what a hit needs. And the policy never learnt to switch them off: half excitation was the resting point of every arm muscle, and moving off it in the right muscles at the right moment is a lot to find by trial and error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relaxed arms
&lt;/h3&gt;

&lt;p&gt;So I changed the arms’ resting point: every arm muscle rests at 10 % instead of 50 %, with the policy’s action still covering the whole range from off to full on. That’s a different starting point, not a different body: the same muscles and strengths. The stance on it solved in 47.1 M steps (pose 0.92). In the punches, the opposing muscles now switch off (the reflex pushes them to zero while the punching muscle goes to full), and the fighter landed its &lt;strong&gt;first muscle-body hit&lt;/strong&gt; within 4 M steps: an uppercut at 4.3 m/s.&lt;/p&gt;

&lt;p&gt;Then it stopped improving. Within about 10 M steps the policy settled on slow punches that keep it on its feet (a &lt;a href="https://ai.kakuto.io/en/glossary/local-optimum/" rel="noopener noreferrer"&gt;local optimum&lt;/a&gt;), 1.5 m/s for the jab, and it stayed there for another 120 M steps (Figure 4). With &lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;exploration noise&lt;/a&gt; on, as in training, it fell in about a quarter of episodes even with the shoves at their weakest; without it, never. With a third of the noise, punches came out sooner (2 % hits early) but it fell in nearly every episode and never recovered. Fast punches knock this body over. The servo body’s legs absorb them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fmuscles-instead-of-motors%2Fchart-3.svg" alt="Paired bars at five points in training for the servo and muscle bodies: falls, hits and miss distance" width="640" height="504"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The punches on the servo body (jab3s, from its stance) and the muscle body with relaxed arms and the reflex (jab3A, from its stance), same punch env and settings, both on RunPod GPUs. Means over 10 M training steps, with exploration noise and shoves, as in training. The servo body improves throughout; the muscle body stays at about a quarter of episodes falling and almost no hits.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftko2gtqdhydz9zu1kmwz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftko2gtqdhydz9zu1kmwz.webp" alt="Two MuJoCo frames of a jab: the servo body with a straight arm, the muscle body with a bent arm" width="800" height="644"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The jab at its furthest reach, deterministic policy, no shoves: the servo body after 145 M steps of punch training (jab3s) and the relaxed-arm muscle body after 133 M (jab3A). The servo arm is straight and on the line; the muscle body keeps its elbow bent and its weight back. Rendered in MuJoCo from the final checkpoints.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I stopped there. The next steps are bigger pieces of work, not more steps: a teacher that shows the muscle arms the servo body’s punch, or a hit-speed bar that starts low and rises as the fighter gets better.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it means
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Possible: yes, for the stance.&lt;/strong&gt; A body with 142 muscles, real leg anatomy among them, learns the Muay Thai stance, its rhythm and shoves, from scratch, in under 40 minutes on one GPU.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;How much longer: 2–3 times with joint muscles, 5–6 times with the full leg&lt;/strong&gt; , measured against the servo body on the same settings. The simulation isn’t slower; the extra is all learning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What carries over:&lt;/strong&gt; everything except the trained models: the body, the references, the rewards, the training code and the tooling. A servo policy as a teacher helps only at the start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What a muscle body needs that a motor body doesn’t:&lt;/strong&gt; a resting point that holds the pose; a reason not to hang on its joint limits; smaller learning steps near its balance limit; for the arms, a resting point low enough to let them move fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What it hasn’t learnt: to punch fast and stay on its feet.&lt;/strong&gt; The servo body gets the punch’s shape for free and its legs absorb the swing; the muscle body has to find both. Its arms can move fast enough. Putting speed and balance together is the open problem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I think, as a coach
&lt;/h2&gt;

&lt;p&gt;My question was a simple one: if this fighter had muscles instead of motors, how much longer would he take to learn, could he learn at all, and how much of what we’ve built would still be useful? I let the experiment run on its own recommendations (“go with all your recommendation”), and from the second day I told it to make the decisions itself on a $50 budget and report back. I watched the videos of each new stance as they came in.&lt;/p&gt;

&lt;p&gt;So far we’ve used servo motors for the body because they’re convenient and quick to learn. But the goal really is to fight Muay Thai as a human. So it’s very important to understand how muscles move, and eventually the &lt;a href="https://ai.kakuto.io/en/glossary/metabolic-cost/" rel="noopener noreferrer"&gt;energy&lt;/a&gt; those movements cost.&lt;/p&gt;

&lt;p&gt;This is a very early experiment. It doesn’t cover all the techniques, and we didn’t try much on &lt;a href="https://ai.kakuto.io/en/glossary/muscle-redundancy/" rel="noopener noreferrer"&gt;redundancy&lt;/a&gt;, or on injury to muscles and &lt;a href="https://ai.kakuto.io/en/glossary/hyperextension/" rel="noopener noreferrer"&gt;hyperextension&lt;/a&gt;. Eventually we’ll do Brazilian Jiu-Jitsu, where a joint can be hyperextended and a ligament broken. So this is literally my first experiment in understanding how a servo robot translates to muscles and a more human-like structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work logs
&lt;/h2&gt;

&lt;p&gt;The runs behind this post, stage by stage. The costs are each RunPod pod’s billed hours times its hourly price, from the RunPod ledger, so they are estimates, not the bill. They include the short GPU checks that the simulation of each new body matched the CPU one.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Work log&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;th&gt;Hours&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/muscle-punches/" rel="noopener noreferrer"&gt;Muscles, stage 3: the punches&lt;/a&gt;28 October 2026 · The five punches on the muscle body, against the servo body on the same settings. The muscle body never punched fast enough to score; why, a stretch reflex and relaxed arms, and where it stopped.&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;$11.18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/muscle-legs/" rel="noopener noreferrer"&gt;Muscles, stage 2: real leg muscles&lt;/a&gt;27–28 October 2026 · MyoSuite's leg muscles on their real paths, mapped onto the fighter: 26 of them, then all 80. A torque-neutral zero action, a cost for resting on joint limits and smaller PPO updates got both to the stance.&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;6.1&lt;/td&gt;
&lt;td&gt;$9.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/muscle-body/" rel="noopener noreferrer"&gt;Muscles, stage 1: joint muscles instead of motors&lt;/a&gt;27 October 2026 · An experiment I asked for: drive the fighter with 86 joint muscles instead of servos, and measure how much longer the stance takes to learn, if it can be learnt at all.&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;4.9&lt;/td&gt;
&lt;td&gt;$5.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;$26.62&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/muscles-instead-of-motors/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muscles</category>
      <category>experiment</category>
      <category>biomechanics</category>
      <category>stance</category>
    </item>
    <item>
      <title>Correcting the knee</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Mon, 26 Oct 2026 12:43:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/correcting-the-knee-38hd</link>
      <guid>https://dev.to/kakuto-io/correcting-the-knee-38hd</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=tZD3fJeKg-M" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fki6qkplrom3std3hyb7c.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=tZD3fJeKg-M" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short.&lt;/strong&gt; Every new technique now starts as &lt;a href="https://ai.kakuto.io/en/glossary/motion-capture/" rel="noopener noreferrer"&gt;motion capture&lt;/a&gt; of me, filmed with two phones and reconstructed in 3D with open-source software on a GPU. It then goes through six more stages before the fighter can use it: retargeting onto the fighter’s body, a table of variations, a one-technique teacher, an evaluation gate, distillation into the student, and a final check. I review the result between every pair of stages, because each one can be wrong in a way its numbers don’t show. The second half of this post is one such case. The rear knee to the body passed every test: it landed, it didn’t fall, and it followed my motion. But after the knee came down the fighter arched backwards for about half a second. The reward allowed it; an opponent wouldn’t. A reference that returns to upright, plus a one-sided penalty on leaning back past it, reduced the lean past the reference from 12.4° to 1.3° in the air and from 9.7° to 0.9° at the bag. Every bag knee still landed and none fell. The fix survived distillation into the student: 1.4° and 1.2°.&lt;/p&gt;

&lt;h2&gt;
  
  
  From describing to capturing
&lt;/h2&gt;

&lt;p&gt;When I started, I taught the fighter the way I’d teach a beginner over the phone. I described the technique in words, sent photos of myself from a few angles, and corrected what I saw: tuck the elbow in more, stretch further, turn the hip. The &lt;a href="https://ai.kakuto.io/en/blog/learning-to-balance-in-a-muay-thai-stance/" rel="noopener noreferrer"&gt;stance and balance&lt;/a&gt; and &lt;a href="https://ai.kakuto.io/en/blog/teaching-the-jab/" rel="noopener noreferrer"&gt;the jab&lt;/a&gt; were built that way, as poses designed on the simulated body itself, and it worked well enough for them.&lt;/p&gt;

&lt;p&gt;It doesn’t work for bigger movements. A knee or a kick moves the whole body through large angles, quickly, and the order of events matters: which foot leaves the floor first, when the hips turn, where the arms go to balance. Describing all of that in words gets you something that moves, but not something that looks like Muay Thai. So I moved to motion capture.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pipeline
&lt;/h2&gt;

&lt;p&gt;I don’t use a commercial motion-capture system. Everything is open source, mainly Pose2Sim, which means the heavy parts can run on whatever GPU machine is cheapest. Figure 1 shows the stages. The purple ones end with me looking at the result before the next stage starts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Film&lt;/strong&gt; me, two phones&lt;/p&gt;

&lt;p&gt;A calibration board on the floor, photographed once from each phone's spot. Then the board is taken away and both phones film the technique at 60 fps from 60–90° apart, without moving.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;2&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;2D keypoints&lt;/strong&gt; GPU&lt;/p&gt;

&lt;p&gt;A pose estimator (RTMPose, with heels and toes) finds the joints in every frame of both videos: about two minutes for a 30-second take.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;3&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Sync and triangulate&lt;/strong&gt; GPU / CPU&lt;/p&gt;

&lt;p&gt;The two videos are lined up by their sound, each joint is triangulated in 3D from the two views, and the paths are smoothed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;4&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Fit my skeleton&lt;/strong&gt; CPU&lt;/p&gt;

&lt;p&gt;A skeleton scaled to my measurements is fitted to the 3D points, giving my joint angles frame by frame.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;5&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Retarget&lt;/strong&gt; CPU&lt;/p&gt;

&lt;p&gt;My joint directions and turns are moved onto the fighter's body, and a small inverse-kinematics step keeps planted feet planted.&lt;/p&gt;

&lt;p&gt;I check the sim beside my video, through each phone, frame by frame. I mark what's wrong and choose between copying me exactly and what works on his body.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;6&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Table of variations&lt;/strong&gt; CPU&lt;/p&gt;

&lt;p&gt;The technique is re-solved for targets a little higher, lower, left and right, so he can strike from wherever he is.&lt;/p&gt;

&lt;p&gt;I check the corners and the in-betweens, where knees twist and feet lift.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;7&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Teacher&lt;/strong&gt; rented GPU&lt;/p&gt;

&lt;p&gt;A copy of the latest model learns only this technique (plus its stance and balance) by reinforcement learning against the table.&lt;/p&gt;

&lt;p&gt;I check short progress clips sent to me through the day.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;8&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Gate&lt;/strong&gt; CPU boxes&lt;/p&gt;

&lt;p&gt;Deterministic tests: hits in the air and at the bag, falls, feet, facing, lean.&lt;/p&gt;

&lt;p&gt;I check the final video, slowed down.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;9&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Distil into the student&lt;/strong&gt; rented GPU&lt;/p&gt;

&lt;p&gt;One student learns every technique from its teacher while keeping all the old skills.&lt;/p&gt;

&lt;p&gt;I check the student's gate and videos. A fault here is fixed in the teacher, then distilled again.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1. From a filmed technique to a skill in the student. Turquoise steps run unattended; purple steps end with my review, and a technique goes back a step (or several) when I find something wrong. Steps 2–3 run on a GPU; steps 7 and 9 on rented GPUs (vast.ai or RunPod RTX 5090s, about 30,000 simulation steps a second).&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Filming and reconstruction
&lt;/h3&gt;

&lt;p&gt;Two phones see the same moment from two directions, so the depth of every joint is measured by &lt;a href="https://ai.kakuto.io/en/glossary/triangulation/" rel="noopener noreferrer"&gt;triangulation&lt;/a&gt; instead of guessed. My first attempt used one phone, guessed depth from bone lengths, and at one point put the legs the wrong way round in the stance while every picture-based check passed. For triangulation to work, each phone’s lens and position must be known exactly. That is &lt;a href="https://ai.kakuto.io/en/glossary/camera-calibration/" rel="noopener noreferrer"&gt;camera calibration&lt;/a&gt;, done with a printed board of known size on the floor.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://ai.kakuto.io/en/glossary/keypoint/" rel="noopener noreferrer"&gt;pose estimator&lt;/a&gt; finds my joints in each frame; Pose2Sim lines up the two videos, triangulates the joints, smooths them with a &lt;a href="https://ai.kakuto.io/en/glossary/low-pass-filter/" rel="noopener noreferrer"&gt;low-pass filter&lt;/a&gt; (12 Hz, not the 6 Hz default for walking, which would round off a kick), and fits a skeleton scaled to me using &lt;a href="https://ai.kakuto.io/en/glossary/inverse-kinematics/" rel="noopener noreferrer"&gt;inverse kinematics&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where it goes wrong
&lt;/h3&gt;

&lt;p&gt;The reconstruction is good, but not good enough to use without checking. The errors I’ve seen fall into three kinds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wrong estimates.&lt;/strong&gt; A foot judged to be below the floor gets pushed back up, and the body pops up and down for a few frames. A limb pointing straight at a camera collapses onto its joint; a sole facing a camera drags the knee onto the foot; left and right swap when the body turns side-on. In the knee take used below, for 0.06 s after the knee the reconstruction throws my pelvis back 26 cm and my rear foot jumps, so the end of the clip had to be replaced.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Different bodies.&lt;/strong&gt; The fighter’s legs are about 25 % longer than mine relative to his trunk. Copying my joint &lt;em&gt;positions&lt;/em&gt; folds his elbows into his head and bends his knees oddly, so &lt;a href="https://ai.kakuto.io/en/glossary/motion-retargeting/" rel="noopener noreferrer"&gt;retargeting&lt;/a&gt; copies directions and turns instead, and fixes only what has to touch something. Even then his body has limits mine doesn’t: I plant my rear foot about 31 cm behind my hips after the knee, past his hip’s range, so his lands 8 cm nearer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimates of what can’t be seen.&lt;/strong&gt; Forearm roll, wrists and collarbones aren’t visible to the cameras and are held at the stance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So step 5 is a review. I watch my video beside the simulated fighter rendered through each phone’s view, slowed down, and point out the differences. Each one is a choice: copy me more exactly, or accept a difference that works better on his body. The corrections go into a layer of eased offsets on named joints.&lt;/p&gt;

&lt;h3&gt;
  
  
  A table of variations
&lt;/h3&gt;

&lt;p&gt;A fighter can’t only strike from one recorded position, because in a fight he and his opponent are both moving. So each technique becomes a table: the same strike re-solved for a grid of targets a little higher, lower, left and right (for the kicks ±10 cm each way). In training the target can be anywhere inside the grid, and the &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt; is &lt;a href="https://ai.kakuto.io/en/glossary/interpolation/" rel="noopener noreferrer"&gt;interpolated&lt;/a&gt; between its nearest entries.&lt;/p&gt;

&lt;p&gt;A perfect reference can still produce bad entries in the table. In the low and mid kicks, the foot’s inverse kinematics flicked the knee inwards by about 40° over 4 frames during a switch hop. Nothing measured caught it; I saw it on the preview. So step 6 is another review.&lt;/p&gt;

&lt;h3&gt;
  
  
  Teacher, gate, student
&lt;/h3&gt;

&lt;p&gt;A teacher is a copy of the latest model that practises only this technique, with every episode a press of it and shoves in between to test balance. It learns by &lt;a href="https://ai.kakuto.io/en/glossary/reinforcement-learning/" rel="noopener noreferrer"&gt;reinforcement learning&lt;/a&gt; (&lt;a href="https://ai.kakuto.io/en/glossary/ppo/" rel="noopener noreferrer"&gt;PPO&lt;/a&gt;), rewarded for following the reference, for landing on the target, and for not falling. It doesn’t copy the reference exactly, and it can’t. The reference has no physics in it: my capture doesn’t know the bag pushes back, or that the fighter’s mass is spread differently from mine. A policy that copied it exactly would fall. During training the GPU box sends me short clips, and I watch them through the day.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://ai.kakuto.io/en/glossary/evaluation-gate/" rel="noopener noreferrer"&gt;gate&lt;/a&gt; then runs deterministic tests: knees in the air and at a heavy bag, six seeds each, with hits, falls, where the feet end, which way he faces and how far he leans. Teachers that pass are distilled into the student (&lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;, described in &lt;a href="https://ai.kakuto.io/en/blog/shadow-clones-learning-in-parallel/" rel="noopener noreferrer"&gt;the shadow-clones post&lt;/a&gt;). The student is checked again, because distillation is a second round of training and things can change in it.&lt;/p&gt;

&lt;p&gt;Even after all of that, the result can be wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  The case: the right knee
&lt;/h2&gt;

&lt;p&gt;The rear knee to the body comes from my take of 23 October: the lead foot steps in about 28 cm, the rear foot leaves the floor, the hips turn about 70° and the right knee drives up and forward into the opponent’s body, 1.14 m high at impact. The knee comes down, the rear foot lands ahead of where it left, and the fighter steps back into his stance. Its teacher took three runs (&lt;a href="https://ai.kakuto.io/en/worklog/knee-teachers/" rel="noopener noreferrer"&gt;work log&lt;/a&gt;): the first landed every knee but finished in a southpaw stance 0.6 m forward, the second fixed the feet, and the third, kneeR3, made the steps home. kneeR3 passed the gate: in the air 5/6, at the bag 6/6, feet back in the stance, no falls. It went into the student, distill4.&lt;/p&gt;

&lt;h3&gt;
  
  
  What the training objective allowed
&lt;/h3&gt;

&lt;p&gt;Leaving out the details, the teacher maximises, at each step ,&lt;/p&gt;

&lt;p&gt;following the reference, landing the knee (within 5 cm of the target and fast), keeping the feet where the reference has them, and not falling. None of these terms says anything about the shape of the trunk after the knee lands, as long as he doesn’t fall and the pose stays close enough to the reference.&lt;/p&gt;

&lt;p&gt;And close enough it was. After the impact, my capture leans back a little: my pelvis 5–9° back and my chest 10–16°, while my stance is near 0° and +1.5°. kneeR3 followed that lean and pushed it further, tipping his pelvis up to about 8° further back than the reference. He bent his lower back about 20° to keep his chest on the reference: hips forward, chest back. That’s an arch. Then he recovered, sometimes with a small hop, and stood in his stance again. Every term was satisfied.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why that is wrong
&lt;/h3&gt;

&lt;p&gt;I noticed it in the student’s video: “after the knee and the feet land back on the ground the fighter arches its back”. From a reward’s point of view this is a perfectly good knee. From a fighter’s point of view it isn’t. For the half-second he is arched, his hips are pushed forward and his shoulders hang back over them, his feet are busy catching him instead of being set, and he can’t step, block or strike back (Figures 4 and 5). That’s when an opponent hits him. The technique isn’t finished when the knee lands; it’s finished when he’s ready again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Measuring it
&lt;/h3&gt;

&lt;p&gt;To fix it I first needed a number for it. The &lt;a href="https://ai.kakuto.io/en/glossary/trunk-lean/" rel="noopener noreferrer"&gt;trunk lean&lt;/a&gt; of a body part is the angle of its “up” axis  along the direction the hips face on the floor, :&lt;/p&gt;

&lt;p&gt;computed for the pelvis and the chest. The gate’s new row is the most either one leans back &lt;em&gt;past the reference&lt;/em&gt; after the hit:&lt;/p&gt;

&lt;p&gt;where &lt;em&gt;+ = \max(x, 0), so leaning forward of the reference counts as zero, and &lt;/em&gt;{\text{up}} is the start of the upright window below. Against the corrected reference, kneeR3 scores  = 12.4° in the air and 9.7° at the bag.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fix
&lt;/h3&gt;

&lt;p&gt;Two changes, one to the target and one to the reward.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reference.&lt;/strong&gt; From 7.05 s of the capture, just after the hip thrust, to 7.35 s, the pelvis’s lean and the spine’s bend are eased to the stance’s and held there to the end. Before 7.05 s the reference is unchanged, including the impact at 6.933 s. I approved the preview before any training. This is one of those trade-offs between copying me and what works: my own lean back after a knee is small and I recover from it without thinking, but on his body, with the policy free to exaggerate it, it turned into an arch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A one-sided reward term.&lt;/strong&gt; After the hit window, every step pays&lt;/p&gt;

&lt;p&gt;where  is the weight the technique’s terms have at that moment. This is a &lt;a href="https://ai.kakuto.io/en/glossary/gaussian-kernel/" rel="noopener noreferrer"&gt;Gaussian kernel&lt;/a&gt; on the lean back past the reference: 1.5 when he’s at or forward of the reference, about 0.9 at 5° back, about 0.2 at 10° and almost nothing past 15°. Leaning forward is free, because leaning forward after a knee into the body is what a fighter does anyway.&lt;/p&gt;

&lt;p&gt;The new teacher, kneeR4, was &lt;a href="https://ai.kakuto.io/en/glossary/fine-tuning/" rel="noopener noreferrer"&gt;warm-started&lt;/a&gt; from kneeR3 on one rented RTX 5090 for its 2-hour cap (207.9 M &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt;, about $1.29). The lean dropped almost at once: by 13 M steps the bag row was down from 9.2° to 1.8°.&lt;/p&gt;

&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;Figure 2 shows the lean of the pelvis and the chest through one knee at the bag, step by step, before and after the fix, in the student. Each line is the median of six seeds and the band their range.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fcorrecting-the-knee%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fcorrecting-the-knee%2Fchart-1.svg" alt="Line chart: pelvis and chest lean in degrees against time after the press, before and after the fix, with the reference dashed" width="640" height="482"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Pelvis and chest lean through one rear knee at the heavy bag, in the student before the fix (distill4-131.1M, kneeR3's knee) and after it (distill7-245.8M, kneeR4's), time from the press, 50 steps a second; median of 6 seeds, band = their range; dashed = the corrected reference. Both lean far back at the impact: that is the hip thrust, and the reference does it too. The difference is after the landing. From about 0.9 s to 1.9 s the pelvis before the fix sits 12° behind his stance on average (20° at worst); after it, 5° (7° at worst). In his stance the pelvis tips about 10° forward; the reference holds it at 0° after its upright window, so after the fix he ends between the two.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The picture is the same in the air and for the teachers. Figure 3 compares the two numbers that matter for all four models, and the table has the rest of the gate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fcorrecting-the-knee%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fcorrecting-the-knee%2Fchart-2.svg" alt="Paired bars before and after the fix for teacher and student, in the air and at the bag: lean past the reference, and pelvis lean behind the stance" width="640" height="348"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Before and after the fix, teachers (kneeR3-183.5M, kneeR4-183.5M) and students (distill4-131.1M, distill7-245.8M), median of 6 seeds. Top: the gate's lean row, the most the pelvis or chest leans back past the reference after the upright window starts. Bottom: how far the pelvis sits behind his own stance, on average, from the end of the upright window until the knee's reference ends (about 0.9–1.9 s after the press).&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;model&lt;/th&gt;
&lt;th&gt;lean past reference, air / bag&lt;/th&gt;
&lt;th&gt;hits, air / bag&lt;/th&gt;
&lt;th&gt;falls&lt;/th&gt;
&lt;th&gt;feet at the end (lead, rear; stance 0.37, 0 m)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;kneeR3-183.5M (before)&lt;/td&gt;
&lt;td&gt;12.4° / 9.7°&lt;/td&gt;
&lt;td&gt;5/6, 6/6&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.42–0.44, −0.01–0.02&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;kneeR4-183.5M (after)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.3° / 0.9°&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0/6, 6/6&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.40–0.41, −0.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;distill4-131.1M (student before)&lt;/td&gt;
&lt;td&gt;11.4° / 10.7°&lt;/td&gt;
&lt;td&gt;in the gate: 11/12 overall&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;distill7-245.8M (student after)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.4° / 1.2°&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2/6, 6/6&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvrapd4000jck4y9j4oq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdvrapd4000jck4y9j4oq.webp" alt="Ten MuJoCo frames of the fighter after his rear knee, seen from behind his right shoulder in two rows: in the top row his hips push forward and his back arches; in the bottom row his trunk stays upright over his feet" width="800" height="538"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The student at the heavy bag, seed 1, seen from behind his right shoulder, with the camera turning with his hips, so the line of his back shows side-on: before the fix (top, distill4-131.1M) and after it (bottom, distill7-245.8M), 1.02, 1.14, 1.26, 1.38 and 1.50 s after the press, the rear foot just down. Before the fix the hips are pushed forward under a trunk that hangs back: the pelvis is tipped 7° and then 11° back in the first two frames and only reaches his stance by the fourth. After it the pelvis stays 4–6° forward the whole time and the trunk is stacked over the feet. Rendered in MuJoCo from the checkpoints, deterministic policy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The arch is the part I pointed at, but what worried me more was the balance. Seen straight from behind (Figure 5), the student before the fix spends the time after the landing catching himself with his feet. After the rear foot comes down it comes up again, 5–11 cm across the six seeds, where after the fix it rises 4–5 cm as he settles it. In seed 1 both feet are off their resting height at once for 0.44 s, a small hop to stay up. After the fix no seed does that. His &lt;a href="https://ai.kakuto.io/en/glossary/centre-of-mass/" rel="noopener noreferrer"&gt;centre of mass&lt;/a&gt; stays between his feet in both models, about two-thirds of the way from the rear foot to the lead foot, so he was never close to falling. He doesn’t fall, but he isn’t set either, and a fighter who isn’t set can’t fight.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2nmg64fefn3q0jyu8dwq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2nmg64fefn3q0jyu8dwq.webp" alt="Ten MuJoCo frames of the fighter after his rear knee, seen from straight behind in two rows: in the top row his feet keep shifting to catch his balance; in the bottom row both feet are planted" width="800" height="538"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The same knee, seed 1, seen from straight behind him, the camera again turning with his hips: before the fix (top, distill4-131.1M) and after it (bottom, distill7-245.8M), at the same five moments. Before the fix he is still catching himself after the landing: his rear foot comes back up 8 cm and his lead foot 6 cm, both at once for 0.44 s. After it the rear foot rises 4 cm as he settles it, the lead foot stays down, and he is back in his guard. Rendered in MuJoCo from the checkpoints, deterministic policy.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What the fix cost, and what it didn’t fix
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Knee hits in the air.&lt;/strong&gt; kneeR4 hits 0/6 in the air, where the kept kneeR3 snapshot hit 5/6. The fix may play a part, but the air row was unstable before it too: kneeR3’s later snapshots hit 2/6 and 0/6. The air test counts a hit only at 3 m/s within 5 cm of the target, a fist’s speed. The reference knee crosses the target plane at under 1 m/s, so a knee that follows my capture rarely counts. At the bag, which is three quarters of the presses and is scored by the push, every knee lands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hips’ bob.&lt;/strong&gt; The hips still rise and fall about 4–5 cm as he comes out of the knee, about the same before and after in the student. This was not the complaint, and the fix doesn’t target it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The stance mismatch.&lt;/strong&gt; The upright window brings the pelvis to the reference’s stance, which is about 10° more upright than the guard stance the base model actually stands in. The term only punishes leaning back past the reference, so he ends between the two (Figure 2). A cleaner fix would take the reference’s stance from the base model.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not every snapshot.&lt;/strong&gt; The fix holds across kneeR4’s snapshots (about 1–5° in the air, 0–1.8° at the bag), but the last one, at 206 M steps, leaned 10.8° in the air on one seed. 183.5 M was kept.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small samples.&lt;/strong&gt; Six seeds per row, deterministic. That’s enough to see a 10° effect clearly, and not enough to rank differences of a degree.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Into the student
&lt;/h3&gt;

&lt;p&gt;The fix was made in the teacher, not the student, because the student’s knee is only as good as the teacher it copies. distill7 was warm-started from distill4 and distilled again with kneeR4 as the knee’s teacher (along with two new uppercut teachers), on a RunPod RTX 5090 for 2.5 hours (&lt;a href="https://ai.kakuto.io/en/worklog/distillation-seven-and-eight/" rel="noopener noreferrer"&gt;work log&lt;/a&gt;). The distance between the student’s and kneeR4’s actions fell from 0.025 to 0.0027 (&lt;a href="https://ai.kakuto.io/en/glossary/mean-squared-error/" rel="noopener noreferrer"&gt;mean squared error&lt;/a&gt;). The student’s lean past the reference went from 11.4° / 10.7° to 1.4° / 1.2°, the same as the teacher, with no falls, the bag knees 6/6 and the old skills at about distill4’s level. I watched its videos and said: “Looks good.”&lt;/p&gt;

&lt;h2&gt;
  
  
  What I think, as a coach
&lt;/h2&gt;

&lt;p&gt;On paper, the knee was already good. The policy maximises the knee’s impact on the target, it’s punished if it falls, and it tries to follow my reference, but not exactly, because the physics is different: the bag’s weight, the recoil, his body against mine. If it copied me exactly it would fall over. So when it staggered back after the knee, arched a little and then recovered, that was perfectly fine by everything we had told it.&lt;/p&gt;

&lt;p&gt;But when I looked at it, all I could see was this: while he’s off balance, he’s going to get hit. In the gym, a knee you can’t recover from straight away is a bad knee, however hard it lands. Nobody counts that in a score; you just see it, the same way you see a fighter who drops his hands after a punch.&lt;/p&gt;

&lt;p&gt;That’s why I don’t trust any stage of this pipeline on its numbers alone. The motion capture can be wrong, the table can twist a knee, the teacher can find a way to satisfy every term and still look wrong, and the student can lose something in distillation. Every time, the fix has been the same: watch it, say what’s wrong in plain words, turn that into something the training can measure, and check again. The knee went from “fine according to all the policy” to something I’d be happy to see in the ring.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work logs
&lt;/h2&gt;

&lt;p&gt;The runs behind this post are in these work logs: the teacher that fixed the knee, and the evaluation and render boxes that made this post’s figures (EC2 spot, about ten minutes each, because my small development server is throttled on CPU). The earlier knee teachers and the student distill7 are counted in &lt;a href="https://ai.kakuto.io/en/blog/shadow-clones-learning-in-parallel/" rel="noopener noreferrer"&gt;the shadow-clones post&lt;/a&gt; and &lt;a href="https://ai.kakuto.io/en/worklog/distillation-seven-and-eight/" rel="noopener noreferrer"&gt;their own work log&lt;/a&gt;. The costs are each machine’s billed hours times its hourly price, from the vast.ai ledger and the EC2 spot price, so they are estimates, not the bill.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Work log&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;th&gt;Hours&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/knee-lean-figures/" rel="noopener noreferrer"&gt;Evaluation: the rear knee's lean, step by step&lt;/a&gt;28 October 2026 · Four short EC2 boxes that traced the trunk's lean through the rear knee, before and after the upright fix, and rendered the stills for the post.&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;$0.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/rear-knee-upright/" rel="noopener noreferrer"&gt;Teacher: the rear knee, landing upright&lt;/a&gt;26 October 2026 · One more rear-knee teacher, so the knee lands upright instead of arched back.&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2.1&lt;/td&gt;
&lt;td&gt;$1.29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2.5&lt;/td&gt;
&lt;td&gt;$1.40&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/correcting-the-knee/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>motioncapture</category>
      <category>knees</category>
      <category>rewarddesign</category>
    </item>
    <item>
      <title>Shadow clones: four Muay Thai techniques learnt in parallel</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Sat, 24 Oct 2026 20:30:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/shadow-clones-four-muay-thai-techniques-learnt-in-parallel-1gn9</link>
      <guid>https://dev.to/kakuto-io/shadow-clones-four-muay-thai-techniques-learnt-in-parallel-1gn9</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=aA3SIhCX-w0" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fy05kof08qrjzwgzjuhdm.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=aA3SIhCX-w0" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In short.&lt;/strong&gt; Each new technique is trained in its own copy of the latest model, a &lt;em&gt;teacher&lt;/em&gt;, on its own rented GPU. A teacher only has to learn its technique and keep the stance and balance. The teachers that pass are then distilled into one &lt;em&gt;student&lt;/em&gt;: it keeps training with &lt;a href="https://ai.kakuto.io/en/glossary/ppo/" rel="noopener noreferrer"&gt;PPO&lt;/a&gt;, and is also pulled towards whichever teacher owns the technique it is doing at that moment. Four teachers passed: the rear straight to the body, the rear knee, the switch knee and the pull counter. The kept student, distill4-131.1M, has the first three and still has every earlier skill. The pull counter only half came back. Several clones finished training, scored well on the numbers and were still wrong, because of the motion they were copying or because of how training rewarded them. This post covers about $80 of training in eight work logs. It is the first part of a longer story.&lt;/p&gt;

&lt;p&gt;This post is written in the first person. Earlier posts talked about “Tony” and “the coach”. From now on it’s just me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Naruto idea
&lt;/h2&gt;

&lt;p&gt;In &lt;em&gt;Naruto Shippuden&lt;/em&gt; there is a scene I kept thinking about while planning this. Naruto has to master a technique in far less time than it should take. Kakashi’s solution is the shadow clone. Naruto makes a crowd of copies of himself, they all train at once, and when a clone is dispelled, everything it learnt goes back to the original. A week of practice fits into a day. There is a catch: the clones’ fatigue comes back too.&lt;/p&gt;

&lt;p&gt;That is how I wanted to add techniques to the fighter. Until now every new skill was &lt;a href="https://ai.kakuto.io/en/glossary/fine-tuning/" rel="noopener noreferrer"&gt;fine-tuned&lt;/a&gt; into one model, one after another, with the older skills held in place by a teacher. Each new technique waited for the one before it, and each one risked the others (&lt;a href="https://ai.kakuto.io/en/glossary/catastrophic-forgetting/" rel="noopener noreferrer"&gt;catastrophic forgetting&lt;/a&gt;). Training techniques separately is close to &lt;a href="https://ai.kakuto.io/en/glossary/embarrassingly-parallel/" rel="noopener noreferrer"&gt;embarrassingly parallel&lt;/a&gt;. A knee doesn’t need to wait for a body straight, so they can run on different machines at the same time.&lt;/p&gt;

&lt;p&gt;So the plan was:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take the latest model (the &lt;em&gt;base&lt;/em&gt;) and make a clone of it for each new technique.&lt;/li&gt;
&lt;li&gt;Train each clone on its own rented GPU. It only has to learn its technique and keep the stance and balance: “all it needs to know is the stance and the balance and just the specific technique”.&lt;/li&gt;
&lt;li&gt;Bring the experience back: distil the clones that pass into one student, which keeps everything the base could do.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fshadow-clones-learning-in-parallel%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fshadow-clones-learning-in-parallel%2Fchart-1.svg" alt="Diagram: the base model fans out into one-technique teachers on separate GPUs; the passing teachers feed back into one student model" width="640" height="298"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. Parallel training as shadow clones. The base (guard18-124.5M, every earlier skill on the new high guard) is copied into one-technique teachers. Each trains on its own rented GPU (vast.ai RTX 5090, or RunPod for the pull counter and the uppercuts). The four that passed (solid) were distilled back into the student. Dashed: clones that finished training and were judged failures, or are not distilled yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The rest of this post describes how a clone is made, how the experience is brought back, and what went wrong. Every run is in the &lt;a href="https://ai.kakuto.io/en/blog/shadow-clones-learning-in-parallel/#the-work-logs" rel="noopener noreferrer"&gt;work logs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making a clone: the one-technique teacher
&lt;/h2&gt;

&lt;p&gt;A teacher starts as a copy of the base: a &lt;a href="https://ai.kakuto.io/en/glossary/mlp/" rel="noopener noreferrer"&gt;multi-layer perceptron&lt;/a&gt; with two hidden layers of 512 units. It reads 448 &lt;a href="https://ai.kakuto.io/en/glossary/observation/" rel="noopener noreferrer"&gt;inputs&lt;/a&gt; and drives 48 motor outputs. Three things turn the copy into a teacher.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A new input, added without changing the network.&lt;/strong&gt; Each technique gets its own input, “this technique is running”, placed just before the last input (which is the balance gate). The new input’s weights into the first layer start at zero. If  is the first layer’s weight matrix, its columns are split as  and the grown network uses&lt;/p&gt;

&lt;p&gt;so on the first step the grown network behaves exactly like the base (&lt;a href="https://ai.kakuto.io/en/glossary/function-preserving-growth/" rel="noopener noreferrer"&gt;function-preserving growth&lt;/a&gt;). It can only start using the input through training. Every teacher reads the same input layout the final student will have, so the student can later learn from all of them on the same observations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practice only that technique.&lt;/strong&gt; Every &lt;a href="https://ai.kakuto.io/en/glossary/episode/" rel="noopener noreferrer"&gt;episode&lt;/a&gt; is a punch episode, and every press is the teacher’s technique, with shoves in between so the balance is still tested.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The parent holds everything else.&lt;/strong&gt; A frozen copy of the base stays on as a teacher everywhere except while the new technique runs (see &lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;). The teacher is free to change its motion during the technique, and is pulled back to the base’s behaviour the rest of the time. That keeps the stance and the recovery from shoves, which the technique has to start from and end in.&lt;/p&gt;

&lt;p&gt;Each technique’s motion comes from my own &lt;a href="https://ai.kakuto.io/en/glossary/motion-capture/" rel="noopener noreferrer"&gt;motion capture&lt;/a&gt;, the &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt; the teacher is rewarded for following. For example, the rear straight to the body is a 1.45 s window of one of my takes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the clones side by side
&lt;/h2&gt;

&lt;p&gt;The trainer runs on one GPU: 2,048 copies of the world (&lt;a href="https://ai.kakuto.io/en/glossary/parallel-environments/" rel="noopener noreferrer"&gt;parallel environments&lt;/a&gt;) for 16 steps each, 32,768 &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt; per iteration. On a rented RTX 5090 that is about 25,000 to 34,000 steps a second. Each clone gets its own machine. Two knee teachers trained side by side, then their fixes ran side by side. Four evasion teachers started within a minute of each other. Two uppercut teachers ran on two RunPod machines at once.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;technique&lt;/th&gt;
&lt;th&gt;teacher kept&lt;/th&gt;
&lt;th&gt;runs&lt;/th&gt;
&lt;th&gt;from the parent&lt;/th&gt;
&lt;th&gt;what it took&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;rear straight to the body&lt;/td&gt;
&lt;td&gt;bodycross4-118.0M&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;guard14 (guard18 holding the rest in the last run)&lt;/td&gt;
&lt;td&gt;a “no low blows” line, the bag moved to the impact point, then retrained on the base’s slower elbows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;rear knee&lt;/td&gt;
&lt;td&gt;kneeR3-183.5M&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;guard14&lt;/td&gt;
&lt;td&gt;the feet kept where the capture has them, then the steps home at the capture’s pace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;switch knee&lt;/td&gt;
&lt;td&gt;kneeL3-214.0M&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;guard14&lt;/td&gt;
&lt;td&gt;the same&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pull counter&lt;/td&gt;
&lt;td&gt;pull1-209.7M&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;distill1-282.5M&lt;/td&gt;
&lt;td&gt;8/8 in the air and 8/8 at the bag, first try&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Training each teacher takes about two hours. Most of the time and money goes into the fixes: several short runs, each warm-started from the last good &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt; with one change. Because the clones are independent, a failed fix on one technique costs nothing on the others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bringing the experience back: distillation
&lt;/h2&gt;

&lt;p&gt;The student starts as the base, grown to read every teacher’s input. It keeps training on the full mix of episodes (punches, blocks, walking, the opponent, shoves and the new techniques). Its &lt;a href="https://ai.kakuto.io/en/glossary/loss-function/" rel="noopener noreferrer"&gt;loss&lt;/a&gt; is PPO’s plus a pull towards the right teacher.&lt;/p&gt;

&lt;p&gt;The student’s &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; is a Gaussian,  (see &lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;stochastic policy&lt;/a&gt;). There are  technique teachers  plus the base . Each state is routed to one of them by its inputs:&lt;/p&gt;

&lt;p&gt;and every minibatch  of the student’s own experience is trained on&lt;/p&gt;

&lt;p&gt;The first three terms are the usual PPO training: the clipped policy objective, the &lt;a href="https://ai.kakuto.io/en/glossary/value-function/" rel="noopener noreferrer"&gt;value&lt;/a&gt; error and a smoothness penalty on the actions (&lt;a href="https://ai.kakuto.io/en/glossary/caps-regularisation/" rel="noopener noreferrer"&gt;CAPS&lt;/a&gt;). The last is a &lt;a href="https://ai.kakuto.io/en/glossary/mean-squared-error/" rel="noopener noreferrer"&gt;squared error&lt;/a&gt; between the student’s mean action and the routed teacher’s mean action, with weight  (2 in the first runs, 4 in the kept one). A few details matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The states are the student’s own.&lt;/strong&gt; The teachers label the states the student actually visits (&lt;a href="https://ai.kakuto.io/en/glossary/on-policy/" rel="noopener noreferrer"&gt;on-policy&lt;/a&gt;), not states from their own runs. Copying a teacher from its own recordings (&lt;a href="https://ai.kakuto.io/en/glossary/behaviour-cloning/" rel="noopener noreferrer"&gt;behaviour cloning&lt;/a&gt;) breaks down once the student drifts off the teacher’s path, because it has never seen those states (&lt;a href="https://ai.kakuto.io/en/glossary/covariate-shift/" rel="noopener noreferrer"&gt;covariate shift&lt;/a&gt;). Asking the teacher what it would do in the student’s states is the DAgger fix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each teacher sees what it was trained on.&lt;/strong&gt; A teacher reads its own slice of the inputs, normalised with its own running statistics. An earlier bug, a teacher seeing inputs scaled by the student’s statistics, had made its advice slightly wrong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The rewards stay on.&lt;/strong&gt; The student still earns every task reward, so it can’t just copy a teacher into a fall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One mean, many teachers.&lt;/strong&gt; Exactly one teacher is in charge of each state, so the targets never conflict. The student has to fit all of them in one network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trainer logs one number per teacher to watch: the student’s mean squared error against that teacher’s action means, over the states routed to it, before each update. If the error stalls high on the new techniques while the base’s stays low, the network has run out of room (&lt;a href="https://ai.kakuto.io/en/glossary/model-capacity/" rel="noopener noreferrer"&gt;capacity&lt;/a&gt;), and I would widen it. It never stalled. In the first run the base’s error stayed at 0.002 throughout. The body straight fell from 0.028 to 0.005 by 39 M steps, the rear knee from 0.054 to 0.007 and the switch knee from 0.059 to 0.008. They were still falling when the run ended at 282.5 M. Three techniques fit in 512 units with room to spare.&lt;/p&gt;

&lt;h2&gt;
  
  
  What came back
&lt;/h2&gt;

&lt;p&gt;Every candidate is judged by the &lt;a href="https://ai.kakuto.io/en/glossary/evaluation-gate/" rel="noopener noreferrer"&gt;gate&lt;/a&gt;: deterministic tests of every skill, the old ones and the new ones. Six distillation runs went through it. Figure 2 compares the base with three students, and the table has the full rows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fshadow-clones-learning-in-parallel%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fshadow-clones-learning-in-parallel%2Fchart-2.svg" alt="Gate scores for guard18, distill1, distill2 and distill4: punch presses landed, opponent punches handled, new techniques landed" width="640" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. The gate for the base (guard18-124.5M) and three students (new techniques: – where the gate had no row for them). distill1 has both knees but not the body straight (its teacher was trained on faster elbows than the base's). distill2 adds the body straight from the retrained teacher but loses the cross in the air. distill4 (kept, at 131.1 M steps) has all three new techniques and is at or above the base on punches, walking, the opponent and distances. It is 3 short on blocks.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;punches /120&lt;/th&gt;
&lt;th&gt;cross in the air /12&lt;/th&gt;
&lt;th&gt;walk /40&lt;/th&gt;
&lt;th&gt;blocks /32&lt;/th&gt;
&lt;th&gt;opponent /160&lt;/th&gt;
&lt;th&gt;distances /60&lt;/th&gt;
&lt;th&gt;body straight /24&lt;/th&gt;
&lt;th&gt;knees R, L /12&lt;/th&gt;
&lt;th&gt;falls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;guard18 (base)&lt;/td&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;–&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;distill1 282.5 M&lt;/td&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;(not in yet)&lt;/td&gt;
&lt;td&gt;6/8, 5/8 at 40 M&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;distill2 52.4 M&lt;/td&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;122&lt;/td&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;10, 12&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;distill4 131.1 M&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;60&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;39&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;11, 9&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ox7d60vsiwc53xc80wq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ox7d60vsiwc53xc80wq.webp" alt="Three MuJoCo frames of the muscular fighter at a heavy bag: a rear straight to the body, a rear knee driven up into the bag, and a switch knee into the bag" width="800" height="267"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. The kept student, distill4-131.1M, throwing the three techniques it learnt from its clones, each at the heavy bag at the moment of impact, seen from its right side: the rear straight to the body (left), the rear knee (middle) and the switch knee (right). Rendered in MuJoCo from the checkpoint, deterministic policy.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The student was picked from snapshots, not from the end of the run. The training averages hardly moved, but the deterministic gate swung from one snapshot to the next (blocks between 21 and 29 in distill3). distill4’s five snapshots were all gated, and the one at 131.1 M was kept. What made distill4 better than distill2 was a stronger pull ( from 2 to 4) and more practice for the cross. That brought the cross in the air back, from 0/12 to the base’s 3/12, and tightened every teacher’s match. The cost is 3 blocks, and putting the block share back (distill5) didn’t recover them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Not everything comes back
&lt;/h2&gt;

&lt;p&gt;distill6 added the fourth teacher, the pull counter (lean back, then a rear straight to the head). The teacher hits it 8/8 in the air and 8/8 at the bag. The student learnt it at the bag (6/6) but not in the air (1–2/6, about 10 cm short), and none of its snapshots beat distill4 overall. So for now the pull counter lives in its clone, not in the fighter. The next distillation gives it more presses and a stronger pull.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6n7pgryk8wg7oxuqi0zz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6n7pgryk8wg7oxuqi0zz.webp" alt="Two MuJoCo frames of the fighter: leaning back with the right fist drawn back, then driving a right straight into the top of the heavy bag" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The pull-counter teacher, pull1-209.7M, at the heavy bag: the lean back away from the punch with the rear fist wound back (left), then the rear straight to the head (right). This one lives in its clone for now: the student learnt it only at the bag.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It is a reminder that distillation is not like Naruto dispelling a clone. The experience doesn’t arrive whole. It has to be trained in, alongside everything else the student must keep, and where two skills compete for the same output the result is a trade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Clones that finished and were still wrong
&lt;/h2&gt;

&lt;p&gt;The worse surprise was clones that finished training, passed or nearly passed the gate, and were wrong when I watched them. The gate says a technique landed. It doesn’t say the technique looked like the one I asked for. These are the main cases. The details, with the numbers, are in the work logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The reference.&lt;/strong&gt; The evasion teachers (slips, rolls, lean back) learnt from my motion capture, but they ran it up to twice as fast. The punch clock, which lets the policy speed up a punch, had been built for punches and was still on for these. A roll squeezed that much becomes a drop. When I asked for a wider, U-shaped head path and the reference itself was widened, the trunk bent sideways to reach it, and the teachers learnt the bend. Every roll and lean-back teacher was judged a failure on video. The slip uppercut is kept only until a better one exists (“looks like a big uppercut [more] than a slip”). They all start again from the original capture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The training policy.&lt;/strong&gt; The lead uppercut over distance landed 40/54 in the air, but after it the fighter turned 90° to his right and stayed there. The cause was not the reference, which ends square at every depth. Training rewarded a home heading that was reset at every press and every recovery from a shove, and the opponent turned to face wherever the fighter faced. Nothing paid for facing one direction. Both uppercuts are now retraining with the heading fixed per episode, and the gate now measures the turn after every technique. Smaller cases of the same kind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A knee that landed in a southpaw stance 0.6 m forward, fixed with terms for the feet.&lt;/li&gt;
&lt;li&gt;A body straight that went below the belt, fixed with a line it may not cross.&lt;/li&gt;
&lt;li&gt;A body-straight teacher trained on faster elbows than the student has, which missed once distilled and had to be retrained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Start again, or restart from a checkpoint?&lt;/strong&gt; Most fixes warm-start from the last checkpoint that was good where it mattered. A teacher whose problem is in its reference has to start again from a checkpoint before it learnt the wrong motion. And the first stepping attempt was given up altogether: the long step never learnt to push off the back leg, and those references will be rebuilt from a better motion capture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I think, as a coach
&lt;/h2&gt;

&lt;p&gt;The shadow-clone idea worked the way I hoped where it worked. Three new techniques arrived in one model without breaking any of the old ones, and none of the clones had to wait for another. It also changes how I coach the fighter. I can look at one technique at a time, in a clone that does nothing else, and correct it before it goes into the student.&lt;/p&gt;

&lt;p&gt;The failures were mostly the kind a coach knows from people. A student who rushes a slip because nobody told them the timing matters. A fighter who finishes a combination facing the wrong way because their drills never asked them to stay square. My comments on the videos were all about shape and timing, things the numbers didn’t catch:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The roll should not just be a drop, it should roll to the side like a U shape.&lt;/p&gt;

&lt;p&gt;Slip and roll are all wrong. It’s going sideways but not by bending the torso.&lt;/p&gt;

&lt;p&gt;Keep to my original reference, like the one from motion capture.&lt;/p&gt;

&lt;p&gt;After the uppercut the fighter turns 90 degree to the right. It needs to keep facing the opponent.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The lesson I take from these is that the motion capture has to stay mine. Every time the reference was edited to get a cleaner number, the movement got less like Muay Thai.&lt;/p&gt;

&lt;h2&gt;
  
  
  The work logs
&lt;/h2&gt;

&lt;p&gt;Everything behind this post is in eight work logs, one per area. Each says why every run was started, what changed, what the gate and the videos showed and what it cost. Together they cover every run since &lt;a href="https://ai.kakuto.io/en/blog/two-fighters-gpu-vs-cpu/" rel="noopener noreferrer"&gt;the last post&lt;/a&gt;, and they add up to the cost at the top of this page and its row on &lt;a href="https://ai.kakuto.io/en/stats/" rel="noopener noreferrer"&gt;the stats page&lt;/a&gt;. The costs are from the vast.ai and RunPod ledgers, each machine’s billed hours times its hourly price. Machines that never came up and RunPod refusals are in them too.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Work log&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;th&gt;Hours&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/uppercuts-over-distance/" rel="noopener noreferrer"&gt;Teachers: the uppercuts over distance&lt;/a&gt;25 October 2026 · Two uppercut teachers trained in parallel on RunPod. The rear one was kept; the lead one turned 90° after the punch, which traced back to how training rewarded facing.&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10.1&lt;/td&gt;
&lt;td&gt;$7.81&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/evasion-teachers/" rel="noopener noreferrer"&gt;Teachers: slips, rolls and the lean back&lt;/a&gt;25 October 2026 · Nine evasion teachers in two rounds of four parallel boxes. They passed the gate and failed on video: rushed by the punch clock, then bent by an edited reference.&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;$12.97&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/distillation/" rel="noopener noreferrer"&gt;Distillation: six runs to the student distill4&lt;/a&gt;24–25 October 2026 · Distilling the body straight, both knees and the pull counter into the base: what each run changed, how the gate picked the student, and what it cost to evaluate.&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;22.9&lt;/td&gt;
&lt;td&gt;$16.27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/pull-counter/" rel="noopener noreferrer"&gt;Teacher: the pull counter&lt;/a&gt;24–25 October 2026 · One run on RunPod after four vast.ai boxes never loaded: a lean back and a rear straight to the head, 8/8 in the air and at the bag.&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3.1&lt;/td&gt;
&lt;td&gt;$3.45&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/body-straight/" rel="noopener noreferrer"&gt;Teacher: the rear straight to the body&lt;/a&gt;24 October 2026 · Four runs to a body-straight teacher: a no-low-blow line, the bag at the impact point, then a retrain on the base's slower elbows.&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;5.7&lt;/td&gt;
&lt;td&gt;$4.01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/knee-teachers/" rel="noopener noreferrer"&gt;Teachers: the rear knee and the switch knee&lt;/a&gt;24 October 2026 · Two knee teachers trained side by side, three runs each: the knees landed first time, the feet and the steps home took two more.&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;9.2&lt;/td&gt;
&lt;td&gt;$6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/higher-guard/" rel="noopener noreferrer"&gt;The higher guard: retraining every skill onto a new stance&lt;/a&gt;22–24 October 2026 · Eighteen runs that moved every skill onto a higher guard, fixed the lead hook and the jab, and produced guard18-124.5M, the base every clone starts from.&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;24.5&lt;/td&gt;
&lt;td&gt;$21.04&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://ai.kakuto.io/en/worklog/fast-stepping/" rel="noopener noreferrer"&gt;Fast stepping and the step-jab (abandoned)&lt;/a&gt;22 October 2026 · Twenty-six short GPU runs on fast steps in and out of range and a jab that steps in. The long step never pushed off the back leg, and the work was stopped to redo the motion capture.&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;12.6&lt;/td&gt;
&lt;td&gt;$9.49&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;71&lt;/td&gt;
&lt;td&gt;108.1&lt;/td&gt;
&lt;td&gt;$81.04&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two of them are not about this post’s techniques but cost money in the same days. The higher guard is the retraining that produced the base every clone started from. Fast stepping is the abandoned attempt mentioned above.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;This is the first part. The uppercut teachers are retraining with the facing fixed. The evasions start again from my original capture, with the punch clock held to the capture’s pace. The pull counter goes into the next distillation with the uppercuts. Kicks are waiting for better motion capture. Each new technique will be one more clone, and each distillation one more round of bringing the experience back.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/shadow-clones-learning-in-parallel/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>distillation</category>
      <category>paralleltraining</category>
      <category>gpu</category>
    </item>
    <item>
      <title>Two fighters and vision: GPU against CPU, optimised</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Fri, 23 Oct 2026 05:08:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/two-fighters-and-vision-gpu-against-cpu-optimised-5cal</link>
      <guid>https://dev.to/kakuto-io/two-fighters-and-vision-gpu-against-cpu-optimised-5cal</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=UfTjjKb0fOM" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frqgka0l5ovpaqnd7u23s.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=UfTjjKb0fOM" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.kakuto.io/en/blog/training-on-a-rented-gpu/" rel="noopener noreferrer"&gt;Training on a rented GPU&lt;/a&gt; compared nine &lt;a href="https://ai.kakuto.io/en/glossary/gpu/" rel="noopener noreferrer"&gt;GPUs&lt;/a&gt; against EC2 &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot machines&lt;/a&gt; on the first skill the fighter learnt: standing in the stance while being shoved. A rented card came out about 4.5 times cheaper. Since then the training has moved on to blocking an opponent, a much heavier job. Tony Yum, the coach:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We’ve already done an analysis on various GPU on stance and balance, but now we have a more complex model with two fighters and vision, so we want to redo the analysis. But just to reduce the scope of the GPU choices, we’ve just chosen RTX 5090 because that’s proven to be the most effective in the last training. But now we’re going to keep optimizing both the CPU usage on EC2 spots versus the RTX GPU and see how far we go, and again test the price and speed comparison between CPU and GPU.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this post compares one GPU, the RTX 5090 rented on vast.ai, against one CPU machine, a 96-&lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPU&lt;/a&gt; EC2 spot machine. It measures both as they were, optimises each until there was little left to gain, and compares them again. As before, the models trained here were thrown away.&lt;/p&gt;

&lt;h2&gt;
  
  
  What makes this training heavier
&lt;/h2&gt;

&lt;p&gt;The stance test trained one body and one network. The blocking training (the &lt;a href="https://ai.kakuto.io/en/glossary/environment/" rel="noopener noreferrer"&gt;environment&lt;/a&gt; from &lt;a href="https://ai.kakuto.io/en/blog/learning-to-block/" rel="noopener noreferrer"&gt;the blocking post&lt;/a&gt;, now with every skill mixed in) has much more in every step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Two fighters.&lt;/strong&gt; Ours, the muscular body, and an opponent who throws recorded punches at it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vision.&lt;/strong&gt; The fighter doesn’t get the opponent’s position for free. It sees his &lt;a href="https://ai.kakuto.io/en/glossary/keypoint/" rel="noopener noreferrer"&gt;keypoints&lt;/a&gt; from its own eyes: 32 rays cast to the points of his body, and any point behind its own gloves is hidden (&lt;a href="https://ai.kakuto.io/en/glossary/occlusion/" rel="noopener noreferrer"&gt;occlusion&lt;/a&gt;), with a tenth of a second of delay.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The punch’s score.&lt;/strong&gt; When a punch arrives, 19 paths from the glove to the head say how much of it got through the guard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Everything mixed.&lt;/strong&gt; Some &lt;a href="https://ai.kakuto.io/en/glossary/episode/" rel="noopener noreferrer"&gt;episodes&lt;/a&gt; face the opponent; the rest are blocks on command, walking to a spot, punches at a bag, or recovering from shoves. Each block press fits the arms to a pose with &lt;a href="https://ai.kakuto.io/en/glossary/inverse-kinematics/" rel="noopener noreferrer"&gt;inverse kinematics&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A second &lt;a href="https://ai.kakuto.io/en/glossary/neural-network/" rel="noopener noreferrer"&gt;network&lt;/a&gt;.&lt;/strong&gt; The walking model from earlier posts runs beside the policy as a teacher, pulling its legs toward a good walk (&lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdoqy7qotw6eyu107g800.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdoqy7qotw6eyu107g800.webp" alt="Three MuJoCo frames of the muscular fighter in a high guard facing an opponent drawn as a red stick figure with green and grey joint markers, throwing a jab, a hook and an uppercut" width="799" height="275"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The opponent environment, from the RTX 5090 run trained in this post: our fighter in its guard, and the opponent drawn as the keypoints the fighter's vision gets (green: seen; grey: hidden behind its own gloves), throwing a jab, a left hook and an uppercut.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The test
&lt;/h2&gt;

&lt;p&gt;Both machines start from the same model (guard5, the current best blocker) with the same settings as real training, and train for 15 minutes.&lt;/p&gt;

&lt;p&gt;The unit of work is one training iteration of &lt;a href="https://ai.kakuto.io/en/glossary/ppo/" rel="noopener noreferrer"&gt;PPO&lt;/a&gt;: collect about 30,000 &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt; from many copies of the world at once (&lt;a href="https://ai.kakuto.io/en/glossary/parallel-environments/" rel="noopener noreferrer"&gt;parallel environments&lt;/a&gt;), then update the network on them, four passes in minibatches of 2,048. The stance test showed that how fast the fighter learns is set by the number of iterations, not the number of steps. So the speed here is &lt;strong&gt;seconds per iteration&lt;/strong&gt; , and the cost &lt;strong&gt;dollars per 1,000 iterations&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CPU:&lt;/strong&gt; a 96-vCPU EC2 spot machine with 72 worker processes, each stepping 6 copies of the world for 64 steps (27,648 steps an iteration), and two learner processes of 12 threads updating the network.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU:&lt;/strong&gt; an RTX 5090 stepping 2,048 copies at once for 16 steps (32,768 steps), all of it, physics and network, on the card with &lt;a href="https://ai.kakuto.io/en/glossary/mujoco-warp/" rel="noopener noreferrer"&gt;MuJoCo Warp&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;EC2 96 vCPU spot&lt;/th&gt;
&lt;th&gt;RTX 5090, vast.ai&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;price&lt;/td&gt;
&lt;td&gt;$1.48/h (c8a), $2.58/h (m8a, the one available)&lt;/td&gt;
&lt;td&gt;$0.67/h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;seconds per iteration&lt;/td&gt;
&lt;td&gt;1.90&lt;/td&gt;
&lt;td&gt;2.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;steps per second&lt;/td&gt;
&lt;td&gt;14,600&lt;/td&gt;
&lt;td&gt;16,300&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$ per 1,000 iterations&lt;/td&gt;
&lt;td&gt;0.78 (c8a), 1.36 (m8a)&lt;/td&gt;
&lt;td&gt;0.37&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Unoptimised, the two took the same time, and the GPU was 2.1 times cheaper. On the stance it had been 4.5 times. Two fighters and vision narrowed the gap.&lt;/p&gt;

&lt;h2&gt;
  
  
  How busy was the CPU?
&lt;/h2&gt;

&lt;p&gt;Tony’s first question once the numbers were in: “How well optimised is the CPU? I.e. what CPU utilisation is it?”&lt;/p&gt;

&lt;p&gt;About three quarters. The trainer’s &lt;a href="https://ai.kakuto.io/en/glossary/profiling/" rel="noopener noreferrer"&gt;profile&lt;/a&gt; splits every iteration in two. The workers collect the next batch while the learners update on the last one (&lt;a href="https://ai.kakuto.io/en/glossary/decoupled-ppo/" rel="noopener noreferrer"&gt;decoupled PPO&lt;/a&gt;), so an iteration takes as long as the slower of the two.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The learners’ update took 1.90 s, the whole iteration. They were the bottleneck.&lt;/li&gt;
&lt;li&gt;The 72 workers stepped the physics for 1.34 s and then waited 0.56 s for the learners, idle 30 % of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So 24 of the 96 vCPUs were always busy and 72 were busy 70 % of the time: about 77 % in all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimising the GPU
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Where the step went.&lt;/strong&gt; The profile of one step with 2,048 copies counted 13,700 &lt;a href="https://ai.kakuto.io/en/glossary/gpu-kernel/" rel="noopener noreferrer"&gt;kernels&lt;/a&gt;, the small programs the GPU runs. About 1,800 were MuJoCo Warp’s physics, rays and arm fitting. The other 11,700 were tiny arithmetic kernels from the &lt;a href="https://ai.kakuto.io/en/glossary/reward-function/" rel="noopener noreferrer"&gt;rewards&lt;/a&gt;, &lt;a href="https://ai.kakuto.io/en/glossary/observation/" rel="noopener noreferrer"&gt;observations&lt;/a&gt; and resets, written line by line in PyTorch. Each did almost no work, and each had a fixed start-up cost. The GPU spent much of the step waiting between them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fusing them.&lt;/strong&gt; &lt;code&gt;torch.compile&lt;/code&gt; reads that PyTorch code and merges chains of small operations into a few bigger kernels (&lt;a href="https://ai.kakuto.io/en/glossary/kernel-fusion/" rel="noopener noreferrer"&gt;kernel fusion&lt;/a&gt;). The physics calls were kept out of it and run as before. A step with 2,048 copies went from 79.5 to 60.2 ms (Figure 2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftwo-fighters-gpu-vs-cpu%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftwo-fighters-gpu-vs-cpu%2Fchart-1.svg" alt="Milliseconds per environment step, eager and compiled, for three numbers of copies of the world" width="640" height="192"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Time for one environment step of the opponent environment on an RTX 5090, as written (eager) and compiled with torch.compile, for 1,024, 2,048 and 4,096 copies of the world. Compiling saves about 18–20 ms a step whatever the number of copies: the start-up cost of the kernels it merged.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two things had to be fixed on the way. The compiled code at first came out in pieces, because some table offsets were numpy integers, which the compiler traced as data instead of constants. Then some outputs came out in 64-bit instead of 32-bit (&lt;a href="https://ai.kakuto.io/en/glossary/floating-point/" rel="noopener noreferrer"&gt;floating point&lt;/a&gt;): the project’s settings are numpy numbers like the 4-degree tolerance &lt;code&gt;np.radians(4.0)&lt;/code&gt;, and the compiler turned them into 64-bit arrays where plain PyTorch treats them as ordinary numbers. The step’s outputs are now converted back to 32-bit. Against the uncompiled step from the same start and the same actions, the rewards matched to 3 in 100,000 for the first steps, and then drifted apart the way any two 32-bit runs of contact physics do, with the same averages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The update as one recording.&lt;/strong&gt; The network update was the other 0.53 s of the iteration. Run as written, its hundreds of small kernels are sent one by one by the host’s CPU, and most rented 5090s sit behind slow server processors: the same update took 0.13 s on a box with a fast desktop processor and about 0.5 s on the usual EPYC servers. Recording one minibatch step once and replaying it (a &lt;a href="https://ai.kakuto.io/en/glossary/cuda-graph/" rel="noopener noreferrer"&gt;CUDA graph&lt;/a&gt;) takes the CPU out: 0.08 s.&lt;/p&gt;

&lt;p&gt;That recording already existed but had been switched off, because the first &lt;a href="https://ai.kakuto.io/en/glossary/rollout/" rel="noopener noreferrer"&gt;rollout&lt;/a&gt; after it crashed the GPU with an illegal memory access, on every vast.ai box. A test with the same pieces didn’t crash, and adding the trainer’s extras back one by one didn’t either. What did work: recording the update before the environment’s own recording, not after. Two runs of 538 and 792 iterations ran clean. The underlying cause is still unknown; most likely the two recordings’ memory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The result: 1.19 s an iteration&lt;/strong&gt; , 27,500 steps a second, against 2.00 s. The environment step is now 1.09 s of that and the update 0.08. A 20-minute run on an ordinary EPYC-hosted 5090 matched the baseline’s training figures iteration by iteration: the same returns, falls, punches, goals, blocks and opponent passes. Only the time changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimising the CPU
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The learners.&lt;/strong&gt; At 12 threads, one learner’s update runs at about 1 &lt;a href="https://ai.kakuto.io/en/glossary/flops/" rel="noopener noreferrer"&gt;TFLOPS&lt;/a&gt;, about half the cores’ theoretical peak, which is typical for networks this small. Six ways of splitting the 96 vCPUs between workers and learners were tried: one learner with 24 threads, two with 8, 12 or 16, three with 8 or 12. Most barely moved the iteration. The best was &lt;strong&gt;60 workers with 7 copies each and three learners of 12 threads&lt;/strong&gt; : 1.91 to 1.74 s an iteration on the same machine, 9 % faster.&lt;/p&gt;

&lt;p&gt;More learners would lose. Each extra learner process adds to the &lt;a href="https://ai.kakuto.io/en/glossary/all-reduce/" rel="noopener noreferrer"&gt;all-reduce&lt;/a&gt;, the step where the processes add up their &lt;a href="https://ai.kakuto.io/en/glossary/gradient-descent/" rel="noopener noreferrer"&gt;gradients&lt;/a&gt; so every copy of the network stays the same, and with three it already took 0.38 s an iteration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fewer bits.&lt;/strong&gt; Running the network’s passes in &lt;a href="https://ai.kakuto.io/en/glossary/bfloat16/" rel="noopener noreferrer"&gt;bfloat16&lt;/a&gt;, 16-bit numbers that the AMD processor multiplies faster, nearly halved the update: 0.88 to 0.48 s at 12 threads. The iteration went to 1.43 s, 25 % faster than at the start. It changes the numbers slightly, and it hasn’t been checked yet that a policy trained this way learns as well, so it is listed separately below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The workers.&lt;/strong&gt; One copy of the environment took 4.4 ms a step, of which &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; itself was about 1.6 ms. The rest was the project’s own Python and numpy around it: numbers clipped one at a time, arrays joined with slow helpers, table lookups. Rewriting the worst of it made one environment about 20 % faster, with every observation and reward identical to the last bit over 6,000 steps. On the 96-vCPU machine, where 72 processes share the memory, it saved 7–11 % of the workers’ time. But the learners still set the pace, so on its own it didn’t shorten the iteration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The machine.&lt;/strong&gt; The same work on an Intel c8i machine took 1.45 times as long in the physics as on AMD’s c8a or m8a, which have a whole core per vCPU. The AMD machines are the ones to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keeping the comparison fair
&lt;/h2&gt;

&lt;p&gt;Midway through, the GPU’s training figures changed: about 200 blocks an iteration instead of 1,150, and far fewer punches. It looked like the compiled code was broken. It wasn’t: the same trainer without compiling showed the same drop. That morning, separate work on kicks had widened the range of the fighter’s ankles, and every reference motion had been rebuilt for the new body. With the old ankles shipped to the machine, the blocks came back.&lt;/p&gt;

&lt;p&gt;So the final numbers use the same body as the first test, on both machines, and the CPU’s before and after ran back to back on one machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimised: the comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;CPU, 32-bit&lt;/th&gt;
&lt;th&gt;CPU, bfloat16 (marked)&lt;/th&gt;
&lt;th&gt;RTX 5090&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;seconds per iteration&lt;/td&gt;
&lt;td&gt;1.91 → &lt;strong&gt;1.74&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1.43&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.00 → &lt;strong&gt;1.19&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;steps per second&lt;/td&gt;
&lt;td&gt;14,500 → 15,300&lt;/td&gt;
&lt;td&gt;17,800&lt;/td&gt;
&lt;td&gt;16,300 → &lt;strong&gt;27,500&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$ per 1,000 iterations&lt;/td&gt;
&lt;td&gt;0.78 → &lt;strong&gt;0.71&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.59&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.37 → &lt;strong&gt;0.22&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;$ per million steps&lt;/td&gt;
&lt;td&gt;0.027&lt;/td&gt;
&lt;td&gt;0.023&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.0068&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;paid set-up before training&lt;/td&gt;
&lt;td&gt;about 2 min&lt;/td&gt;
&lt;td&gt;about 2 min&lt;/td&gt;
&lt;td&gt;about 10 min (~$0.11)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;CPU prices at c8a spot ($1.48/h), the cheapest 96-vCPU AMD machine; the measurements are from an m8a with the same processor. GPU at $0.67/h.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftwo-fighters-gpu-vs-cpu%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftwo-fighters-gpu-vs-cpu%2Fchart-2.svg" alt="Seconds per iteration and dollars per thousand iterations for CPU and GPU, before and after optimising" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Seconds per training iteration and dollars per 1,000 iterations for the opponent environment, before and after optimising, on a 96-vCPU EC2 spot machine (priced at c8a) and an RTX 5090 on vast.ai. CPU bf16 runs the learner's network passes in 16-bit numbers, which changes the learning slightly and hasn't been checked yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What it shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The RTX 5090 is now about 3.2 times cheaper per iteration than the best 32-bit setup on EC2, and faster&lt;/strong&gt; : 1.19 s an iteration against 1.74. Against bfloat16 learners on the CPU it is 2.7 times cheaper. Per step, about four times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The GPU gained more from optimising&lt;/strong&gt; : 41 % off the iteration against 9 % (25 % with bfloat16). Its waste was in starting work (thousands of tiny kernels, a CPU sending them one by one), and that can be removed. The CPU’s learner was already doing its arithmetic at a fair rate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cheapest 5090s should now be as good as any.&lt;/strong&gt; With the update recorded, the CPU next to the card only replays recordings, so a $0.60–0.67 server box should run as fast as a $0.91 one with a fast desktop processor. The final run, on an old EPYC server, reached 1.19 s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The GPU costs more to start&lt;/strong&gt; : about 10 minutes from renting to the first iteration in these runs (booting, rebuilding the reference tables, compiling the physics and then the fused kernels), about 11 cents. For runs of an hour or more it hardly matters.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Coach Tony thinks
&lt;/h2&gt;

&lt;p&gt;Tony framed this one as a follow-up rather than a new survey: keep the GPU choice to the RTX 5090, “proven to be the most effective in the last training”, and “keep optimizing both the CPU usage on EC2 spots versus the RTX GPU and see how far we go”. When the first comparison came back, his question was about the CPU side, how much of the machine was actually being used, and his instruction afterwards was to keep optimising both “until you think there is pretty well optimised”, then see how cost and speed compare.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The GPU’s step.&lt;/strong&gt; About half of the 1.09 s is MuJoCo Warp’s own physics, the rest the environment’s kernels and a reset that runs on every copy every step. More copies cost little more time (4,096 take 99 ms a step against 60 ms for 2,048), so 4,096 copies for 8 steps would make the same batch in about 0.8 s. That shortens each copy’s run between updates, which changes the learning, so it needs a learning test first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The start-up.&lt;/strong&gt; The compiling could be kept between machines instead of redone each time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;bfloat16 on the CPU&lt;/strong&gt; would need a learning test before it is used, but with the GPU this far ahead, the CPU is now the backup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;Most of the money went on short GPU and CPU runs to measure each change, and on chasing the GPU crash. The vast.ai figures come from each machine’s billed time and hourly price; the EC2 figures are estimates from each run’s length and the zone’s spot price.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;item&lt;/th&gt;
&lt;th&gt;machines&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;the first comparison: 15 minutes on each&lt;/td&gt;
&lt;td&gt;1 RTX 5090, 1 EC2 m8a.24xlarge&lt;/td&gt;
&lt;td&gt;about 0.7&lt;/td&gt;
&lt;td&gt;about $1.06&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPU optimising: benchmarks, the crash hunt, test and final runs&lt;/td&gt;
&lt;td&gt;15 RTX 5090 (two never answered)&lt;/td&gt;
&lt;td&gt;about 3.2&lt;/td&gt;
&lt;td&gt;about $2.65&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CPU optimising: benchmarks and the final comparison&lt;/td&gt;
&lt;td&gt;7 EC2 spot (c8i, c7a, c8a, m8a, 96 vCPU)&lt;/td&gt;
&lt;td&gt;about 1.4&lt;/td&gt;
&lt;td&gt;about $3.00&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 5.3&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $6.70&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/two-fighters-gpu-vs-cpu/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>cost</category>
      <category>gpu</category>
      <category>trainingspeed</category>
    </item>
    <item>
      <title>Training on a rented GPU: four and a half times cheaper</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Wed, 21 Oct 2026 07:54:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/training-on-a-rented-gpu-four-and-a-half-times-cheaper-37a9</link>
      <guid>https://dev.to/kakuto-io/training-on-a-rented-gpu-four-and-a-half-times-cheaper-37a9</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=vus5pIEIbYw" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuisspy06hdlzd2wi0oqu.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=vus5pIEIbYw" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every post so far has trained the fighter on Amazon EC2 &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot machines&lt;/a&gt; with 96 or 192 &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt;. Tony Yum, the coach, on where that was going:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As I’m provisioning more and more virtual CPUs on EC2 spot instances, the cost is racking up. And this is only the beginning. There are a lot more training to do, possibly bigger networks. So it’s only going to get more expensive. So let’s think of a way to save money.&lt;/p&gt;

&lt;p&gt;GPU is one option, but there are some complications with the number of contacts and the way the body is built. So some experiments are needed. Yes, in order to save costs, I’ll have to throw even more money at an experiment, but it’ll be a good investment, I believe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So this post isn’t about a new skill. It is about the machine the skills are learnt on: whether the training is cheaper on a rented &lt;a href="https://ai.kakuto.io/en/glossary/gpu/" rel="noopener noreferrer"&gt;GPU&lt;/a&gt;, what the code had to change to get there, and which GPU is cheapest. The models trained here were thrown away; only the timings and the bills mattered.&lt;/p&gt;

&lt;p&gt;It covers one morning, 04:05 to 07:54 UTC on 21 October.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a GPU wasn’t the obvious answer
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://ai.kakuto.io/en/blog/learning-to-block/" rel="noopener noreferrer"&gt;the blocking post&lt;/a&gt; a rented GPU was tried for a few minutes and set aside: training waits on the physics, and the physics ran on the CPU. A GPU only helped the small network.&lt;/p&gt;

&lt;p&gt;The way round that is to move the physics too. &lt;a href="https://ai.kakuto.io/en/glossary/mujoco-warp/" rel="noopener noreferrer"&gt;MuJoCo Warp&lt;/a&gt; is a version of &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; that runs on the GPU and simulates thousands of copies of the world at once, all in step. That has two catches for this fighter.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The body.&lt;/strong&gt; The muscular body has 89 &lt;a href="https://ai.kakuto.io/en/glossary/degrees-of-freedom/" rel="noopener noreferrer"&gt;degrees of freedom&lt;/a&gt; in one tree, from the pelvis out to every finger joint, and 63 egg-shaped muscles on top. GPU simulators are built for robots with a few dozen joints. The simple body (Figure 1, right) has 43.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The contacts.&lt;/strong&gt; On a CPU each copy of the world keeps as many contacts as it needs. On the GPU every copy gets a fixed number of slots, set before training starts. After a fall, a muscular body lying on the floor reaches 32 contacts and 260 constraint rows, the equations the physics solves to keep things from passing through each other. Smaller slots overflowed and crashed the run; the slots that work leave most of the memory empty most of the time.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3m99b0jeeyqle79hh4bx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3m99b0jeeyqle79hh4bx.webp" alt="Four side views of the MuJoCo fighter in the Muay Thai stance: the muscular body standing and being shoved, then the simple body standing and being shoved, with a red arrow for each shove" width="800" height="267"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The two bodies the test trained, each after solving the stance with shoves on: muscular-fast (left pair) and simple (right pair), in the stance and 0.1 s into a shove (red arrow; 55 N and 32 N). These are the EC2 runs of the test; the GPU runs solved the same task, but their checkpoints went with the rented machines.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The test
&lt;/h2&gt;

&lt;p&gt;The task was the first one the fighter ever learnt: stand in the stance, keep the rhythm, and stay up while being shoved (&lt;a href="https://ai.kakuto.io/en/blog/learning-to-balance-in-a-muay-thai-stance/" rel="noopener noreferrer"&gt;the balance post&lt;/a&gt;). Each machine trained it from nothing until it was solved: amplitude at full, at most 5 % of &lt;a href="https://ai.kakuto.io/en/glossary/episode/" rel="noopener noreferrer"&gt;episodes&lt;/a&gt; ending in a fall, and episodes lasting the full 10 s. Both bodies were tested, muscular-fast and simple.&lt;/p&gt;

&lt;p&gt;Two figures were kept for every machine: &lt;strong&gt;time to solve&lt;/strong&gt; , and &lt;strong&gt;cost per solve&lt;/strong&gt; , which is that time times the machine’s price per hour.&lt;/p&gt;

&lt;p&gt;Both sides train many copies of the world at once, &lt;a href="https://ai.kakuto.io/en/glossary/parallel-environments/" rel="noopener noreferrer"&gt;parallel environments&lt;/a&gt;. The CPU side was two ordinary EC2 spot runs with the usual trainer: 72 worker processes with 6 copies each.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;machine&lt;/th&gt;
&lt;th&gt;body&lt;/th&gt;
&lt;th&gt;price&lt;/th&gt;
&lt;th&gt;time to solve&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;c8i.24xlarge spot, 96 vCPU&lt;/td&gt;
&lt;td&gt;muscular-fast&lt;/td&gt;
&lt;td&gt;$1.45/h&lt;/td&gt;
&lt;td&gt;714 s&lt;/td&gt;
&lt;td&gt;$0.29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c8a.24xlarge spot, 96 vCPU&lt;/td&gt;
&lt;td&gt;simple&lt;/td&gt;
&lt;td&gt;$2.02/h&lt;/td&gt;
&lt;td&gt;404 s&lt;/td&gt;
&lt;td&gt;$0.23&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 1: tuning the code for one GPU
&lt;/h2&gt;

&lt;p&gt;The first GPU was an RTX 5090, the newest consumer card, rented on vast.ai for $0.74 an hour. vast.ai is a market where people and small data centres rent out their GPU machines by the second.&lt;/p&gt;

&lt;p&gt;The GPU trainer was written two days earlier and tested on an older card. On the 5090 it ran 44,000–47,000 &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt; a second with 4,096 copies of the world, the GPU at 97 %. The physics took nine tenths of the time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding the slow part.&lt;/strong&gt; &lt;a href="https://ai.kakuto.io/en/glossary/profiling/" rel="noopener noreferrer"&gt;Profiling&lt;/a&gt; timed every small program the GPU ran (each one a &lt;a href="https://ai.kakuto.io/en/glossary/gpu-kernel/" rel="noopener noreferrer"&gt;kernel&lt;/a&gt;). One took 53 % of the time: the factorisation of the &lt;a href="https://ai.kakuto.io/en/glossary/mass-matrix/" rel="noopener noreferrer"&gt;mass matrix&lt;/a&gt;, the table that says how hard each joint is to move given everything attached to it. MuJoCo Warp has a fast method for bodies up to 64 degrees of freedom. The muscular body’s 89, all in one tree, fell back to a slow general method: 24 separate launches per factorisation, one for each level of the tree, twice in every physics step.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A replacement.&lt;/strong&gt; The new version (&lt;code&gt;warp_factor.py&lt;/code&gt;) gives each copy of the world a group of 64 GPU threads that do the whole factorisation in one launch, waiting for each other between levels instead of starting a new kernel. Long sums are split into chunks of 8 so no thread is left doing all the work. The factorisation went from 38.6 to 8.9 ms of GPU time per step, and the physics got 28 % faster: 76,000 steps a second at 8,192 copies. It is the same physics: on the same episode with the same actions, the joint angles matched the stock method to a millionth of a radian, as close as &lt;a href="https://ai.kakuto.io/en/glossary/floating-point/" rel="noopener noreferrer"&gt;32-bit numbers&lt;/a&gt; allow.&lt;/p&gt;

&lt;p&gt;The simple body didn’t need this. Its 43 degrees of freedom fit MuJoCo Warp’s fast method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then the surprise: fewer copies of the world trained faster.&lt;/strong&gt; With the new factorisation and 8,192 copies, the GPU trained at 61,000 steps a second, five times the CPU machine. After 12 minutes the fighter had reached only 60 % of the full stance. The CPU machine had solved it in less.&lt;/p&gt;

&lt;p&gt;The reason is the &lt;a href="https://ai.kakuto.io/en/glossary/curriculum-learning/" rel="noopener noreferrer"&gt;curriculum&lt;/a&gt;. Each time the stance gets wider, it waits a fixed number of training iterations, about two episodes for every copy of the world, before it can rise again. Each iteration steps every copy 32 times. So a solve takes about 350–500 iterations whatever the machine, and the time to solve is that number times the seconds per iteration. More copies only make each iteration take longer. Training is fastest with as few copies as keep the GPU busy, and on the 5090 that was 1,024 (Figure 2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-1.svg" alt="Steps per second and time to solve for 8192, 2048, 1024 and 512 copies of the world on the GPU and for the CPU machine" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Training the muscular-fast body from nothing on the RTX 5090 with different numbers of copies of the world (parallel environments), against the 96-vCPU CPU machine. More copies give more steps a second, but each training iteration takes longer, and the solve needs about the same number of iterations, so 8,192 copies hadn't solved it after 722 s. 1,024 copies solved it in 386 s on this seed; a second seed took 529 s.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At 1,024 copies the GPU is no longer short of work to do; it is waiting. Each of the thousands of small kernels in a physics step has a fixed start-up cost, and with 1,024 copies that cost sets the pace, not the arithmetic. So the next change cut the waiting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No questions to the CPU in the middle of a step.&lt;/strong&gt; Code like “did any copy fall?” makes the CPU stop and wait for the GPU’s answer. Falls, resets, shoves and foot forces were rewritten to work on every copy at once with a mask, and the trainer reads its figures from the GPU once an iteration.&lt;/p&gt;

&lt;p&gt;Muscular-fast at 1,024 copies stayed at 31,000–32,000 steps a second on the 5090. On that machine the physics was the limit. The waiting mattered on the next machines.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: nine GPUs
&lt;/h2&gt;

&lt;p&gt;A script (&lt;code&gt;vast_bench.py&lt;/code&gt;) rented the cheapest offer of each GPU type at the same time, copied the code over, ran the same speed tests and two minutes of training per body, and handed the machine back. Nine types, from a 2018 data-centre T4 at $0.15 an hour to an RTX PRO 6000 at $1.00.&lt;/p&gt;

&lt;p&gt;The first pass was a disappointment. Every machine except the 5090’s took 0.7–1.4 s per iteration to update the network, where the 5090 took 0.2 s. The 5090 had happened to sit in a desktop with a fast new processor. Most rented GPUs sit in servers with slower, older processors, and the trainer was waiting on them. An L40S, a card nearly as fast as the 5090 here, trained at 13,000 steps a second.&lt;/p&gt;

&lt;p&gt;So the CPU was taken out of the loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The network update as a &lt;a href="https://ai.kakuto.io/en/glossary/cuda-graph/" rel="noopener noreferrer"&gt;CUDA graph&lt;/a&gt;.&lt;/strong&gt; One training step on a minibatch (run the network, work out the gradients, clip them, update the weights) is recorded once and replayed as a single unit, instead of the CPU sending each of its hundreds of kernels one at a time. 0.6–0.7 s an iteration became 0.2 s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The whole environment step as a CUDA graph&lt;/strong&gt; , the physics included. Only 5 % on its own.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One lookup instead of eight.&lt;/strong&gt; The reference motion (where each joint should be in the stance’s rhythm) was 8 tables looked up one by one, three times a step: 8 of the 21 ms the step spent outside the physics. Now the tables sit side by side and one lookup reads them all, and the non-physics work fell to 8.7 ms. With that and the contact slots halved for the simple body (the foot-force check reads every slot), the simple body went from 41,000 to 48,000 steps a second on an RTX 3090.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two bugs turned up on the way. The first step of every run had been simulated twice, once to prepare the GPU code and once for real (harmless, now fixed). And once, a heap of fallen muscular bodies ran out of constraint slots, the second catch above. The slots went up from 320 to 512 rows, at no measurable cost, and the trainer now prints &lt;code&gt;OVERFLOW&lt;/code&gt; when any copy runs out.&lt;/p&gt;

&lt;p&gt;With the new code, a second pass of the survey (Figure 3) gave cards behind ordinary server processors their real speed. A second test on the two cheapest, on different machines in other countries, gave the same seconds per iteration within a few percent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-2.svg" alt="Dollars per solve and seconds to solve for ten machines, muscular-fast body" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Cost and time to solve the stance with the muscular-fast body, per machine, including the paid set-up before training (about 1.5 minutes). GPUs are rented on vast.ai at that morning's offer, with 1,024 copies of the world on the final code; times come from the measured seconds per iteration times 426 iterations. g6.xlarge is EC2's own L4 machine, priced with the L4's speed measured on vast.ai (an estimate). c8a 96 and c8a 192 are the EC2 CPU spot machines; the 192-vCPU time is estimated from its measured speed-up. A single solve varies by about 30 % from seed to seed.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: GPU against EC2
&lt;/h2&gt;

&lt;p&gt;The full list, cost per solve with set-up included. ”~” marks an estimated time.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;machine&lt;/th&gt;
&lt;th&gt;where&lt;/th&gt;
&lt;th&gt;$/h&lt;/th&gt;
&lt;th&gt;muscular-fast&lt;/th&gt;
&lt;th&gt;$&lt;/th&gt;
&lt;th&gt;simple&lt;/th&gt;
&lt;th&gt;$&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RTX 5080&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.39&lt;/td&gt;
&lt;td&gt;515 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.065&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;230 s&lt;/td&gt;
&lt;td&gt;0.034&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L40S&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.44&lt;/td&gt;
&lt;td&gt;452 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.065&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;227 s&lt;/td&gt;
&lt;td&gt;0.038&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3090&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.20&lt;/td&gt;
&lt;td&gt;1163 s&lt;/td&gt;
&lt;td&gt;0.070&lt;/td&gt;
&lt;td&gt;451 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.030&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 4090&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.51&lt;/td&gt;
&lt;td&gt;436 s&lt;/td&gt;
&lt;td&gt;0.074&lt;/td&gt;
&lt;td&gt;217 s&lt;/td&gt;
&lt;td&gt;0.043&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;RTX 5090&lt;/strong&gt; (fastest)&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.69&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;377 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.089&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;185 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.053&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;T4&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;2326 s&lt;/td&gt;
&lt;td&gt;0.100&lt;/td&gt;
&lt;td&gt;1025 s&lt;/td&gt;
&lt;td&gt;0.046&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L4&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.36&lt;/td&gt;
&lt;td&gt;1074 s&lt;/td&gt;
&lt;td&gt;0.117&lt;/td&gt;
&lt;td&gt;389 s&lt;/td&gt;
&lt;td&gt;0.048&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;A100&lt;/td&gt;
&lt;td&gt;vast.ai&lt;/td&gt;
&lt;td&gt;0.46&lt;/td&gt;
&lt;td&gt;931 s&lt;/td&gt;
&lt;td&gt;0.129&lt;/td&gt;
&lt;td&gt;403 s&lt;/td&gt;
&lt;td&gt;0.062&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;g6.xlarge (L4)&lt;/td&gt;
&lt;td&gt;EC2 spot&lt;/td&gt;
&lt;td&gt;0.48&lt;/td&gt;
&lt;td&gt;~1074 s&lt;/td&gt;
&lt;td&gt;~0.167&lt;/td&gt;
&lt;td&gt;~389 s&lt;/td&gt;
&lt;td&gt;~0.076&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;g6e.xlarge (L40S)&lt;/td&gt;
&lt;td&gt;EC2 spot&lt;/td&gt;
&lt;td&gt;1.47&lt;/td&gt;
&lt;td&gt;~452 s&lt;/td&gt;
&lt;td&gt;~0.259&lt;/td&gt;
&lt;td&gt;~227 s&lt;/td&gt;
&lt;td&gt;~0.167&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c8a.24xlarge, 96 vCPU&lt;/td&gt;
&lt;td&gt;EC2 spot&lt;/td&gt;
&lt;td&gt;1.34&lt;/td&gt;
&lt;td&gt;714 s&lt;/td&gt;
&lt;td&gt;0.299&lt;/td&gt;
&lt;td&gt;404 s&lt;/td&gt;
&lt;td&gt;0.184&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c8a.48xlarge, 192 vCPU&lt;/td&gt;
&lt;td&gt;EC2 spot&lt;/td&gt;
&lt;td&gt;3.65&lt;/td&gt;
&lt;td&gt;~529 s&lt;/td&gt;
&lt;td&gt;~0.627&lt;/td&gt;
&lt;td&gt;~299 s&lt;/td&gt;
&lt;td&gt;~0.394&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;What it shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A rented consumer GPU solves the stance for less than a quarter of the price&lt;/strong&gt; : $0.065 on an RTX 5080 or L40S against $0.30 on the 96-vCPU spot machine for muscular-fast, $0.03–0.04 against $0.18 for simple. And it is faster too: the 5080, L40S and 4090 take 55–70 % of the CPU machine’s time, the 5090 about half.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cheapest cards are all within about 15 % of each other&lt;/strong&gt; : RTX 5080, L40S, RTX 3090 and RTX 4090. The 3090 is the cheapest by the hour but more than twice as slow. The 5090 is the fastest at about 30 % more per solve, worth it when time matters more than money.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data-centre cards are poor value here.&lt;/strong&gt; The A100, L4 and T4 are built for large blocks of matrix maths and lots of memory, but this physics is ordinary 32-bit arithmetic in thousands of small steps. It wants clock speed, not memory or tensor cores.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EC2’s own GPU machines don’t pay.&lt;/strong&gt; The same L40S costs 3.4 times as much on EC2 as on vast.ai. The best of them, g6.xlarge with an L4, costs about half the CPU machine per solve but is slower than it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The simple body costs about half as much on a GPU&lt;/strong&gt; : it runs 1.7 times as many steps a second and needs about the same number of iterations. On the CPU the gap is only 1.3 times.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ftraining-on-a-rented-gpu%2Fchart-3.svg" alt="Dollars per solve for the muscular-fast and simple bodies on five machines" width="640" height="192"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. Dollars per solve for the two bodies on the cheapest GPUs and the 96-vCPU EC2 machine, set-up included.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting a machine ready
&lt;/h2&gt;

&lt;p&gt;Speed per iteration isn’t the whole bill. A rented machine is paid for from the moment it starts, before any training. On vast.ai the time spent downloading the software image is free; copying the code over, installing the physics libraries and preparing the GPU code is paid at the full rate.&lt;/p&gt;

&lt;p&gt;At first the copy was slow. The script sent every file in the project, 57 MB, 51 MB of it a table only the walking environment uses, and many cheap hosts have slow incoming connections: the A100 in California took 17 minutes to receive it, then 26 minutes to install the libraries over the same line. Now the script sends 1.4 MB and asks for hosts with at least 500 Mbit/s. On a good host the paid set-up is about 1.5 minutes, one or two cents, about what an EC2 CPU machine takes from launch to the first iteration (75–93 s).&lt;/p&gt;

&lt;p&gt;The real risk is a bad host. An RTX 4090 in Thailand ran a tenth as fast as another 4090 on both passes. An RTX PRO 6000 started, never answered, and cost $0.51 for nothing. An RTX 5080 had a driver too old for the GPU code and couldn’t see its own card. The script now asks for a recent driver and gives up on any machine that doesn’t answer within 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Coach Tony thinks
&lt;/h2&gt;

&lt;p&gt;Tony’s brief for the morning was to optimise the GPU code for the machine first, then compare: both bodies, other GPU machines to find the cheapest, and EC2. He called the experiment money spent to save money, “a good investment”. The models could be thrown away.&lt;/p&gt;

&lt;p&gt;When the first survey came back, he asked why the uploads were so slow and wanted the set-up costs in the comparison, not just the training time. That is where the 57 MB upload and the bad-host losses came to light.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;Only the stance runs on the GPU so far. Punching, walking, blocking and the opponent environment each need their own GPU version before they can move off EC2. On these numbers that work pays for itself quickly: the last post’s 20 blocking runs cost about $33 on EC2.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;Most of the cost was renting GPUs to measure them, plus two CPU runs on EC2 to compare against, each left running a few minutes past its solve. The vast.ai figure comes from vast.ai’s charge records; the EC2 figure is an estimate from each run’s hours and spot price.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;item&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;RTX 5090 on vast.ai: profiling, the new factorisation, the copies-of-the-world tests, the simple body&lt;/td&gt;
&lt;td&gt;about 1.7&lt;/td&gt;
&lt;td&gt;about $1.21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RTX 3090 on vast.ai: the CPU-out-of-the-loop work and two runs from nothing&lt;/td&gt;
&lt;td&gt;about 1.1&lt;/td&gt;
&lt;td&gt;about $0.22&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;the survey: about 17 GPU machines over two passes and a timed re-run&lt;/td&gt;
&lt;td&gt;about 5.5 (estimate)&lt;/td&gt;
&lt;td&gt;about $2.61&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2 EC2 spot runs (c8i.24xlarge and c8a.24xlarge, 96 vCPU)&lt;/td&gt;
&lt;td&gt;about 0.8&lt;/td&gt;
&lt;td&gt;about $1.38&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $5.40&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/training-on-a-rented-gpu/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>cost</category>
      <category>gpu</category>
      <category>trainingspeed</category>
    </item>
    <item>
      <title>Blocking: reading a punch you see a tenth of a second late</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Tue, 20 Oct 2026 17:43:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/blocking-reading-a-punch-you-see-a-tenth-of-a-second-late-5ba1</link>
      <guid>https://dev.to/kakuto-io/blocking-reading-a-punch-you-see-a-tenth-of-a-second-late-5ba1</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=32C7WBZUwII" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7q8fa5rkjkc16ly33bl4.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=32C7WBZUwII" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end of &lt;a href="https://ai.kakuto.io/en/blog/walking-in-the-stance/" rel="noopener noreferrer"&gt;the footwork post&lt;/a&gt;, the fighter could stand in its stance, throw five punches and walk to a spot. Every target so far had been a point in the air or a bag. None of them hit back.&lt;/p&gt;

&lt;p&gt;This post is about defence. Tony Yum, the coach, explains why it is hard:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Blocking is a complicated thing. Firstly, there’s a reaction time. What you see and process is actually behind reality. And you don’t know what your opponent is actually thinking, whether it’s throwing a jab or a hook. All you have is the visual clues, like the turning of the hip, the movement of the shoulder or elbow. That can also become a feint. So it’s a very interesting chess game.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And what this first step leaves out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In the real combat fight, you’re thinking about distancing. You wouldn’t allow your opponent to stand in striking distance and just stand there. Typically, you would go in and out of the pocket. You might bob your head to avoid jabs. You might be prepared to move, or you might trade. You might think: that quick jab was a bait, and you’re actually thinking to move out of the way and do a big cross. So all that is in consideration. But one baby step at a time.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So: one punch at a time, from an opponent standing in range, and the fighter only allowed to block. No slipping, no stepping back, no countering. It sees the opponent a tenth of a second late, and it has to tell from his first movements which punch is coming.&lt;/p&gt;

&lt;p&gt;It covers 20 training runs over about 18 hours, from 23:43 UTC on 19 October to 18:04 UTC on 20 October. The model that was kept finished training at 17:43 UTC on 20 October.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four blocks
&lt;/h2&gt;

&lt;p&gt;Tony sent photos of the blocks he wanted, and four poses were built from them (Figure 1):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Left high block&lt;/strong&gt; , against the opponent’s right hook: the left elbow up in front of the face at forehead height, the forearm back along the temple, chin tucked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Right high block&lt;/strong&gt; , the same on the right, against the left hook.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Front block&lt;/strong&gt; , against the jab and cross: both forearms upright and pressed together in front of the face.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low front block&lt;/strong&gt; , against the uppercut: the front block with the elbows down at the chest, so the forearms close the gap under the chin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fighter fights bare-fisted. Gloves were tried and dropped the same day: they covered the eyes in the guard, and the fighter will grapple later.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fib2s14wqiw7rifci3p8c.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fib2s14wqiw7rifci3p8c.webp" alt="Five front views of the MuJoCo fighter: the Muay Thai guard, then the left high block, right high block, front block with both forearms in front of the face, and low front block" width="799" height="187"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The guard and the four blocks, from the front, as posed (no physics). Left to right: the stance guard, left high, right high, front, low front. Share of punch paths each one stops before they reach the head: left high 79 % of the left side, right high 73 % of the right side, front 95 % of the face straight on, low front 93 % of the chin from below; the guard alone 5–25 %.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: blocks on command
&lt;/h2&gt;

&lt;p&gt;Option one was to put an opponent in front of the fighter, let it get hit, and wait for it to discover blocking. With only “getting hit is bad” to go on, a &lt;a href="https://ai.kakuto.io/en/glossary/reinforcement-learning/" rel="noopener noreferrer"&gt;reinforcement learning&lt;/a&gt; agent is more likely to invent an odd flinch than a Muay Thai block. So training came in two stages. First, blocks on command: a button says which block, and the &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt;, the neural network that drives the body, learns to raise it fast and hold it without falling over. Then the button goes, an opponent comes in, and the same policy decides which block and when.&lt;/p&gt;

&lt;p&gt;While the button is held, the blocking arm’s motor targets switch to the block’s pose. The rewards pay for speed (a bonus for reaching 90 % of the pose’s cover, in full within 0.15 s), for holding still, for keeping the elbow bent on the way up (Tony’s rule against a wide, telegraphed swing), and for a smooth return to the guard. The legs and trunk keep their stance rewards.&lt;/p&gt;

&lt;p&gt;The fighter must not forget what it already knows. Tony’s rule: “make sure that none of the previous techniques are ever forgotten. So it still knows how to balance and it still knows how to do all the punches and walk.” Half the training &lt;a href="https://ai.kakuto.io/en/glossary/episode/" rel="noopener noreferrer"&gt;episodes&lt;/a&gt; are blocks; the other half are the walking environment’s exactly, with walking and punches. A frozen copy of the walking model acts as a teacher (&lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;) whenever no block is held. And no model is kept until it passes a skills gate: at least 58 of 120 test punches, at least 39 of 40 walking targets with no falls, in no more than about 8.3 s each.&lt;/p&gt;

&lt;p&gt;Three of the four blocks came at once. The left high block never covered, in 15 M &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt;. Three runs found out why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The poses were worked out on the reference stance, but the trained fighter stands with its chest turned about 8° further and leaning 7° further back. With every joint exactly on the pose’s angle on that trunk, the block covered only 82 % of its design. So at each press, the arm is now fitted to where the head actually is, with &lt;a href="https://ai.kakuto.io/en/glossary/inverse-kinematics/" rel="noopener noreferrer"&gt;inverse kinematics&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;That alone didn’t move it. The policy adds its own small offsets to every motor target, and its guard habit held the left shoulder about 4° low and 8° in: the arm stayed 3.9 cm off the pose. A reward for pulling the elbow and wrist to the pose didn’t break the habit in 10 M steps either.&lt;/li&gt;
&lt;li&gt;What worked was turning the habit down: while a block is up, the policy’s offsets on the blocking arm count only 30 %. In 4.6 M steps all four blocks covered, and every old skill passed the gate.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then the high blocks were too slow: 0.26 s for the left, 0.21 s for the right. The fighter’s left shoulder swings from 53° to 129° in that block. Each joint is driven by a &lt;a href="https://ai.kakuto.io/en/glossary/position-servo/" rel="noopener noreferrer"&gt;position servo&lt;/a&gt;, and its damping, the part that resists speed, cancelled the pull 20 ms into the swing. No amount of training could fix that. Softening the damping to a quarter while a high block rises did: 0.12 s for the left, 0.08 s for the right, 0.10 s for the front and 0.07 s for the low front block, every press covered, with punches and walking still passing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there time to block?
&lt;/h2&gt;

&lt;p&gt;Before the opponent came in, one question needed numbers: can a block arrive in time at all?&lt;/p&gt;

&lt;p&gt;The opponent is the fighter itself. Its own fast punches (jab, cross, both hooks and the uppercut) were recorded once and are replayed, without physics, from in front of it. From those recordings: when is the first visible sign of each punch, and when does the fist land?&lt;/p&gt;

&lt;p&gt;The fighter doesn’t see him as an image. It sees 16 &lt;a href="https://ai.kakuto.io/en/glossary/keypoint/" rel="noopener noreferrer"&gt;keypoints&lt;/a&gt; (head, neck, shoulders, elbows, wrists, fists, hips, knees, ankles), each as a 3D vector from its own head, with velocities and a short history of 40 and 80 ms back (&lt;a href="https://ai.kakuto.io/en/glossary/frame-stacking/" rel="noopener noreferrer"&gt;frame stacking&lt;/a&gt;). It sees them late. Tony chose a &lt;a href="https://ai.kakuto.io/en/glossary/latency/" rel="noopener noreferrer"&gt;vision delay&lt;/a&gt; of 100 ms, about a fast professional’s. And it can be blind. Rays go from both eyes to each keypoint, and a point is hidden if the fighter’s own arms are in the way (&lt;a href="https://ai.kakuto.io/en/glossary/occlusion/" rel="noopener noreferrer"&gt;occlusion&lt;/a&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;punch&lt;/th&gt;
&lt;th&gt;first moves&lt;/th&gt;
&lt;th&gt;lands&lt;/th&gt;
&lt;th&gt;warning&lt;/th&gt;
&lt;th&gt;cover at landing*&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;jab&lt;/td&gt;
&lt;td&gt;elbow and fist, 0.083 s&lt;/td&gt;
&lt;td&gt;0.187 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.10 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.50 (guard: 0.48)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cross&lt;/td&gt;
&lt;td&gt;elbow, 0.079 s&lt;/td&gt;
&lt;td&gt;0.220 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.14 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.68&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;left hook&lt;/td&gt;
&lt;td&gt;fist, 0.110 s&lt;/td&gt;
&lt;td&gt;0.342 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.23 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;right hook&lt;/td&gt;
&lt;td&gt;elbow, 0.106 s&lt;/td&gt;
&lt;td&gt;0.343 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.24 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uppercut&lt;/td&gt;
&lt;td&gt;fist and elbow, 0.081 s&lt;/td&gt;
&lt;td&gt;0.235 s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0.15 s&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0.79&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;* The share of the block’s cover in place when the fist lands, reacting at the first movement plus 100 ms. Times are from the opponent’s decision to punch, which the fighter can’t see. With 100 ms of delay, the jab’s 0.10 s of warning is used up before the fighter even knows it has started. Reacting to what it sees, the fighter can’t add anything to its guard against a full-speed jab. Against the hooks there is time for most of a block.&lt;/p&gt;

&lt;p&gt;One surprise: in every punch the hips move 20–60 ms &lt;em&gt;after&lt;/em&gt; the arm. Tony reads the hip turn; in these punches, the first sign is the elbow or the fist.&lt;/p&gt;

&lt;p&gt;From that table Tony set a pass mark per punch, the share of the punch that must be stopped at full speed: jab 0.50 (keep the guard: beating the jab needs anticipation or distance), cross 0.65, hooks 0.70, uppercut 0.75. Damage counts partially: the share of the fist’s path that reaches the head or neck before it meets an arm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: the opponent
&lt;/h2&gt;

&lt;p&gt;Now the button went, and the policy got four new outputs of its own: one per block. Punches come one after another, with half a second to two seconds of the opponent moving in his stance in between. Tony calls these slow combos: “it’s one shot after another, so it’s not a real true combo.” The opponent’s speed rises with a &lt;a href="https://ai.kakuto.io/en/glossary/curriculum-learning/" rel="noopener noreferrer"&gt;curriculum&lt;/a&gt;: punches start at 50–60 % speed, and the top speed goes up as the fighter passes.&lt;/p&gt;

&lt;p&gt;Getting the fighter to block for itself at all took three runs. Its exploration (&lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;random noise&lt;/a&gt; on its outputs) flipped a button up and down within a step or two, so a random press dropped the block before the arm moved. Presses now hold their block for at least 0.25 s. Then a smoothness term in training (&lt;a href="https://ai.kakuto.io/en/glossary/caps-regularisation/" rel="noopener noreferrer"&gt;CAPS&lt;/a&gt;) was flattening the buttons, since a press is exactly a sudden jump in an output. The buttons were freed from it. In the third run, the fighter blocked.&lt;/p&gt;

&lt;p&gt;It raised the low front block against everything, and it raised it &lt;em&gt;before&lt;/em&gt; the opponent punched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The giveaways
&lt;/h2&gt;

&lt;p&gt;The fighter wasn’t reading punches. It had found a cheaper cue (&lt;a href="https://ai.kakuto.io/en/glossary/shortcut-learning/" rel="noopener noreferrer"&gt;shortcut learning&lt;/a&gt;), and it would do so four times:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;He came alive before each punch.&lt;/strong&gt; Between punches the opponent stood frozen, and each recorded punch began 0.18 s before the press with his stance’s movement. So he twitched just before every punch. The opponent was re-recorded with 2 s of stance motion before each punch, so he never stands still.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each punch had its own distance.&lt;/strong&gt; Tony spotted this one: the hooks stood closer. Head to head, the jab and cross came from 0.78 m, the right hook 0.62 m, the left hook 0.52 m, the uppercut 0.46 m. Telling the distance is easier than telling the punch.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The overlap wasn’t enough.&lt;/strong&gt; Varying each punch’s distance only partly hid it. One distance range (0.57–0.73 m) for every punch fixed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The uppercut stood him lower.&lt;/strong&gt; Each recording had its target at its own height on his body, so lining the uppercut up with the fighter’s head stood him 4–5 cm lower. His head is now at one height for every punch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two other things went wrong in between, neither of them the fighter’s fault. The network scales its inputs using running averages of what it has seen (&lt;a href="https://ai.kakuto.io/en/glossary/observation/" rel="noopener noreferrer"&gt;observation normalisation&lt;/a&gt;). Those averages share one sample count for every input, and by then it was 1.2 billion. The opponent’s inputs, added later, kept their starting values (mean 0, spread 1) when their real spread was 0.29, some 0.016. For five runs the fighter had been all but blind to the opponent. Its buttons pulsed every 0.75 s on its own rhythm, whatever he did. The averages were re-estimated, and still nothing changed: a reward for pressing the suitable button (a dense &lt;a href="https://ai.kakuto.io/en/glossary/reward-shaping/" rel="noopener noreferrer"&gt;shaping reward&lt;/a&gt;) was too weak a signal.&lt;/p&gt;

&lt;p&gt;What worked was telling it directly. The opponent is scripted, so the training knows which punch is coming. An &lt;a href="https://ai.kakuto.io/en/glossary/auxiliary-loss/" rel="noopener noreferrer"&gt;auxiliary loss&lt;/a&gt; pulls the right button’s output up while a punch can be seen, and the others down. The damage still decides whether blocking pays. Within 5 M steps, the fighter raised different blocks for different punches, and right away it found giveaways 3 and 4.&lt;/p&gt;

&lt;p&gt;With all four gone, in the ninth run against the opponent, the fighter waited. No block before he punched. Then the front block against the jab and cross, the right high block against the left hook, the left high block against the right hook and the low front block against the uppercut, with the high blocks rising 0.24–0.28 s into his punch. The check that proves it reads the punch: move his punch later, and the fighter’s block moves with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv8zh171804pxdxroljrh.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv8zh171804pxdxroljrh.webp" alt="Five side views of the MuJoCo fighter blocking a stick-figure opponent's jab, cross, left hook, right hook and uppercut" width="800" height="140"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. The kept model at the moment each punch is scored, full speed, side view. The opponent is drawn as his 16 keypoints: green where the fighter can see them, grey where its own arms hide them. Left to right: jab (low front block, 32 % of the punch through, passes), cross (front block, 32 %, passes), left hook (right high block, 0 %), right hook (left high block, raised 0.26 s into the punch, 79 % through: fails), uppercut (front block, 0 %).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Full speed
&lt;/h2&gt;

&lt;p&gt;Reading the punch was one thing. Doing it at full speed was another. The curriculum only raised the speed once 80 % of punches at the top speed passed, and it never got there: for 23 M steps nothing faster than 60 % was trained. Lowering the bar to 60 % moved it, and full speed reached 21 of 30 test throws. Then it stuck at 13–19 for the next three runs, including one where a quarter of all punches came at full speed.&lt;/p&gt;

&lt;p&gt;What was left was the jab, which the time budget says can’t be read in time, and the right hook. The fighter’s left high block came about 0.1 s after the &lt;a href="https://ai.kakuto.io/en/glossary/oracle/" rel="noopener noreferrer"&gt;oracle&lt;/a&gt;’s, a script that presses the right block at the opponent’s first movement plus the 100 ms delay. Tony’s first idea was a faster left block. Measured first, it wasn’t slow: softer damping and more torque barely changed the damage. The cause was the timing of its guess. Before the punch can be told apart (about 0.22 s in), the right high block’s button hovered half up, a guess at a left hook. In 3 of 12 right hooks it pressed that guess just before the left button rose, and the 0.25 s hold kept the wrong block up through the hook. So a block may now be swapped for another during its hold; only dropping it waits. Without any training, that alone took the right hooks passed from 3 of 12 to 5.&lt;/p&gt;

&lt;p&gt;The last run asked which block actually works at each distance. Holding every block up early against every punch at five distances showed that the rule “one block per punch” was wrong in two places. Against the uppercut, the front block lets only 7–12 % through at 0.59–0.65 m, where the low front block lets 43–68 % through. Against a jab from 0.68 m or more, the left high block stops it better than the front block. The rewards now teach the measured best block at each distance. At 14.5 M steps full speed reached 24 of 30, the best yet, with the jab 6 of 6 and the uppercut 6 of 6.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-1.svg" alt="Full-speed passes of 30 and all-speed passes of 120 for ten opponent runs, opp4 to opp15" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. The opponent runs from the first without giveaways (opp4) to the kept model (opp15), each at its best test. Top: punches passed of 30 at full speed (5 punches × 6 throws). Bottom: passed of 120 (the same at 50, 70, 90 and 100 % speed). Six throws per punch make the scores noisy by a few points. opp7 and opp8 were stopped before their tests.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The kept model, on the skills gate’s tests (8 throws per punch at each speed):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Against the opponent:&lt;/strong&gt; 117 of 160 passed, 31 of 40 at full speed, with no falls. The gated model before it scored 78 of 160.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blocks on command still work:&lt;/strong&gt; all 32 presses covered (left high 0.12 s, right high 0.08 s, front 0.11 s, low front 0.07 s), also with shoves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Old skills kept:&lt;/strong&gt; 61 of 120 punches, 40 of 40 walking targets with no falls. But walking got slower: 8.45 s per target, just over the 8.3 s mark. The model before it, which passes every mark, is kept as a fallback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What it can’t do yet:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The far right hook.&lt;/strong&gt; Held up from before the punch, the left high block still lets about 0.44 of a right hook from 0.73 m through. Those hooks start almost straight ahead and slip between the elbow and the fist onto the temple. A search for a better pose within Tony’s shape found almost nothing (0.77 to 0.79 of the paths stopped): the elbow is at the end of its reach. It needs a different shape, which is Tony’s call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The mid-range uppercut.&lt;/strong&gt; The front block at 0.61–0.65 m is only half learnt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The jab, mostly.&lt;/strong&gt; At training distances, 7 of 12 jabs pass.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Coach Tony thinks
&lt;/h2&gt;

&lt;p&gt;Tony’s most interesting point is about the front block:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;One very interesting point is that if the agent always holds a front block, like the forearm blocking the face, he actually gets penalised, not by the reinforcement learning punishment, but rather by the fact that he won’t be able to see if the hands are in front of the face.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is how the fighter’s vision was built, and it was a deliberate choice. With both forearms in front of its face, the fighter sees none of the 13 points tested on an opponent ahead (Figure 1’s fourth pose): no fists, no elbows, no shoulders. The stance guard sees 10, the low front block all 13 between its fists. There is no reward term for being blind. The cost is meant to be what it costs a real fighter: the next punch comes, and you didn’t see which one. A “can’t see” penalty would first have taught the fighter not to block at all. (There is one small cost for holding any block while no punch is coming, so that it doesn’t keep one up all the time.)&lt;/p&gt;

&lt;p&gt;He also sees how far this is from a fight. The punches come one at a time, from an opponent who stands in range and never feints. In his own thinking out loud during the runs: stay out of jab range so the opponent has to step in, and the step is the tell; move the head in the rhythm so a fast jab can miss; learn an opponent’s habits, his rhythm, his favourite combinations. None of that is in this model. But it now sees an opponent, late and partly blind, and picks a block from what he does, not from where he stands.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path, in numbers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-2.svg" alt="Timeline of the 20 blocking runs from 23:43 UTC on 19 October to 18:04 UTC on 20 October" width="640" height="642"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The 20 runs on one clock (UTC, 19–20 October). Filled bars are runs whose model passed the skills gate and was kept. block1–5 are blocks on command; opp1–15 are against the opponent. The gap at 03:30–05:20 is the punch recording and the time-budget table.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;what changed&lt;/th&gt;
&lt;th&gt;outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;block1&lt;/td&gt;
&lt;td&gt;blocks on command; half the episodes walking and punching; the walker as teacher&lt;/td&gt;
&lt;td&gt;three blocks work; the left high block never covers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;block2&lt;/td&gt;
&lt;td&gt;the arm fitted to the head at each press&lt;/td&gt;
&lt;td&gt;left still 5–13 % covered&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;block3&lt;/td&gt;
&lt;td&gt;a reward pulling the elbow and wrist to the pose&lt;/td&gt;
&lt;td&gt;the guard habit stays&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;block4&lt;/td&gt;
&lt;td&gt;the policy’s arm offsets at 30 % during a block&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;all four covered, every skill kept&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;block5&lt;/td&gt;
&lt;td&gt;soft damping while a high block rises&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;left 0.12 s (from 0.26), right 0.08 s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp1&lt;/td&gt;
&lt;td&gt;the opponent, keypoints, 100 ms delay, real blindness; the fighter’s own buttons&lt;/td&gt;
&lt;td&gt;no block ever kept up&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp2&lt;/td&gt;
&lt;td&gt;presses hold for 0.25 s&lt;/td&gt;
&lt;td&gt;the smoothness term flattens the buttons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp3&lt;/td&gt;
&lt;td&gt;buttons free of the smoothness term&lt;/td&gt;
&lt;td&gt;blocks for itself, but from giveaways 1 and 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp4&lt;/td&gt;
&lt;td&gt;he never stands still; overlapping distances&lt;/td&gt;
&lt;td&gt;giveaways gone; guard only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp5&lt;/td&gt;
&lt;td&gt;a reward for the suitable button&lt;/td&gt;
&lt;td&gt;no change: found the input-scaling bug&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp6&lt;/td&gt;
&lt;td&gt;the opponent inputs rescaled&lt;/td&gt;
&lt;td&gt;no change&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp7&lt;/td&gt;
&lt;td&gt;an auxiliary loss on the buttons&lt;/td&gt;
&lt;td&gt;a block per punch, read from his distance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp8&lt;/td&gt;
&lt;td&gt;one distance range&lt;/td&gt;
&lt;td&gt;the right block per punch, the uppercut read from his height&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp9&lt;/td&gt;
&lt;td&gt;one head height&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;reads the punch&lt;/strong&gt; ; never trained past 60 % speed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp10&lt;/td&gt;
&lt;td&gt;the curriculum’s bar 80 % → 60 %&lt;/td&gt;
&lt;td&gt;full speed 21/30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp11&lt;/td&gt;
&lt;td&gt;a bigger training batch (a speed test)&lt;/td&gt;
&lt;td&gt;the same learning; then a trainer bug, discarded&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp12&lt;/td&gt;
&lt;td&gt;opp11 again from its last clean model&lt;/td&gt;
&lt;td&gt;full speed flat, 13–15/30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp13&lt;/td&gt;
&lt;td&gt;a quarter of the punches at full speed&lt;/td&gt;
&lt;td&gt;full speed flat, 15–17/30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp14&lt;/td&gt;
&lt;td&gt;a block may be swapped during its hold&lt;/td&gt;
&lt;td&gt;19/30; kept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;opp15&lt;/td&gt;
&lt;td&gt;the rewards teach the block that works at each distance&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;24/30, 93/120: kept&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Making training faster and cheaper
&lt;/h2&gt;

&lt;p&gt;The blocking runs were also a day of tuning the training machines. A training run has two sides working at the same time (&lt;a href="https://ai.kakuto.io/en/glossary/decoupled-ppo/" rel="noopener noreferrer"&gt;decoupled PPO&lt;/a&gt;). Worker processes simulate the fighter in hundreds of copies of the environment and collect experience. Learner processes use the last batch of experience to update the network. Whichever side is slower sets the pace, and the other side’s processors wait.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The muscular body was wasting time on its own fists.&lt;/strong&gt; Profiling a punching run counted 38 contacts per physics step, and 31.6 of them were the body touching itself, almost all fingers on fingers inside the fists. The fingers aren’t driven by the policy: motors hold them in a fist, in a pose that overlaps the finger shapes slightly, so the physics resolved about 25 contacts every step for nothing. Turning off contacts between the parts of each hand took that to 12.5 contacts per step and made a physics step 1.8 times faster (742 to 412 µs). The punches still land as before (fist speed 4.06 against 4.12 m/s). This “muscular-fast” body is the default for every run from the fourth opponent run on. It can’t be used for grappling later, when the hand has to open and grip.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A GPU doesn’t help yet.&lt;/strong&gt; A rented &lt;a href="https://ai.kakuto.io/en/glossary/gpu/" rel="noopener noreferrer"&gt;GPU&lt;/a&gt; (a GTX 1080 for about $0.06 an hour, on vast.ai) rendered the fighter at 1920×1080 in 0.4 s, so it is useful for videos. But training waits on the physics, which runs on the CPU, not on the small network. Moving the physics to the GPU would mean rewriting every environment, and the muscular body’s 63 egg-shaped muscles are a bad fit for GPU simulators. vast.ai’s large CPU machines were no cheaper per step than the c8a spot machines on EC2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bigger machines, then faster code.&lt;/strong&gt; In the morning the &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot&lt;/a&gt; quota was raised to 192 &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt;, and the ninth opponent run moved to a c8a.48xlarge: 192 cores for $3.83 an hour. It ran 1.4 times the steps of the 96-vCPU machine for 2.4 times the price. About 70 % of the time its workers were idle, waiting for the learners. Then the code changed, one thing at a time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://ai.kakuto.io/en/glossary/shared-memory/" rel="noopener noreferrer"&gt;Shared memory&lt;/a&gt;.&lt;/strong&gt; The network’s weights and the collected experience had been sent between processes through pipes, copied and repacked by one core. Now every process reads them from the same memory. 44 → 50 M steps an hour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Four learners instead of two&lt;/strong&gt; , with 144 workers. 60 M an hour. A test of seven layouts found all of them limited by the learners: more learners do the maths faster, but spend as much extra time agreeing on each update.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A training batch twice the size.&lt;/strong&gt; Fewer of those agreements per update. It changes how the network learns, so Tony agreed to test it on its own first: 8 % faster, and the fighter learnt about as well per step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each learner prepares its own part of the batch&lt;/strong&gt; , instead of one core preparing it all and sending it out. 70 M an hour, 59 % faster than the morning on the same machine. The first version of this had a bug: three learners prepared their part from a buffer the workers were already refilling, so three quarters of each batch was wrong. 9 M steps of training were thrown away, and every change to the trainer is now checked on its first update.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Which machine is cheapest?&lt;/strong&gt; Faster isn’t cheaper. With the new code, a 96-vCPU c8a.24xlarge ran 50.5 M steps an hour with its workers 85 % busy, a balanced machine. At $1.87 an hour, that is $0.037 per million steps. The 192-vCPU c8a was 1.35 times faster but $0.055 per million, because half its cores still waited for the learners. An m8a with 192 cores did 64 M an hour, nearly as fast as the c8a. The c8i machines split each core into two hardware threads, so a “vCPU” there is half a core: a c8i simulated about 1.45 times slower than a c8a with the same vCPU count. Tony chose cost over speed, and the last two runs went back to 96 vCPUs. Capacity mattered too: the 192-vCPU machines were taken back three times in two hours that afternoon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Flearning-to-block%2Fchart-3.svg" alt="Million steps per hour and dollars per million steps for eight machine and code changes" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. Training speed and cost on the opponent environment, 20 October, in the order things were tried. 192: c8a.48xlarge at $3.83 an hour; m8a: m8a.48xlarge (192 vCPU) at $3.33; 96: c8a.24xlarge at $1.87; c8i: c8i.24xlarge (96 vCPU, two threads per core) at about $1.44. Cost per million steps is the spot price divided by the speed. The 50 and 60 M figures are from a benchmark; the rest from live runs. The c8i figure is from a later run with the batch back at its normal size.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;Most training runs used a c8a.24xlarge on Amazon EC2, a machine with 96 vCPUs, rented as a spot instance in us-east-1 at about $1.4–1.9 an hour. When it had no spare capacity, the launch script fell back to the same size from c8i or c7a. Five runs in the middle used the 192-vCPU machine (above). Amazon took the machine back 13 times. Each run saves a &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt; often, so it carried on where it stopped on a new machine. In the late afternoon spot capacity ran out altogether, and the last two runs finished on on-demand machines at about $4.15 an hour.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;item&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20 training runs&lt;/td&gt;
&lt;td&gt;about 13&lt;/td&gt;
&lt;td&gt;about $30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9 skills gates, punch recordings, the block-by-distance table and a baseline test, on smaller machines&lt;/td&gt;
&lt;td&gt;about 3.5&lt;/td&gt;
&lt;td&gt;about $2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;one speed test of the training layout on 192 vCPUs&lt;/td&gt;
&lt;td&gt;about 0.2&lt;/td&gt;
&lt;td&gt;about $0.80&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 17&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $33&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are estimates from each run’s start and stop times and the price at the time, not from the bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;The fighter can see an opponent and block single punches it can read. The next things it needs are the ones Tony listed. A second, faster punch after the first, so that covering the eyes costs something. Feints. A &lt;a href="https://ai.kakuto.io/en/glossary/recurrent-neural-network/" rel="noopener noreferrer"&gt;memory&lt;/a&gt; longer than a tenth of a second, to learn an opponent’s rhythm and habits. And above all, distance: stepping out of range, so the opponent has to step in, and the step is the tell.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/learning-to-block/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>blocking</category>
      <category>perception</category>
      <category>rewarddesign</category>
    </item>
    <item>
      <title>Footwork: walking to a spot in a Muay Thai stance</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Mon, 19 Oct 2026 15:44:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/footwork-walking-to-a-spot-in-a-muay-thai-stance-459l</link>
      <guid>https://dev.to/kakuto-io/footwork-walking-to-a-spot-in-a-muay-thai-stance-459l</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=qlbGByT2kYo" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fa2i3xrhr9th830dypc0n.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=qlbGByT2kYo" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end of &lt;a href="https://ai.kakuto.io/en/blog/faster-punches/" rel="noopener noreferrer"&gt;the faster punches post&lt;/a&gt;, the fighter could throw five punches from its guard, quickly and on command. But it threw them all from the same spot. A fighter who can’t move can’t choose when to be in range.&lt;/p&gt;

&lt;p&gt;Tony Yum, the coach, puts it like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Controlling the distance is one of the most important facets of striking martial arts. You want to be close enough that you are still engaged, but not close enough that the opponent can hit you. Every striking technique has slightly different range, and your opponent has different range. And so whoever understands the distance best has a huge advantage.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This post is about the first step towards that: footwork. Not the sudden step in to land a punch, or the quick step out to avoid one. That comes later. This is the slow movement at the start of a round, when two fighters are sussing each other out: moving around in a good Muay Thai stance, forward, back, sideways and diagonally, and pivoting to turn.&lt;/p&gt;

&lt;p&gt;It covers 22 training runs over 25 hours, from 17:34 UTC on 18 October to the evening of 19 October. The model that was kept finished training at 15:44 UTC on 19 October.&lt;/p&gt;

&lt;h2&gt;
  
  
  The task: a spot and a facing
&lt;/h2&gt;

&lt;p&gt;The fighter is given a target: a spot on the floor for the ball of its lead foot, and a direction to face. It has to get there, in its stance, and settle. The spot can be anywhere: ahead, behind, to the side, or behind it with an order to turn and face it.&lt;/p&gt;

&lt;p&gt;As with the punches, the movement starts as a &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt;, an animation with no physics in it. This one was built from a 28-second video of Tony walking in his stance: forward, backward, a pivot to face the camera, forward and back again, and pivots back. From the video came a library of single steps: 16 directions around the body, each at any size up to a full step (26 cm forward, 22 cm back, 20 cm to the side), plus pivots to turn left and right. Going forward, the lead foot steps first and lands on its ball; the rear foot follows, low. Going back, the rear foot steps first. Each step is timed to one beat of the fighter’s rhythm, the gentle weight shift it makes in its stance, so the walk keeps the same pulse as everything else it does. The foot and hip positions are scripted, and &lt;a href="https://ai.kakuto.io/en/glossary/inverse-kinematics/" rel="noopener noreferrer"&gt;inverse kinematics&lt;/a&gt; works out the joint angles.&lt;/p&gt;

&lt;p&gt;Something has to decide which step to take next. That is a simple &lt;a href="https://ai.kakuto.io/en/glossary/motion-planner/" rel="noopener noreferrer"&gt;planner&lt;/a&gt;, like the ones that move characters in a video game. At the start of each beat, it looks at where the target is. If the facing is more than 30° off, it pivots. Otherwise it steps straight towards the spot, in whatever direction that is, sized to land on it. The &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt;, the neural network that drives the body, has to turn each planned step into a real one, with real muscles and gravity, while the fighter is being shoved now and then.&lt;/p&gt;

&lt;p&gt;And it must not forget its punches. A frozen copy of the best punching model, the one from the faster punches post, acts as a teacher (&lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;): whenever the fighter isn’t walking, the new policy is pulled towards the teacher’s actions. Walking is free to change; the punches should not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: a pivot can’t twist a loaded foot
&lt;/h2&gt;

&lt;p&gt;Each run continued from the model before it (&lt;a href="https://ai.kakuto.io/en/glossary/fine-tuning/" rel="noopener noreferrer"&gt;fine-tuning&lt;/a&gt;), starting from the punching model. The first run learnt to step, but in 8.8 M &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt; of training it never once turned the body in a pivot. Eight pivots in a row, the hips turned 0° of 45°.&lt;/p&gt;

&lt;p&gt;The reference had spun the lead foot on its ball while the weight was on it. Real feet can do that on a canvas, but the simulated foot’s contact with the floor doesn’t slip when twisted. And the lead hip can’t rotate 45° over a planted foot anyway. The reference was asking for something the body couldn’t do.&lt;/p&gt;

&lt;p&gt;The second run used a different pivot: all the weight onto the flat lead foot, the rear foot lifts and swings round while the hips turn over the planted foot, the rear foot lands, and then the lead foot lifts a little and re-aims. 30° per beat. Within 6 M steps, pivots turned 21–23° each. But now the steps had stopped working: the lead foot hardly moved. The rewards for walking were simply too small. Getting 26 cm nearer the target paid about 0.5 per beat, against about 50 per beat for holding a good stance. The third run made the walking rewards several times stronger, and the steps came back, slowly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: tell the muscles in advance
&lt;/h2&gt;

&lt;p&gt;Steps were landing, but short: a forward step covered 4 % of the planned distance, a sideways one under 20 %. Two changes fixed most of it.&lt;/p&gt;

&lt;p&gt;Each joint is driven by a &lt;a href="https://ai.kakuto.io/en/glossary/position-servo/" rel="noopener noreferrer"&gt;position servo&lt;/a&gt;, a motor that pulls the joint towards a target angle. A servo lags behind a target that keeps moving. So the walk’s servo targets now lead the reference by that lag, a kind of &lt;a href="https://ai.kakuto.io/en/glossary/feed-forward/" rel="noopener noreferrer"&gt;feed-forward&lt;/a&gt;: the muscles are told where the leg will need to be, not where it is now. And 30 % of training episodes now started partway through a step, in the reference’s pose and speed (&lt;a href="https://ai.kakuto.io/en/glossary/reference-state-initialisation/" rel="noopener noreferrer"&gt;reference state initialisation&lt;/a&gt;), so the policy practised the middle of a step and not only its start.&lt;/p&gt;

&lt;p&gt;One run later, steps covered 92 % of the plan going back, 58 % forward and 56 % sideways. Six of eight test targets were reached. The two misses circled round the spot, 10–15 cm away, taking small steps that overshot. The planner was changed so that a spot, once reached, stays reached. From then on, every test target was reached, 8 out of 8, with no falls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: don’t forget the punches
&lt;/h2&gt;

&lt;p&gt;By then the fighter had walked for about 100 M steps, and the punch test said it had lost something. The punching model scored 38 of 60 presses on its own test; the walker scored 20. The teacher’s pull (weight 2) had let the punches drift.&lt;/p&gt;

&lt;p&gt;Raising the teacher’s weight to 10 didn’t help, and the reason was a bug. A neural network sees its inputs scaled to a standard range, using running averages of what it has seen so far (&lt;a href="https://ai.kakuto.io/en/glossary/observation/" rel="noopener noreferrer"&gt;observation normalisation&lt;/a&gt;). The teacher was being fed inputs scaled with the &lt;em&gt;student’s&lt;/em&gt; averages, which had drifted as walking data came in. The teacher’s advice was off by about 0.007 per motor, sometimes 0.025. That is small, but it was the same size as the differences that made the punches miss. Pulling harder towards slightly wrong advice can’t fix anything. With the teacher on its own scaling, the punches came back.&lt;/p&gt;

&lt;p&gt;The test itself also had a flaw. Each test pressed every punch six times, at six moments in the fighter’s rhythm. But the walking environment drew its random numbers in a different order, so its six presses fell at different moments, and six presses swing the score by a lot. The punching model itself scored 19 of 60 in the walking environment, against 38 in its own. With the moments fixed and 20 presses per punch, the punching model scored 112 of 200, and the walker after the fix 107. The loss before the fix had been real, but about 10 points, not 30.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: steer with the steps, not with the rewards
&lt;/h2&gt;

&lt;p&gt;The walk reached every target, but slowly: about 7.5 s per target. Measuring each step showed where the time went. The hips drifted 3–10° per step, always the same way for a given direction, until the facing was so far off that a pivot was needed, and pivots moved the lead foot 5–13 cm.&lt;/p&gt;

&lt;p&gt;The first fix asked the fighter to steer up to 10° per step through the rewards alone. It didn’t learn it, and got slower: the reference’s joint angles were still those of a straight step, so the rewards for matching the pose held the hips straight. The second fix put the steering into the reference: 32 new steps, each a normal step that also turns 10° left or right while the foot is in the air. That worked at once. Forward steps reached their full length (27–28 cm, against 17–22), and a target took 6.7 s instead of 7.4.&lt;/p&gt;

&lt;p&gt;Tony asked for one more thing here: make sure training includes turning all the way round, to face a target behind. It already did (about 11 % of training targets needed a turn of more than 150°), but turning round now took the longest: five or six pivots of about 33°. So the left pivot was made to turn 60°, the hips turning half over the planted lead foot and half over the rear foot once it lands. The right pivot had to stay at 30°: turning right, the rear hip runs out of rotation as soon as the foot swings past the hips. The planner turns the way that needs fewer pivots. A 180° turn on the spot went from 5.9 s to 3.5 s (Figure 2).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjsxbq08b1f0d1fm5kmze.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjsxbq08b1f0d1fm5kmze.webp" alt="Six side-view frames of the MuJoCo fighter in a Muay Thai guard stepping forward towards a green marker on the floor" width="800" height="251"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The kept model walking forward 1.2 m to the green spot (green line: the facing), seen from the side, at 0, 1, 2, 3, 4 and 5.4 s after the target is set. It arrives at 5.4 s, about 10 cm from the spot. No shoves and no exploration noise; with shoves this target takes 7.6 s on average.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosm330gw1xouwawnwd5z.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosm330gw1xouwawnwd5z.webp" alt="Six frames of the MuJoCo fighter pivoting on its lead foot until it faces the opposite direction" width="800" height="251"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. Turning 180° on the spot, at 0, 0.72, 1.44, 2.16, 2.88 and 3.76 s. Three 60° left pivots: the weight goes onto the lead foot, the rear foot swings round in the air, and the hips turn half over each foot. Done at 3.76 s, facing the other way (green line).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: Tony’s eye for style
&lt;/h2&gt;

&lt;p&gt;At this point, the walk worked. It reached all 40 test targets (ten kinds of target, four times each, with shoves) in 6.09 s on average, landing 5.4 cm from the spot, and the punches held. Then Tony watched it as a coach.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After each step it goes back to Muay Thai stance … make the walking stay in walking mode and not flip between stance and walking.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He was right. Every step in the reference started and ended at rest in the stance, and about a quarter of each step had no foot moving. Each step was split into four versions: moving off, flowing through, arriving, and the single step. Walking on, the fighter now passed through the stance instead of stopping in it. The hips still slowed to about a quarter of walking speed at each stance, so the next run paid for the hips’ speed over the floor. That didn’t move it either. Tony saw why first:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After every step it goes into the stance again … almost like there’s 70% weight on the back leg and 30 at the front … ideally, there should be no stance at all, just from step to step.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The reference itself returned to the stance’s weight, 69 % on the rear foot, between every two steps. So the stance was taken out of the middle of a walk: the weight at 50/50 between flowing steps. Then came more of Tony’s notes, one at a time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“The back leg often drags and that even sometimes trips up the model.” The feet were lifted higher, with a reward for clearing the floor and a cost for scraping it.&lt;/li&gt;
&lt;li&gt;“First the heel lift, but then the toes should follow so that in mid-air the foot is flat rather than having the toes hanging down.” The rear foot now levels off in the air. The ankle can’t bend far enough to hold it fully flat behind the body, so it was lifted higher to get close.&lt;/li&gt;
&lt;li&gt;“I still see the heavy back foot weight … and the front leg with the heel off the floor.” The lead heel now stays down between steps.&lt;/li&gt;
&lt;li&gt;“The target destination of the walk doesn’t need to be so accurate … the punch itself should be able to adjust a little bit of distance.” A target now counts as reached within 15 cm and 15°, not 8 cm and 8°.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each change made the walk look more like Tony’s. And each one made it harder. The higher rear foot made every step a balancing act, and the policy answered by taking shorter steps. Then:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It looks like he’s limping … he tilts almost to the front leg, his body even tilts to the left.&lt;/p&gt;

&lt;p&gt;I still see a lot of limping, like it’s bowing diagonally forward, so the torso is bending.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of the new rewards paid for the right share of weight on each foot. The fighter’s way of loading the front foot was to lean over it: a bow, 8.2° beyond the stance’s own lean on average and up to 16°. That is a textbook case of &lt;a href="https://ai.kakuto.io/en/glossary/reward-hacking/" rel="noopener noreferrer"&gt;reward hacking&lt;/a&gt;: it did what the numbers asked, not what was meant. The next run removed that reward and added one for keeping the trunk upright. The bow went (4° on average), but the fighter had been using it to get its weight across. Without it, it couldn’t step left:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The diagonal step is completely wrong. It keeps stepping forward and back. It doesn’t actually move forward.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Steps to the left now covered 9–15 cm of the planned 20, with 90 % or more of the weight left on the rear foot. The fighter stalled about 28 cm from the spot, just outside the 25 cm within which the planner would have called it close enough, and shuffled its lead foot back and forth. One more reward, for the hips following the reference’s path, made it worse: 17 of 40 targets.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fac9ee5ohhh26ffh0t0cx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fac9ee5ohhh26ffh0t0cx.webp" alt="Two front views of the MuJoCo fighter mid-step: on the left the trunk leans diagonally over the front leg, on the right it stays upright" width="800" height="454"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. Bowing and upright, both walking forward to the same target, seen from the front, each at its moment of greatest trunk lean. Left: the 'limp' model, leaning 11.6° beyond its stance over its front leg. Right: the kept model, 3.1°.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Function first
&lt;/h2&gt;

&lt;p&gt;Tony made the call:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay let’s remove all the requirement for the looks. Walking to the target is the most important. Except it should not bow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next run went back to the best walker, the one from before the style work (40 of 40, 6.09 s per target), with its original reference. Every look reward came off: hip speed, foot height, scraping, the weight share. Two things stayed: the reward for keeping the trunk upright, and the loose 15 cm arrival.&lt;/p&gt;

&lt;p&gt;At 20.7 M steps it reached all 40 targets, with no falls, in 6.70 s on average. Its forward bow averaged 2.8° beyond the stance, at most 6.9°. Its punches scored 60 of 120 on the 12-press test, the same as every walking run since the teacher fix. That is the model this post keeps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fwalking-in-the-stance%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fwalking-in-the-stance%2Fchart-1.svg" alt="Targets reached of 40 and seconds per target for eight walking runs, from 'walks on' through the style changes to 'function first'" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The style series, every run tested on the same 40 targets (10 kinds × 4, with shoves). Top: targets reached. Bottom: mean seconds per target reached (the dashed line is the 7 s bar Tony set for the final model). 'walks on' is the model before the style work, and 'function first' went back to it. 'hips' reached only 17 targets, so its time covers only the easy ones.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A last run tried to fix the weak spot: steps sideways. The upright reward had counted any lean as a bow, including the small sideways lean a sideways step needs. So that run allowed sideways lean and banned only forward lean. Its steps got shorter everywhere, and it reached 38 of 40. The sideways lean wasn’t what held the steps back.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Coach Tony thinks
&lt;/h2&gt;

&lt;p&gt;Tony’s own summary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It turns out it’s very difficult to learn how to walk stylistically. It went from lifting the leg at every step, like Muay Thai stance, to limping, putting too much weight on the front leg, dragging the back feet. But the more constraints [I] added on stylistically, the worse the walking becomes. So there’s a balance between style and actual practical movements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is what the numbers show too (Figure 4). Every one of his notes was a fair coaching point, and the fighter did change in the way he asked. But every new rule was one more thing to satisfy at once, on a body that was already busy staying upright under shoves and keeping its punches. Each rule cost a little speed or a little reach, and two of them broke the walk.&lt;/p&gt;

&lt;p&gt;For now, function wins. The fighter gets to the spot, upright, ready to punch. Tony also pointed out that the arrival doesn’t need to be exact: the punch itself can adjust a little for distance and direction. The style can come back later, one rule at a time, on a walk that works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The kept model, tested on the 40 targets with shoves on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every target reached, no falls:&lt;/strong&gt; 6.70 s per target on average, landing 7.8–13 cm from the spot (counted as arrived within 15 cm).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turning round is quick:&lt;/strong&gt; 180° on the spot in about 3.7 s; a target 1 m behind, turn and face it, in about 8.5 s.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upright:&lt;/strong&gt; forward or backward lean beyond the stance 2.8° on average, never over 6.9°, against the limping model’s 8.2° average and 16.3° peak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Punches kept:&lt;/strong&gt; 60 of 120, where the punching model it started from scores about 56 %.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The weak spot is stepping sideways. A sideways step covers 10–11 cm of the planned 20, so it takes more of them: 7.3–8.3 s for a target 0.8 m to the side, about as long as 1.2 m forward (7.6 s). It is also still the walk Tony criticised: it drops back towards the stance between steps, and the trailing foot swings low, heel up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path, in numbers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fwalking-in-the-stance%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fwalking-in-the-stance%2Fchart-2.svg" alt="Timeline of the 22 walking runs from 17:34 UTC on 18 October to 18:33 UTC on 19 October" width="640" height="702"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The 22 runs on one clock (UTC, 18–19 October). Filled bars are runs whose model was kept (frozen). The gap overnight is a pause between runs. 'walk19' was frozen but not used; 'walk22' was frozen but did worse than 'walk21', the model kept.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;what changed&lt;/th&gt;
&lt;th&gt;outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;walk1&lt;/td&gt;
&lt;td&gt;walk to a spot and a facing; the punching model as teacher&lt;/td&gt;
&lt;td&gt;steps work; pivots turn 0°: the reference twisted a loaded foot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk2&lt;/td&gt;
&lt;td&gt;pivot over a planted lead foot, 30° per beat&lt;/td&gt;
&lt;td&gt;pivots learnt; steps stop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk3&lt;/td&gt;
&lt;td&gt;walking rewards several times stronger&lt;/td&gt;
&lt;td&gt;steps start landing, slowly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk4&lt;/td&gt;
&lt;td&gt;servo feed-forward; 30 % of episodes start mid-step&lt;/td&gt;
&lt;td&gt;steps reach 56–92 % of plan; 6/8 targets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk5&lt;/td&gt;
&lt;td&gt;a reached spot stays reached (no circling)&lt;/td&gt;
&lt;td&gt;8/8 targets, no falls; punches drifting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk6&lt;/td&gt;
&lt;td&gt;lower learning rate, tighter landing&lt;/td&gt;
&lt;td&gt;8/8 in 9–11 s, 5–8 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk7&lt;/td&gt;
&lt;td&gt;teacher weight 2 → 10&lt;/td&gt;
&lt;td&gt;stopped: the teacher used the wrong input scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk8&lt;/td&gt;
&lt;td&gt;teacher on its own scaling&lt;/td&gt;
&lt;td&gt;punches back (107/200 against 112); 7.4 s per target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk9&lt;/td&gt;
&lt;td&gt;steer through the rewards&lt;/td&gt;
&lt;td&gt;not learnt, slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk10&lt;/td&gt;
&lt;td&gt;steering steps in the reference&lt;/td&gt;
&lt;td&gt;6.7 s per target, full-length steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk11&lt;/td&gt;
&lt;td&gt;60° left pivots&lt;/td&gt;
&lt;td&gt;180° turn in 3.5 s; 6.3 s per target&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk12&lt;/td&gt;
&lt;td&gt;walk on through the stance&lt;/td&gt;
&lt;td&gt;40/40, 6.09 s; hips still slow in the stance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk13&lt;/td&gt;
&lt;td&gt;reward the hips’ speed&lt;/td&gt;
&lt;td&gt;no change: the reference still stopped in the stance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk14&lt;/td&gt;
&lt;td&gt;no stance between steps; feet lifted, scraping costs&lt;/td&gt;
&lt;td&gt;flowing walk; feet still scrape&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk15&lt;/td&gt;
&lt;td&gt;flat rear foot in the air, lifted 7 cm&lt;/td&gt;
&lt;td&gt;shorter steps, 7.1 s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk16&lt;/td&gt;
&lt;td&gt;lead heel down between steps&lt;/td&gt;
&lt;td&gt;7.4 s; sits back on the rear foot&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk17&lt;/td&gt;
&lt;td&gt;arrival within 15 cm; weight-share reward&lt;/td&gt;
&lt;td&gt;6.7 s, but limps and bows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk18&lt;/td&gt;
&lt;td&gt;trunk-upright reward; weight share off&lt;/td&gt;
&lt;td&gt;no bow; can’t step left, 32/40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk19&lt;/td&gt;
&lt;td&gt;reward the hips’ path&lt;/td&gt;
&lt;td&gt;worse: 17/40&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk20&lt;/td&gt;
&lt;td&gt;the old sideways steps back&lt;/td&gt;
&lt;td&gt;stopped after 5 minutes for walk21&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk21&lt;/td&gt;
&lt;td&gt;walk12’s walk, no look rewards except upright&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;40/40, 6.70 s, no bow: kept&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;walk22&lt;/td&gt;
&lt;td&gt;allow sideways lean&lt;/td&gt;
&lt;td&gt;shorter steps, 38/40&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;Every training run used one c8a.24xlarge on Amazon EC2, a machine with 96 &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt;, rented as a &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot instance&lt;/a&gt; in us-east-1 at $1.48–1.80 an hour. When that type had no spare capacity, the launch script fell back to the same size from the same generation (c8i), and once to the generation before (c7a). It ran 33–38 M simulation steps an hour. Amazon took the machine back mid-run five times. Every run saves a &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt; once a minute, so each time the run carried on from where it stopped on a new machine, losing a few minutes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;item&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;22 training runs&lt;/td&gt;
&lt;td&gt;about 19&lt;/td&gt;
&lt;td&gt;about $29&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;about 30 test and table-building jobs on smaller machines&lt;/td&gt;
&lt;td&gt;about 5&lt;/td&gt;
&lt;td&gt;about $2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;two speed tests of the training layout (one hung for 2 h)&lt;/td&gt;
&lt;td&gt;about 2.4&lt;/td&gt;
&lt;td&gt;about $3.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 26&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $35&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The tests ran on separate, smaller machines, so the training machine never stopped to evaluate. One of the speed tests found that splitting the training work in two ran 4 % faster, which every run since has used. These are estimates from each run’s start and stop times and the spot price at the time, not from the bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;The walk gets the fighter where it needs to be. It doesn’t yet look like Tony walking, and it is slow sideways. Two ideas not yet tried: plan shorter sideways steps, so the plan matches what the fighter actually does, or allow more steps per target.&lt;/p&gt;

&lt;p&gt;The next skill is already building on this model. Blocking training started from it, with the walk, the stance and the punches all held by the same kind of teacher, so the fighter can move, punch and defend in one body.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/walking-in-the-stance/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>footwork</category>
      <category>walking</category>
      <category>rewarddesign</category>
    </item>
    <item>
      <title>Faster punches: from trained amateur towards professional</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Sun, 18 Oct 2026 16:27:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/faster-punches-from-trained-amateur-towards-professional-2hia</link>
      <guid>https://dev.to/kakuto-io/faster-punches-from-trained-amateur-towards-professional-2hia</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=rJ_gUoeeUBE" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvleg431x4uc0ouxglyko.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=rJ_gUoeeUBE" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the end of &lt;a href="https://ai.kakuto.io/en/blog/five-punches/" rel="noopener noreferrer"&gt;the five punches post&lt;/a&gt;, the fighter could throw a jab, a cross, two hooks and an uppercut, into the air or a 35 kg heavy bag, without falling over. Tony Yum, the coach, was happy with it, but not finished.&lt;/p&gt;

&lt;p&gt;His verdict had two parts. First, the punches were okay, but some still fell a little short, above all the cross. Second, the speed. For an average person who trains, it was not bad. At a professional level he expects more: a faster fist at the impact, and the &lt;strong&gt;whole punch&lt;/strong&gt; , from the guard to the target and back, completed faster.&lt;/p&gt;

&lt;p&gt;This post covers the afternoon of 18 October: seven training runs, from 11:45 to 16:27 UTC. Some of the fixes were changes to how the fighter is trained and rewarded. One was a change to its body: Tony allowed the elbow a stronger, faster motor.&lt;/p&gt;

&lt;p&gt;The video at the top of this post shows the result. The figures below are stills from the &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; simulation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure first
&lt;/h2&gt;

&lt;p&gt;Before changing anything, the first step was to measure. Was the fighter slower than its &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt;, the animation each punch is learnt from? Then something in the training was holding it back. Or was it exactly as fast as the animation? Then the animation itself was the ceiling.&lt;/p&gt;

&lt;p&gt;It was the second. Every punch reached the target on the animation’s own schedule, within a few hundredths of a second: the jab in 0.22 s from the button press, the cross in 0.26 s, the hooks in about half a second, the uppercut in 0.36 s. The reason was built into the setup. The &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; doesn’t move the joints directly. It adds a small correction to the animation’s pose, and motors pull each joint towards the sum. The animation ran on its own clock, so the fighter could bend the shape of a punch a little, but not its timing.&lt;/p&gt;

&lt;p&gt;And the &lt;a href="https://ai.kakuto.io/en/glossary/reward-function/" rel="noopener noreferrer"&gt;reward&lt;/a&gt; didn’t ask for more. Nothing paid for reaching the target sooner, and the pay for fist speed stopped growing once the fist matched the animation’s speed. The fighter was doing exactly what it was paid for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: let the fighter set the pace
&lt;/h2&gt;

&lt;p&gt;The first change gave the policy control of the clock. It got one more output, the speed of the punch’s &lt;a href="https://ai.kakuto.io/en/glossary/phase-variable/" rel="noopener noreferrer"&gt;clock&lt;/a&gt;: anything from the animation’s pace to twice as fast. The animation still shows the shape of the punch, but the policy now decides how fast to play it. A new reward paid, once per punch, for reaching the target sooner than the animation, and the pay for fist speed was allowed to grow to one and a half times its old top.&lt;/p&gt;

&lt;p&gt;The first run did the opposite of what was intended. Within 11 M &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt;, every punch had got &lt;strong&gt;slower&lt;/strong&gt; : the jab took 0.36 s to reach the target instead of 0.22, the left hook 0.92 s instead of 0.52. The clock was being turned down, not up.&lt;/p&gt;

&lt;p&gt;The reason was in the reward’s arithmetic. Most of the style terms, how well the hips turn, where the hands are, how upright the body is, are paid on every step, 50 times a second. A punch that takes twice as long collects them twice. That was worth more than the new bonus for being quick, so the policy slowed down to collect. It is a textbook case of &lt;a href="https://ai.kakuto.io/en/glossary/reward-hacking/" rel="noopener noreferrer"&gt;reward hacking&lt;/a&gt;: the policy did what the numbers said, not what was meant.&lt;/p&gt;

&lt;p&gt;The fix was to make the length of a punch irrelevant to its style pay. The clock could now only speed up (one to two times the animation’s pace), and while a punch runs, every per-step reward is multiplied by the clock’s speed. A punch played at double speed collects its style pay at double the rate, for half as long: the same total either way. Only the quickness and the impact can tell a fast punch from a slow one.&lt;/p&gt;

&lt;p&gt;The second run worked straight away for the pivot punches. The hooks reached the target in 0.36–0.39 s instead of 0.48–0.52, and the uppercut in 0.24 s instead of 0.36. They were hitting at 5.5–6.3 m/s. Figure 1 shows the difference on the left hook: by the time the old fighter’s fist reaches the target, the new one has hit and is back in its guard.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ese7122z6bmp2k2fkb0.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8ese7122z6bmp2k2fkb0.webp" alt="Two rows of five frames of the MuJoCo fighter throwing a left hook; in the bottom row the fist reaches the green target two frames earlier and returns to the guard" width="800" height="381"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The left hook in the air, before (top: the five punches post's final model) and after (bottom: the final model of this post), at the same times after the button press: 0.12, 0.24, 0.34, 0.44 and 0.52 s. The green dot is the target. After: the fist reaches it at 0.34 s and is back in the guard by 0.44 s. Before: it arrives at 0.52 s.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: stopping short shouldn’t pay
&lt;/h2&gt;

&lt;p&gt;The straight punches, the jab and cross, didn’t follow. Both now ran up to about 10 m/s, and then braked and stopped about 2.6 cm short of the target.&lt;/p&gt;

&lt;p&gt;Again, the reward explained it. In the five punches work, a punch that fell short was scored by its top speed on the way, so a fist that stopped 3 cm short still learnt something (Tony’s “don’t make it so binary”). With the speed pay raised to one and a half times, stopping 2.6 cm short at 10 m/s now paid more than arriving at 2.4 m/s. A cut fixed it: a punch that stops short is now scored at 0.4 times its top speed, and never above 6 m/s. Stopping short at 10 m/s scores like arriving at 4 m/s, and it earns no quickness pay.&lt;/p&gt;

&lt;p&gt;That run’s jab and cross went through the target again, but they arrived slowly, at about 3 m/s. They stayed that way for 50 M steps: the training numbers in Figure 7 below are flat through the whole run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: an elbow that can straighten
&lt;/h2&gt;

&lt;p&gt;The obvious guess was the hips: perhaps the body wasn’t driving far enough forward for the arm to reach. Measuring showed otherwise. The hips were about where the animation put them. The arm was the problem: the punching elbow never straightened past 37–44°, where the animation reaches 20–25°.&lt;/p&gt;

&lt;p&gt;Was that the policy’s choice? A test answered it. The policy’s elbow output was overridden during the punch, and forced to ask for a fully straight arm. The elbow still stopped at 37–40°. So the policy wasn’t choosing a bent arm. The motor couldn’t straighten it in time.&lt;/p&gt;

&lt;p&gt;Each joint is driven by a &lt;a href="https://ai.kakuto.io/en/glossary/position-servo/" rel="noopener noreferrer"&gt;position servo&lt;/a&gt;. It pulls towards a target angle like a spring, with a damper that resists motion so the joint doesn’t wobble, and its total &lt;a href="https://ai.kakuto.io/en/glossary/torque/" rel="noopener noreferrer"&gt;torque&lt;/a&gt; is capped. On a slow movement the damper hardly matters. On a fast elbow extension it took the whole torque budget, and the animation holds the arm straight for only 0.01 s before it starts back. The fist ran out of time. This was very likely the old “can’t reach” problem of the cross all along.&lt;/p&gt;

&lt;p&gt;Tony’s question was a practical one:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If I allow the elbow to straighten faster would that help? I could continue to use the existing neural network right?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes on both counts. The network’s inputs and outputs don’t change, so training could carry on from the same model. The elbow motors got a 1.5 times higher torque cap, 90 to 135 N m, and a quarter of the damping, 36 to 13.5 N m s per radian. This is a judgement call about the body, not the training: the coach decided the fighter’s elbow should be able to snap straight like a trained athlete’s, and the simulated arm is now stronger there than before. Figure 2 shows the effect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzj15m9allyhvjvi2xajo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzj15m9allyhvjvi2xajo.webp" alt="Two rows of four side-view frames of the MuJoCo fighter throwing a cross; in the bottom row the arm straightens fully and the fist reaches the green target" width="800" height="477"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. The cross from the side, before and after the elbow change, at 0.18, 0.20, 0.22 and 0.24 s after the press. Top: the old elbow motor; the arm stays bent and the fist stops short of the target (green). Bottom: the stronger, less damped elbow motor, one training run later; the arm reaches full length at the target.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The elbow straightened at once: 16–17° at full extension, against 37–44° before. The training hit rate jumped from about 18 % to 27 %, and full-reach jabs hit 41–49 % of the time in training, against 10–14 %. It is the largest single step in Figure 7.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: the shoulder has to come through
&lt;/h2&gt;

&lt;p&gt;The jab was now reaching. The cross was still a centimetre or two short. Measuring along the punch line at full extension showed why: the cross’s hips were in the right place, but its chest and rear shoulder were 6–8.5 cm behind the animation’s. The trunk wasn’t turning the rear shoulder through. A cross is thrown from the back foot through the hips and the trunk to the fist, a &lt;a href="https://ai.kakuto.io/en/glossary/kinetic-chain/" rel="noopener noreferrer"&gt;kinetic chain&lt;/a&gt;, and here the chain broke at the shoulder.&lt;/p&gt;

&lt;p&gt;Was the trunk too weak? No: the spine and shoulder motors never reached their torque caps during the cross. They simply weren’t being asked. So a new reward term asked them: it pays, on every step of a straight punch, for the punching shoulder being no further behind the animation’s than about 4 cm.&lt;/p&gt;

&lt;p&gt;The first version did nothing. The lag opened only in the last one or two steps before the impact, and carried on after it, where the term no longer counted. So it paid almost nothing either way. The second version made it nearly three times stronger (4 per step), narrower (3 cm) and counted it on through the impact. Within 10 M steps the air cross started hitting, for the first time in this whole series. The cross’s shoulder lag at its worst fell from 7–9 cm to 2–6.5 cm, and back to about 0–1 cm by the end of the hit.&lt;/p&gt;

&lt;p&gt;After about 15 M steps the training hit rate levelled off at about 33 %. Ten more million steps changed nothing, so the run was stopped at a &lt;a href="https://ai.kakuto.io/en/glossary/early-stopping/" rel="noopener noreferrer"&gt;plateau&lt;/a&gt;, at 16:27 UTC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The final model was tested the same way as in the five punches post: no exploration noise (&lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;deterministic&lt;/a&gt;), six presses per punch at different moments of the fighter’s rhythm, in the air and against the heavy targets. Figure 3 shows its punches at the moment they reach the target.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff108i0c1cqq60kt7pyif.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff108i0c1cqq60kt7pyif.webp" alt="Five frames of the MuJoCo fighter at the moment of impact of a jab, cross, left hook, right hook and uppercut" width="800" height="189"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. The final model's five punches in the air, each at the moment it reaches the target (green): jab at 0.18 s after the press, cross at 0.22 s, left and right hooks at 0.34 s, uppercut at 0.24 s. All five hit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every punch now reaches the target sooner than before, from 0.04 s sooner for the jab to 0.19 s for the left hook (Figure 4). Every one of them is also sooner than the animation it learnt from. The cross, the punch Tony singled out, changed most: in the air it used to stop short in four presses out of six, at about 1 m/s. Now it lands in five out of six, at 4.4 m/s. Figure 5 has it frame by frame.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-1.svg" alt="Time to the target and fist speed at the target for each punch, before and after the speed work" width="640" height="348"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. Before (the five punches post's final model) and after (this post's), in the air, deterministic, six presses per punch; medians. Top: time from the button press to the fist reaching the target; the dashed marks either side are the reference animation's time. Bottom: the fist's speed along the punch line as it reaches the target. Before, the cross stopped short in four presses of six.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd2p449u9so4tti1r54dj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd2p449u9so4tti1r54dj.webp" alt="Two rows of five frames of the MuJoCo fighter throwing a cross; the bottom row reaches the green target sooner and is pulling back by the last frame" width="800" height="381"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The cross in the air, before (top) and after (bottom), at 0.06, 0.12, 0.18, 0.22 and 0.26 s after the press, same rhythm state. After: the fist is at the target (green) at 0.22 s, at 5.5 m/s, and already on its way back at 0.26 s. Before: it is still travelling at 0.26 s and arrives at 1.4 m/s, too slow to count as a hit.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In the full test it scored 38 hits out of 60, against 34 before, and it never fell (Figure 6).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-2.svg" alt="Final model test: hits in the air and on the heavy targets for the jab, cross, left hook, right hook and uppercut" width="640" height="276"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6. The final model's test, six presses per punch, deterministic. Top: hits in the air (within 10 cm at 3 m/s or more). Bottom: hits on the heavy targets (the 35 kg bag; for the uppercut the 25 kg ball). Total: 38 of 60, no falls (before: 34 of 60). The cross went from 0 to 5 in the air; the jab lost one press on the bag.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not everything got better:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The hooks and the uppercut on the heavy targets&lt;/strong&gt; still connect light: 10–15 N s of &lt;a href="https://ai.kakuto.io/en/glossary/momentum/" rel="noopener noreferrer"&gt;momentum&lt;/a&gt; into the bag, under its bar of about 21 N s, as before. The left hook slows from about 4 m/s in the air to about 1 m/s on the bag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The left hook arrives sooner but a little slower&lt;/strong&gt; : 4.2 m/s at the target, against 5.3 before. The uppercut is about the same. The quickness came mostly from cutting out wasted time, not from a faster fist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The straight punches meet the target at the very end of the arm’s reach.&lt;/strong&gt; They peak at about 8.5 m/s on the way and slow to 4.5–5 m/s by the target. In some rhythm states they still stop just short. A professional punches &lt;em&gt;through&lt;/em&gt; the target, with the hips driving or a step in, so the fist is still accelerating at the impact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The path, in numbers
&lt;/h2&gt;

&lt;p&gt;Every run except the first continued from the model before it (&lt;a href="https://ai.kakuto.io/en/glossary/fine-tuning/" rel="noopener noreferrer"&gt;fine-tuning&lt;/a&gt;). A frozen copy of an earlier model acted as a teacher for the stance and the rhythm, as in the five punches post (&lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;), but it no longer had any say over the punches, whose timing was the thing to change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-3.svg" alt="Training hit rate and full-reach cross hit rate over five chained runs, about 150 million steps" width="640" height="318"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 7. Training, five runs end to end (the first, the slow-down run, was dropped and isn't shown). Teal: the share of all punches in training that hit. Purple: the share of full-reach crosses that hit. Means per million steps, with exploration noise on. The short-fist run is flat for 50 M steps; the stronger elbow and then the stronger shoulder term are the two jumps.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-4.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffaster-punches%2Fchart-4.svg" alt="Timeline of the seven speed runs from 11:46 to 16:27 UTC on 18 October" width="640" height="252"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 8. The seven runs on one clock (UTC, 18 October). Filled bars are the runs whose model was kept (frozen). The 'shoulder' run's first launch crashed at start-up and was relaunched two minutes later. Short gaps between runs were Amazon's spot request for the previous machine still closing.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;what changed&lt;/th&gt;
&lt;th&gt;outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;own clock&lt;/td&gt;
&lt;td&gt;the policy sets the punch’s speed (half to twice the animation’s), a reward for arriving sooner&lt;/td&gt;
&lt;td&gt;every punch slower: per-step style pay rewarded long punches; dropped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clock ×1–2&lt;/td&gt;
&lt;td&gt;the clock only speeds up; per-step pay scaled by the clock’s speed&lt;/td&gt;
&lt;td&gt;hooks and uppercut 25–33 % sooner and hitting; jab and cross stop 2.6 cm short&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;short fist&lt;/td&gt;
&lt;td&gt;a punch that stops short scores at 0.4 times its top speed&lt;/td&gt;
&lt;td&gt;jab and cross reach, but slowly; the elbow can’t straighten; flat for 50 M steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;elbows&lt;/td&gt;
&lt;td&gt;elbow torque cap ×1.5, damping ×0.25&lt;/td&gt;
&lt;td&gt;the elbow straightens; training hit rate 18 % → 27 %&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shoulder&lt;/td&gt;
&lt;td&gt;reward for the punching shoulder keeping up&lt;/td&gt;
&lt;td&gt;too weak: the lag opened after the term stopped counting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shoulder ×4&lt;/td&gt;
&lt;td&gt;the shoulder term stronger, narrower, through the impact&lt;/td&gt;
&lt;td&gt;the air cross lands; 38/60 in the test; final model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;All seven runs used the same machine as the end of the five punches work: a c8a.24xlarge on Amazon EC2, with 96 &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt;, rented as a &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot instance&lt;/a&gt; in us-east-1d at $1.80 an hour. The same machine on demand costs about $4.90. It ran about 37 M simulation steps an hour; the long “short fist” run managed about 25 M, because the progress videos were being rendered on the same machine.&lt;/p&gt;

&lt;p&gt;Every run saved a &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt; once a minute, and a new run could start from any earlier run’s, so a stopped run’s training was never lost. The one crash (an attribute set too late when a training episode started mid-punch) cost three minutes and 9 cents.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;own clock&lt;/td&gt;
&lt;td&gt;0.38&lt;/td&gt;
&lt;td&gt;$0.69&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clock ×1–2&lt;/td&gt;
&lt;td&gt;0.58&lt;/td&gt;
&lt;td&gt;$1.05&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;short fist&lt;/td&gt;
&lt;td&gt;1.6&lt;/td&gt;
&lt;td&gt;$2.88&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;elbows&lt;/td&gt;
&lt;td&gt;0.62&lt;/td&gt;
&lt;td&gt;$1.11&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shoulder (crashed launch)&lt;/td&gt;
&lt;td&gt;0.05&lt;/td&gt;
&lt;td&gt;$0.09&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shoulder&lt;/td&gt;
&lt;td&gt;0.4&lt;/td&gt;
&lt;td&gt;$0.72&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;shoulder ×4&lt;/td&gt;
&lt;td&gt;0.85&lt;/td&gt;
&lt;td&gt;$1.53&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 4.5&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $8&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are estimates from each run’s start and stop times and the zone’s spot price at the time, not from the bill. About 160 M simulation steps in all, about 5 cents per million. The same work on demand would have cost about $22.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next
&lt;/h2&gt;

&lt;p&gt;Tony’s two points were the cross falling short and the punches not being fast enough for a professional. The first is mostly fixed: the cross lands in the air and on the bag. The second is half done. Every punch now completes sooner, faster than the animation it learnt from, but the fist isn’t yet hitting harder.&lt;/p&gt;

&lt;p&gt;That is the next step. The straight punches need to go through the target at speed rather than reach it at full stretch, which means more drive from the hips, or a step in. The same step-in is needed for targets further away, where a real fighter lunges. And the hooks and the uppercut have to put real weight into the bag, not just touch it.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/faster-punches/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>punches</category>
      <category>speed</category>
      <category>rewarddesign</category>
    </item>
    <item>
      <title>Five punches: the cross, the hooks and the uppercut</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Sun, 18 Oct 2026 10:00:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/five-punches-the-cross-the-hooks-and-the-uppercut-lng</link>
      <guid>https://dev.to/kakuto-io/five-punches-the-cross-the-hooks-and-the-uppercut-lng</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=LefFvIvXGqk" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3nmcykfc13twffogofeh.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=LefFvIvXGqk" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ai.kakuto.io/en/blog/teaching-the-jab/" rel="noopener noreferrer"&gt;The jab&lt;/a&gt; took two days. Once it was fast, accurate and stepping in, Tony Yum wanted the rest of the basic Muay Thai punches: the cross, the left and right hooks, and the lead uppercut. All five in one fighter, on command, from the same guard.&lt;/p&gt;

&lt;p&gt;This post covers the next 18 hours: ten training runs, from the afternoon of 17 October to 10:00 UTC on 18 October, when the last one finished. The fighter went from punching the air to punching a 35 kg heavy bag, and from one punch to five.&lt;/p&gt;

&lt;p&gt;Tony’s verdict at the end, in short: it isn’t perfect, and he is happy with it. A couple of punches still fall a little short. The rest look close to how an ordinary person who trains would throw them. The next step is to make them look like an athlete’s, and that is already under way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Four new punches
&lt;/h2&gt;

&lt;p&gt;Each new punch started, like the jab, as a &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt;: an animation built pose by pose from Tony’s description and photos, with no physics in it. His specs read like a coach’s notes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The cross&lt;/strong&gt; (the rear straight). The right arm shoots out, the fist turning over so the palm faces the floor. The chest turns left, the lead foot steps in, and the rear foot pivots on its ball with the heel up. The left glove stays on the cheek.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hooks.&lt;/strong&gt; “The power comes from the legs, hips and core, not the arm.” The arm takes the hook shape, elbow bent about 90° at shoulder height, and then stays locked to the chest. The body’s turn carries the fist through the target. A small wind-up the other way comes first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The uppercut.&lt;/strong&gt; The load is a turn, not a squat. The hips and chest turn left over the lead leg, and the fist drops to chest height. Then the turn reverses from the feet up, and the fist drives straight up into the chin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fighter then has to do all of this in a &lt;a href="https://ai.kakuto.io/en/glossary/physics-simulation/" rel="noopener noreferrer"&gt;physics simulation&lt;/a&gt;, with weight, momentum and feet that can slip. One &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; runs all five punches. It sees which button was pressed and where the target is, and it gets a &lt;a href="https://ai.kakuto.io/en/glossary/reward-function/" rel="noopener noreferrer"&gt;reward&lt;/a&gt; for following that punch’s reference and hitting the target fast. Figure 1 shows where it ended up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fglhwlgp0sk30eq80pbmm.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fglhwlgp0sk30eq80pbmm.webp" alt="Ten frames of the MuJoCo fighter throwing a jab, cross, left hook, right hook and uppercut at a green target dot, before and at the impact" width="799" height="405"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The five punches of the final model (18 October, 10:00 UTC), in the air. Top: just before the impact. Bottom: the moment the fist is nearest the target (green dot). Left to right: jab, cross, left hook, right hook, uppercut. The rear foot comes up onto its ball in the cross and the right hook, and the uppercut's fist arrives from below.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Air, then a pad, then a heavy bag
&lt;/h2&gt;

&lt;p&gt;Tony’s brief had one more part. Real fighters don’t only shadow box, so the fighter shouldn’t either:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Train from hitting air, then a light target, then a heavy bag, so it learns the impact and the recoil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the targets became part of a &lt;a href="https://ai.kakuto.io/en/glossary/curriculum-learning/" rel="noopener noreferrer"&gt;curriculum&lt;/a&gt; (Figure 2). At level 0 the fighter punches a point in the air, and only speed and accuracy count. From level 0 to 1 a pad appears, the size of a focus mitt, on springs, and grows from 0.75 to 3 kg. From level 1 to 2 it becomes a heavy bag on a rope, from 12.5 up to 35 kg. The uppercut gets its own targets, because hitting a hanging bag from below makes no sense: a pad facing down, then a heavy ball hanging at chin height. That was Tony’s idea too.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-1.svg" alt="The target curriculum: level 0 punches the air, levels 0 to 1 a pad on springs from 0.75 to 3 kg, levels 1 to 2 a heavy bag from 12.5 to 35 kg; the uppercut gets a pad facing down and then a hanging ball. The level rises by 0.1 when every punch hits at least 40 % of the time with at most 20 % falls." width="640" height="300"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. The target curriculum. The level rises by 0.1 when, over 20 training iterations, every punch hits at least 40 % of the time with at most 20 % falls. Above level 0, three presses in four get a target and one stays in the air, so the fighter keeps practising both. The green dot is the aim point: from the second morning it sits inside the target, so the punch has to go through the surface.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: don’t forget the jab
&lt;/h2&gt;

&lt;p&gt;The first run started from the best jab and added the four new punches. Within 2.7 M &lt;a href="https://ai.kakuto.io/en/glossary/environment-step/" rel="noopener noreferrer"&gt;steps&lt;/a&gt;, about seven minutes, the jab was falling apart. Its hits dropped from 28 % to 2–7 %, and its speed from 2.7 to 1.3 m/s. The fighter was still on its feet, but it had bought its balance with a slower jab. This is &lt;a href="https://ai.kakuto.io/en/glossary/catastrophic-forgetting/" rel="noopener noreferrer"&gt;catastrophic forgetting&lt;/a&gt;, and an earlier attempt with several buttons had lost the jab in the same way and never got it back.&lt;/p&gt;

&lt;p&gt;The fix was to give the old policy a job: teacher. A frozen copy of the best jab policy watches the new one during training. Whenever no new punch is running, in the stance, the rhythm and the jab, the new policy pays a penalty for doing anything different from the teacher. While a cross, hook or uppercut runs, it is free to learn. This is a form of &lt;a href="https://ai.kakuto.io/en/glossary/policy-distillation/" rel="noopener noreferrer"&gt;policy distillation&lt;/a&gt;, and it worked at once. The jab stayed at 5–6 m/s for the next 36 M steps while everything else was learnt around it.&lt;/p&gt;

&lt;p&gt;The hooks and the uppercut were quick. They hit within about 10 M steps. They are pivot punches: the body turns, the arm is carried, and the reference had already worked out the shape. The curriculum then climbed from the air to the 35 kg bag in about 18 M steps. After about an hour and a half of training, four punches were landing on the heavy bag with no falls. The fists arrived a little slower on the bag than in the air, 3–4 m/s against 5–6, as if bracing for the contact.&lt;/p&gt;

&lt;p&gt;The fifth punch was the cross, and it was 9–12 cm short.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: the cross that rode the rhythm
&lt;/h2&gt;

&lt;p&gt;The cross was the jab’s old problem again. A straight punch from the rear hand has further to go. To reach, the hips have to drive forward about 19 cm in 0.16 s, at up to 1.75 m/s. The policy’s hips stayed 9–11 cm behind the reference’s, so the arm ran out of reach and the fist stopped short.&lt;/p&gt;

&lt;p&gt;The next run gave the cross 40 % of the button presses, a reward for the hips keeping up with the reference, and a target that started 10 cm nearer and stepped back 2 cm whenever the cross hit often enough. The teacher held the other four punches in place. Over 103 M steps the cross went from 17 cm short to reaching its full-reach target.&lt;/p&gt;

&lt;p&gt;But the test videos had been flattering it. Each grid of test videos showed three presses per punch, and those three happened to come at good moments. A wider test, six presses per punch at different points in the fighter’s rhythm, found the cross 0 for 12. Tony’s fighter stands in a Muay Thai rhythm, rocking gently between the feet. The cross only worked when the rock was big. From a big rock the fist arrived at 2.6–4.1 m/s. From a near-still stance it stopped 3–7 cm short, at 0 m/s, in 9 presses out of 10. The policy was borrowing the rock’s momentum for its hip drive, not making its own.&lt;/p&gt;

&lt;p&gt;Two more runs went at this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Press more crosses from a still stance.&lt;/strong&gt; No better: still 3–5 cm short from still, and worse from a rock. Then Amazon took the machine back (more on that below).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pay for the hips’ forward speed and turn directly.&lt;/strong&gt; The turn got fixed: 5–8° short became spot on. The hips moved about 1 cm nearer. After 61 M steps the cross was no better, and slower from a rock.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Three runs had now failed to make the body drive its hips 19 cm in 0.16 s from a dead stop. That was the point to stop changing the reward, and to ask the coach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: through the target, not to it
&lt;/h2&gt;

&lt;p&gt;Tony was watching the grids on his phone, and he saw something else first:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;That green dot, the target should be inside the heavy bag and inside the small target. Otherwise, you’ll end up hitting the surface. You need to go through. So put the target in the middle.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;He was right, and it was a basic mistake. The target’s surface had been placed at the aim point, so every punch was trained to arrive at the surface and stop. The aim point moved inside the target, first at the bag’s centre, then (after “the middle of the bag’s too central”) 7.5 cm in. A hit was now scored where the knuckle meets the surface, and the punch was asked to carry on through it.&lt;/p&gt;

&lt;p&gt;That raised a second question: what should a heavy bag reward? The first answer was distance, how far the bag swings. It plateaued at about 18 cm. The fist stayed on the bag for only 0.04–0.08 s, because the reference pulls the arm straight back, so every punch was a single knock. Then Tony ruled distance out entirely:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Never push the bag. It’s all about impact. Impact and snap back. Don’t push into the bag. Impact and pull back.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the heavy targets now pay for two things. The &lt;strong&gt;impact&lt;/strong&gt; is how fast the bag moves in the first 0.06 s after the fist reaches it, which measures the punch’s &lt;a href="https://ai.kakuto.io/en/glossary/momentum/" rel="noopener noreferrer"&gt;momentum&lt;/a&gt;. The &lt;strong&gt;snap back&lt;/strong&gt; pays for the fist leaving the bag within 0.2 s. The jab learnt both straight away: 31–34 N s into the bag, and off it in 0.06–0.08 s. The cross and the hooks stayed light.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: make it easier to get right
&lt;/h2&gt;

&lt;p&gt;After the cross had stalled through several runs, Tony looked at it as a coach would look at a student who keeps missing:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The target should be a little bit closer. And also whether it’s considered a hit or not, let’s not make it so binary. You get more reward the closer you are to the target.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Three changes followed in the same run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The cross’s target moved 6 cm nearer. A cross that stops short of a target at full stretch is mostly a reach problem, and a real fighter would simply stand a little closer.&lt;/li&gt;
&lt;li&gt;A punch that falls short now scores by its top speed on the way, not zero. Before, the reward jumped from almost nothing to a lot at the surface, and a fist stopping 3 cm short learnt nothing about stopping 2 cm short. Now each centimetre and each m/s counts. This is &lt;a href="https://ai.kakuto.io/en/glossary/reward-shaping/" rel="noopener noreferrer"&gt;reward shaping&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The bars came down. The target for a hit got bigger, 10 cm instead of 5. A test showed the misses were nearly all within 5 cm already, and they missed on speed or impact. So the speed for a hit in the air came down from 3.5 to 3 m/s, and on the heavy bag to about 21 N s from 31. Tony’s answer to that question was two words: “Lower the bars.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The cross started landing. Full-reach crosses in training went from 0 % to 34–42 % hits, and it hit the bag in three test presses out of three.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: what only a coach sees
&lt;/h2&gt;

&lt;p&gt;With the punches landing, Tony’s notes turned to things no hit rate shows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A step back before the punch.&lt;/strong&gt; “Why does it always take a step back?” On the jab, the fighter shifted its weight back, lifted the lead foot and moved it about 5 cm &lt;em&gt;back&lt;/em&gt;, then stepped in. On the cross, the rear foot slid back as the heel came up. The reference does neither: the rear foot stays planted and the lead foot steps straight in. A new reward term paid for neither foot going behind its starting spot until the punch returns. The lead foot’s step back went from up to 4 cm to almost none.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The head.&lt;/strong&gt; “The head’s really tilted to the side.” It was, by about 30–35° in the guard. None of the references tilts it. Tracing back through every saved model found where it came from: a jab run on 17 October that trained against much harder shoves. Before that run the tilt was 5–9°. After it, 20–30°, and the teacher had faithfully passed it on to every run since.&lt;/p&gt;

&lt;p&gt;A reward for keeping the head near the reference did nothing in 6 M steps: the head was a small part of a large reward. So the next test was blunt. The neck and head were locked to the reference, and the punches were re-tested. They scored 15 hits out of 40 locked, against 16 out of 40 free, with the same speeds and no falls. The tilt had been doing nothing useful. The neck stays locked, and the head is level (Figure 3).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3iu8egy1zpghcmhfdgx6.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3iu8egy1zpghcmhfdgx6.webp" alt="Two close-ups of the MuJoCo fighter in its guard: on the left the head tilted to the side, on the right the head level" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. The guard before and after the head fix, from the front, two seconds into the same rhythm. Left: the model at 08:12 UTC on 18 October, head tilted about 30° to the side, a habit learnt under hard shoves the day before. Right: the final model, with the neck and head locked to the reference, head level. The punches scored the same either way.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stands
&lt;/h2&gt;

&lt;p&gt;The final model is from the last run, frozen at 46 M steps. It was tested with no exploration noise (&lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;deterministic&lt;/a&gt;), six presses per punch at different moments of the rhythm, in the air and against the heavy targets. It never fell. Figure 4 shows the bag row, and Figure 5 the scores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcyakx9zk0wen8wckqr3j.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcyakx9zk0wen8wckqr3j.webp" alt="Ten frames of the MuJoCo fighter hitting a hanging heavy bag with a jab, cross and both hooks, and a hanging ball with an uppercut" width="799" height="405"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The final model against the heavy targets: the 35 kg bag, and for the uppercut the 25 kg ball hanging at chin height. Top: just before the impact. Bottom: the impact. The aim point is hidden 7.5 cm inside the surface, so the fist has to go through it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-2.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-2.svg" alt="Final model test: hits in the air and on the heavy targets, and momentum given to the target, for the jab, cross, left hook, right hook and uppercut" width="640" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 5. The final model's test, six presses per punch, deterministic. Top: hits in the air (within 10 cm at 3 m/s or more). Middle: hits on the heavy targets. Bottom: the momentum given to the target in the first 0.06 s after contact; the dashed line is the bag's hit bar, about 21 N s. The uppercut's ball is lighter and its bar is about 17 N s. Total: 34 hits out of 60, no falls.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The jab&lt;/strong&gt; is the best of them: 11 of 12, and 29–33 N s into the 35 kg bag.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The cross&lt;/strong&gt; lands on the bag, 5 of 6. In the air it is fast, about 7 m/s, but passes 2–5 cm off or stops short. This is the punch that is still “a little short”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The hooks and the uppercut&lt;/strong&gt; hit every time in the air, 18 of 18, at 5–6 m/s. On the heavy targets they connect, but light: 11–15 N s on the bag, under its bar.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the coach’s side, that is a fighter with a real combination. The stance holds, the head is up, the feet don’t shuffle back before a punch, and each punch has the right shape: the hips turn, the rear heel comes up on the cross, the hooks are carried by the body. It looks like someone who has trained for a while. Not yet like a fighter.&lt;/p&gt;

&lt;h2&gt;
  
  
  The path, in numbers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-3.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Ffive-punches%2Fchart-3.svg" alt="Timeline of the ten punching runs from 15:53 UTC on 17 October to 10:00 UTC on 18 October" width="640" height="342"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 6. The ten runs on one clock (UTC, 17–18 October). Each run started from the best or latest model of an earlier one. Filled bars are the runs whose model was kept (frozen); outlined ones were stopped or superseded, and their lessons carried forward. The gap before midnight began with a reclaimed spot machine that went unnoticed for an hour.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;what changed&lt;/th&gt;
&lt;th&gt;outcome&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;five buttons&lt;/td&gt;
&lt;td&gt;four new punches on top of the best jab&lt;/td&gt;
&lt;td&gt;the jab decayed within 2.7 M steps; stopped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;teacher&lt;/td&gt;
&lt;td&gt;the jab policy anchors everything except the new punches&lt;/td&gt;
&lt;td&gt;four punches on the 35 kg bag in 36 M steps; the cross 9–12 cm short&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cross&lt;/td&gt;
&lt;td&gt;cross 40 % of presses, hip-drive reward, nearer target that steps back&lt;/td&gt;
&lt;td&gt;the cross reaches, but only from a big rhythm rock; 0/12 in the wider test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;still&lt;/td&gt;
&lt;td&gt;most crosses from a near-still stance&lt;/td&gt;
&lt;td&gt;no better from still; spot machine reclaimed at 32 M&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push&lt;/td&gt;
&lt;td&gt;pay for the hips’ forward speed and turn&lt;/td&gt;
&lt;td&gt;turn fixed, hips 1 cm nearer; not kept&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aim inside&lt;/td&gt;
&lt;td&gt;the aim point inside the pad and the bag&lt;/td&gt;
&lt;td&gt;punches go through the surface; stopped for the next idea&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push the bag&lt;/td&gt;
&lt;td&gt;pay for how far the bag swings; uppercut pad and ball&lt;/td&gt;
&lt;td&gt;plateaued at ~18 cm swing; Tony: “never push the bag”&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;snap back&lt;/td&gt;
&lt;td&gt;pay for impact in 0.06 s and leaving the bag&lt;/td&gt;
&lt;td&gt;the jab learns it; cross and hooks light&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nearer, graded&lt;/td&gt;
&lt;td&gt;cross 6 cm nearer, graded short punches, bigger target, lower bars&lt;/td&gt;
&lt;td&gt;the cross lands: 34–42 % at full reach in training&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;feet and head&lt;/td&gt;
&lt;td&gt;no step back before the punch; head level&lt;/td&gt;
&lt;td&gt;the final model: 34/60, no falls&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What it cost
&lt;/h2&gt;

&lt;p&gt;The fighter trains in the cloud on Amazon EC2 &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot instances&lt;/a&gt;, spare capacity sold at a discount that Amazon can take back at two minutes’ notice. Most of this work ran on a c8a.24xlarge: 96 &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt;, at $1.47–1.80 an hour depending on the zone, against about $4.90 on demand.&lt;/p&gt;

&lt;p&gt;The machine changed at the start of this work. On the usual 64-vCPU machine, the simulation wasn’t the bottleneck any more; the learning update was, and the simulator cores sat idle about 40 % of the time. Moving to 96 vCPUs, with bigger batches and fewer passes over each batch, took training from about 22 M to about 40 M steps an hour: 1.8 times the speed for about 1.5 times the price.&lt;/p&gt;

&lt;p&gt;Spot had its costs. Amazon reclaimed a machine three times in these 18 hours. Twice the run resumed within minutes from its last &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt;. Once, late on 17 October, the watcher kept showing the last status line and nobody noticed for an hour, which is the gap in Figure 6.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;machine-hours&lt;/th&gt;
&lt;th&gt;cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;five buttons&lt;/td&gt;
&lt;td&gt;0.15&lt;/td&gt;
&lt;td&gt;$0.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;teacher&lt;/td&gt;
&lt;td&gt;1.5&lt;/td&gt;
&lt;td&gt;$1.87&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cross&lt;/td&gt;
&lt;td&gt;2.8&lt;/td&gt;
&lt;td&gt;$4.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;still&lt;/td&gt;
&lt;td&gt;0.9&lt;/td&gt;
&lt;td&gt;$1.57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push&lt;/td&gt;
&lt;td&gt;1.8&lt;/td&gt;
&lt;td&gt;$2.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aim inside&lt;/td&gt;
&lt;td&gt;1.0&lt;/td&gt;
&lt;td&gt;$1.50&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;push the bag&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;$2.85&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;snap back&lt;/td&gt;
&lt;td&gt;1.3&lt;/td&gt;
&lt;td&gt;$2.10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;nearer, graded&lt;/td&gt;
&lt;td&gt;1.4&lt;/td&gt;
&lt;td&gt;$2.15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;feet and head&lt;/td&gt;
&lt;td&gt;1.7&lt;/td&gt;
&lt;td&gt;$2.75&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about 14&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;about $22&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These are estimates from each run’s start and stop times and the spot price of its zone at the time, not from the bill. About 470 M simulation steps in all, a little under 5 cents per million.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next: from trained to professional
&lt;/h2&gt;

&lt;p&gt;Tony is pleased with this. The fighter throws five recognisable punches from a Muay Thai guard, on command, into the air or a heavy bag, without falling over. But he wants more than a trained amateur.&lt;/p&gt;

&lt;p&gt;Measuring the final model against the animations showed why it looks the way it does. Every punch reaches the target on the reference’s own schedule: the jab in 0.22 s, the cross in 0.26 s, the hooks in about half a second. Nothing in the reward paid for getting there sooner. The hooks’ fists peak at 5.6–5.8 m/s, against 8.3–8.8 m/s in the animation, and the cross arrives slowly or short.&lt;/p&gt;

&lt;p&gt;A professional’s punch differs in exactly these places. It gets to the target sooner, hits harder at impact, and comes back to the guard faster. So the next runs let the fighter set its own pace, and pay for quickness and for speed at the target. That work started an hour and three quarters after this run finished. It will be the next post, with a video of all five punches.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/five-punches/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>punches</category>
      <category>rewarddesign</category>
      <category>coaching</category>
    </item>
    <item>
      <title>The jab: the simplest punch, and a long lesson</title>
      <dc:creator>Tony Yum</dc:creator>
      <pubDate>Sun, 18 Oct 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/kakuto-io/the-jab-the-simplest-punch-and-a-long-lesson-1647</link>
      <guid>https://dev.to/kakuto-io/the-jab-the-simplest-punch-and-a-long-lesson-1647</guid>
      <description>&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=zF1b_8VsTyM" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F07w57o4xgzg118tsfzf2.jpg" alt="Watch the video on YouTube" width="480" height="360"&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=zF1b_8VsTyM" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The jab is the first punch anyone learns. Lead hand out, lead hand back. Tony Yum has taught it to beginners for years, so he expected it to be the easy one for the AI fighter too.&lt;/p&gt;

&lt;p&gt;It wasn’t. Over two days and 23 training runs, the jab turned out to hold most of the lessons of the project so far. This post follows that path from the coach’s side. The previous posts cover &lt;a href="https://ai.kakuto.io/en/blog/learning-to-balance-in-a-muay-thai-stance/" rel="noopener noreferrer"&gt;how the fighter learnt to stand&lt;/a&gt; and &lt;a href="https://ai.kakuto.io/en/blog/coaching-an-ai-fighter/" rel="noopener noreferrer"&gt;how the coaching works&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a jab really is
&lt;/h2&gt;

&lt;p&gt;To a beginner, a jab is an arm movement. To a coach, the arm is the last link of a &lt;a href="https://ai.kakuto.io/en/glossary/kinetic-chain/" rel="noopener noreferrer"&gt;kinetic chain&lt;/a&gt; that starts at the feet. Tony’s spec for the &lt;a href="https://ai.kakuto.io/en/glossary/reference-motion/" rel="noopener noreferrer"&gt;reference motion&lt;/a&gt; read like a checklist he would give a student:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The lead foot steps forward a little (16 cm) as the fist goes out, and turns with the hips.&lt;/li&gt;
&lt;li&gt;The hips turn about 45° to the right, so the left shoulder goes forward and the right shoulder back.&lt;/li&gt;
&lt;li&gt;The fist turns over on the way, so the palm faces the floor at full extension.&lt;/li&gt;
&lt;li&gt;The weight stays about 50/50 between the feet. The jab doesn’t fall onto the front leg.&lt;/li&gt;
&lt;li&gt;The chin stays tucked behind the lead shoulder. The rear glove comes up beside the right cheek.&lt;/li&gt;
&lt;li&gt;After the snap the fist comes straight back to the guard, and the lead foot steps back into the stance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The fist goes out in 0.14 seconds and is back in the guard 0.14 seconds later. The video at the top of this post shows the result.&lt;/p&gt;

&lt;p&gt;There is a catch. The reference is an animation. It was built pose by pose with &lt;a href="https://ai.kakuto.io/en/glossary/inverse-kinematics/" rel="noopener noreferrer"&gt;inverse kinematics&lt;/a&gt;, shaped by Tony’s corrections until it looked right. Nothing in it obeys physics. It has no mass, no momentum and no feet that slip. It is, in Tony’s words, &lt;em&gt;vibe-created&lt;/em&gt;. Figure 1 shows its key moments, with a line down from its &lt;a href="https://ai.kakuto.io/en/glossary/centre-of-mass/" rel="noopener noreferrer"&gt;centre of mass&lt;/a&gt; to show where the weight sits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Futny7amqxi8fus1e6txa.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Futny7amqxi8fus1e6txa.webp" alt="Five key frames of the jab reference on the grey MuJoCo body, from the front three-quarter view and from the side" width="799" height="424"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 1. The jab reference in MuJoCo, from the front three-quarter view (top) and the side (bottom). Left to right: the stance, the fist on its way out, full extension 0.14 s after the start, the snap back, and the lead foot back in the stance. The red line drops from the body's centre of mass to the floor, so it shows where the weight sits between the feet. This is the animation only: no physics yet.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The fighter then has to do the same movement in a &lt;a href="https://ai.kakuto.io/en/glossary/physics-simulation/" rel="noopener noreferrer"&gt;physics simulation&lt;/a&gt;, where everything has weight. A &lt;a href="https://ai.kakuto.io/en/glossary/reward-function/" rel="noopener noreferrer"&gt;reward function&lt;/a&gt; scores how well it does. The &lt;a href="https://ai.kakuto.io/en/glossary/policy/" rel="noopener noreferrer"&gt;policy&lt;/a&gt; tries millions of jabs and keeps whatever scores best. So everything below is about one question: when the animation and physics disagree, which parts of the animation does the coach insist on, and which does he let go?&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 1: reaching out and touching
&lt;/h2&gt;

&lt;p&gt;The first run copied the reference and paid a reward for hitting a target at full reach. The fighter kept its balance and stretched its arm out, but never stepped. Every jab landed 15 cm short.&lt;/p&gt;

&lt;p&gt;The reason was simple arithmetic. A hit paid about 2 % of what a whole episode paid. Standing still in a good stance paid the rest. So the safe choice was to keep the feet planted. With the hit reward made four times bigger, the fighter started to step and hit. After target distances were added as a &lt;a href="https://ai.kakuto.io/en/glossary/curriculum-learning/" rel="noopener noreferrer"&gt;curriculum&lt;/a&gt;, it hit within 5 cm on 93 % of full-reach jabs.&lt;/p&gt;

&lt;p&gt;Tony watched the videos and wasn’t impressed. “It’s reaching out and touching.” There was no speed and no power.&lt;/p&gt;

&lt;p&gt;This was the first clash between the animation and physics. The reference fist slowed to zero on the target and held there for 0.04 seconds, like a finger pressing a doorbell. The reward paid for every moment the fist stayed near the target, so arriving gently and staying there scored best. The policy did exactly what it was paid for, a mild case of &lt;a href="https://ai.kakuto.io/en/glossary/reward-hacking/" rel="noopener noreferrer"&gt;reward hacking&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the reference changed: no hold, and a quicker jab. The target moved 7 cm inside the point where the reference’s fist stops, so the punch goes &lt;em&gt;through&lt;/em&gt; it, as a real jab goes through the target. The reward changed too. One payment per jab, multiplied by the fist’s speed when it crosses the target.&lt;/p&gt;

&lt;p&gt;The fist’s top speed rose from 5.5 to 7.4 m/s. Jabs at nearer targets now hit at 4.4 to 5.4 m/s, against about 1 m/s before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 2: the step that never came back
&lt;/h2&gt;

&lt;p&gt;Then Tony saw something in the grid of test videos. After each jab, the fighter stayed where it had stepped. A second later it faced 29 to 39° to the right, with both feet 10 to 20 cm from where they had started.&lt;/p&gt;

&lt;p&gt;Every part of the stance reward was measured in the body’s own frame. A stance a little forward and turned to the side scored just as well as the original one. The fighter had no reason to go back, and no way to see where it had started.&lt;/p&gt;

&lt;p&gt;The obvious fix was a “home” reward: after each punch, face forward again with the feet back in place. The fighter learnt that. But it stopped stepping into the jab at all. Its hips ended up 15 to 18 cm behind the reference at impact, and the punch lost its power.&lt;/p&gt;

&lt;p&gt;Was the home reward stopping the step? Two runs went side by side to find out, one with the home reward and one without. Neither stepped. Both lost the jab’s speed, from 1.5 m/s at the target down to 0.4 to 0.7 m/s. Meanwhile their total scores went up, from the stance terms. Not stepping had become a &lt;a href="https://ai.kakuto.io/en/glossary/local-optimum/" rel="noopener noreferrer"&gt;local optimum&lt;/a&gt;. Stepping in &lt;em&gt;and&lt;/em&gt; back would have scored more. But it is a long, coordinated sequence the policy had never found, and every small step towards it scored worse at first.&lt;/p&gt;

&lt;p&gt;Here Tony made a coaching call:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The speed is important and so is the style before and on impact. But the step back can be more relaxed stylistically, to make it easier to recover.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the reward split the jab in two. Up to the impact it asked for style and speed: the reference’s turn, the foot placement, and a fist moving at least as fast as the reference’s. After the impact, the stance reward eased off to simply “stay up and keep your guard” for half a second. The home target also got twice as forgiving, 20° and 12 cm.&lt;/p&gt;

&lt;p&gt;It worked straight away. The new run hit on 54 % of its training jabs at 4.4 m/s. The old reward, over the same time, managed about 0 % at 0.6 to 1.2 m/s.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 3: the hips, and how much rotation to ask for
&lt;/h2&gt;

&lt;p&gt;The arm was now fast, but the hips stayed 11 cm behind the reference at impact. That is an arm punch, the beginner’s mistake of jabbing without the body behind it. In the reward, the hips were worth about 3 points per jab against about 45 for the fist’s speed and the hit. The policy had worked out that the hips didn’t matter much.&lt;/p&gt;

&lt;p&gt;The next run multiplied the impact payment by how close the hips were to the reference’s at impact. Hits dropped to 17 % at first, because the impact suddenly paid less. Then they recovered. By the end the hips were 6 cm behind, with 57 % hits at 4.0 m/s. Most of the gap had been the step’s length, not the hips’ turn.&lt;/p&gt;

&lt;p&gt;Tony then gave the body some freedom:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the hip movement, that rotation, the hip and the feet, is costing the jab speed and accuracy, focus on the top half of the body. The step is still important, stepping forward is important, but the actual rotation can be relaxed a bit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So the hip score now counted only how far the hips lagged &lt;em&gt;forward&lt;/em&gt;, not their sideways offset or their turn. The turn’s tolerance widened from 8° to 20°. A new term asked the arms and shoulders to follow the reference up to the impact. The jab improved again: 66 % hits at 4.5 m/s, hips 5.7 cm behind.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 4: the bow
&lt;/h2&gt;

&lt;p&gt;Freedom has a price. Tony spotted it in the next grid:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After the jab and the recovery, the character wobbles forward like a little bow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Half a second after each jab, the chest pitched 13 to 16° forward, then straightened up. The relaxed return asked only “stay up and keep your guard”, and a bow does both. The body had found the cheapest way to soak up the punch’s momentum.&lt;/p&gt;

&lt;p&gt;The fix was to give the trunk back one rule during the relaxed return: keep the chest within 4° of the reference’s tilt. The legs kept their freedom. The bow went from about 15° to under 4°. The jab got better too: 76 % hits at 4.6 m/s, and the hips 4.9 cm behind, inside the 5 cm goal for the first time. Figure 2 shows one of its jabs, now under physics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdk6g9a9qnk3gn16xz12n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdk6g9a9qnk3gn16xz12n.webp" alt="Five frames of the trained MuJoCo fighter throwing a jab at a green target ball and returning to its guard" width="800" height="178"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 2. One jab by the trained fighter, from the run that fixed the bow (11 M steps), at a target (green ball) level and straight ahead. Left to right: the guard, the fist on its way, the hit, the snap back, and the guard again, with the chest upright. Compare the reference in Figure 1.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It had a side effect. With the chest held only &lt;em&gt;after&lt;/em&gt; the punch, the fighter’s ready stance drifted back to a 5° lean. So the chest rule was extended to cover every moment except the punch’s drive itself. The stance stood upright again, with no bow, and the fighter hit 9 out of 9 test targets at every aim, up to 15 cm off centre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lesson 5: distance
&lt;/h2&gt;

&lt;p&gt;A real opponent isn’t always at the perfect distance, so the targets moved nearer and farther. Two more coaching calls came out of it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Too close.&lt;/strong&gt; A target 25 cm nearer forced a cramped jab: a bent arm and no step. Tony’s verdict: it “looks really bad”, and at that range a fighter should throw an elbow or a knee anyway. The close jab was dropped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Too far.&lt;/strong&gt; For targets beyond full reach, the hips stayed behind again, 9 to 10 cm, and the jab slowed down. A reward for the hips’ position at the moment the fist crosses the target helped full-reach jabs, from about 4 to about 5 m/s. The far jab still didn’t get fast.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That run gave the most accurate jab so far: 85 % hits on a fixed test of 54 jabs, at a median of 4.7 m/s. Figure 3 is the grid Tony got on his phone from that version. The near and mid jabs hit hard. At full reach they still hit, a little slower. The far jabs get there, but slowly. The far jab is waiting for a new reference. Tony will film himself throwing a normal jab and a long one, side on, so the longer step can be copied from a real body.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qw9zuho0wm7mis33tam.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7qw9zuho0wm7mis33tam.webp" alt="A 4 by 3 grid of MuJoCo jabs at targets from 12 cm nearer to 5 cm beyond full reach, each labelled with its distance to the target and fist speed" width="732" height="1234"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 3. A test grid from the most accurate jab (10 M steps), caught at the moment of impact. Each panel is one jab at a fixed target (green ball). Rows: the target 12 cm nearer than full reach, 6 cm nearer, at full reach and 5 cm beyond it. Columns: to the fighter's right, centre and left. Under each panel: how close the fist came to the target and how fast it was going there, green for a hit (within 5 cm at 3.5 m/s or more). The far jabs reach the target at only 1–3 m/s.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The path, in numbers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fteaching-the-jab%2Fchart-1.svg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fai.kakuto.io%2Ffeed-media%2Fen%2Fteaching-the-jab%2Fchart-1.svg" alt="Hit rate, fist speed and hip lag for five jab runs: home reward, style, hips, upper body, upright" width="640" height="408"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure 4. The five jab runs of the early morning of 17 October (UTC), each continuing from the one before. Top: the share of training jabs that hit within 5 cm at 3.5 m/s or more. Middle: the fist's speed at the target. Bottom: how far the hips were behind the reference's at impact (lower is better). Training numbers, with exploration noise on.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The same numbers as a table:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;run&lt;/th&gt;
&lt;th&gt;what changed&lt;/th&gt;
&lt;th&gt;hits&lt;/th&gt;
&lt;th&gt;fist speed&lt;/th&gt;
&lt;th&gt;hips behind at impact&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;home reward&lt;/td&gt;
&lt;td&gt;come back to the stance after each jab&lt;/td&gt;
&lt;td&gt;~0 %&lt;/td&gt;
&lt;td&gt;0.6–1.2 m/s&lt;/td&gt;
&lt;td&gt;12–14 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;style&lt;/td&gt;
&lt;td&gt;style and speed up to impact, relaxed return&lt;/td&gt;
&lt;td&gt;54 %&lt;/td&gt;
&lt;td&gt;4.4 m/s&lt;/td&gt;
&lt;td&gt;10.9 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;hips&lt;/td&gt;
&lt;td&gt;impact pays less with the hips behind&lt;/td&gt;
&lt;td&gt;57 %&lt;/td&gt;
&lt;td&gt;4.0 m/s&lt;/td&gt;
&lt;td&gt;6 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;upper body&lt;/td&gt;
&lt;td&gt;arms first, hip turn relaxed&lt;/td&gt;
&lt;td&gt;66 %&lt;/td&gt;
&lt;td&gt;4.5 m/s&lt;/td&gt;
&lt;td&gt;5.7 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;upright&lt;/td&gt;
&lt;td&gt;no bow in the return&lt;/td&gt;
&lt;td&gt;76 %&lt;/td&gt;
&lt;td&gt;4.6 m/s&lt;/td&gt;
&lt;td&gt;4.9 cm&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Hits and speeds are from training, with the policy’s exploration noise on. Each run continued from the one before (&lt;a href="https://ai.kakuto.io/en/glossary/fine-tuning/" rel="noopener noreferrer"&gt;fine-tuning&lt;/a&gt;), so the skill built up.&lt;/p&gt;

&lt;p&gt;One machine quirk is worth knowing. In several later runs the training numbers held steady while the noise-free, &lt;a href="https://ai.kakuto.io/en/glossary/stochastic-policy/" rel="noopener noreferrer"&gt;deterministic&lt;/a&gt; jab slowly got worse after about 10 M steps. So runs now save a &lt;a href="https://ai.kakuto.io/en/glossary/checkpoint/" rel="noopener noreferrer"&gt;checkpoint&lt;/a&gt; every couple of million steps, and the best one is picked by testing the jab itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it cost, and which machine
&lt;/h2&gt;

&lt;p&gt;The fighter trains in the cloud on Amazon EC2, as described in &lt;a href="https://ai.kakuto.io/en/blog/learning-to-balance-in-a-muay-thai-stance/" rel="noopener noreferrer"&gt;the balance post&lt;/a&gt;. A physics simulator like &lt;a href="https://ai.kakuto.io/en/glossary/mujoco/" rel="noopener noreferrer"&gt;MuJoCo&lt;/a&gt; runs on the processor, one copy of the fighter per core, so the number of &lt;a href="https://ai.kakuto.io/en/glossary/vcpu/" rel="noopener noreferrer"&gt;vCPUs&lt;/a&gt; is what buys speed. A graphics card adds very little.&lt;/p&gt;

&lt;p&gt;The default machine is a c8a.16xlarge: 64 vCPUs, about 29 M simulation steps an hour. Rented as a &lt;a href="https://ai.kakuto.io/en/glossary/spot-instance/" rel="noopener noreferrer"&gt;spot instance&lt;/a&gt;, from Amazon’s spare capacity, it cost about $0.97 an hour in us-east-1 over these two days. The same machine on demand costs $3.28. On that machine a typical jab run of 15 M steps took 40 to 50 minutes, so each experiment cost well under a dollar.&lt;/p&gt;

&lt;p&gt;Three decisions shaped the bill:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Spot, and a fallback when spot fails.&lt;/strong&gt; Amazon can take a spot machine back at two minutes’ notice. Training saves a checkpoint every minute and a watcher relaunches the run, so a reclaim costs a few minutes. On the afternoon of 16 October one run was reclaimed six times in 90 minutes. It moved to an on-demand machine for its last 35 minutes, about $2, to finish. When no c8a was free, a c7a.16xlarge filled in: about 30 % slower, but from a different pool of spare machines.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Two smaller machines for a side-by-side test.&lt;/strong&gt; The account could run 64 spot vCPUs at a time. For the home-reward test, two runs had to start together with the same settings. So they each ran on a c8a.8xlarge: half the cores, at about $0.68 an hour. That is about 40 % more per core, but it gave a fair comparison in the same half hour.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short runs, often stopped early.&lt;/strong&gt; Each run had a deadline and a step budget, and the grids of test videos showed problems within 5 M steps. When a run clearly wasn’t going anywhere, it was stopped and the next idea started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding up the start and stop times of the 23 jab and punch runs from 16 and 17 October gives about 16 machine-hours. At the spot prices of those days that comes to roughly $16, including the on-demand finish. Two days of a coach’s ideas, tested, for the price of a lunch.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the coach learnt
&lt;/h2&gt;

&lt;p&gt;Each fix moved the problem somewhere else.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay for a hit, and the fighter reaches and touches.&lt;/li&gt;
&lt;li&gt;Pay for speed, and it steps in and never comes back.&lt;/li&gt;
&lt;li&gt;Make it come back, and it stops stepping, and the jab goes weak.&lt;/li&gt;
&lt;li&gt;Relax the way back, and it bows.&lt;/li&gt;
&lt;li&gt;Hold the chest after the punch, and the stance leans back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is a bug in the AI. Each time, the policy did exactly what the reward asked. The reference was made without physics, so it can’t all be copied. The coach has to choose which details are the jab and which are decoration.&lt;/p&gt;

&lt;p&gt;For Tony the answer came out in an order he recognises from the gym. The speed and the shape up to the impact come first. The step forward comes next, because that is where the power comes from. The chest stays upright, and the head stays up. The hip turn and the legs on the way back can be looser, as long as the fighter ends up back in its stance, guard up.&lt;/p&gt;

&lt;p&gt;It is also the order in which he fixes a beginner’s jab. A student told to “get back to your guard” often stops stepping in. A student told to “turn your hips” sometimes turns everything and loses the target. Coaching means asking for one thing at a time, and noticing what the student gives up to get it. The fighter just does it faster, and on a phone screen.&lt;/p&gt;




&lt;p&gt;Read it on &lt;a href="https://ai.kakuto.io/en/blog/teaching-the-jab/" rel="noopener noreferrer"&gt;ai.kakuto.io&lt;/a&gt;, with the interactive charts and the glossary.&lt;/p&gt;

</description>
      <category>muaythai</category>
      <category>jab</category>
      <category>rewarddesign</category>
      <category>coaching</category>
    </item>
  </channel>
</rss>
