Machine Learning Engineer
I build ML tools that work on data they've never seen before.
Two pure-frontend pieces, built to show both halves of graphics programming.
Crumb — a cafe site where the food is a live 3D render, not a photograph. Scroll and a burger flies toward you, comes apart layer by layer, and reassembles. No model files: a bun is a profile curve spun around an axis, cheese is a superellipse with drooping corners. Solid shaded meshes, per-fragment lighting, a real shadow map — and a test that projects the meshes through the camera to prove the food never leaves the shot. Take a look →
Inside a Neural Network — scroll, and the camera flies through a five-layer network while it computes. The opposite discipline: additive points and lines, no depth buffer at all, three instanced draw calls for 12,670 instances. The whole choreography is one pure function of scroll position, tested in Node without a browser. Take the flight →
Both are hand-written WebGL and GLSL. No three.js, no framework, no build step.
You bring your own CSV and they figure it out. Most run real Python — scikit-learn, statsmodels, scipy — compiled to WebAssembly in your browser, so there's no server to wake up, nothing to sign up for, and nothing you upload ever leaves your machine.
| Project | What it does | Try it |
|---|---|---|
| AutoML Studio | Infers column types, detects the task, builds the pipeline, trains a model family — on any CSV | demo |
| Drift Detector | PSI, KS and chi-square between two data snapshots, ending in one actionable verdict | demo |
| A/B Test Analyzer | Significance, power and Bayesian P(B>A) — statistics validated against scipy on 464 cases | demo |
| Time Series Forecaster | Eight models scored by walk-forward validation against naive baselines | demo |
| Clustering Explorer | Finds segments, then checks them against a shuffled null | demo |
| Digit Recognizer | 97.58% on held-out MNIST, running as a 40-line forward pass in plain JavaScript | demo |
| EDA Report | Ranked findings plus associations df.corr() cannot see; exports one self-contained HTML file |
demo |
| Dataset Explorer | Opens a 100,000-row CSV in 461 ms and scrolls it at 60 fps | demo |
| Chart Studio | Seven chart types as hand-written SVG, with SVG and PNG export | demo |
Because a model is easier to feel than to read about.
| Project | The idea | Try it |
|---|---|---|
| Mind Reader | Rock paper scissors against a Hedge ensemble that learns your habits — 100% against a predictable player, and correctly 32.9% against a truly random one | play |
| Keep a Straight Face | The page tries to make you laugh; a smile detector calibrated to your own resting face decides when you cracked | play |
| Hum to Fly | Flappy Bird where pitch is altitude, driven by a YIN detector accurate to 0.05 cents | play |
| Gesture Drive | Steer a car with your index finger — MediaPipe plus a One Euro filter tuned against a jitter-matched EMA | demo |
| Expression Reader | Teach a face-expression classifier your own face in ten seconds — softmax regression written from scratch, trained in the browser | demo |
The model is the easy part. Calling .fit() is four characters. What
decides whether a project works is everything around it — and each of these got
the wrong answer at some point, producing plausible output rather than an
error:
- Is an all-unique integer column an ID, or a rounded price? (Getting it wrong turned a regression into a nonsense 4-class problem.)
- Does
resample().sum()return0orNaNfor a month with no sales? (It returns0, so three missing months became a revenue collapse that never happened.) - Is
01/02/2023January 2nd or February 1st? (pandas parses both happily, so counting successful parses cannot tell them apart.)
A number nobody checked is a guess. The A/B analyser's distribution
functions are validated against scipy on 464 committed cases at 1e-12. The
digit recognizer's JavaScript forward pass matches its NumPy original to
4.77e-6. Writing those checks is where most of the bugs turned up — including
normCdf(-20) returning 0 instead of 2.75e-89.
Say when the answer is weak. k-means will happily partition pure noise. A 40-row dataset will report 94% cross-validated accuracy and 56% on held-out data. A test checked twenty times has a 64% false-positive rate, not 5%. These tools say so, in plain language, at the point where you'd otherwise draw the wrong conclusion.
Python · scikit-learn · pandas · NumPy · SciPy · statsmodels · FastAPI
Computer vision · MediaPipe · Signal processing · Web Audio · Canvas
JavaScript · SVG · Canvas · Web Workers · Pyodide / WebAssembly
Git · GitHub Actions · Playwright · Docker
See all fourteen projects →
LinkedIn ·
devapriyan1723@gmail.com


