Skip to content

Latest commit

Β 

History

8 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SMS Spam Classifier πŸ“±

Python Scikit-Learn Jupyter Notebook NLP Naive Bayes Spam Classifier

A Natural Language Processing (NLP) and Machine Learning project that classifies SMS messages as Ham (Not Spam) or Spam using TF-IDF vectorization and Naive Bayes.

The project is implemented in spam_classifier.ipynb and follows the complete workflow from data understanding and exploratory data analysis to text preprocessing, vectorization, model training, and evaluation.


🎯 Objective

The objective of this project is to build a machine learning model that can identify whether an SMS message is:

  • Ham (Not Spam) β€” a normal message
  • Spam β€” an unwanted or promotional message

πŸ“Š Dataset

The project uses the SMS Spam Collection dataset from the following source:

https://raw.githubusercontent.com/justmarkham/pycon-2016-tutorial/master/data/sms.tsv

The dataset initially contains:

  • 5572 messages
  • 2 columns
    • label
    • message

The original class distribution is:

Label Count Percentage
Ham 4825 86.59%
Spam 747 13.41%

A local copy of the dataset is saved as:

dataset/spam.csv

πŸ› οΈ Technologies Used

  • Python
  • Pandas
  • NumPy
  • Matplotlib
  • Seaborn
  • Scikit-learn
  • WordCloud
  • Jupyter Notebook

The project dependencies are listed in requirements.txt.


πŸ”„ Project Workflow

SMS Dataset
     ↓
Data Understanding
     ↓
Exploratory Data Analysis
     ↓
Remove Duplicates
     ↓
Text Preprocessing
     ↓
Check & Remove Empty Messages
     ↓
TF-IDF Vectorization
     ↓
Train-Test Split
     ↓
Multinomial Naive Bayes
     ↓
Model Evaluation

1. πŸ“Š Data Understanding

The first phase explores the basic structure of the dataset.

The notebook checks:

  • Dataset shape
  • Column names
  • Data types
  • Missing values
  • Duplicate rows
  • Class distribution

The dataset contains 403 duplicate rows.

The labels are converted from:

ham
spam

to numerical values using LabelEncoder:

ham  β†’ 0
spam β†’ 1

2. πŸ”Ž Exploratory Data Analysis (EDA)

Several aspects of the SMS data are analyzed before training the model.

Class Distribution

The project visualizes the distribution of Ham and Spam messages.

The dataset is imbalanced, with Ham messages making up the majority of the data.

Message Length

The following feature is created:

df['message_length'] = df['message'].apply(len)

This represents the total number of characters in an SMS.

Word Count

The following feature is also created:

df['word_count'] = df['message'].apply(lambda x: len(x.split()))

This represents the number of words in each message.

Word Frequency Analysis

The project extracts words from Ham and Spam messages and identifies the most frequently occurring words.

It also performs a second analysis after removing English stopwords and some SMS-specific terms.

Word Clouds

Separate word clouds are generated for:

  • Spam messages
  • Ham messages

Correlation

A correlation heatmap is used to examine relationships among the numerical features created during EDA.


3. 🧹 Data Cleaning

Duplicate rows are removed using:

df = df.drop_duplicates()

The dataset changes from:

5572 rows
    ↓
5169 rows

After duplicate removal, the class distribution becomes:

Label Count
Ham 4516
Spam 653

4. πŸ“ Text Preprocessing

A custom clean_text() function is used to prepare SMS messages for machine learning.

The preprocessing steps are:

  1. Lowercasing
  2. URL removal
  3. Email address removal
  4. Number removal
  5. Punctuation removal
  6. Whitespace normalization
  7. Tokenization
  8. Stopword removal
  9. Removal of words with length ≀ 2
  10. Joining the processed tokens back into a string

Example conceptually:

Raw SMS
   ↓
Lowercase
   ↓
Remove URLs, emails, numbers and punctuation
   ↓
Tokenize
   ↓
Remove stopwords
   ↓
Remove very short words
   ↓
Cleaned SMS

The cleaned messages are stored in:

df['cleaned_message']

Empty Messages After Cleaning

After preprocessing, the notebook checks whether any messages became empty:

empty_messages = df[df['cleaned_message'].str.strip() == '']

There are 36 empty messages after cleaning.

These rows are removed because an empty text representation provides no text features for the model.

After removing them:

5169 rows
   ↓
5133 rows

Final class distribution:

Label Count
Ham 4480
Spam 653

The index is then reset.


5. πŸ”’ TF-IDF Text Vectorization

Machine learning algorithms cannot directly process SMS text, so the cleaned messages are converted into numerical features.

The project uses:

from sklearn.feature_extraction.text import TfidfVectorizer

tfidf = TfidfVectorizer(max_features=5000)

The vectorizer is fitted and transformed using:

X = tfidf.fit_transform(df['cleaned_message']).toarray()

Result

The final feature matrix has the shape:

X.shape = (5133, 5000)

This means:

  • 5133 rows β†’ SMS messages
  • 5000 columns β†’ TF-IDF features

The target variable is:

y = df['label']

with:

y.shape = (5133,)

So the data passed to the machine learning model consists of:

X β†’ TF-IDF features
y β†’ Spam/Ham labels

6. βœ‚οΈ Train-Test Split

The dataset is split into training and testing sets using:

train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=42,
    stratify=y
)

Split

Dataset Messages
Training 4106
Testing 1027

stratify=y is used to maintain a similar spam/ham distribution in both sets.

The observed spam percentages are:

Training: 12.71%
Testing:  12.76%

7. πŸ€– Naive Bayes Model

Three Naive Bayes algorithms were implemented and evaluated for the SMS classification task:

  • GaussianNB()
  • MultinomialNB()
  • BernoulliNB()

All three algorithms were trained using the TF-IDF feature representation and evaluated on the test dataset.

After comparing their performance, Multinomial Naive Bayes achieved good accuracy with high precision compared with the other two algorithms.

Therefore, MultinomialNB was selected as the final model for this project.

from sklearn.naive_bayes import GaussianNB, MultinomialNB, BernoulliNB

gnb = GaussianNB()
mnb = MultinomialNB()
bnb = BernoulliNB()

The selected final model is:

mnb = MultinomialNB()

mnb.fit(X_train, y_train)

y_pred = mnb.predict(X_test)

Model Selection

SMS Messages
      ↓
Text Preprocessing
      ↓
TF-IDF Vectorization
      ↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ GaussianNB()                β”‚
β”‚ MultinomialNB() ⭐           β”‚
β”‚ BernoulliNB()               β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
      ↓
Performance Comparison
      ↓
MultinomialNB Selected πŸ†

8. πŸ“ˆ Model Evaluation

The current notebook evaluates the model using:

  • Accuracy
  • Confusion Matrix
  • Precision

The final Multinomial Naive Bayes results are:

Accuracy

97.08%

Precision

100%

Confusion Matrix

[[896   0]
 [ 30 101]]

Because the labels are encoded as:

0 β†’ Ham
1 β†’ Spam

the confusion matrix can be interpreted as:

Predicted Ham Predicted Spam
Actual Ham 896 0
Actual Spam 30 101

This means:

  • 896 Ham messages were correctly classified as Ham.
  • 0 Ham messages were classified as Spam.
  • 101 Spam messages were correctly classified as Spam.
  • 30 Spam messages were classified as Ham.

The model therefore achieved perfect precision for the Spam class on this test set, while some spam messages were still missed.


πŸ“ Project Structure

spam-classifier/
β”‚
β”œβ”€β”€ dataset/
β”‚   └── spam.csv
β”‚
β”œβ”€β”€ spam_classifier.ipynb
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ .gitignore
└── README.md

A Python virtual environment is also used locally:

venv/

The virtual environment is excluded from version control through .gitignore.


βš™οΈ Installation

1. Clone the repository

git clone <your-repository-url>
cd spam-classifier

2. Create a virtual environment

python -m venv venv

3. Activate the environment

Windows CMD

venv\Scripts\activate

Windows PowerShell

venv\Scripts\Activate.ps1

4. Install dependencies

pip install -r requirements.txt

The notebook also contains a WordCloud installation cell:

pip install wordcloud

If WordCloud is not already installed in your environment, install it separately.


▢️ Run the Project

Start Jupyter Notebook:

jupyter notebook

Open:

spam_classifier.ipynb

Then run the notebook cells from top to bottom.

The notebook automatically downloads the dataset and creates:

dataset/spam.csv

πŸ“Œ Current Model

The current project contains one active machine learning model:

Cleaned SMS
     ↓
TF-IDF
     ↓
Multinomial Naive Bayes
     ↓
Spam / Ham

Although GaussianNB and BernoulliNB are initialized in the notebook, their training and prediction code is currently commented out. Therefore, they are not part of the active final model.


About

SMS Spam Detection using Multinomial Naive Bayes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages