Concepts / tf-idf Features for Text

tf-idf Features for Text

Once a text classifier has been trained, the natural question is which parts of the input it relied on.

  • Programming

Why Coefficients Matter After Training

Once a text classifier has been trained, the natural question is which parts of the input it relied on. When the classifier is a logistic regression model trained on tf-idf features, the answer lives in the model's coefficients. Each feature has a coefficient, and this article is about reading those coefficients.

A trained model can have hundreds or thousands of coefficients. A plain list of that many numbers is hard to read, so the practice shown in the source is to draw them as a bar chart. The chart makes the relative sizes of the coefficients visible at a glance. By the end of this article you should be comfortable reading that chart, knowing what each bar stands for, and tracing the small selection logic that decides which bars appear.

The selection logic is where beginners most often make mistakes, so we will go slowly through it. We will use a small made-up example, because the source chart itself cannot be re-run here and the feature names and values in our example are invented for illustration only.

Following Each Feature to Its Coefficient

The text is first turned into tf-idf features, which are extracted from the text using the tf-idf technique and then passed as input to the logistic regression model. The model learns one coefficient per feature from that input. A logistic regression coefficient is a learned number for each feature, and the source states that coefficients determine each feature's importance in the model.

Because there is exactly one coefficient for each tf-idf feature, each bar in the chart corresponds to one feature. The chart is therefore a view of the trained model, not a view of the raw text. Every bar you see can be traced back to a coefficient that the fitted model stored.

goodcoefficient 0.8badcoefficient -1.2moviecoefficient 0.1boringcoefficient -0.5greatcoefficient 1.5
Which coefficient belongs to which vocabulary term, and how do the feature positions line up with the coefficient array? Each position in the feature list has one matching coefficient at the same position.

The diagram above uses invented terms and values. Its purpose is to show the alignment: position 0 in the feature names pairs with position 0 in the coefficient array, position 1 with position 1, and so on. If those positions were misaligned, each bar would be labeled with the wrong word.

The Call That Draws the Chart

The source produces the chart with a single call to a plotting helper named visualize_coefficients. The call does not compute anything on its own. It receives the coefficients and their names, and then draws them. Which coefficients appear is decided inside the helper, which is why the count parameter matters for what you see in the picture.

python
Notes on the code
  • fitted_coefficients: the learned coefficient for each feature, taken from the trained model
  • feature_names: the name of each tf-idf feature, in the same order as the coefficients
  • n_top_features=40: the count parameter that controls how many coefficients are drawn
fitted coefficientslearned by the modelvisualize_coefficientsplotting helperbar chartselected bars drawnfeature namesthe tf-idf termsn_top_featurescount parameter, 40 in thesourcevaluesnameshow manydraws
Where does each of the three arguments come from, and how does each one reach the plotted bars? The coefficients and names are paired and then the helper uses the count to choose which bars to draw.

Tracing a Sort-and-Slice Selection

The chart shows the largest and smallest coefficients, not the middle of the list. Picking out the extremes requires two operations in a specific order. First you sort the coefficients by value. Then you slice. Slicing an unsorted list selects by position, not by value, so the order of these two operations determines the result.

Here is a made-up example with five features. The names and values are invented and are not output from any real model. We pair each name with its value, sort the pairs by value, and then slice off the two lowest and the two highest. The middle of the list is simply left out, just as features with middle-sized values are not drawn in the chart.

python
Output (expected)
[('bad', -1.2), ('boring', -0.5)]
[('good', 0.8), ('great', 1.5)]
Notes on the code
  • zip pairs each name with its value so they stay together when sorting
  • sorted with key=lambda p: p[1] orders the pairs by the value, not by the name
  • [:2] takes the first two items of the sorted list, which are the two lowest values
  • [-2:] takes the last two items of the sorted list, which are the two highest values
  • movie, with value 0.1, is in the middle and is never selected
Pairs in originalordergood, bad, movie, boring,greatSorted by valuebad, boring, movie, good,greatTwo lowestbad, boringTwo highestgood, greatsort by valueslice [:2]slice [-2:]
In what order do the sort and the slice happen, and which items does the selection return at each step? Each stage hands its result to the next.
python
Output (expected)
[('good', 0.8), ('bad', -1.2)]
[('boring', -0.5), ('great', 1.5)]
Notes on the code
  • This version slices the unsorted pairs, so it selects by position in the original list
  • good and bad are simply the first two features, not the two lowest values
  • The result mixes a high value (0.8) into the low end, which the sorted version never does

What the Chart Shows and Leaves Out

A bar chart of the largest and smallest coefficients makes the relative sizes visible and lets you see the feature names alongside them. It does not tell you everything about importance. The table below separates what the chart displays from what it leaves out.

Visible in the chartNot shown by the chart
Feature names of the drawn coefficientsCoefficients of features that were left out of the selection
Relative sizes of the drawn coefficientsHow the features perform on unseen data
Which drawn values are larger or smaller than othersWhether the middle of the ranking matters
The extremes selected by the helperHow the count parameter divides between the two ends, which the source does not settle

What the bar chart of largest and smallest coefficients does and does not show

Mistakes When Reading Selection Logic

  • Common mistake

    Slicing the coefficients without sorting them first

    What it looks like

    pairs[:2] on the made-up list returns good and bad, even though good has a high value of 0.8

    Why it fails

    A slice selects by position in the list, not by the value stored at that position

    Do this instead

    Sort the pairs by value with sorted(pairs, key=lambda p: p[1]) and only then take the first and last items

  • Common mistake

    Treating the middle of the list as hidden noise to be checked

    What it looks like

    Assuming movie, with value 0.1, is an unimportant feature because it is absent from the two-ended selection

    Why it fails

    The selection is only a view of the extremes, so a feature missing from the chart is not thereby shown to be unimportant or important

    Do this instead

    Remember the chart highlights the ends of the ranking and says nothing about the features it leaves out

  • Common mistake

    Assuming the chart reports performance on new text

    What it looks like

    Reading a large bar as proof the feature improves predictions on unseen documents

    Why it fails

    The chart displays coefficients of the trained model, which is a view of the fitted model rather than an evaluation

    Do this instead

    Use the chart to see what the model relied on, and evaluate separately if you need to know how it performs on new data

  • Common mistake

    Ignoring the count parameter when interpreting how many bars appear

Predicting a Selection Before Running It

EASY

Using the same five made-up pairs (good 0.8, bad -1.2, movie 0.1, boring -0.5, great 1.5), work out the answer on paper before checking. Part one: what does sorting by value and then taking the first two items return? Part two: what does taking the last two items of the sorted list return? Part three: explain in one sentence why sorting has to come before slicing.

Hints
  • Write the five values in order from smallest to largest first
  • The two lowest values are the first two items of the sorted list
  • Compare your answer with the output of the code in the example above

What do you think happens?

Without sorting, what does pairs[-2:] return from the original five pairs in order good, bad, movie, boring, great?

  • good and bad

  • boring and great

  • movie and boring

  • great and bad

Reveal answer
Answer:

boring and great

The original list ends with boring then great, so slicing the last two positions returns those two items. They are not the two highest values in this case only because of where they happen to sit; the position-based slice does not check value.

Key Takeaways

  • A logistic regression coefficient is a learned number for each tf-idf feature, and the source states that coefficients determine each feature's importance in the model
  • visualize_coefficients receives the fitted coefficients, the feature names, and a count parameter, and then draws the selected bars; the source's call uses n_top_features=40
  • Selecting the largest and smallest coefficients requires sorting by value before slicing, because slicing an unsorted list selects by position
  • The bar chart shows relative sizes and names of selected coefficients, but not performance on unseen data, and the source leaves the meaning of smallest and the split of the count parameter open

Related concepts

More concepts starting with T