Concepts / CountVectorizer and the Bag-of-Words Representation

CountVectorizer and the Bag-of-Words Representation

A pre-defined stopwords list, such as scikit-learn's ENGLISH_STOP_WORDS with 318 entries, is a library-supplied collection of common words that text processing usually ignores.

  • Programming
Interactive lab

Try it: Text Vectorization: Tokens to Vectors

The text-to-tensor pipeline: standardize, split into tokens, build a frequency-ranked vocabulary with padding and [UNK], map tokens to integer ids, pad or truncate, then one-hot or multi-hot encode and look the ids up in an embedding table.

How it works

  1. Standardize: lowercase and delete punctuation.
  2. Split on whitespace into tokens.
  3. Build the vocabulary: 0 = padding, 1 = [UNK], then words by frequency (ties: first appearance), capped at max tokens.
  4. Map each token to its id (1 if it did not make the vocabulary), then pad with 0 or truncate to the sequence length.
  5. Encode: one-hot rows per position or one multi-hot row per text; embed: id k selects row k of the embedding table.

Default run (18 steps): Raw text (59 characters): "The movie was great. The plot was great, the acting wasn't!". A model cannot read strings, so it is turned into numbers step by step. … Embedding lookup: id k selects row k of a fixed 8 x 3 table, giving a (8, 3) dense matrix instead of (8, 8) sparse one-hots. Row 0 (padding) is looked up too; a trained Embedding layer would learn these rows.

Simplified: Bounded ASCII text (up to 200 characters, 40 tokens), whitespace splitting only, and a small FIXED embedding table (a real Embedding layer learns its rows). The multi-hot vector keeps the padding slot (always 0) so its positions line up with the ids.

Educational simulation

Loading the simulation…

Ordinary Words That Crowd the Feature Matrix

Read any English paragraph and count the words that show up everywhere: 'the', 'and', 'is', 'of'. These words appear in almost every English document, so they tell a model very little about what any single document is about. Yet when a computer turns a document into numbers, every distinct word it sees can become a feature, and each feature takes up a column. Common words therefore keep a seat in the representation even though they contribute almost no information.

This article looks at one practical response: a pre-defined stopwords list. You will see what such a list contains, how it is handed to CountVectorizer, and what changes in the resulting features. Before reading each explanation, try to trace the code in your head and decide what you expect each stage to produce. Then compare your expectation with what the code actually does.

What a Stopwords List Contains

Definition

A pre-defined stopwords list, such as scikit-learn's ENGLISH_STOP_WORDS with 318 entries, is a library-supplied collection of common words that text processing usually ignores.

The scikit-learn library provides this list under the name ENGLISH_STOP_WORDS in its feature extraction text module. You can import it directly and ask how many entries it holds. The source reports that the list contains 318 stopwords. The list is a set-like collection rather than an ordered sequence, so the source converts it to a list before slicing it. The slice in the source takes every tenth entry, which is a quick way to sample the contents without printing all 318 words.

python
Notes on the code
  • The import brings in the built-in list of English stopwords.
  • len() reports how many entries the list holds; the source reports 318.
  • Converting to a list lets us slice it, and [::10] keeps every tenth entry as a sample.

The sampled words look ordinary. The source's sample includes pronouns such as 'he' and 'me', the determiner 'the', and connecting words such as 'although' and 'into'. Notice that the sample contains no subject-specific vocabulary. The list is built around words that carry grammatical function rather than meaning about a particular topic, which is why it is a generic starting point for English text. A movie review, a news article, and a recipe all tend to contain these same function words.

Bag of Words: Where Each Word Gets a Column

CountVectorizer transforms text into a matrix of token counts. Think of the result as a grid. Each row is one document, and each column is one vocabulary word. The vocabulary is the set of distinct words the vectorizer has decided to keep, and every word in it owns exactly one column. The number stored where a row and a column meet is how often that word appears in that document. Because word order is not recorded in these counts, the representation is often called a bag of words.

moviecount 2funcount 1longcount 1next columnnext column
How does a word's position in the vocabulary determine which column holds its count for a document? In this generated illustration, each word owns one column index, and the value shown is how often that word appears in one document.

Trace one row through this map. The document in this illustration contains 'movie' twice, 'fun' once, and 'long' once. Its row therefore holds 2 in the column for 'movie', 1 in the column for 'fun', and 1 in the column for 'long'. Change the vocabulary and the column for each word changes with it, but the rule stays the same: a word's column is fixed by its place in the vocabulary, and its cell records its count in that document.

Passing stop_words to CountVectorizer

CountVectorizer accepts a stop_words parameter. When you set that parameter to the string 'english', the vectorizer uses the built-in ENGLISH_STOP_WORDS list. The setting is chosen when the object is created, and the vocabulary is learned later, when fit is called on the training text. The source also notes that you can augment the built-in list and pass your own, but it mentions that option without a worked example, so treat it as a direction for further study rather than a tested procedure.

python
Notes on the code
  • The stop_words argument is supplied in the constructor, so the choice is fixed before any text is seen.
  • fit() reads the documents, applies the stopword filter, and learns the vocabulary.
  • get_feature_names_out() lists the words that survived as features.

Where the Stopword Step Sits in the Workflow

It helps to see the stopword step as one stage in a sequence rather than as a standalone operation. Text is first split into tokens. The stopword filter then removes the tokens that appear in the list. The remaining tokens form the vocabulary, and the count matrix records how often each vocabulary item appears in each document. This is a simplified conceptual model. It shows where the stopword decision sits, not every internal detail of the library.

Tokenize textsplit into tokensFilter stopwordsremove listed tokensBuild vocabularyremaining tokensCount matrixcounts per documenttokenskept tokensvocabulary
At which step can a word that should be removed survive, causing an unexpected feature count? The stopword filter is the decision point; a problem earlier or later in the sequence shows up as a surprising count.

Predicting the Effect on the Feature Count

What do you think happens?

Applying ENGLISH_STOP_WORDS to a text can make the number of features do which of these?

  • Only decrease, or stay the same

  • Only increase

  • Always increase by exactly 318

Reveal answer
Answer:

Only decrease, or stay the same

Removing stopwords is a filter applied to candidate words, so the feature count can only shrink or stay the same. The list is not added to the features; it only removes words from consideration. The size of the reduction depends on which of the list's words actually appear in your text, and it can never exceed the length of the list.

The reasoning behind the answer is what matters. Each stopword that appears in the text is one candidate word that no longer becomes a feature. Words not on the list are untouched. Because the filter only removes candidates, the vocabulary after filtering is never larger than the vocabulary before. The source adds a more hopeful claim: although the count can only fall, the performance of a downstream model might improve. Whether it does is an empirical question, and the source frames it as something to test by trying the change and measuring the result.

Worked example

Removing stopwords from one small document

A document contains the words 'the', 'movie', 'was', and 'fun'. Suppose the stopwords list contains 'the' and 'was'. How many features does this document contribute before and after filtering?

  1. 1
    Count candidates before filtering

    The document offers four distinct candidate words: 'the', 'movie', 'was', and 'fun'. Before any filtering, that is four potential features.

  2. 2
    Check each candidate against the list

    'the' appears in the list, so it is removed. 'movie' does not appear in the list, so it stays. 'was' appears in the list, so it is removed. 'fun' does not appear in the list, so it stays.

  3. 3
    Count what remains

    Two words survive, 'movie' and 'fun'. The document is now represented only by the words that remain, and the removal was applied to the words of the text, not to the document itself.

  4. 4
    Compare the two counts

    The count fell from four to two. This matches the rule that filtering can only decrease the number of features.

Result

The document contributes two features, 'movie' and 'fun', down from four.

themoviemoviefunwasfunkeptkept
How does the vocabulary shrink when the stopwords list is applied, and which words are dropped? The words 'the' and 'was' are dropped; 'movie' and 'fun' remain.

Mistakes That Produce Unexpected Counts

When a stopwords experiment gives a surprising feature count, the cause is usually at one of a few specific points. Because the stopword setting is supplied at construction and used during fitting, the most informative first question is which stage produced the result you are looking at. The points below are the ones to check first.

  • Common mistake

    Expecting stopword removal to increase the number of features

    What it looks like

    Applying the list and seeing fewer columns, then assuming the filter is broken.

    Why it fails

    The filter only removes candidate words, so the count can only shrink or stay the same.

    Do this instead

    Expect a count that is equal to or lower than the unfiltered count, then check how many listed words actually occur in the text.

  • Common mistake

    Passing the setting at the wrong stage

    What it looks like

    Expecting an already fitted vectorizer to change behavior after its stop_words value is altered.

    Why it fails

    The setting is chosen when the vectorizer is constructed and applied during fitting, so the earlier result still reflects the old setting.

    Do this instead

    Construct a new vectorizer with the desired stop_words value and call fit again.

  • Common mistake

    Assuming a smaller feature count means a better model

    What it looks like

    Dropping stopwords and concluding the model must now perform better.

    Why it fails

    The source states that any gain in model performance must be measured rather than assumed.

    Do this instead

    Train the model with and without the change and compare the results on held-out data.

  • Common mistake

    Looking only at the final matrix and not at the vocabulary that produced its columns

Practice: Tracing a Stopwords Experiment

MEDIUM

A colleague fits CountVectorizer(stop_words='english') on a set of documents and reports a vocabulary size that is larger than the one they got from the same documents last week. Before any code is changed, which stage of the workflow would you check first, and what would you compare?

Hints
  • Think about the order of the workflow: tokenize, filter stopwords, build vocabulary, count.
  • Ask whether the two runs used the same stop_words setting and the same documents.
  • Remember that filtering can only remove candidates, so a larger vocabulary points to a difference in input or setting.

Key Takeaways

  • A pre-defined stopwords list, such as ENGLISH_STOP_WORDS with 318 entries, is a library-supplied set of common words that text processing usually ignores because they carry little information about a document's topic.
  • CountVectorizer builds a bag-of-words matrix in which each vocabulary word owns one column and each cell holds that word's count in one document.
  • Passing stop_words='english' at construction makes the vectorizer filter the built-in list during fitting, and this filter can only decrease or leave unchanged the number of features.
  • The stopword decision sits between tokenization and vocabulary building, so unexpected counts are usually traced to that stage or to the stop_words setting used when the vectorizer was constructed.
  • Whether removing stopwords improves a downstream model is an empirical question that must be answered by measuring results, not assumed.

Related concepts

More concepts starting with C