Model-Based Feature Selection Strategies
Model-based feature selection uses a selector that is first fitted with fit(X_train, y_train) and then applied with transform(X_train) to produce a reduced feature matrix.
Reading the Selection Calls First
This article begins with code rather than a definition. A model-based feature selector reduces a training set by deciding which feature columns to keep. The pattern you will read below comes from a worked exercise in which a feature selector reduces a training set from 80 features to 40. Read the lines once through, then work out what each line should do before you read the explanation that follows.
- select.fit examines the training data and learns which features to keep
- select.transform applies that decision to X_train and returns a new array
- The result is stored in a new variable, so X_train is left unchanged
- The two print statements report the shape of each array as evidence of what happened
The source snippet does not show how select was created, so the selector is assumed to have been set up earlier in the same exercise. What the snippet does show is the complete pattern: one call to fit, one call to transform, and two print statements. The shape printout is the evidence you will use to check whether the selection behaved as expected. The code above is a reconstruction of that pattern, written to match the calls the source describes.
What do you think happens?
Before reading on: after the fit and transform calls, what shape should X_train_l1 print, given that X_train started with 80 features across 284 samples?
Reveal answer
(284, 40)
The selector keeps 40 of the 80 feature columns. The 284 samples remain unchanged, so only the column count drops.
Fitting Before Transforming
The method select.fit(X_train, y_train) is the step where the selector examines the training data. It receives both the feature matrix X_train and the target values y_train, because a model-based selector decides which features matter by using a model that is trained on those inputs and targets. The fit call changes the state of the select object, but it does not return a new dataset.
The method select.transform(X_train) is the step that applies the decision. It takes the feature matrix and returns a new array that contains only the features the selector kept. In the source, that result is stored in a new variable, X_train_l1, so the original X_train is left unchanged. This separation matters when you debug: if the shape of X_train_l1 is wrong, the problem lies in the fit step, the transform step, or the data that was passed to them.
The order of the calls is fixed. The selector must be fitted before transform is called, because transform relies on the decision made during fit. The training matrix enters the process in two places: it is used to learn the selection during fit, and it is then passed to transform to produce the reduced array. The diagram below traces that flow.
| Aspect | fit(X_train, y_train) | transform(X_train) |
|---|---|---|
| What it reads | Both X_train and y_train | Only X_train |
| What it stores | The selection decision inside the select object | Nothing new; it uses the stored decision |
| What it returns | No new dataset | A new array with only the kept features |
| Must run | First | After fit has been called |
The roles of the two selector methods, as described in the source
Reading the Two Shapes
Shape is the most useful first check in this exercise because it reports two facts at once: how many samples remain and how many features remain. A shape is written as a pair of numbers, rows first and then columns. Comparing the two shapes printed by the script tells you exactly what the transform step did.
Comparing X_train with X_train_l1
The script prints the shape of X_train and then the shape of X_train_l1. What changed, and what stayed the same?
- 1Read the sample count
The first number in each shape is the row count, which is the number of samples. The source reports 284 samples, and that value is unchanged across the selection.
- 2Read the feature count of X_train
The second number in the original shape is the column count, which is the number of features. The source reports 80 features before selection.
- 3Read the feature count of X_train_l1
The second number in the reduced shape is 40, so transform returned an array with half as many feature columns.
- 4Compare the two pairs
The rows stayed the same and the columns changed. Selection removes features, not samples.
X_train_l1 has the same 284 rows as X_train but only 40 columns instead of 80.
What get_support() Returns
After the reduced array has been checked, the source looks at which features were selected. The call select.get_support() returns a mask, an array that records, for each original feature, whether the selector kept it. The mask has one entry per original feature, so each position answers the question: was this feature kept?
get_support()returns one True or False entry per original featurereshape(1, -1)turns the one-dimensional mask into a single row- matshow draws that row as a strip of cells
- cmap='gray_r' uses a reversed grayscale palette in which True is black and False is white
The mask is reshaped with mask.reshape(1, -1) before it is displayed. This turns the one-dimensional mask into a single row with one column per original feature. The matshow function then draws that row as a strip of cells, and the cmap='gray_r' argument chooses the reversed grayscale palette in which True cells are black and False cells are white. The source's tick marks run from 0 to 70 along the horizontal axis, which marks the range of feature positions across the strip.
Reading the Mask Plot
Because the mask is drawn as a single row, the horizontal position of each cell corresponds to an original feature position, not to a sample. Position 0 is the first original feature, the next position is the second, and so on. Reading the strip from left to right is therefore a scan across the feature columns of the original matrix. A black cell means that feature was kept by the selector, and a white cell means it was dropped.
The source labels this horizontal axis "Sample index". That label describes the strip in a misleading way, since the cells represent features and not samples. When you write your own version of this plot, change the label so that it matches what the axis actually shows, such as "Feature index".
Tracing a Misbehaving Script
When a selection script misbehaves, locate the failure by comparing each step's output with its expected output, starting from the fit call and moving forward. Check the output of each step in order, and stop at the first step whose result differs from what you expected. The problem originates there or in the data that was passed into it.
- 1After select.fit, confirm that the script ran without error. Fit returns no dataset, so there is no array shape to check at this step.
- 2After select.transform, compare the shape of X_train_l1 with the expected column count. The row count should match X_train.
- 3After
get_support, check that the mask has one entry per original feature. Then confirm the number of True entries matches the reduced column count. - 4Only after the mask is correct, look at the plot. A plot that looks wrong may simply reflect a wrong axis label or palette, not a wrong selection.
Mistakes That Hide the Real Problem
Common mistake Calling transform before fit
Why it failsTransform relies on the decision made during fit, so there is no learned selection to apply until fit has run.
Do this insteadCall select.fit(X_train, y_train) first, then call select.transform(X_train).Common mistake Expecting fit to return the reduced dataset
Why it failsFit changes the state of the select object but does not return a new dataset.
Do this insteadStore the output of transform in a new variable such as X_train_l1.
Common mistake Assuming the number of rows changed when the features dropped
Why it failsModel-based selection removes feature columns. The 284 samples remain unchanged in the source exercise.
Do this insteadRead the shape as a pair, rows first and then columns, and expect only the column count to change.
Common mistake Reading the mask strip as sample positions
Why it failsEach cell in the mask strip represents an original feature, so the axis position tracks feature index.
Do this insteadRelabel the axis as a feature index when you write your own plot, since the source's "Sample index" label is misleading.
Common mistake Confusing True and False colours on the mask plot, which are reversed by the gray_r palette: True is black and False is white
Checking Your Understanding
A script prints X_train with shape (284, 80) and X_train_l1 with shape (284, 50). Using only the shape printouts, what can you conclude about the transform step, and what would you check next?
Hints
- Compare the row counts first, then the column counts.
- The source's expected column count after selection is 40, so ask why this run kept 50.
- Think about which step produced the reduced array, and what you would inspect to find the first divergence.
Key Takeaways
- A model-based selector is fitted with
fit(X_train, y_train), which learns the selection and returns no new dataset, and then applied withtransform(X_train), which returns the reduced array. - Shape reports rows and columns together: in the source exercise the samples stay at 284 while the features drop from 80 to 40.
get_support()returns a mask with one entry per original feature; reshaping it to a single row and drawing it with matshow shows kept features in black and dropped features in white.- When a script misbehaves, compare each step's output with its expected output, starting from fit, and stop at the first step that diverges.