In this guide, we’ll show how you can use EvalML to automatically find the best pipeline for predicting whether a patient has breast cancer. Along the way, we’ll highlight EvalML’s built-in tools and features for understanding and interacting with the search process.
[1]:
import evalml from evalml import AutoMLSearch from evalml.utils import infer_feature_types
First, we load in the features and outcomes we want to use to train our model.
[2]:
X, y = evalml.demos.load_fraud(n_rows=1000, return_pandas=True)
Number of Features Boolean 1 Categorical 6 Numeric 5 Number of training examples: 1000 Targets False 85.90% True 14.10% Name: fraud, dtype: object
First, we will clean the data. Since EvalML accepts a pandas input, it can run type inference on this data directly. Since we’d like to change the types inferred by EvalML, we can use the infer_feature_types utility method. Here’s what we’re going to do with the following dataset:
infer_feature_types
Reformat the expiration_date column so it reflects a more familiar date format.
expiration_date
Cast the lat and lng columns from float to str.
lat
lng
Use infer_feature_types to specify what types certain columns should be. For example, to avoid having the provider column be inferred as natural language text, we have specified it as a categorical column instead.
provider
The infer_feature_types utility method takes a pandas or numpy input and converts it to a Woodwork data structure, providing us with flexibility to cast the data as necessary.
[3]:
X['expiration_date'] = X['expiration_date'].apply(lambda x: '20{}-01-{}'.format(x.split("/")[1], x.split("/")[0])) X[['lat', 'lng']] = X[['lat', 'lng']].astype('str') X = infer_feature_types(X, feature_types= {'store_id': 'categorical', 'expiration_date': 'datetime', 'lat': 'categorical', 'lng': 'categorical', 'provider': 'categorical'}) X
In order to validate the results of the pipeline creation and optimization process, we will save some of our data as a holdout set.
[4]:
X_train, X_holdout, y_train, y_holdout = evalml.preprocessing.split_data(X, y, problem_type='binary', test_size=.2)
Note: To provide data to EvalML, it is recommended that you create a DataTable object using the Woodwork project. Here, split_data() returns Woodwork data structures.
DataTable
split_data()
EvalML also accepts and works well with pandas DataFrames. But using the DataTable makes it easy to control how EvalML will treat each feature, as a numeric feature, a categorical feature, a text feature or other type of feature. Woodwork’s DataTable includes features like inferring when a categorical feature should be treated as a text feature.
DataFrames
EvalML has many options to configure the pipeline search. At the minimum, we need to define an objective function. For simplicity, we will use the F1 score in this example. However, the real power of EvalML is in using domain-specific objective functions or building your own.
Below EvalML utilizes Bayesian optimization (EvalML’s default optimizer) to search and find the best pipeline defined by the given objective.
EvalML provides a number of parameters to control the search process. max_batches is one of the parameters which controls the stopping criterion for the AutoML search. It indicates the maximum number of rounds of AutoML to evaluate, where each round may train and score a variable number of pipelines. In this example, max_batches is set to 1.
max_batches
** Graphing methods, like AutoMLSearch, on Jupyter Notebook and Jupyter Lab require ipywidgets to be installed.
** If graphing on Jupyter Lab, jupyterlab-plotly required. To download this, make sure you have npm installed.
[5]:
automl = AutoMLSearch(X_train=X_train, y_train=y_train, problem_type='binary', objective='f1', max_batches=1)
When we call search(), the search for the best pipeline will begin. There is no need to wrangle with missing data or categorical variables as EvalML includes various preprocessing steps (like imputation, one-hot encoding, feature selection) to ensure you’re getting the best results. As long as your data is in a single table, EvalML can handle it. If not, you can reduce your data to a single table by utilizing Featuretools and its Entity Sets.
search()
You can find more information on pipeline components and how to integrate your own custom pipelines into EvalML here.
[6]:
automl.search()
Generating pipelines to search over... ***************************** * Beginning pipeline search * ***************************** Optimizing for F1. Greater score is better. Searching up to 1 batches for a total of 9 pipelines. Allowed model families: xgboost, random_forest, catboost, linear_model, decision_tree, extra_trees, lightgbm
Batch 1: (1/9) Mode Baseline Binary Classification P... Elapsed:00:00 Starting cross validation Finished cross validation - mean F1: 0.000 Batch 1: (2/9) Logistic Regression Classifier w/ Imp... Elapsed:00:00 Starting cross validation Finished cross validation - mean F1: 0.268 Batch 1: (3/9) Random Forest Classifier w/ Imputer +... Elapsed:00:04 Starting cross validation Finished cross validation - mean F1: 0.744 Batch 1: (4/9) XGBoost Classifier w/ Imputer + DateT... Elapsed:00:06 Starting cross validation Finished cross validation - mean F1: 0.762 Batch 1: (5/9) CatBoost Classifier w/ Imputer + Date... Elapsed:00:09 Starting cross validation Finished cross validation - mean F1: 0.759 Batch 1: (6/9) Elastic Net Classifier w/ Imputer + D... Elapsed:00:10 Starting cross validation Finished cross validation - mean F1: 0.000 Batch 1: (7/9) Extra Trees Classifier w/ Imputer + D... Elapsed:00:12 Starting cross validation Finished cross validation - mean F1: 0.000 Batch 1: (8/9) LightGBM Classifier w/ Imputer + Date... Elapsed:00:15 Starting cross validation Finished cross validation - mean F1: 0.756 Batch 1: (9/9) Decision Tree Classifier w/ Imputer +... Elapsed:00:17 Starting cross validation Finished cross validation - mean F1: 0.472 High coefficient of variation (cv >= 0.2) within cross validation scores. Decision Tree Classifier w/ Imputer + DateTime Featurization Component + One Hot Encoder may not perform as estimated on unseen data. Search finished after 00:19 Best pipeline: XGBoost Classifier w/ Imputer + DateTime Featurization Component + One Hot Encoder Best pipeline F1: 0.762019
After the search is finished we can view all of the pipelines searched, ranked by score. Internally, EvalML performs cross validation to score the pipelines. If it notices a high variance across cross validation folds, it will warn you. EvalML also provides additional data checks to analyze your data to assist you in producing the best performing pipeline.
[7]:
automl.rankings
If we are interested in see more details about the pipeline, we can view a summary description using the id from the rankings table:
id
[8]:
automl.describe_pipeline(3)
************************************************************************************** * XGBoost Classifier w/ Imputer + DateTime Featurization Component + One Hot Encoder * ************************************************************************************** Problem Type: binary Model Family: XGBoost Pipeline Steps ============== 1. Imputer * categorical_impute_strategy : most_frequent * numeric_impute_strategy : mean * categorical_fill_value : None * numeric_fill_value : None 2. DateTime Featurization Component * features_to_extract : ['year', 'month', 'day_of_week', 'hour'] * encode_as_categories : False 3. One Hot Encoder * top_n : 10 * features_to_encode : None * categories : None * drop : None * handle_unknown : ignore * handle_missing : error 4. XGBoost Classifier * eta : 0.1 * max_depth : 6 * min_child_weight : 1 * n_estimators : 100 Training ======== Training for binary problems. Total training time (including CV): 2.4 seconds Cross Validation ---------------- F1 MCC Binary Log Loss Binary AUC Precision Balanced Accuracy Binary Accuracy Binary # Training # Validation 0 0.800 0.788 0.222 0.828 0.963 0.840 0.951 533.000 267.000 1 0.774 0.771 0.246 0.821 1.000 0.816 0.948 533.000 267.000 2 0.712 0.708 0.292 0.798 0.955 0.782 0.936 534.000 266.000 mean 0.762 0.756 0.254 0.816 0.973 0.812 0.945 - - std 0.045 0.042 0.036 0.016 0.024 0.029 0.008 - - coef of var 0.059 0.056 0.140 0.019 0.025 0.036 0.008 - -
We can also view the pipeline parameters directly:
[9]:
pipeline = automl.get_pipeline(3) print(pipeline.parameters)
{'Imputer': {'categorical_impute_strategy': 'most_frequent', 'numeric_impute_strategy': 'mean', 'categorical_fill_value': None, 'numeric_fill_value': None}, 'DateTime Featurization Component': {'features_to_extract': ['year', 'month', 'day_of_week', 'hour'], 'encode_as_categories': False}, 'One Hot Encoder': {'top_n': 10, 'features_to_encode': None, 'categories': None, 'drop': None, 'handle_unknown': 'ignore', 'handle_missing': 'error'}, 'XGBoost Classifier': {'eta': 0.1, 'max_depth': 6, 'min_child_weight': 1, 'n_estimators': 100}}
We can now select the best pipeline and score it on our holdout data:
[10]:
pipeline = automl.best_pipeline pipeline.score(X_holdout, y_holdout, ["f1"])
OrderedDict([('F1', 0.8333333333333333)])
We can also visualize the structure of the components contained by the pipeline:
[11]:
pipeline.graph()