 Data Science

# Email Spam Filtering Using Naive Bayes Classifier

9 minute read | June 14, 2021 Written by:
Sakshi Gupta

Get expert insights straight to your inbox.

Naive Bayes is a probabilistic algorithm based on the Bayes Theorem used for email spam filtering in data analytics. If you have an email account, we are sure that you have seen emails being categorised into different buckets and automatically being marked important, spam, promotions, etc. Isn’t it wonderful to see machines being so smart and doing the work for you?

More often than not, these labels added by the system are right. So does this mean our email software is reading through every communication and now understands what you as a user would have done? Absolutely right! In this age and time of data analytics & machine learning, automated filtering of emails happens via algorithms like Naive Bayes Classifier, which apply the basic Bayes Theorem on the data.

In this article, we will understand briefly about the Naive Bayes Algorithm before we get our hands dirty and analyse a real email dataset in Python. This blog is second in the series to understand the Naive Bayes Algorithm. You can read part 1 here in the introduction to Bayes Theorem & Naive Bayes Algorithm blog.

## The Naive Bayes Classifier Formula

One of the most simple yet powerful classifier algorithms, Naive Bayes is based on Bayes’ Theorem Formula with an assumption of independence among predictors. Given a Hypothesis A and evidence B, Bayes’ Theorem calculator states that the relationship between the probability of Hypothesis before getting the evidence P(A) and the probability of the hypothesis after getting the evidence P(A|B) is:

Here:

• A, B = events
• P(A|B) = probability of A given B is true
• P(B|A) = probability of B given A is true
• P(A), P(B) = the independent probabilities of A and B

This theorem, as explained in one of our previous articles, is mainly used for classification techniques in data analytics. The Naive Bayes theorem calculator pays an important role in spam detection of emails.

## Detecting Email Spam

Modern spam filtering software continuously struggles to categorise the emails correctly. Unwanted spam & promotional communication is the toughest of them all. Spam communication algorithms must be iterated continuously since there is an ongoing battle between spam filtering software and anonymous spam & promotional mail senders. Naive Bayes Algorithm in data analytics forms the base for text filtering in Gmail, Yahoo Mail, Hotmail & all other platforms.

Like Naive Bayes, other classifier algorithms like Support Vector Machine, or Neural Network also get the job done! Before we begin, here is the dataset for you to download:

Email Spam Filtering Using Naive Bayes Algorithm
This would be a zipped file, attached in the email. Please allow users to download this data.

For convenience, we have already split the data into train & test files. Let’s get into it:

```import pandas as pd
# read training data & test data

Always review the first 5 rows of the dataset:

`df_test.sample(5)df_train.sample(5)`

Your output for train dataset may look something like this:

And the output for test dataset would look something like this:

If you notice, you will realise that we have two columned CSV files here. Type column contains whether the email is marked as Spam or Ham & the email columns contains body (main text) of the email. Both the train & test datasets have the same format.

Ensuring data consistency is of utmost importance in any data analytics problem. Let’s do some descriptive statistics as the first step in the data analytics problem, on our training data.

`df_train.describe(include = 'all')`

In the output, we will see that there are 2000 records. We have two unique Type and 2000 unique emails. Let’s detail a little more about Type column.

`df_train.groupby('type').describe()`

As we can see, in our test data, we have an equal number (1000 each) of Spam and Ham. There is no duplicate data in the email column. Let’s sanitise our data now.

```import email_pre as ep
from gensim.models.phrases import Phrases

def do_process(row):
global bigram
temp = ep.preprocess_text(row.email,[ep.lowercase,
ep.remove_html,
ep.remove_esc_chars,
ep.remove_urls,
ep.remove_numbers,
ep.remove_punct,
ep.lemmatize,
ep.keyword_tokenize])

if not isinstance(temp,str):
print temp

return ' '.join(bigram[temp.split(" ")])

def phrases_train(sen_list,min_ =3):
if len(sen_list) <= 10:
print("too small to train! ")
return

if isinstance(sen_list,list):
try:
bigram.save("email_EN_bigrams_spam")
print "retrain!"

except Exception as ex:
print "first "
bigram = Phrases(sen_list, min_count=min_, threshold=2)
bigram.save("email_EN_bigrams_spam")
print ex```

Phrase Model train (we can run this once & save it)

```train_email_list = [ep.preprocess_text(mail,[ep.lowercase,
ep.remove_html,
ep.remove_esc_chars,
ep.remove_urls,
ep.remove_numbers,
ep.remove_punct,
ep.lemmatize,
ep.keyword_tokenize]).split(" ") for mail in df_train.email.values]

print "after pre_process :"
print " "
print len(train_email_list)
print df_train.ix.email,">>"*80,train_email_list```

Here is the output after an initial pre_processing:

2000

`df_train["class"] = df_train.type.replace(["Spam","Ham"],[0,1]) df_test["class"] = df_test.type.replace(["Spam","Ham"],[0,1])`

Bigram Training

`phrases_train(train_email_list,min_=3) bigram = Phrases.load("email_EN_bigrams_spam") len(bigram.vocab)`

And let’s retrain again! Here is the output:

159158

`print len(dict((key,value) for key, value in bigram.vocab.iteritems() if value >= 15))`

You may get this as the output:

4974

`df_train["clean_email"] = df_train.apply(do_process,axis=1) df_test["clean_email"] = df_test.apply(do_process,axis=1) # df_train.head() print "phrase found train:",df_train[df_train['clean_email'].str.contains("_")].shape print "phrase found test:",df_test[df_test['clean_email'].str.contains("_")].shape`

Output

`phrase found train: (371, 3)phrase found test: (7, 3)`

Let’s start training for Spam Detection now:

`df_train.head()`

Output

For the next section, you can proceed with the Naive Bayes part of the algorithm:

`from sklearn.pipeline import Pipeline from sklearn.feature_extraction.text import CountVectorizer from sklearn.feature_extraction.text import TfidfTransformer from sklearn.naive_bayes import MultinomialNB text_clf = Pipeline([('vect', CountVectorizer()), `
`           ('tfidf', TfidfTransformer()), ('clf', MultinomialNB()), ])`
```text_clf.fit(df_train.clean_email, df_train["class"])
predicted = text_clf.predict(df_test.clean_email)
from sklearn import metrics
array = metrics.confusion_matrix(df_test["class"], predicted)
import seaborn as sn
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

df_cm = pd.DataFrame(array, ["Spam","Ham"],
["Spam","Ham"])

sn.set(font_scale=1.4)#for label size
sn.heatmap(df_cm, annot=True,annot_kws={"size": 16})# font size```

After running the Naive Bayes Algorithm, the output looks something like this:

`print metrics.classification_report(df_test["class"], predicted, target_names=["Spam","Ham"])`

We print the metrics to see something like this:

precision    recall  f1-score   support

`            Spam       1.00      1.00      1.00        43            Ham       1.00      1.00      1.00        57`
`avg / total       1.00      1.00      1.00       100`

In order to assess the model, we put the test data into our created model after which we compare our results. As you can see in the output above, it is visible that out of 43 spam mail, the model successfully identifies all the 43 spam mails. And in the same way, out of 57 ham mail, the model successfully identifies all the 57 Ham mails.

Our application of the Bayes theorem formula in a Naive Bayes Classifier technique is working successfully on this dataset. While it is unusual to have 100% success from a model, we have been able to achieve it due to the small size of training & testing datasets. All we need to ensure is that the model trains with sufficient data. If this happens, it will deliver more accurate results.

For further reading, see here the data science definition guide or the data scientist job description.

Since you’re here…
Curious about a career in data science? Experiment with our free data science learning path, or join our Data Science Bootcamp, where you’ll get your tuition back if you don’t land a job after graduating. We’re confident because our courses work – check out our student success stories to get inspired.