Introduction
In this 10xAI's knowledge article, we will understand the Feature Interaction effect in Machine Learning. We will also understand its impact, techniques to find it. In the learning process, we will also understand a very important Feature vs Target plot i.e. Partial Dependent Plot.
Features will be said to have an Interaction effect when the target increased or decreased more than when the two features are present together compared to their individual effect on the target.
$$y = \alpha f1 + \beta f2 + \gamma f1f2 $$
In the above equation, f1 and f2 are two features and f1f2 term is the interaction effect
Interaction Effect can be of multiple types i.e. don't expect it always to be additive. We will not cover too much theoretical detail. You can read more on this in the beautiful book by Max Kuhn and Kjell Johnson [Here]
What is the effect of feature Interaction
Two key effects of Feature Interaction are
- Not all models are able to figure out the effect inherently, so such models will miss this important information
- It affect our interpretation of Feature Importance e.g. in the above case f1,f2 will have higher importance when present together
The LinearRegression model will not consider the interaction term by default. We can add such terms by using Polynomial Features. We can observe in the plot below, how the target will move when there is an Interaction effect, and when itis absent.
It's obvious that a LinearRegression will not be able to model the pattern when the effect is present.
A tree-based model is able to capture the Feature Interaction effect inherently. This looks surprising. Try to guess the reason and post your answer in the comment.
Let's see the Code
Let's check a Regression model on California Housing Data, We will follow the following steps.
- Fit a Linear Regression Model on the data set
- Check the coef of each feature to see the Importance
- Create polynomial features and repeat the step but with L1 regularization so that we get rid of not so useful features
- Observe the new Features which are added to feature importance ranking. These will a mix of Interacted-Features and Degree 2 features
# .....Load and pre-process te data #1
# Define Model and fit data
from sklearn.linear_model import SGDRegressor
model_reg = SGDRegressor(eta0=0.001) # eta0=0.001
model_reg.fit(x_train, y_train)
# Check Coeff
coef = pd.DataFrame(model_reg.coef_.reshape(1, -1), columns = x_train.columns) #2
df = coef.T.sort_values(by=[0], ascending=False, key=lambda col: col.abs()) #3
df
Code-explanation
#1 - California housing data is available in Google Colab's sample data folder. You can simply load and pre-process it.
#2,#3 - Get the coeff and sort it. Remember that importance is decided by Magitude not the sign, that's why we passed a function to compare only the absolute value.
Result
latitude >longitude >median_income >population> total_bedrooms >households >total_rooms >housing_median_age
As we can observe, latitude and longitude are the most important features. Followed by median_income. We will not discuss much on feature important as that in itself worth a full post. Now let's repeat the exercise with polynomial features
# Polynomial Features
def poly_feat(x,deg): #1
from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures(degree = deg)
x = pd.DataFrame(poly.fit_transform(x), columns=poly.get_feature_names(x.columns))
return x
d = 2
x_train = poly_feat(x_train, d) #2
# Very strong L1 Regularization
from sklearn.linear_model import Lasso
model_reg = Lasso(alpha=253, max_iter=5000) #3
model_reg.fit(x_train, y_train)
# Check Coeff
coef = pd.DataFrame(model_reg.coef_.reshape(1, -1), columns = x_train.columns)
df = coef.T.sort_values(by=[0], ascending=False, key=lambda col: col.abs())
df
Code-explanation
#1 - Function to create polynomial features. It is available in Scikit-Learn.
#2,#3 - Calling the above function and fitting to a LASSO model.
Result
latitude >longitude> total_bedrooms>median_income>population>latitude median_income>total_rooms>longitude median_income>.........
We can observe that the Interacted features of Latitude/Longitude with median_Income has come up in the importance ranking. This hints towards a probable interaction effect between the Features.
This was an indirect technique but intuitive to explain the effect. Now in the next section, let's understand an approach to figure it out
Partial Dependence and its Plot
A partial dependence plot tells us how a Feature impacts the Target assuming all other features as constant. Using this information, we can figure out the Interaction between two features.
Let's understand the general math first.
Let's assume two features F1, F2 contributes to the output as 50, 50 (a fictitious unit). The contribution due to their interaction is 25.
When both the features are used,
total contribution = 125
When only one feature is used
F1, F2 contribution = 50 (because interaction effect will not come into play)
⇒ Difference = 125 - [50(for f1) + 50(for f2) + 0(for Interaction)] = 25
This is a general approach to figure out the interaction effect. This was a basic approach to develop intuition. Let's understand the formal way to do it. There may be some other approaches but we will discuss the approach known as partial dependence plot.We need to do some data Feature twisting/turning before we draw the plot. Here are the steps -
- Replace all the values for a particular feature with a constant value, keep other feature as it is
- Calculate the target and calculate its average for all the samples. This is our first point for one value of
the feature[Check the Image below] - Repeat the above steps for all the different values for the feature
- This will give us the Feature-Target mapping with other feature being constant
We can do the same for two features together. Hence, partial_dependence(F1)+partial_dependence(F2) will be compared with partial_dependence(F1,F2 joint) to figure out the interaction effect.
Let's Code it
We don't need to do it all as Scikit-learn has got a module to do so.
from sklearn.inspection import partial_dependence
features = [1] #latitude
par_1 = partial_dependence(model_reg, x_train, features, method='auto',)
par_1_pred = par_1[0][0]
features = [7] #median_income
par_7 = partial_dependence(model_reg, x_train, features, method='auto',)
par_7_pred = par_7[0][0]
features = [(1, 7)] #joint partial_dependence
par_1_7 = partial_dependence(model_reg, x_train, features, method='auto')
joint_pred = par_1_7[0][0][:,0]
Code-explanation
We have simply used the partial_dependence Class to calculate the same for latitude, median_income and their joint value.
Plot the curve for the sum and joint. In the case of Interaction, the joint plot will move very steeply as compared to the sum of the two features.
plt.plot(par_1_pred+par_7_pred)
plt.plot(joint_pred)
This shows an interaction effect between Latitude and median_income. Let's do the same exercise for latitude and total_rooms.
In this case, both the line have a similar slope. This show an absence of interaction between the two.
The good news is that you don't need to do all this complex exercise. Scikit-Learn provided you with a simple Class to plot the two-way partial_dependence plot.
from sklearn.inspection import plot_partial_dependence
features = [(1, 7)] # latitude and median_income
plot_partial_dependence(model_reg, x_train, features, n_jobs=-1)
If you read the above plot, with a fixed latitude, the target is moving exponentially(the coloured zone) with median_income. This indicates the presence of Interaction.
As you would expect, the partial_dependent plot for latitude and total_rooms will not indicate a similar pattern.
Summary and references
You might not need this knowledge always but when the sample and feature volume s not so big and interpretation is a key need. You will need this important concept.
Be mindful that this exercise requires a lot of computation. So this must be considered.
The focus of this post was around the interaction effect, so we exclude the single-feature Vs Target partial_depence plot. You may plot that too using Scikit-learn and understand how a single feature affects the target independent of other features
Read these to dive deep