Machine Learning Spam Detection Project

Machine Learning project 04

Machine Learning Spam Detection Project

Build and evaluate a complete spam detection workflow with reproducible Python code, explicit metrics, and honest limitations.

Explore Machine Learning training in VizagView all project ideas

Dataset and objective

A balanced set of ordinary and spam-like SMS examples embedded for a completely runnable lesson.

Skills practised

  • Text feature extraction
  • Class labels
  • Confusion matrices
  • False-positive awareness

Requirements

  • Python 3.10 or later
  • A terminal or command prompt
  • python -m pip install scikit-learn
  • About 45-60 minutes to build and review

Machine Learning workflow

  1. Data: A balanced set of ordinary and spam-like SMS examples embedded for a completely runnable lesson.
  2. Preprocessing: Word unigrams and bigrams are converted to TF-IDF features after a stratified split.
  3. Model: Class-weighted LogisticRegression produces ham or spam predictions.
  4. Evaluation: A labelled confusion matrix and classification report on the holdout messages.

Complete Python code

Save the code as ml_spam_detection.py. The random state and data handling are included so the result can be reproduced and reviewed.

"""Train a small SMS spam classifier with TF-IDF and logistic regression."""

from __future__ import annotations

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import classification_report, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline


MESSAGES = [
    ("Are we still meeting at 4 pm today?", "ham"),
    ("Please send the revised report before lunch", "ham"),
    ("Your appointment is confirmed for Monday", "ham"),
    ("Can you pick up milk on your way home", "ham"),
    ("The class link is in the group chat", "ham"),
    ("Happy birthday have a wonderful day", "ham"),
    ("I reached safely call me when free", "ham"),
    ("The meeting room has changed to 204", "ham"),
    ("Thanks for helping with the project", "ham"),
    ("Dinner will be ready at eight", "ham"),
    ("Your parcel was delivered to reception", "ham"),
    ("Let us review the code tomorrow morning", "ham"),
    ("URGENT claim your free cash prize now", "spam"),
    ("You won a guaranteed reward click this link", "spam"),
    ("Exclusive offer buy now and receive a bonus", "spam"),
    ("Congratulations winner call this premium number", "spam"),
    ("Act today to collect your free vacation", "spam"),
    ("Limited deal send bank details to receive money", "spam"),
    ("You have been selected for a secret reward", "spam"),
    ("Claim free gift cards before this offer expires", "spam"),
    ("Earn money instantly with no work required", "spam"),
    ("Final notice verify your account at this unknown link", "spam"),
    ("Cash bonus waiting reply WIN to collect", "spam"),
    ("Lowest loan rate guaranteed apply immediately", "spam"),
]


def train_model(random_state: int = 42):
    texts, labels = zip(*MESSAGES)
    x_train, x_test, y_train, y_test = train_test_split(
        texts, labels, test_size=0.33, random_state=random_state, stratify=labels
    )
    model = make_pipeline(
        TfidfVectorizer(lowercase=True, ngram_range=(1, 2)),
        LogisticRegression(max_iter=1000, class_weight="balanced", random_state=random_state),
    )
    model.fit(x_train, y_train)
    predictions = model.predict(x_test)
    return model, y_test, predictions


def main() -> None:
    model, y_test, predictions = train_model()
    print("SMS Spam Detection Evaluation")
    print("Confusion matrix [ham, spam]:")
    print(confusion_matrix(y_test, predictions, labels=["ham", "spam"]))
    print(classification_report(y_test, predictions, zero_division=0))
    message = input("Message to classify (or press Enter to stop): ").strip()
    if message:
        print("Prediction:", model.predict([message])[0])
    print("Never auto-block real messages using this tiny demonstration dataset.")


if __name__ == "__main__":
    main()

How the pipeline works

Word unigrams and bigrams are converted to TF-IDF features after a stratified split.

Class-weighted LogisticRegression produces ham or spam predictions. A labelled confusion matrix and classification report on the holdout messages.

Run the project

  1. Create and activate a virtual environment.
  2. Install the dependencies with python -m pip install scikit-learn.
  3. Run python ml_spam_detection.py.
  4. Review every printed metric together with the limitation below; a single score never proves deployment readiness.

How to interpret the evaluation

Classification projects report class-aware metrics so majority classes do not hide weak performance. Regression projects report errors in target units and include R-squared or a simple baseline where appropriate. Always verify the split strategy matches how new data will arrive.

Accuracy, ethics, and safety limits

Never auto-block real communication using this small example dataset. False positives can hide legitimate messages, while adversarial spam changes constantly.

Ways to extend the project

Use a licensed full SMS dataset, deduplicate messages before splitting, tune a decision threshold, measure false-positive cost, and add model monitoring.

Continue learning Machine Learning

Try the next project, return to the Softenant project library, or explore the Machine Learning course in Vizag for guided data preparation, model evaluation, and portfolio feedback.