Concepts / Building Text Classification Pipelines with Grid Search

Building Text Classification Pipelines with Grid Search

Coefficients are read by pairing each learned weight with its feature name from the same fitted pipeline, which requires the vectorizer and classifier arrays to line up by position.

  • Programming

Why Accuracy Is Not Enough

Once a text classifier has been trained, its accuracy tells you how often it is right, but it does not tell you why it is right. A model can score well for reasons that have nothing to do with the meaning you care about, so a good score alone is a weak form of evidence. This article shows how to open up a trained text model and read what it learned.

For a linear model such as logistic regression, the learned weights, called coefficients, are the most direct record of what the model picked up from the training text. Each weight is attached to one feature. In a text model, a feature is a token or an n-gram: a single word, a pair of adjacent words, or a run of three words. Analyzing coefficients means reading those weights against the feature names they belong to.

What do you think happens?

A review contains the phrase 'not worth'. Looking only at that phrase, which kind of review does the model lean toward?

  • A positive review

  • A negative review

  • Neither, because the word 'worth' is positive

Reveal answer
Answer:

A negative review

In the source example, 'not worth' indicates a negative review, even though the word 'worth' appears in it. The word beside it changes the direction of the signal, which is the central idea of this article.

Finding the Fitted Model Inside the Search

The grid search is the outer object. It wraps a pipeline, and the best version of that pipeline is available as grid.best_estimator_. You do not need to re-run the search to inspect the model. You only need to walk down from the grid search object to the pipeline that won, and then to the two named steps inside it.

The pipeline has two named steps. The first is a tf-idf vectorizer, which turns text into rescaled n-gram columns. The second is a logistic regression classifier, which learns one weight per column. The names matter: you reach each component by its step name, not by guessing its position in a list of objects. Once you have the vectorizer, you can ask it for the names of its columns. Once you have the classifier, you can ask it for its coefficients. Those two outputs are the two halves you must combine.

grid search objectwraps the pipeline searchbest_estimator_fitted pipelinevectorizer steptf-idf n-gram columnsfeature namesone per columnclassifier steplogistic regressioncoefficientsone weight per columnbest estimatornamed stepnamed stepcolumn nameslearned weights
Starting from the grid search object, which named steps lead to the feature names and the coefficients?

Pairing Names with Weights by Position

The extraction works only because position matters. The first entry in the feature name array describes the same column as the first entry in the coefficient array. The second name matches the second weight, and so on. Nothing in the code checks this for you. The pairing is a rule about order, not a rule about content.

worthweight 0.10not worthweight -1.20definitely worthweight 1.35well worthweight 0.95
How does each coefficient position map to the feature name at the same position? The weights shown are illustrative, not measured values.

Because the pairing is positional, check the lengths before you trust any ranking. The two sequences should have the same number of entries, one per feature. If they do not, the pairing step is already wrong, and no later interpretation can repair it. This failure is hard to notice because the output still looks plausible. Every name still appears next to a number, but some of those numbers belong to other columns.

Worked example

Ranking the illustrative features

Using the illustrative names and weights from the diagram, list the top two features pushing toward a positive review and the top feature pushing toward a negative review.

  1. 1
    Check the lengths

    There are four names and four weights, so every name has exactly one weight at the same position.

  2. 2
    Pair by position

    Position 0 gives worth with 0.10, position 1 gives not worth with -1.20, position 2 gives definitely worth with 1.35, and position 3 gives well worth with 0.95.

  3. 3
    Sort by weight

    Sorting from largest to smallest gives definitely worth (1.35), well worth (0.95), worth (0.10), and not worth (-1.20).

  4. 4
    Read the ends

    The top two positive entries are definitely worth and well worth. The most negative entry is not worth.

Result

Top positive: definitely worth, then well worth. Top negative: not worth.

Reading the Sign and Size of a Weight

Once each name is paired with its weight, the weights can be read in two ways. The sign tells you which direction a feature pushes the prediction. A weight with one sign pushes the model toward one class of review, and a weight with the opposite sign pushes it toward the other. The size tells you how strongly that push happens relative to the other features. A weight near zero contributes little either way.

Coefficient patternDirection of pushStrengthIllustrative example
Positive and largeToward the positive classStrong push relative to other featuresdefinitely worth at 1.35
Positive and smallToward the positive classWeak pushworth at 0.10
Negative and large in sizeToward the other classStrong push relative to other featuresnot worth at -1.20
Near zero, either signLittle directionContributes little either wayA feature with a weight close to 0

Reading coefficients by sign and size. The example values are illustrative.

The visualization in the source code ranks features this way, so the strongest signals are visible without scanning the full list. The ranking uses the same pairing you built earlier. If the pairing is wrong, the ranking is wrong too, even though the chart looks clean.

Same Word, Different Meaning

A unigram model sees the word 'worth' as a single column. Its weight reflects an average over every sentence where that word appears, whatever surrounds it. Once bigrams and trigrams are added, the model gets separate columns for phrases that contain 'worth', and those phrases can point in different directions. The source highlights three of them. The phrase 'not worth' indicates a negative review. The phrases 'definitely worth' and 'well worth' indicate a positive review. The same word appears in all three, and the surrounding word changes its meaning.

Feature typeColumn for 'worth'What the weight reflectsDirection in the source example
UnigramOne column for the word aloneAn average over every sentence containing the wordCannot separate the three contexts
BigramSeparate columns such as 'not worth' and 'well worth'What the model does with that exact two-word sequence'not worth' is negative; 'well worth' is positive
TrigramSeparate columns for three-word runs such as 'definitely worth'What the model does with that exact three-word sequence'definitely worth' is positive

How the same word is represented under different n-gram settings.

Key point

A coefficient list from a bigram or trigram model is more informative than a unigram list, because a weight on a phrase tells you what the model does with that exact sequence. When you read the top features, look for multi-word entries first, since that is where the context is preserved.

Tracing a Mismatch to Its Cause

When a ranked list does not match what you expected, the fastest route to the cause is to walk the pipeline in the same order the code does. The divergence usually appears at one of three points: the fitted object, the vectorizer's names, or the pairing of names with weights. The flowchart below follows that order and adds the length check from earlier.

ranking looks wrongunexpected top featurescheck fitted objectgrid.best_estimator_name count equalsweight count?one name per weightpair names withweights onceat the point of combinationranking matchesexpectationpairing verifiedtrace the step thatchanged arraysreordering or a differentfitted objectstart hereconfirm vectorizer namesyesnoafter fixingverified
Which check comes first, and which step changes the feature set or ordering so that names and weights no longer correspond?

The key to the flowchart is the decision node. If the two arrays have different lengths, the pairing is already broken, so you must trace back to whatever changed the arrays before you interpret any weight. If the lengths match, pair the arrays once, at the point where they are combined, and then rank.

  • Common mistake

    Trusting a ranking that looks plausible

    What it looks like

    Every name sits next to a number, so the list appears to make sense.

    Why it fails

    The pairing is positional and nothing checks it, so a misaligned list can look correct.

    Do this instead

    Check that the name count equals the weight count before reading any ranking.

  • Common mistake

    Reordering names and weights separately

    What it looks like

    Sorting the name array on its own, then pairing it with the unsorted coefficient array.

    Why it fails

    The first name no longer describes the first weight, so every pair after the reorder is wrong.

    Do this instead

    Pair the two arrays once, in their original order, then sort the paired result.

  • Common mistake

    Reading a unigram weight as if it describes a phrase

    What it looks like

    Taking the weight on 'worth' and assuming it describes 'not worth'.

    Why it fails

    A unigram column averages over every context of the word, so it cannot describe one phrase.

    Do this instead

    Look for the bigram or trigram column that matches the exact phrase.

  • Common mistake

    Judging a coefficient's size without comparing it to the others

    What it looks like

    Calling a weight of 0.95 large without looking at the other weights in the model.

    Why it fails

    Size only has meaning relative to the other features in the same fitted model.

    Do this instead

    Compare the weight with the rest of the ranked list before calling it strong or weak.

Practicing the Pairing Check

MEDIUM

A colleague reports that the feature 'not worth' has the largest positive weight in the model. You suspect the names and weights are misaligned. Describe the order of checks you would run, and state what result would confirm the misalignment and what result would rule it out.

Hints
  • Start at the fitted object: is it the grid search's best estimator?
  • Compare the number of feature names with the number of coefficients before anything else.
  • Ask whether the two arrays were paired once, in their original order.

Summary of the Workflow

  1. 1
    Open the grid search result and reach the best estimator with grid.best_estimator_.
  2. 2
    Use the named steps to reach the vectorizer for column names and the classifier for coefficients.
  3. 3
    Check that the number of names equals the number of coefficients.
  4. 4
    Pair the two arrays once, by position, and then rank the pairs.
  5. 5
    Read each weight by its sign for direction and its size, relative to the other weights, for strength.
  6. 6
    Prefer bigram and trigram features when you need to see how context changes meaning.

At a glance

  • A grid search result wraps a best pipeline, and its named steps give you the fitted vectorizer and classifier.
  • Feature names and coefficients correspond only by position, so check that their lengths match before trusting any ranking.
  • The sign of a coefficient gives the direction of push, and its size gives strength relative to the other features in the same model.
  • The same word can carry opposite meanings in different phrases, so multi-word features preserve context that a unigram loses.
  • When a ranking looks wrong, walk the pipeline in order: fitted object, then names, then the single pairing step.

Related concepts

More concepts starting with B