Kwikmsg is a messaging app. Users are getting fake prize and loan messages, and some lose money to them.
The safety team has 240 messages that users already marked as spam (fake) or ham (a real message). They want a filter that reads a new message and decides whether to move it to the spam folder.
Goal: Predict label (spam / ham) from the words of a message. Naive Bayes is fast, simple and works well on text, so it is the classic first spam filter.
240 messages, one row each.
| message_id | message | label |
|---|---|---|
| 1 | "Your OTP for login is 850555. Do not share it with anyone" | ham |
| 2 | "Rs 2000 debited from your account for rent" | ham |
| 3 | "Can you send me the notes from today's class?" | ham |
| 4 | "Click the link I sent to join the meeting" | ham |
| 5 | "Hey are we still meeting at 8 today?" | ham |
| 6 | "Click the link I sent to join the meeting" | ham |
First 6 of 240 rows · realistic practice data
Press Run on each step in order, or run them all at once. You can change any code and run it again.
Starting Python…
Look at a few messages of each kind. Text data is different from number columns: the model has to learn from words.
CountVectorizer makes one column per word and counts how often each word appears in each message. This is called a bag of words: the order of words is lost, only the counts remain. Common words like "the" and "is" are removed with stop_words="english".
Keep 25% of the messages hidden for the test, with the same share of spam in both parts.
Naive Bayes learns how often each word appears in spam and in ham. For a new message, it multiplies these chances word by word. It is called naive because it treats every word as independent of the others, which is not true, but it still works surprisingly well.
The vectorizer and the model go in one pipeline, so new text is always turned into numbers the same way.
For a spam filter, the two mistakes are not equal. A spam message in the inbox is annoying. A real message sent to spam (say, an OTP or a message from mom) is worse. The confusion matrix shows both.
The model keeps a log-probability for every word in each class. The difference between the two tells how strongly a word points to spam. The top words should make sense to a human.
If a word never appeared in ham during training, its chance in ham would be zero, and one word would decide everything. alpha adds a small count to every word so nothing is ever exactly zero. This is called Laplace smoothing. Try a few values.
Write your own messages in the list and run again. The model shows the chance of spam for each one.
20 questions on new data. You write the code; hints point the way without giving it.