Adversarial examples playground
A neural network can be confidently, catastrophically wrong on an input that looks completely normal to you. Pick or draw a digit, then add a gradient-crafted perturbation and watch the classifier flip — while the image looks unchanged. This is the family of attack at the centre of my research; here it runs live in your browser.
How it works
The classifier is a small multilayer perceptron — 784 inputs (one per pixel), a 128-unit hidden layer, ten outputs — trained on MNIST to about 98% accuracy. It is deliberately tiny and dependency-free: the weights are a ~150 KB file, and the forward pass is a few dozen lines of hand-written TypeScript. No TensorFlow.js, no ONNX runtime, nothing loaded from a CDN.
The attack is the interesting part. FGSM — the Fast Gradient Sign Method — asks a simple question: for each pixel, which way should I nudge it to make the model more wrong? That direction is the sign of the gradient of the loss with respect to the input, so the whole attack is x′ = x + ε · sign(∇ₓ loss). To compute ∇ₓ I run the same backpropagation the trainer used, but stop one layer early — at the image instead of the weights. PGD (Projected Gradient Descent) iterates that step and projects back into an ε-ball each time; it’s slower but stronger, and it’s the standard benchmark attack in the literature.
Because the perturbation is bounded by ε in the L∞ sense — no single pixel moves by more than ε — a small ε stays invisible to the eye while still crossing the model’s decision boundary. That is the whole unsettling point of adversarial examples: robustness to random noise says nothing about robustness to adversarial noise.
My MSc research applies exactly this idea outside the image domain — to intrusion-detection models on the Controller Area Network bus, where an attacker perturbs network features rather than pixels to slip malicious traffic past a deep-learning detector, and where adversarial training (folding these very examples back into training) is one of the defences. Digits are just the version you can see. Honest caveats: this is a plain MLP, not a hardened or adversarially-trained model, and a hand-drawn digit is normalised to roughly match MNIST — so treat it as an intuition pump, not a benchmark.