Skip to content
View talontownsend's full-sized avatar

Block or report talontownsend

Block user

Prevent this user from interacting with your repositories and sending you notifications. Learn more about blocking users.

You must be logged in to block users.

Content in all repositories owned by your account will be closed.
Maximum 250 characters. Please don’t include any personal information such as legal names or email addresses. Markdown is supported. This note will only be visible to you.
Report abuse

Contact GitHub support about this user’s behavior. Learn more about reporting abuse.

Report abuse
talontownsend/README.md

Talon Townsend

Chemical engineer building production ML, control systems, and agentic software. Process R&D and machine learning at J.R. Simplot; finishing a B.S. in Chemical Engineering at the University of Utah (Computational Methods & Data Science emphasis) in May 2027.

The thread through everything here is honest evaluation. Building something that scores well is the easy half. The half I care about is working out whether the score means anything, and saying so when it doesn't.


fh6-traction-control – traction control and ABS with a setpoint you can aim

47th in the world out of 130,698 players, top 1% globally, in the fastest class in the game, with this software in the loop. The car was a ~2000 hp electric hypercar tuned to rear-wheel drive: roughly the worst case a traction controller can be handed, and the far end of the plant-gain range the scheduler exists to cover.

The naive version of this does not work. There is a 100 to 120 ms transport delay between sending a throttle value and seeing the resulting slip, which is enormous for a closed loop; textbook-reasonable gains drive it into a 2.5 Hz limit cycle that is slower than no assistance at all. Slip per unit throttle also varies by an order of magnitude between a hatchback and a hypercar, so the loop estimates plant gain online and rescales the PID against it, delay-matched against the throttle sent one transport delay ago rather than the current one.

The part I find most interesting is a learning problem rather than a control one. Brake slip at peak grip is not a constant: it swings 4x to 7x across tire compounds and surfaces, so the ABS setpoint has to be learned while driving. But a regulating controller censors the evidence it needs to learn. Once it holds slip at the ceiling, it prevents the overshoot that would reveal more grip existing above it. Measured on the rig, the ceiling sat still for six and a half minutes with 49 frames of near-miss evidence stuck just below threshold. Two things break the deadlock: the first few frames after a cut still reflect full brake torque because of the transport delay, making every hard stop a free open-loop probe, plus deliberate bounded probe pulses in straight-line braking only.

Most of the remaining engineering is refusing to learn from misleading frames. Seven evidence gates, each added because replaying real recorded telemetry showed the previous version reaching a measurably wrong conclusion: partial-pedal braking looks identical to grip falloff, downforce makes available grip speed-dependent, braking over a crest unloads the wheels and reads exactly like total grip collapse. The learner is tested against a bundled recording, so analysis/replay_learner.py lets you check the claims rather than believe them.

Tested without a game, a controller, or drivers: roughly 190 checks including delayed-plant simulations swept across plant gains that assert bounded oscillation. That suite is what caught the limit cycle.

so2-virtual-analyzer – running live in a 2,200 ton/day sulfuric acid plant

An SO₂ emissions model that takes over when the regulatory monitor goes offline. Test R² 0.908, RMSE 11.7 ppm, and it passes the EPA's Relative Accuracy Test Audit, a federal field validation rather than a held-out split. Outage-safe by construction: no monitor signals or target history anywhere in the feature set, because a backup that depends on the thing it's backing up isn't a backup. Chronological calendar-day splits and forward-chaining CV that mirrors the live retrain. Scores every 15 minutes, retrains monthly.

LLM-Chess-Player – post-training a 1.3B model on one RTX 4090

LoRA SFT → GRPO-based RLVR → an endgame demonstration curriculum. Fixing the SFT loss function took top-1 move accuracy from 10% to 21%, and game strength barely moved. The bottleneck was never prediction. It was conversion: executing a technique the model already knew. RL plateaued there at 0–2%; a single SFT pass over demonstrations reached 59%. Procedures have to be demonstrated, not reward-shaped.

I hand-wrote a pure-Python alpha–beta engine (~1538 Elo at depth 4) purely to serve as an independent evaluator, because the metric I started with was measuring the wrong thing and I couldn't tell from inside it.

ziggy-racer – an autonomous racing controller with no neural network in the control path

A 71 Hz sense → plan → act loop: UDP telemetry in, virtual gamepad out, OCR for the state no API exposes. Friction-circle grip model with live load-transfer measurement, so it lifts before the rear goes light rather than after. Off-track rate cut from 6.4% to 1.4%; laps within about a second of the game's built-in AI.

Every change lives behind a config flag and gets A/B tested against a continuous log. The fix I'm most pleased with landed at p ≈ 0.0001 on a Fisher's exact test. The engineering logbook records every lever that didn't work, with reasoning, so I don't quietly retry it six weeks later.

wordle-neural-solver – 2.9M parameters, no dictionary at inference

Policy distillation from a classical teacher, plus DAgger iterations targeting the states where the student actually broke. 99.56% win rate across all 14,855 words; 89.81% in hard mode with zero rule violations across 66,580 guesses. It emits valid dictionary words 100% of the time having never been shown a dictionary.


Also here: Lua and Java patches for game mods, mostly finding performance bugs in code I didn't write, then publishing the fix along with how I found it.

How I work

  • Validate chronologically. Random splits on time-series data are the most comfortable way to fool yourself.
  • Build the independent evaluator before trusting the metric. If the only thing checking your model is the thing that trained it, you don't have a measurement.
  • Refuse to learn from misleading data. Most of the work in an adaptive system is deciding what does not count as evidence, and you only find those cases by replaying what actually happened.
  • A/B test with significance testing. "It feels better" is a hypothesis, not a result.
  • Publish the negative results. The levers that didn't work are usually worth more to the next person than the one that did.

Salt Lake City, Utah · LinkedIn · talon.townsend11@gmail.com

Pinned Loading

  1. so2-virtual-analyzer so2-virtual-analyzer Public

    ML virtual analyzer predicting stack SO2 for a sulfuric-acid plant as a CEMS-outage backup. CatBoost, leakage-safe chronological evaluation, outage-safe features, deployed on SEEQ Data Lab. Test R2…

    Python

  2. wordle-neural-solver wordle-neural-solver Public

    A 2.9M-parameter neural network that plays Wordle blind - no dictionary, no candidate list, no search. 99.56% exact win rate over all 14,855 words.

    Python 1

  3. ziggy-racer ziggy-racer Public

    Autonomous self-driving controller for Forza Horizon 6 — a control stack that teaches itself a race circuit from physics and its own experience, driving through a virtual gamepad. Self-taught to wi…

    Python

  4. LLM-Chess-Player LLM-Chess-Player Public

    Fine-tuning a 1.3B LLM to play chess on a single RTX 4090 - SFT, RLVR/GRPO, conversion curricula, and a hand-built alpha-beta engine, all honestly measured

    Python