Skip to content

About

Browser-side FGSM adversarial attack demo using TensorFlow.js and MNIST samples.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

MNIST-Adversary

Interactive adversarial ML demo for MNIST digit classification. The browser shows FGSM on real test-set digits, and the Python tooling evaluates the same exported CNN against random noise, FGSM, and PGD.

Live demo | Course presentation

This project was built for CS38300 Ethics in Machine Learning. The goal is to make adversarial examples visible: start with a real MNIST test-set image, compute an input-gradient perturbation, and watch a compact CNN's prediction change as epsilon increases.

What is real

  • The selected digit images are real MNIST test-set samples from public/mnist_samples.json.
  • The browser loads exported CNN weights from public/model_weights.json.
  • FGSM is computed in TensorFlow.js with the gradient of the loss with respect to the input image.
  • Model metrics are exported to public/model_metrics.json.
  • scripts/evaluate_attacks.py loads the exported weights and compares random noise, FGSM, and PGD over multiple epsilon values.
  • Attack results are written to public/attack_results.json, public/attack_results.md, and public/examples/attack_comparison.png.
  • scripts/train_mnist.py trains the model and exports the public JSON assets used by the browser.

What is intentionally limited

  • This is an educational demo, not a robust adversarial-ML benchmark.
  • The model is a compact two-epoch CNN, not an adversarially trained classifier.
  • The UI shows one curated test sample per digit so the attack is easy to inspect.
  • The offline evaluation uses a fixed 2,000-example subset by default so it can run quickly on a laptop.

Model

Architecture:

Input 28 x 28 x 1
Conv2D(32, 3x3, ReLU, same padding)
MaxPool(2x2)
Conv2D(64, 3x3, ReLU, same padding)
MaxPool(2x2)
Dense(128, ReLU)
Dropout(0.25 during training)
Dense(10, Softmax)

Current exported FGSM evaluation from the full MNIST test set:

FGSM epsilon Test accuracy
0.00 98.54%
0.05 95.85%
0.10 88.81%
0.15 74.43%
0.20 52.65%
0.25 28.92%
0.30 11.62%

Attack comparison

The comparison below was generated with:

python3 scripts/evaluate_attacks.py --limit 2000 --pgd-steps 10

It uses the same exported weights as the browser demo. Random noise is included as a sanity check, not as an adversarial method.

Attack 0.00 0.05 0.10 0.15 0.20 0.25 0.30
Random noise 97.90% 97.80% 97.95% 97.80% 97.90% 97.75% 97.55%
FGSM 97.90% 94.35% 86.25% 68.85% 47.50% 24.00% 9.30%
PGD 97.90% 94.00% 79.90% 47.25% 9.85% 0.15% 0.00%

FGSM and PGD comparison

Demo walkthrough

1. Start from a clean MNIST image

The model first classifies the selected test-set digit with high confidence.

Initial State

2. Increase epsilon

The app computes:

x_adv = clip(x + epsilon * sign(grad_x loss(model, x, y)))

The perturbation view shows which pixels are brightened or darkened.

Noise Visualization

3. Inspect the misclassification

At higher epsilon values, the adversarial image can still look like the original digit to a human while the classifier's top prediction changes.

Misclassification

Run locally

npm install
npm run dev

Open http://localhost:3000.

GitHub Actions runs TypeScript checks, a production build, and the Python tests on pushes and pull requests.

Reproduce the model export

The app does not need Python to run. Python is only needed if you want to retrain/export the model assets.

python3 -m pip install numpy pillow pytest torch
python3 scripts/train_mnist.py
python3 scripts/evaluate_attacks.py --limit 2000 --pgd-steps 10
python3 -m pytest -q

The script writes:

  • public/model_weights.json
  • public/model_metrics.json
  • public/mnist_samples.json
  • public/attack_results.json
  • public/attack_results.md
  • public/examples/attack_comparison.png

Stack

  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • TensorFlow.js
  • PyTorch
  • GitHub Actions

Reference

Goodfellow et al. (2015). Explaining and Harnessing Adversarial Examples. ICLR. arXiv:1412.6572

About

Browser-side FGSM adversarial attack demo using TensorFlow.js and MNIST samples.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages