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
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, andUppercase_Count. - Stacked sparse TF-IDF outputs with dense structural features using
scipy.sparse.hstack.
Train-Test Validation:
- Utilized
stratifyparameter withintrain_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.
- Utilized
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%})")