Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Bag of words and TF-IDF weights

After this lesson: I can count words and weight the ones that matter.

55 min lesson3 commandsJupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

Describing a text by its words

A bag of words describes a text by counting how often each word appears and ignoring the order. TF-IDF (term frequency, inverse document frequency) goes one step further and gives more weight to words that are rare across texts.

With these two ideas a program can say which words a text is really about. Search engines and spam filters both start here.

By the end of this lesson

Note

I can count words and weight the ones that matter.

Key words

WordWhat it means
Bag of wordsa text described by its word counts, with the order thrown away
Term frequencyhow often a word appears in a text, as a share of its tokens
Document frequencyhow many texts contain a word
Inverse document frequencya number that is high for rare words and zero for words in every text
TF-IDFterm frequency multiplied by inverse document frequency

The cells students fill in are left blank in this preview.

A bag of words keeps counts, not order

Imagine tipping the words of a text into a bag and shaking it. You can still count each word, but you can no longer say which came first.

In Python a dictionary does the job. Each word is a key and its count is the value. "The bus is late" and "Late is the bus" give the same bag.

Count the words in a text

Code: python
text = "the bus is late the bus is full the train is late"
counts = {}
for word in text.split():
    if word in counts:
        counts[word] = counts[word] + 1
    else:
        counts[word] = 1
print(counts)
# Change the text. Which word has the biggest count now?

Count with the library's counter

Command
docker exec jupyter python3 -c "from collections import Counter; print(Counter('the bus is late the bus is full'.split()).most_common(2))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Count the words in one column

Command
docker exec jupyter sh -c "cut -d, -f4 hires.csv | sort | uniq -c"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Term frequency makes texts of different length fair

A raw count favours long texts. A word appearing 3 times in a book means less than 3 times in a short note.

Term frequency divides the count by the number of tokens: the share of the text the word takes. 2 late in 4 tokens is 0.5. 2 late in 10 tokens is 0.2.

Compare a short and a long text

Code: python
short = "late bus".split()
long = "the bus is late and the train is late too".split()
for tokens in [short, long]:
    count = tokens.count("late")
    print(len(tokens), "tokens,", count, "late, term frequency", round(count / len(tokens), 3))
# Make the long text longer. What happens to the term frequency?

Rare words say more about a text

The word "the" is in nearly every text, so it cannot tell texts apart. A rare word can.

Document frequency counts the texts that contain a word. Inverse document frequency is log10 of the number of texts divided by that count. It is 0 for a word in every text, and bigger for rarer words.

Work out two inverse values

Command
docker exec jupyter python3 -c "import math; print(round(math.log10(4 / 2), 3), round(math.log10(4 / 1), 3))"

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

TF-IDF multiplies the two

The TF-IDF weight of a word in a text is its term frequency times its inverse document frequency. A word scores high when it is common in this text and rare in the others.

The table works it out for the text "the bus is late and the train is late", from a set of four short texts.

Worked example: weights in one text

WordCountTerm frequencyTexts with itInverseWeight
the20.2224 of 400
is20.2224 of 400
late20.2222 of 40.3010.067
bus10.1112 of 40.3010.033
train10.1111 of 40.6020.067

The cells students fill in are left blank in this preview.

A common mistake

Warning

Many people think the most frequent word is the most important one. The most frequent words are usually "the" and "is", which are in every text. A word matters when it is frequent here and rare elsewhere, which is what TF-IDF measures.

Going further

Four texts are a tiny collection. In a real collection of thousands, "and" would be in most of them and its weight would fall towards 0.

Add three more short texts to the set in the assignment. Which weights change, and why?

About this lab and its source: JupyterLab data science lab: pandas, Matplotlib and scikit-learn in the browser

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.