Concepts / Creating Interaction Features

Creating Interaction Features

Interaction and polynomial features enrich a feature representation, especially for linear models.

  • Programming

Why a Model Depends on Its Columns

A model learns from the numbers you give it, so the way those numbers are laid out matters as much as the algorithm that consumes them. One way to enrich a feature representation, especially for linear models, is to add interaction features and polynomial features built from the original data. This kind of feature engineering shows up in statistical modeling and in many practical machine learning applications.

This article follows one concrete case. A linear model is fit to binned data, and the binned model has learned only a constant for each bin. The question is what happens when one more column is placed next to the bin columns. To answer it, you will trace the shape of the feature matrix at each step, because the shapes tell you what the model actually receives.

Tracing Shapes Step by Step

The source frames the representation as a trace. Each part of the combining expression produces an array, and the final array is the one the linear model receives. Rather than trusting the plot, follow the shape of the data after each construction step. The shape is a pair of numbers: the number of rows, which is the number of data points, and the number of columns, which is the number of features.

In this example the data set has 100 rows, one per data point. Before the stacking step, the original feature and the binned features each have 100 rows. The final printed result for the interaction representation is (100, 20): still 100 rows, and 20 columns. The rest of the explanation shows where those 20 columns come from.

Original feature100 rows, 1 columnBin indicators100 rows, 10 columnsProduct features100 rows, 10 columnsStacked matrix100 rows, 20 columnsassign to binsrestrict to each binnp.hstacknp.hstack
After binning, after the elementwise product, and after np.hstack, what is the shape at each step, and which step is the first to produce an unexpected column count?

The pipeline above shows the important rule for this section: the row count stays fixed at 100 throughout, and only the column count changes. If the number you print at the end does not match what you count from the two blocks, the problem lies in the stacking step or in the inputs passed to it, not in the regression. Checking shapes after each step lets you find that point quickly.

Bin Indicators and Product Features

The new data set has 20 features, and they come in two families. The first family records which bin each data point falls into. These are the bin indicator columns: for each bin, a column that marks whether the data point lies inside that bin. The second family takes the original x-axis feature and restricts it to each bin. Each product feature holds the original x-axis value inside its bin and zero everywhere else.

Bin indicatorscolumns 1 to 10, one perbinProduct featurescolumns 11 to 20, originalx inside each binconcatenated side by side
Which columns correspond to the bin indicators and which correspond to the product features, and how do the column positions map back to the input feature's ranges?

Both families are concatenated into one matrix, so the linear model sees a single set of columns and fits them together. Each bin contributes one indicator column and one product column, so the bin ranges are mirrored in both halves of the matrix. Reading a column position therefore tells you which bin it belongs to and whether it is an indicator or a restricted copy of the original value.

python
Output (expected)
(100, 20)
Notes on the code
  • Each block has 100 rows, one per data point, and 10 columns, one per bin.
  • np.hstack places the two blocks side by side and keeps the row count fixed.
  • The printed shape confirms 100 rows and 10 plus 10 equals 20 columns.

The code above uses placeholder zero arrays only to show the shapes; in the real representation the blocks hold the indicator and product values. The shape reasoning is what carries over: two blocks of 10 columns each, stacked horizontally over the same 100 rows, produce 20 columns.

Per-Bin Offsets and Slopes

Start with what the binned model already does. A linear model on binned data learns a constant value for each bin. Each bin is an interval of the original input, and every point that falls inside it receives the same predicted value. The result is a step-like shape: flat within each bin, with jumps at the bin edges. Such a model cannot express a slope on its own, because a constant has no slope.

When the linear regression is fit on the binned-plus-product representation, the result is a separate line for each bin. The lines do not have to share one slope. Each bin ends up with its own offset and its own slope. The model is still linear in its features, but the features now let the slope change from one bin to the next. In symbols, within bin $j$ the prediction takes the form $a_j + b_j x$, where $a_j$ is the offset and $b_j$ is the slope for that bin.

Single lineone offset and one slopeBin 1 lineown offset and slopeBin 2 lineown offset and slopeBin 10 lineown offset and slope
How does the fit differ between the original single-slope representation and the binned-plus-product representation, where each bin gets its own intercept and slope?

Adding the Original Feature Back In

A linear model can learn more than offsets. It can also learn slopes. One way to give the model a slope is to add the original feature back in, next to the binned columns. The original feature and the binned features are two blocks of columns describing the same 100 data points. The stacking step places them side by side, so each row carries the raw value together with its bin indicators.

The model now has a single coefficient that applies to the raw input value across all bins. That shared coefficient acts as one global slope, while the bin columns continue to supply a separate level for each bin. In the source example this produces an 11-dimensional data set: the original feature plus the 10 bin columns.

Worked example

Counting columns after adding the original feature

The binned representation has 10 bin indicator columns over 100 rows. The original feature is one column over the same 100 rows. How many columns result after stacking the original feature with the bin columns, and what is the resulting shape?

  1. 1
    Count the original block

    The original feature is a single column, so its block contributes 1 column.

  2. 2
    Count the bin block

    The bin indicators contribute 10 columns, one per bin.

  3. 3
    Add the blocks

    The stacked column count is the sum of the two blocks: 1 plus 10 equals 11.

  4. 4
    Check the rows

    np.hstack keeps the row count fixed, so the rows remain 100.

Result

The stacked matrix has shape (100, 11), an 11-dimensional data set with one global slope term and 10 per-bin levels.

Notice that the stacking step adds columns, not rows. Adding columns changes what each data point looks like to the model, while the number of data points stays the same. That is why the printed row count remains 100 after stacking, and why the column count is always the sum of the column counts of the blocks being joined.

Common Mistakes When Stacking Feature Blocks

  • Common mistake

    Expecting the row count to change when columns are stacked

    What it looks like

    Stacking a 100 by 10 block with a 100 by 10 block and expecting 200 rows.

    Why it fails

    np.hstack adds columns while keeping the row count fixed, because each row is still one data point.

    Do this instead

    Expect 100 rows and 20 columns. Only the column count grows.

  • Common mistake

    Assuming bin indicators alone give the model a slope

    What it looks like

    Fitting a model on the bin columns only and expecting a sloped line within each bin.

    Why it fails

    A linear model on binned data learns a constant for each bin, which has no slope.

    Do this instead

    Add product features to get per-bin slopes, or keep the original feature to get one global slope.

  • Common mistake

    Trusting the plot instead of the shapes

    What it looks like

    Looking only at the fitted lines and not checking that the stacked matrix has the expected number of columns.

    Why it fails

    A plot can look reasonable even when the column count is wrong, so the error stays hidden.

    Do this instead

    Print the shape after each construction step and compare it with the count you expect from the blocks.

  • Common mistake

    Forgetting that the original feature adds one column, not one per bin

Predicting Column Counts Before Stacking

What do you think happens?

You stack a binned block with 10 columns and a product block with 10 columns over the same 100 rows. What shape does the result have?

Reveal answer
Answer:

(100, 20)

The row count stays at 100 because each row is still one data point. The column count is the sum of the two blocks, 10 plus 10, giving 20 columns.

EASY

A binned block has 100 rows and 10 columns. The original feature block has 100 rows and 1 column. Predict the shape after stacking them with np.hstack, then state how many columns come from each block and which block supplies the single global slope.

Hints
  • Count the columns of each block separately before adding them.
  • The original feature is the block that gives the model one shared coefficient across all bins.
  • The row count should not change when you stack columns.
MEDIUM

A colleague stacks two blocks of 100 rows, one with 10 columns and one with 11 columns, and reports a shape of (200, 21). Identify the step where the result departs from what you expected, and state the shape you should have seen.

Hints
  • Check the row count first: stacking columns should keep it fixed.
  • The correct column count is the sum of the two blocks.

Key Takeaways

  • Interaction features enrich a feature matrix, which matters most for linear models.
  • The binned-plus-product representation has 20 columns over 100 rows: 10 bin indicator columns and 10 product features, each holding the original x value inside its bin and zero elsewhere.
  • A linear model on this representation fits a separate offset and slope for each bin, because the product features let the slope change between bins.
  • Keeping the original feature alongside the bin columns adds one global slope, giving an 11-dimensional data set in the source example.
  • Check the shape after each construction step: np.hstack adds columns while keeping the row count fixed, so the first unexpected column count shows where the problem is.

Related concepts

More concepts starting with C