SMS Spam Detection Pipeline (TF-IDF + SMOTE)

Project Overview

This repository contains an end-to-end Machine Learning pipeline designed to classify SMS messages as Ham (legitimate) or Spam. The project addresses severe class imbalance using Synthetic Minority Over-sampling Technique (SMOTE) combined with linear decision modeling and domain-specific feature engineering.

Architecture and Pipeline Strategy

  1. Preprocessing and Feature Engineering:

    • Cleaned raw text via lowercasing, punctuation removal, and stop-word filtering.
    • Vectorized text using 3,000 TF-IDF unigram and bigram features.
    • Extracted 4 structural domain features: has_URL, Currency_Count, Exclamation_Count, and Uppercase_Count.
    • Stacked sparse TF-IDF outputs with dense structural features using scipy.sparse.hstack.
  2. Train-Test Validation:

    • Utilized stratify parameter within train_test_split (80/20 split) to preserve class proportions across subsets.
    • Conducted strict data leakage verification to guarantee zero duplicate text sentence overlap between training and test sets.
  3. Imbalance Mitigation:

    • Benchmarked baseline Multinomial Naive Bayes against Class-Weighted Logistic Regression and SMOTE Resampling.
    • Applied SMOTE strictly to the training partition (x_train_final) to prevent evaluation data contamination.

Performance Benchmark Comparison

Strategy / Model Overall Accuracy Spam Precision Spam Recall Spam F1-Score
Baseline (Multinomial Naive Bayes) 0.9836 0.9859 0.9014 0.9417
Class-Weighted (Logistic Regression) 0.9816 0.8910 0.9789 0.9329
SMOTE Resampling (Logistic Regression) 0.9855 0.9324 0.9592 0.9456

Evaluation Context

  • Focus on Spam Class Metrics: Accuracy is distorted by majority class representation (~87% Ham). Minority class Spam evaluation provides the primary indicator of operational model reliability.
  • Model Selection Rationale: The SMOTE Logistic Regression model achieved the optimal balance between high Precision (minimizing false positives on clean emails) and high Recall (catching evasive spam messages).

Usage Instructions

import joblib
from huggingface_hub import hf_hub_download
import scipy.sparse as sp
import re

# Download and load the complete pipeline bundle
repo_id = "umair1710/spam-classifier-tfidf-logistic-regression"
model_path = hf_hub_download(repo_id=repo_id, filename="spam_classifier_pipeline.pkl")
bundle = joblib.load(model_path)

vectorizer = bundle['vectorizer']
model = bundle['model']

def predict_message(raw_text):
    tfidf_feat = vectorizer.transform([raw_text])
    has_url = 1 if re.search(r'http[s]?://|www\.', raw_text) else 0
    curr_cnt = len(re.findall(r'[\$\£\€]', raw_text))
    excl_cnt = raw_text.count('!')
    upper_cnt = sum(1 for c in raw_text if c.isupper())
    num_feats = sp.csr_matrix([[has_url, curr_cnt, excl_cnt, upper_cnt]])
    final_input = sp.hstack([tfidf_feat, num_feats], format='csr')
    prediction = model.predict(final_input)[0]
    confidence = model.predict_proba(final_input)[0][prediction]
    label = 'Spam' if prediction == 1 else 'Ham'
    return label, confidence

# Inference Example
label, confidence = predict_message("WINNER!! Claim your $1000 prize now at http://win.com!")
print(f"Prediction: {label} (Confidence: {confidence:.2%})")
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support