title: Spam Email Classifier with XAI (v2)
emoji: π§
colorFrom: blue
colorTo: red
sdk: gradio
sdk_version: 5.23.0
python_version: '3.11'
app_file: app.py
pinned: false
license: mit
tags:
- spam-detection
- xai
- lime
- shap
- eli5
- scikit-learn
- nlp
- explainable-ai
models:
- VoltageVagabond/spam-xai-model-v2
- VoltageVagabond/spam-classifier-mlx
- VoltageVagabond/spam-classifier-liquid
datasets:
- VoltageVagabond/spam-email-dataset
Spam Email Classifier with XAI Explanations
ENGT 375 β Applied Machine Learning | Spring 2026 | Old Dominion University
Disclaimer: This model was created as a student project for Applied Machine Learning at ODU. It is intended for educational and research purposes only and should not be used as a sole spam/phishing filter in production. Classification accuracy may vary, and the model may produce incorrect or misleading results. Always use established email security tools for real-world spam filtering.
A Gradio web app that classifies emails as spam or ham and provides explainable AI (XAI) insights using three different methods (LIME, SHAP, and ELI5).
What's new in v2: beginner-friendly notebook refactor (explicit for-loops over comprehensions, no decorators, no premature abstractions), lecture-style charts in the student teaching notebook, a separate app_student.py / utils_student.py / retrain_student.py track for course readers, and a fresh full-dataset retrain (99,999 samples β 69,999 train / 30,000 test) producing a re-tuned classification threshold of 0.3714. v2 is deployed as its own HuggingFace Space at VoltageVagabond/spam-xai-classifier-v2.
Features
- Paste any email and get an instant spam/ham prediction
- LIME explanations β which words pushed the decision
- SHAP feature importance β game-theoretic attribution
- ELI5 β model internal feature weights and permutation importance
- Side-by-side comparison of all three XAI methods
- Plain English summary of why the model made its decision
- User feedback β thumbs up/down to log corrections for batch retraining
- Adjustable classification threshold
How to Run Locally
# Install dependencies
pip install -r requirements.txt
# Train the model (first run only β produces models/voting_model.joblib)
python3 train_ensemble.py
# Launch the Gradio web app
python3 app.py
# Or open the student teaching notebook
jupyter notebook notebooks/spam_classifier_xai_student.ipynb
You can also double-click any of these .command files in Finder:
launch-gradio.commandβ opens the Gradio web UI in your browserlaunch-notebook.commandβ opens the student notebook in Jupyterlaunch-app.commandβ opens the legacy Streamlit app (kept for reference; the active UI islaunch-gradio.command)retrain-fast.commandβ quick retrain (~2-5 min, single RF, no grid search)retrain-full.commandβ full retrain (~15-30 min, voting ensemble + grid search)
Retraining
python3 retrain.py --mode fast # quick retrain, single RF
python3 retrain.py --mode full # full retrain, voting ensemble + grid search
python3 retrain.py --mode full --no-feedback # full retrain, ignore user feedback log
The retrain script reads accumulated user corrections from data/feedback/feedback_log.csv and merges them into the training data with 5x weighting.
Model
Voting ensemble (Random Forest + Logistic Regression + Linear SVM with calibration) trained on the full Kaggle 100K spam dataset + GitHub email-dataset (99,999 samples total: 69,999 train / 30,000 test), using 3,000 TF-IDF features + 24 hand-crafted metadata features.
| Model | Accuracy | F1 Score |
|---|---|---|
| Random Forest | 97.75% | 0.976 |
| Logistic Regression | 96.57% | 0.964 |
| SVM (LinearSVC + calibration) | 96.89% | 0.967 |
| VotingClassifier (deployed) | 97.40% | 0.973 |
Optimal classification threshold: 0.3714 (targeting 99% ham precision; value read from models/optimal_threshold.joblib written by train_ensemble.py).
Notebooks
| Notebook | Purpose |
|---|---|
notebooks/spam_classifier_xai_student.ipynb |
Main teaching notebook (turn-in artifact for the course). Full XAI walkthrough with LIME, SHAP, ELI5, and a feature reduction experiment based on Kuzlu et al. 2020 |
notebooks/spam_classifier_gradio.ipynb |
Shorter pipeline focused on the ensemble model and Gradio deployment |
Documentation
docs/references/how-to.htmlβ full reference index with clickable links to all local PDFs (LIME, SHAP, TreeSHAP, Kuzlu et al., 5 spam-detection papers) and HTML guides (sklearn user guide, Gradio quickstart, HF Spaces docs, Molnar Interpretable ML book)docs/07-code-sources-reference.mdβ markdown version of the references with citation entriesCHANGELOG.mdβ full project history from v0.1 (Streamlit) through v1.1 (merged Gradio)
Tech Stack
- scikit-learn β Random Forest, Logistic Regression, LinearSVC, VotingClassifier, CalibratedClassifierCV, TfidfVectorizer, MinMaxScaler, GridSearchCV, metrics
- LIME + SHAP + ELI5 β explainability
- Gradio β web interface (live deployment on HuggingFace Spaces)
- NLTK β text preprocessing (Porter stemmer, English stopwords)
- scipy.sparse β efficient handling of TF-IDF + metadata feature combination
Sibling Projects
This is the sklearn / classical ML variant. Two LLM-based variants are in sibling folders:
../spam-classifier-mlx/β Apple MLX LoRA fine-tune of Qwen3.5-0.8B../spam-classifier-liquid/β HuggingFace TRL+PEFT LoRA fine-tune of Liquid AI LFM2.5-1.2B
Citation
If you reference this work academically:
Balfour, D. (2026). Spam Email Classifier with Explainable AI.
ENGT 375 Applied Machine Learning project, Old Dominion University, Spring 2026.
https://huggingface.co/spaces/VoltageVagabond/spam-xai-classifier-v2