Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ML Spam Detector API with Explainability

A machine learning system that classifies/detects SMS spam messages using TF-IDF vectorization using logistic regression (scikit-learn) with ~96.42% accuracy, exposes predictions via a FastAPI JSON API, and explains why the model made each decision using interpretable feature contributions. You can interact with the API from simple CLI utilities.

The model is trained on the UCI SMS Spam Collection dataset and is saved as artifacts/model.joblib. The dataset contains 5,574 SMS messages labeled as ham (not spam) or spam, stored as tab-separated lines with two columns: label and text (the message content). This project maps ham to 0 and spam to 1, then trains and evaluates using a stratified train/test split.

Key Features

Spam classification using:

  • TF-IDF vectorization
  • Logistic Regression (scikit-learn)

Model explainability:

  • Shows which words influenced the prediction
  • Percent-based contribution for interpretability

FastAPI backend:

  • /predict endpoint for real-time inference

Human-friendly CLI client:

  • Pretty-printed predictions and explanations

Pytest test suite:

  • Model tests
  • Prediction logic tests
  • API endpoint tests

Dockerized:

  • One-command containerized deployment

Example Output

utils/call_api.py output

API Response:
{
    "message": "free phone now",
    "prediction": "spam",
    "confidence": 52.515,
    "explanation": [
        {
            "word": "free",
            "direction": "spam",
            "percent": 79.99
        },
        {
            "word": "phone",
            "direction": "spam",
            "percent": 20.01
        }
    ]
}

utils/call_api_pretty.py output

"free phone now"

Prediction: SPAM
Confidence: 52.515%

Why? (Percentages show relative contributions of words to the model's decision, not absolute probability)
• "free" increased spam likelihood by 79.99%
• "phone" increased spam likelihood by 20.01%

Project Structure

ML-Spam-Detector-API/
├── app/                    # FastAPI application
│   ├── main.py             # API entry point with `/predict` endpoint
│   └── schemas.py          # Pydantic request/response models
├── model/                  # ML model training & evaluation
│   ├── dataset.py          # Dataset download + loading helpers
│   ├── train.py            # Trains/saves TF-IDF + Logistic Regression model
│   ├── evaluate.py         # Evaluates the saved model on the test split
│   ├── predict.py          # Prediction + explanation helpers (used by API)
│   ├── load_model.py       # Helper function to load the model
│   └── try_predict.py      # Example batch predictions using the saved model
├── utils/                  # CLI utilities
│   ├── call_api.py         # Simple interactive API CLI client.
│   └── call_api_pretty.py  # Pretty-printed interactive API CLI client.
├── tests/                  # Pytest test suite for API, model loading, and predictions
│   ├── test_api.py
│   ├── test_model.py
│   └── test_predict.py
├── artifacts/              # Contains saved model
│   └── model.joblib
├── data/                   # Contains UCI SMS Spam Collection dataset
│   └── SMSSpamCollection
├── Dockerfile
├── requirements.txt
└── README.md

Tech Stack

Machine Learning / Data Processing

  • Pandas (data loading, preprocessing, exploration)
  • scikit-learn (TF-IDF vectorization, Logistic Regression)

Backend

  • FastAPI
  • Pydantic
  • Uvicorn

DevOps / Tooling

  • Docker
  • Pytest
  • Requests

Metrics

From the current evaluation run on the held-out test split:

Classification Report:
              precision    recall  f1-score   support

           0     0.9603    1.0000    0.9798       242
           1     1.0000    0.7297    0.8438        37

    accuracy                         0.9642       279
   macro avg     0.9802    0.8649    0.9118       279
weighted avg     0.9656    0.9642    0.9617       279

Confusion Matrix:
[[242   0]
 [ 10  27]]

Try It Yourself!!

1. Setup virtual environment

python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

2. Train the model

python model/train.py

This downloads the dataset to data/SMSSpamCollection (if missing), trains the model, and saves it to artifacts/model.joblib.

3. Evaluate the model

python model/evaluate.py

Evaluates on the held-out test split and prints the classification report and confusion matrix.

4. Run the API

uvicorn app.main:app --reload

Example request:

curl -X POST http://127.0.0.1:8000/predict \
  -H "Content-Type: application/json" \
  -d '{"message": "Free entry in 2 a wkly comp"}'

Response fields:

  • message: original input
  • prediction: spam or not_spam
  • confidence: percentage probability
  • explanation: top contributing words and their impact

Note: Instead of running step 4 locally, you can run the service via the Docker section below.

5. Test the API from the CLI

After starting the API, in a separate terminal run:

python utils/call_api.py

Or the pretty-printed variant:

python utils/call_api_pretty.py

Type messages directly into the terminal to see predictions and explanations.

Note: Example responses for both variants were shown above.

Docker

Build the image (make sure artifacts/model.joblib exists first):

docker build -t ml-spam-detector .

Run the API container:

docker run --rm -p 8000:8000 ml-spam-detector

Testing

Run the full test suite:

pytest

Tests cover:

  • Model loading
  • Prediction correctness
  • API endpoint behavior

About

ML Spam Detector API with Explainability

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages