Avoiding Overfitting¶
The ultimate goal of machine learning is to make accurate predictions on unseen data. EvalML aims to help you build a model that will perform as you expect once it is deployed in to the real world.
One of the benefits of using EvalML to build models is that it provides guardrails to ensure you are building pipelines that will perform reliably in the future. This page describes the various ways EvalML helps you avoid overfitting to your data.
[1]:
import evalml
Detecting Label Leakage¶
A common problem is having features that include information from your label in your training data. By default, EvalML will provide a warning when it detects this may be the case.
Let’s set up a simple example to demonstrate what this looks like
[2]:
import pandas as pd
X = pd.DataFrame({
"leaked_feature": [6, 6, 10, 5, 5, 11, 5, 10, 11, 4],
"leaked_feature_2": [3, 2.5, 5, 2.5, 3, 5.5, 2, 5, 5.5, 2],
"valid_feature": [3, 1, 3, 2, 4, 6, 1, 3, 3, 11]
})
y = pd.Series([1, 1, 0, 1, 1, 0, 1, 0, 0, 1])
clf = evalml.AutoClassifier(
max_pipelines=1,
model_types=["linear_model"],
)
clf.fit(X, y)
*****************************
* Beginning pipeline search *
*****************************
Optimizing for Precision. Greater score is better.
Searching up to 1 pipelines.
Possible model types: linear_model
WARNING: Possible label leakage: leaked_feature, leaked_feature_2
✔ Logistic Regression Classifier w/ O... 0%| | Elapsed:00:07
✔ Logistic Regression Classifier w/ O... 100%|██████████| Elapsed:00:07
✔ Optimization finished
In the example above, EvalML warned about the input features leaked_feature
and leak_feature_2
, which are both very closely correlated with the label we are trying to predict. If you’d like to turn this check off, set detect_label_leakage=False
.
The second way to find features that may be leaking label information is to look at the top features of the model. As we can see below, the top features in our model are the 2 leaked features.
[3]:
best_pipeline = clf.best_pipeline
best_pipeline.feature_importances
[3]:
feature | importance | |
---|---|---|
0 | leaked_feature | -1.773115 |
1 | leaked_feature_2 | -1.731261 |
2 | valid_feature | -0.247665 |
Perform cross-validation for pipeline evaluation¶
By default, EvalML performs 3-fold cross validation when building pipelines. This means that it evaluates each pipeline 3 times using different sets of data for training and testing. In each trial, the data used for testing has no overlap from the data used for training.
While this is a good baseline approach, you can pass your own cross validation object to be used during modeling. The cross validation object can be any of the CV methods defined in scikit-learn or use a compatible API.
For example, if we wanted to do a time series split:
[4]:
from sklearn.model_selection import TimeSeriesSplit
X, y = evalml.demos.load_breast_cancer()
clf = evalml.AutoClassifier(
cv=TimeSeriesSplit(n_splits=6),
max_pipelines=1
)
clf.fit(X, y)
*****************************
* Beginning pipeline search *
*****************************
Optimizing for Precision. Greater score is better.
Searching up to 1 pipelines.
Possible model types: linear_model, random_forest, xgboost
✔ XGBoost Classifier w/ One Hot Encod... 0%| | Elapsed:00:00
✔ XGBoost Classifier w/ One Hot Encod... 100%|██████████| Elapsed:00:00
✔ Optimization finished
if we describe the 1 pipeline we built, we can see the scores for each of the 6 splits as determined by the cross-validation object we provided. We can also see the number of training examples per fold increased because we were using TimeSeriesSplit
[5]:
clf.describe_pipeline(0)
********************************************************************************************
* XGBoost Classifier w/ One Hot Encoder + Simple Imputer + RF Classifier Select From Model *
********************************************************************************************
Problem Types: Binary Classification, Multiclass Classification
Model Type: XGBoost Classifier
Objective to Optimize: Precision (greater is better)
Number of features: 18
Pipeline Steps
==============
1. One Hot Encoder
2. Simple Imputer
* impute_strategy : most_frequent
3. RF Classifier Select From Model
* percent_features : 0.6273280598181127
* threshold : -inf
4. XGBoost Classifier
* eta : 0.5928446182250184
* max_depth : 4
* min_child_weight : 8.598391737229157
Training
========
Training for Binary Classification problems.
Total training time (including CV): 0.5 seconds
Cross Validation
----------------
Precision F1 Recall AUC Log Loss MCC # Training # Testing
0 0.974 0.822 0.822 0.950 0.578 0.650 83.000 81.000
1 1.000 0.988 0.988 1.000 0.163 0.976 164.000 81.000
2 0.981 0.981 0.981 0.968 0.139 0.944 245.000 81.000
3 0.963 0.929 0.929 0.991 0.113 0.774 326.000 81.000
4 0.984 0.960 0.960 0.993 0.147 0.830 407.000 81.000
5 0.983 0.983 0.983 0.998 0.083 0.936 488.000 81.000
mean 0.981 0.944 0.944 0.983 0.204 0.852 - -
std 0.012 0.064 0.064 0.020 0.186 0.125 - -
coef of var 0.013 0.067 0.067 0.020 0.909 0.147 - -
Detect unstable pipelines¶
When we perform cross validation we are trying generate an estimate of pipeline performance. EvalML does this by taking the mean of the score across the folds. If the performance across the folds varies greatly, it is indicative the the estimated value may be unreliable.
To protect the user against this, EvalML checks to see if the pipeline’s performance has a variance between the different folds. EvalML triggers a warning if the “coefficient of variance” of the scores (the standard deviation divided by mean) of the pipelines scores exeeds .2.
This warning will appear in the pipeline rankings under high_variance_cv
.
[6]:
clf.rankings
[6]:
id | pipeline_name | score | high_variance_cv | parameters | |
---|---|---|---|---|---|
0 | 0 | XGBoostPipeline | 0.980845 | False | {'eta': 0.5928446182250184, 'min_child_weight'... |
Create holdout for model validation¶
EvalML offers a method to quickly create an holdout validation set. A holdout validation set is data that is not used during the process of optimizing or training the model. You should only use this validation set once you’ve picked the final model you’d like to use.
Below we create a holdout set of 20% of our data
[7]:
X, y = evalml.demos.load_breast_cancer()
X_train, X_holdout, y_train, y_holdout = evalml.preprocessing.split_data(X, y, test_size=.2)
[8]:
clf = evalml.AutoClassifier(
objective="recall",
max_pipelines=3,
detect_label_leakage=True
)
clf.fit(X_train, y_train)
*****************************
* Beginning pipeline search *
*****************************
Optimizing for Recall. Greater score is better.
Searching up to 3 pipelines.
Possible model types: linear_model, random_forest, xgboost
✔ XGBoost Classifier w/ One Hot Encod... 0%| | Elapsed:00:00
✔ XGBoost Classifier w/ One Hot Encod... 33%|███▎ | Elapsed:00:00
✔ Random Forest Classifier w/ One Hot... 67%|██████▋ | Elapsed:00:06
✔ Random Forest Classifier w/ One Hot... 100%|██████████| Elapsed:00:06
✔ Optimization finished
then we can retrain the best pipeline on all of our training data and see how it performs compared to the estimate
[9]:
pipeline = clf.best_pipeline
pipeline.fit(X_train, y_train)
pipeline.score(X_holdout, y_holdout)
[9]:
(0.951048951048951, {})