The idea behind real spam filters
Introduction to Data Science and Machine Learning · Md Mahbub E Noor · University of Barishal
counts[word] = counts.get(word, 0) + 1
def defines a function: a named, reusable blockmessage is the input (a parameter)return hands back the answer and stopsis_spam("...")def is_spam(message):
text = message.lower()
for word in ["free", "win", "prize"]:
if word in text:
return True
return False
print(is_spam("Win a phone today"))
print(is_spam("See you at 5"))True False
.split() cuts text at spaces into a list.lower() so WIN and win matchprize, is not prizemessage = "Win a FREE prize, win now" words = message.lower().split() print(words) print(len(words))
['win', 'a', 'free', 'prize,', 'win', 'now'] 6
{key: value}counts["win"]counts["prize"] = 1counts = {"win": 2, "free": 1}
print(counts["win"])
counts["prize"] = 1
counts["win"] = counts["win"] + 1
print(counts)2
{'win': 3, 'free': 1, 'prize': 1}counts.get(word, 0) means: the current count, or 0 if we have never seen this word.
def count_words(messages):
counts = {}
for msg in messages:
for word in msg.lower().split():
counts[word] = counts.get(word, 0) + 1
return counts
spam_msgs = ["Win a free prize", "Free cash win now",
"Claim your free gift"]
spam_counts = count_words(spam_msgs)
print(spam_counts){'win': 2, 'a': 1, 'free': 3, 'prize': 1, 'cash': 1,
'now': 1, 'claim': 1, 'your': 1, 'gift': 1}The first two spam messages. counts.get(word, 0) is the count before this word; the dictionary then stores one more.
counts = {}
for msg in messages:
for word in msg.lower().split():
counts[word] = counts.get(word, 0) + 1| message | word | count before | count after |
|---|---|---|---|
| 'Win a free prize' | 'win' | 0 | 1 |
| 'Win a free prize' | 'a' | 0 | 1 |
| 'Win a free prize' | 'free' | 0 | 1 |
| 'Win a free prize' | 'prize' | 0 | 1 |
| 'Free cash win now' | 'free' | 1 | 2 |
| 'Free cash win now' | 'cash' | 0 | 1 |
| 'Free cash win now' | 'win' | 1 | 2 |
| 'Free cash win now' | 'now' | 0 | 1 |
Next row: arrow key or the ▶ button. Predict it first!
WATCH FOR
Silent video: press play, pause any time.
ham_msgs = ["See you at the library",
"Is class at 10 now",
"Can you send the notes"]
ham_counts = count_words(ham_msgs)
for w in ["free", "now", "you"]:
print(w, spam_counts.get(w, 0),
ham_counts.get(w, 0))free 3 0 now 1 1 you 0 2
Add a point for each word seen in spam, subtract one for each word seen in normal messages.
def spam_score(message):
score = 0
for word in message.lower().split():
score = score + spam_counts.get(word, 0)
score = score - ham_counts.get(word, 0)
return score
for msg in ["Free prize for you", "See you in class",
"Claim cash now"]:
print(spam_score(msg), msg)2 Free prize for you -4 See you in class 2 Claim cash now
word_count(message) that returns how many words a message hasspam_score on a new messagedef word_count(message):
...
return ...
print(word_count("Win a free prize")) # expect 4Starter code: replace the ... with your own code
Read the last line of an error first. It names the problem.
| What you typed | What Python says | What it means |
|---|---|---|
print(spam_counts["hello"]) | KeyError: 'hello' | The key does not exist. Use spam_counts.get("hello", 0). |
def double(x):
x * 2
print(double(4)) | None | No error, but None: the function forgot to return. |
print(spam_score()) | TypeError: spam_score() missing 1 required positional argument: 'message' | The function needs an input. Pass a message. |
In the lab you can
Opens in a new tab and works offline. All labs: labs/START_HERE.html
def f(x): | Define a function with input x |
return value | Hand back the answer |
text.split() | Cut text into a list of words |
d = {"a": 1} | A dictionary: key → value |
d["a"] | Look up a key (error if missing) |
d.get("a", 0) | Look up, or 0 if missing |
d["a"] = 5 | Add or change a key |
d.get(k, 0) + 1 | The word-counting pattern |
Due before Lecture 5 · [date]
Without looking, write count_words() again and test it on 3 sentences. Then compare with the slide.
Write longest_word(message) that returns the longest word. Test: "Claim your fantastic prize" should give "fantastic".
Add 5 spam and 5 normal messages of your own. Recount, then print the spam and ham counts for 5 words you choose.
Run spam_score on 6 new messages. How many does it get right? Explain one mistake.
What would happen to spam_score if we had 1,000 spam examples but only 10 normal ones? Answer in 3 sentences.
Watch it again at home to revise.