{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# What to expect from AutoML software\n",
"Automated machine learning (AutoML) takes a higher-level approach to machine learning than most practitioners are used to, so we've gathered a handful of guidelines on what to expect when running AutoML software such as TPOT.\n",
"\n",
"#### AUTOML ALGORITHMS AREN'T INTENDED TO RUN FOR ONLY A FEW MINUTES\n",
"Of course, you can run TPOT for only a few minutes, and it will find a reasonably good pipeline for your dataset. However, if you don't run TPOT for long enough, it may not find the best possible pipeline for your dataset. It may not even find any suitable pipeline at all, in which case a RuntimeError('A pipeline has not yet been optimized. Please call fit() first.') will be raised. Often it is worthwhile to run multiple instances of TPOT in parallel for a long time (hours to days) to allow TPOT to thoroughly search the pipeline space for your dataset.\n",
"\n",
"#### AUTOML ALGORITHMS CAN TAKE A LONG TIME TO FINISH THEIR SEARCH\n",
"AutoML algorithms aren't as simple as fitting one model on the dataset; they consider multiple machine learning algorithms (random forests, linear models, SVMs, etc.) in a pipeline with multiple preprocessing steps (missing value imputation, scaling, PCA, feature selection, etc.), the hyperparameters for all of the models and preprocessing steps, and multiple ways to ensemble or stack the algorithms within the pipeline.\n",
"\n",
"As such, TPOT will take a while to run on larger datasets, but it's important to realize why. With the default TPOT settings (100 generations with 100 population size), TPOT will evaluate 10,000 pipeline configurations before finishing. To put this number into context, think about a grid search of 10,000 hyperparameter combinations for a machine learning algorithm and how long that grid search will take. That is 10,000 model configurations to evaluate with 10-fold cross-validation, which means that roughly 100,000 models are fit and evaluated on the training data in one grid search. That's a time-consuming procedure, even for simpler models like decision trees.\n",
"\n",
"Typical TPOT runs will take hours to days to finish (unless it's a small dataset), but you can always interrupt the run partway through and see the best results so far. TPOT also provides a warm_start and a periodic_checkpoint_folder parameter that lets you restart a TPOT run from where it left off.\n",
"\n",
"#### AUTOML ALGORITHMS CAN RECOMMEND DIFFERENT SOLUTIONS FOR THE SAME DATASET\n",
"If you're working with a reasonably complex dataset or run TPOT for a short amount of time, different TPOT runs may result in different pipeline recommendations. TPOT's optimization algorithm is stochastic, which means that it uses randomness (in part) to search the possible pipeline space. When two TPOT runs recommend different pipelines, this means that the TPOT runs didn't converge due to lack of time or that multiple pipelines perform more-or-less the same on your dataset.\n",
"\n",
"This is actually an advantage over fixed grid search techniques: TPOT is meant to be an assistant that gives you ideas on how to solve a particular machine learning problem by exploring pipeline configurations that you might have never considered, then leaves the fine-tuning to more constrained parameter tuning techniques such as grid search or bayesian optimization."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# TPOT with code\n",
"\n",
"We've designed the TPOT interface to be as similar as possible to scikit-learn.\n",
"\n",
"TPOT can be imported just like any regular Python module. To import TPOT, type:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Matplotlib is building the font cache; this may take a moment.\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n",
" from .autonotebook import tqdm as notebook_tqdm\n"
]
}
],
"source": [
"import tpot\n",
"from tpot import TPOTClassifier"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"then create an instance of TPOT as follows:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"classification_optimizer = TPOTClassifier()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"It's also possible to use TPOT for regression problems with the TPOTRegressor class. Other than the class name, a TPOTRegressor is used the same way as a TPOTClassifier. You can read more about the TPOTClassifier and TPOTRegressor classes in the API documentation."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"from tpot import TPOTRegressor\n",
"regression_optimizer = TPOTRegressor()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Fitting a TPOT model works exactly like any other sklearn estimator. Some example code with custom TPOT parameters might look like:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generation: : 5it [00:32, 6.57s/it]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"auroc_score: 0.9950396825396826\n"
]
}
],
"source": [
"import sklearn\n",
"import sklearn.datasets\n",
"import sklearn.metrics\n",
"import tpot\n",
"\n",
"classification_optimizer = TPOTClassifier(search_space=\"linear-light\", max_time_mins=30/60, n_jobs=30, cv=5)\n",
"\n",
"X, y = sklearn.datasets.load_breast_cancer(return_X_y=True)\n",
"X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, random_state=1, test_size=0.2)\n",
"\n",
"classification_optimizer.fit(X_train, y_train)\n",
"\n",
"auroc_score = sklearn.metrics.roc_auc_score(y_test, classification_optimizer.predict_proba(X_test)[:,1])\n",
"print(\"auroc_score: \", auroc_score)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Scorers, Objective Functions, and multi objective optimization.\n",
"\n",
"There are two ways of passing objectives into TPOT. \n",
"\n",
"1. `scorers`: Scorers are functions that have the signature (estimator, X_test, y_test) and take in estimators that are expected to be fitted to training data. These can be produced with the [sklearn.metrics.make_scorer](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.make_scorer.html) function. This function is used to evaluate the test folds during cross validation (defined in the `cv` parameter). These are passed into TPOT via the scorers parameter. This can take in the scorer itself or the string corresponding to a scoring function ([as listed here](https://scikit-learn.org/stable/modules/model_evaluation.html)). TPOT also supports passing in a list of several scorers for multi-objective optimization. For each fold of CV, TPOT only fits the estimator once, then evaluates all provided scorers in a loop.\n",
"\n",
"2. `other_objective_functions` : Other objective functions in TPOT have the signature (estimator) and returns a float or list of floats. These get passed a single unfitted estimator once, outside of cross validation. The user may choose to fit the pipeline within this objective function as well.\n",
"\n",
"\n",
"\n",
"Each scorer and objective function must be accompanied by a list of weights corresponding to the list of objectives, these are `scorers_weights` and `other_objective_function_weights`, respectively. By default, TPOT maximizes objective functions (this can be changed by `bigger_is_better=False`). Positive weights means that TPOT will seek to maximize that objective, and negative weights correspond to minimization. For most selectors (and the default), only the sign matters. The scale of the weight may matter if using a custom selection function for the optimization algorithm. A zero weight means that the score will not have an impact on the selection algorithm.\n",
"\n",
"Here is an example of using two scorers\n",
"\n",
" scorers=['roc_auc_ovr',tpot.objectives.complexity_scorer],\n",
" scorers_weights=[1,-1],\n",
"\n",
"\n",
"Here is an example with a scorer and a secondary objective function\n",
"\n",
" scorers=['roc_auc_ovr'],\n",
" scorers_weights=[1],\n",
" other_objective_functions=[tpot.objectives.number_of_leaves_objective],\n",
" other_objective_functions_weights=[-1],\n",
"\n",
"\n",
"TPOT will always automatically name the scorers based on the function name for the columns in the final results dataframe. TPOT will use the function name as the column name for `other_objective_functions`. However, if you would like to specify custom column names, you can set the `objective_function_names` to be a list of names (str) for each value returned by the function in `other_objective_functions`. This can be useful if your additional functions return more than one value per function.\n",
"\n",
"It is possible to have either the scorer or other_objective_function to return multiple values. In that case, just make sure that the `scorers_weights` and `other_objective_function_weights` are the same length as the number of returned scores.\n",
"\n",
"\n",
"TPOT comes with a few additional built in objective functions you can use. The first table are objectives applied to fitted pipelines, and thus are passee into the `scorers` parameter. The second table are objective functions for the `other_objective_functions` param.\n",
"\n",
"Scorers:\n",
"| Function | Description |\n",
"| :--- | :----: |\n",
"| tpot.objectives.complexity_scorer | Estimates the number of learned parameters across all classifiers and regressors in the pipelines. Additionally, currently transformers add 1 point and selectors add 0 points (since they don't affect the complexity of the \"final\" predictive pipeline.) |\n",
"\n",
"Other Objective Functions.\n",
"\n",
"| Function | Description |\n",
"| :--- | :----: |\n",
"| tpot.objectives.average_path_length | Computes the average shortest path from all nodes to the root/final estimator (only supported for GraphPipeline) |\n",
"| tpot.objectives.number_of_leaves_objective | Calculates the number of leaves (input nodes) in a GraphPipeline |\n",
"| tpot.objectives.number_of_nodes_objective | Calculates the number of nodes in a pipeline (whether it is an scikit-learn Pipeline, GraphPipeline, Feature Union, or the previous nested within each other) |"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Measuring Model Complexity\n",
"\n",
"When running TPOT, including a secondary objective that measures model complexity can sometimes be beneficial. More complex models can yield higher performance, but this comes at the cost of interpretability. Simpler models may be more interpretable but often have lower predictive performance. Sometimes, however, vast increases in complexity only marginally improve predictive performance. There may be other simpler and more interpretable pipelines with marginal performance decreases that could be acceptable for the increased interpretability. However, these pipelines are often missed when optimizing purely for performance. By including both performance and complexity as objective functions, TPOT will attempt to optimize the best pipeline for all complexity levels simultaneously. After optimization, the user will be able to see the complexity vs performance tradeoff and decide which pipeline best suits their needs. \n",
"\n",
"Two methods of measuring complexity to consider would be `tpot.objectives.number_of_nodes_objective` or `tpot.objectives.complexity_scorer`. The number of nodes objective simply calculates the number of steps within a pipeline. This is a simple metric, however it does not differentiate between the complexity of different model types. For example, a simple LogisticRegression counts the same as the much more complex XGBoost. The complexity scorer tries to estimate the number of learned parameters included in the classifiers and regressors of the pipeline. It is challenging and potentially subjective how to exactly quantify and compare complexity between different classes of models. However, this function provides a reasonable heuristic for the evolutionary algorithm that at least separates out qualitatively more or less complex algorithms from one another. While it may be hard to compare the relative complexities of LogisticRegression and XGBoost exactly, for example, both will always be on opposite ends of the complexity values returned by this function. This allows for pareto fronts with LogisticRegression on one side, and XGBoost on the other.\n",
"\n",
"An example of this analysis is demonstrated in a following section."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Built In Configurations\n",
"TPOT can be used to optimize hyperparameters, select models, and optimize pipelines of models including determining the sequence of steps. **Tutorial 2** goes into more detail on how to customize search spaces with custom hyperparameter ranges, model types, and possible pipeline configurations. TPOT also comes with a handful of default operators and parameter configurations that we believe work well for optimizing machine learning pipelines. Below is a list of the current built-in configurations that come with TPOT. These can be passed in as strings to the `search space` parameter of any of the TPOT estimators.\n",
"\n",
"| String | Description |\n",
"| :--- | :----: |\n",
"| linear | A linear pipeline with the structure of \"Selector->(transformers+Passthrough)->(classifiers/regressors+Passthrough)->final classifier/regressor.\" For both the transformer and inner estimator layers, TPOT may choose one or more transformers/classifiers, or it may choose none. The inner classifier/regressor layer is optional. |\n",
"| linear-light | Same search space as linear, but without the inner classifier/regressor layer and with a reduced set of faster running estimators. |\n",
"| graph | TPOT will optimize a pipeline in the shape of a directed acyclic graph. The nodes of the graph can include selectors, scalers, transformers, or classifiers/regressors (inner classifiers/regressors can optionally be not included). This will return a custom GraphPipeline rather than an sklearn Pipeline. More details in Tutorial 6. |\n",
"| graph-light | Same as graph search space, but without the inner classifier/regressors and with a reduced set of faster running estimators. |\n",
"| mdr |TPOT will search over a series of feature selectors and Multifactor Dimensionality Reduction models to find a series of operators that maximize prediction accuracy. The TPOT MDR configuration is specialized for genome-wide association studies (GWAS), and is described in detail online here.\n",
"\n",
"Note that TPOT MDR may be slow to run because the feature selection routines are computationally expensive, especially on large datasets. |\n",
"\n",
"The `linear` and `graph` configurations by default allow for additional stacked classifiers/regressors within the pipeline in addition to the final classifier/regressor. If you would like to disable this, you can manually get the search space without inner classifier/regressors through the function `tpot.config.template_search_spaces.get_template_search_spaces` with `inner_predictios=False`. You can pass the resulting search space into the `search space` param. "
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"import tpot\n",
"from tpot.search_spaces.pipelines import SequentialPipeline\n",
"from tpot.config import get_search_space\n",
"\n",
"stc_search_space = SequentialPipeline([\n",
" get_search_space(\"selectors\"),\n",
" get_search_space(\"all_transformers\"),\n",
" get_search_space(\"classifiers\"),\n",
"])\n",
"\n",
"est = tpot.TPOTEstimator(\n",
" search_space = stc_search_space,\n",
" scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n",
" scorers_weights=[1.0, -1.0],\n",
" classification = True,\n",
" cv = 5,\n",
" max_eval_time_mins = 10,\n",
" early_stop = 2,\n",
" verbose = 2,\n",
" n_jobs=4,\n",
")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using a built in method"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"est = tpot.TPOTEstimator(\n",
" search_space = \"linear\",\n",
" scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n",
" scorers_weights=[1.0, -1.0],\n",
" classification = True,\n",
" cv = 5,\n",
" max_eval_time_mins = 10,\n",
" early_stop = 2,\n",
" verbose = 2,\n",
" n_jobs=4,\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The specific hyperparameter ranges used by TPOT can be found in files in the tpot/config folder. The template search spaces listed above are defined in tpot/config/template_search_spaces.py. Search spaces for individual models can be acquired in the tpot/config/get_configspace.py file (`tpot.config.get_search_space`). More details on customizing search spaces can be found in Tutorial 2.\n",
"\n",
"\n",
" `tpot.config.template_search_spaces.get_template_search_spaces`\n",
" Returns a search space which can be optimized by TPOT.\n",
"\n",
" Parameters\n",
" ----------\n",
" search_space: str or SearchSpace\n",
" The default search space to use. If a string, it should be one of the following:\n",
" - 'linear': A search space for linear pipelines\n",
" - 'linear-light': A search space for linear pipelines with a smaller, faster search space\n",
" - 'graph': A search space for graph pipelines\n",
" - 'graph-light': A search space for graph pipelines with a smaller, faster search space\n",
" - 'mdr': A search space for MDR pipelines\n",
" If a SearchSpace object, it should be a valid search space object for TPOT.\n",
" \n",
" classification: bool, default=True\n",
" Whether the problem is a classification problem or a regression problem.\n",
"\n",
" inner_predictors: bool, default=None\n",
" Whether to include additional classifiers/regressors before the final classifier/regressor (allowing for ensembles). \n",
" Defaults to False for 'linear-light' and 'graph-light' search spaces, and True otherwise. (Not used for 'mdr' search space)\n",
" \n",
" cross_val_predict_cv: int, default=None\n",
" The number of folds to use for cross_val_predict. \n",
" Defaults to 0 for 'linear-light' and 'graph-light' search spaces, and 5 otherwise. (Not used for 'mdr' search space)\n",
"\n",
" get_search_space_params: dict\n",
" Additional parameters to pass to the get_search_space function.\n",
"\n",
"### cross_val_predict_cv\n",
"\n",
"Additionally, utilizing `cross_val_predict_cv` may increase performance when training models with inner classifiers/regressors. If this parameter is set, during model training any classifiers or regressors that is not the final predictor will use `sklearn.model_selection.cross_val_predict` to pass out of sample predictions into the following steps of the model. The model will still be fit to the full data which will be used for predictions after training. Training downstream models on out of sample predictions can often prevent overfitting and increase performance. The reason is that this gives downstream models a estimate of how upstream models compare on unseen data. Otherwise, if an upsteam model heavily overfits the data, downsteam models may simply learn to blindly trust the seemingly well-predicting model, propagating the over-fitting through to the end result.\n",
"\n",
"The downside is that cross_val_predict_cv is significantly more computationally demanding, and may not be necessary for your given dataset. \n"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"linear_with_cross_val_predict_sp = tpot.config.template_search_spaces.get_template_search_spaces(search_space=\"linear\", classification=True, inner_predictors=True, cross_val_predict_cv=5)\n",
"classification_optimizer = TPOTClassifier(search_space=linear_with_cross_val_predict_sp, max_time_mins=30/60, n_jobs=30, cv=5)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Terminating Optimization (Early Stopping)\n",
"\n",
"Note that we use a short time duration for a quick example, but in practice, you may need to run TPOT for a longer duration. By default, TPOT sets a time limit of 1 hour with a max limit of 5 minutes per pipeline. In practice, you may want to increase these values.\n",
"\n",
"There are three methods of terminating a TPOT run and ending the optimization process. TPOT will terminate as soon as one of the conditions is met.\n",
"* `max_time_mins` : (Default, 60 minutes) After this many minutes, TPOT will terminate and return the best pipeline it found so far.\n",
"* `early_stop` : The number of generations without seeing an improvement in performance, after which TPOT terminates. Generally, a value of around 5 to 20 is sufficient to be reasonably sure that performance has converged.\n",
"* `generations`: The total number of generations of the evolutionary algorithm to run.\n",
"\n",
"By default, TPOT will run until the time limit is up, with no generation or early stop limits."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Best Practices and tips:\n",
"\n",
"* When running tpot from an .py script, it is important to protect code with `if __name__==\"__main__\":` . This is because of how TPOT handles parallelization with Python and Dask."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generation: : 1it [03:13, 193.20s/it]\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 0 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 1 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 2 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 3 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 4 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 5 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 6 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 7 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 8 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 9 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 10 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 11 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 12 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 13 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 14 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 15 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 16 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 17 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 18 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 19 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 20 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 21 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 22 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 23 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 24 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 25 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 26 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 27 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 28 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 29 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 30 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 31 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 32 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 33 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 34 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 35 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 36 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 37 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 38 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 39 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 40 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 41 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 42 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 43 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 44 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 45 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 46 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 47 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 48 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 49 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 50 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 51 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 52 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 53 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 54 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 55 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 56 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 57 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 58 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/preprocessing/_discretization.py:307: UserWarning: Bins whose width are too small (i.e., <= 1e-8) in feature 59 are removed. Consider decreasing the number of bins.\n",
" warnings.warn(\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.999621947852182\n"
]
}
],
"source": [
"from dask.distributed import Client, LocalCluster\n",
"import tpot\n",
"import sklearn\n",
"import sklearn.datasets\n",
"import numpy as np\n",
"\n",
"if __name__==\"__main__\":\n",
" scorer = sklearn.metrics.get_scorer('roc_auc_ovo')\n",
" X, y = sklearn.datasets.load_digits(return_X_y=True)\n",
" X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, train_size=0.75, test_size=0.25)\n",
"\n",
"\n",
" est = tpot.TPOTClassifier(n_jobs=4, max_time_mins=3, verbose=2, early_stop=3)\n",
" est.fit(X_train, y_train)\n",
"\n",
"\n",
" print(scorer(est, X_test, y_test))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Example analysis and the Estimator class \n",
"\n",
"Here we use a toy example dataset included in scikit-learn. We will use the `light` configuration and the `complexity_scorer` to estimate complexity.\n",
"\n",
"Note, for this toy example, we set a relatively short run time. In practice, we would recommend running TPOT for a longer duration with an `early_stop` value of around 5 to 20 (more details below)."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Generation: : 4it [02:34, 38.64s/it]\n",
"/opt/anaconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/neural_network/_multilayer_perceptron.py:690: ConvergenceWarning: Stochastic Optimizer: Maximum iterations (200) reached and the optimization hasn't converged yet.\n",
" warnings.warn(\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.9978289188015632\n"
]
}
],
"source": [
"from dask.distributed import Client, LocalCluster\n",
"import tpot\n",
"import sklearn\n",
"import sklearn.datasets\n",
"import numpy as np\n",
"\n",
"import tpot.objectives\n",
"\n",
"\n",
"scorer = sklearn.metrics.get_scorer('roc_auc_ovr')\n",
"\n",
"X, y = sklearn.datasets.load_breast_cancer(return_X_y=True)\n",
"X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, train_size=0.75, test_size=0.25)\n",
"\n",
"\n",
"est = tpot.TPOTClassifier(\n",
" scorers=[scorer, tpot.objectives.complexity_scorer],\n",
" scorers_weights=[1.0, -1.0],\n",
"\n",
" search_space=\"linear\",\n",
" n_jobs=4, \n",
" max_time_mins=60, \n",
" max_eval_time_mins=10,\n",
" early_stop=2,\n",
" verbose=2,)\n",
"est.fit(X_train, y_train)\n",
"\n",
"print(scorer(est, X_test, y_test))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"You can access the best pipeline selected by TPOT with the `fitted_pipeline_` attribute. This is the pipeline with the highest cross validation score (on the first scorer, or first objective function if no scorer is provided.)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
"
],
"text/plain": [
"Pipeline(steps=[('minmaxscaler', MinMaxScaler()),\n",
" ('selectpercentile',\n",
" SelectPercentile(percentile=68.60012151662)),\n",
" ('featureunion-1',\n",
" FeatureUnion(transformer_list=[('skiptransformer',\n",
" SkipTransformer()),\n",
" ('passthrough',\n",
" Passthrough())])),\n",
" ('featureunion-2',\n",
" FeatureUnion(transformer_list=[('skiptransformer',\n",
" SkipTransformer()),\n",
" ('passthrough',\n",
" Passthrough())])),\n",
" ('mlpclassifier',\n",
" MLPClassifier(activation='identity', alpha=0.0023692590029,\n",
" hidden_layer_sizes=[139, 139],\n",
" learning_rate='invscaling',\n",
" learning_rate_init=0.0004707733364,\n",
" n_iter_no_change=32))])"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"best_pipeline = est.fitted_pipeline_\n",
"best_pipeline"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"array([1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,\n",
" 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0,\n",
" 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1,\n",
" 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1,\n",
" 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0,\n",
" 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1,\n",
" 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1])"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"best_pipeline.predict(X_test)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Saving the Pipeline\n",
"\n",
"We recommend using dill or pickle to save the instance of the fitted_pipeline_. Note that we do not recommend pickling the TPOT object itself."
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"import dill as pickle\n",
"with open(\"best_pipeline.pkl\", \"wb\") as f:\n",
" pickle.dump(best_pipeline, f)\n",
"\n",
"#load the pipeline\n",
"import dill as pickle\n",
"with open(\"best_pipeline.pkl\", \"rb\") as f:\n",
" my_loaded_best_pipeline = pickle.load(f)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## The evaluated_individuals Dataframe - Further analysis of results\n",
"\n",
"The `evaluated_individuals` attribute of the tpot estimator object is a Pandas Dataframe containing information about a run. Each row corresponds to an individual pipeline explored by tpot. The dataframe contains the following columns:\n",
"\n",
"| Column | Description |\n",
"| :--- | :----: |\n",
"| \\ | The first set of columns will correspond to each objective function. These can either be automatically named by TPOT, or passed in by the user. |\n",
"| Parents | This contains a tuple that contains the indexes of the 'parents' of the current pipeline. For example, (29, 42) means that the pipelines in indexes 29 and 42 were utilized to generate that pipeline. |\n",
"| Variation_Function | The function applied to the parents to generate the new pipeline |\n",
"| Individual | The individual class that represents a specific pipeline and hyperparameter configuration. This class also contains functions for mutation and crossover. To get the sklearn estimator/pipeline object from the individual you can call the `export_pipeline()` function. (as in, `pipe = ind.export_pipeline()`) |\n",
"| Generation | The generation where the individual was created. (Note that the higher performing pipelines from previous generations may still be present in the current \"population\" of a given generation if selected.) |\n",
"| Submitted Timestamp | Timestamp, in seconds, at which the pipeline was sent to be evaluated. This is the output of time.time(), which is \"Return the time in seconds since the epoch as a floating-point number. \" |\n",
"| Completed Timestamp | Timestamp at which the pipeline evaluation completed in the same units as Submitted Timestamp |\n",
"| Pareto_Front\t | If you have multiple parameters, this column is True if the pipeline performance fall on the pareto front line. This is the set of pipelines with scores that are strictly better than pipelines not on the line, but not strictly better than one another. |\n",
"| Instance | This contains the unfitted pipeline evaluated for this row. (This is the pipeline returned by calling the export_pipeline() function of the individual class) |\n"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"['roc_auc_score', 'complexity_scorer']"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"#get the score/objective column names generated by TPOT\n",
"est.objective_names"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
roc_auc_score
\n",
"
complexity_scorer
\n",
"
Parents
\n",
"
Variation_Function
\n",
"
Individual
\n",
"
Generation
\n",
"
Submitted Timestamp
\n",
"
Completed Timestamp
\n",
"
Eval Error
\n",
"
Pareto_Front
\n",
"
Instance
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
0.0
\n",
"
1.740178e+09
\n",
"
1.740178e+09
\n",
"
INVALID
\n",
"
NaN
\n",
"
(MaxAbsScaler(), RFE(estimator=ExtraTreesClass...
\n",
"
\n",
"
\n",
"
1
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
0.0
\n",
"
1.740178e+09
\n",
"
1.740179e+09
\n",
"
INVALID
\n",
"
NaN
\n",
"
(RobustScaler(quantile_range=(0.1386847479391,...
\n",
"
\n",
"
\n",
"
2
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
0.0
\n",
"
1.740178e+09
\n",
"
1.740178e+09
\n",
"
INVALID
\n",
"
NaN
\n",
"
(RobustScaler(quantile_range=(0.0087917518794,...
\n",
"
\n",
"
\n",
"
3
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
0.0
\n",
"
1.740178e+09
\n",
"
1.740178e+09
\n",
"
INVALID
\n",
"
NaN
\n",
"
(Passthrough(), Passthrough(), FeatureUnion(tr...
\n",
"
\n",
"
\n",
"
4
\n",
"
0.969262
\n",
"
241.2
\n",
"
NaN
\n",
"
NaN
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
0.0
\n",
"
1.740178e+09
\n",
"
1.740178e+09
\n",
"
None
\n",
"
NaN
\n",
"
(RobustScaler(quantile_range=(0.0359502923061,...
\n",
"
\n",
"
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
...
\n",
"
\n",
"
\n",
"
245
\n",
"
0.986280
\n",
"
44.0
\n",
"
(184, 184)
\n",
"
ind_crossover
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
4.0
\n",
"
1.740179e+09
\n",
"
1.740179e+09
\n",
"
None
\n",
"
NaN
\n",
"
(RobustScaler(quantile_range=(0.1428289713161,...
\n",
"
\n",
"
\n",
"
246
\n",
"
0.902845
\n",
"
9.0
\n",
"
(145, 148)
\n",
"
ind_mutate , ind_mutate , ind_crossover
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
4.0
\n",
"
1.740179e+09
\n",
"
1.740179e+09
\n",
"
None
\n",
"
NaN
\n",
"
(MinMaxScaler(), SelectFwe(alpha=0.00184795618...
\n",
"
\n",
"
\n",
"
247
\n",
"
0.992851
\n",
"
5301.0
\n",
"
(155, 133)
\n",
"
ind_mutate , ind_mutate , ind_crossover
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
4.0
\n",
"
1.740179e+09
\n",
"
1.740179e+09
\n",
"
None
\n",
"
NaN
\n",
"
(MaxAbsScaler(), SelectFwe(alpha=0.00212090942...
\n",
"
\n",
"
\n",
"
248
\n",
"
0.992349
\n",
"
7749.0
\n",
"
(152, 152)
\n",
"
ind_mutate
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
4.0
\n",
"
1.740179e+09
\n",
"
1.740179e+09
\n",
"
None
\n",
"
NaN
\n",
"
(MinMaxScaler(), SelectFromModel(estimator=Ext...
\n",
"
\n",
"
\n",
"
249
\n",
"
0.515242
\n",
"
9.0
\n",
"
(182, 182)
\n",
"
ind_mutate
\n",
"
<tpot.search_spaces.pipelines.sequential.Seque...
\n",
"
4.0
\n",
"
1.740179e+09
\n",
"
1.740179e+09
\n",
"
None
\n",
"
NaN
\n",
"
(MaxAbsScaler(), VarianceThreshold(threshold=0...
\n",
"
\n",
" \n",
"
\n",
"
250 rows × 11 columns
\n",
"
"
],
"text/plain": [
" roc_auc_score complexity_scorer Parents \\\n",
"0 NaN NaN NaN \n",
"1 NaN NaN NaN \n",
"2 NaN NaN NaN \n",
"3 NaN NaN NaN \n",
"4 0.969262 241.2 NaN \n",
".. ... ... ... \n",
"245 0.986280 44.0 (184, 184) \n",
"246 0.902845 9.0 (145, 148) \n",
"247 0.992851 5301.0 (155, 133) \n",
"248 0.992349 7749.0 (152, 152) \n",
"249 0.515242 9.0 (182, 182) \n",
"\n",
" Variation_Function \\\n",
"0 NaN \n",
"1 NaN \n",
"2 NaN \n",
"3 NaN \n",
"4 NaN \n",
".. ... \n",
"245 ind_crossover \n",
"246 ind_mutate , ind_mutate , ind_crossover \n",
"247 ind_mutate , ind_mutate , ind_crossover \n",
"248 ind_mutate \n",
"249 ind_mutate \n",
"\n",
" Individual Generation \\\n",
"0 "
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAA1IAAAHWCAYAAAB9mLjgAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAATVRJREFUeJzt3Qd4FOX6//87EJJAQoj03gSV3sWAlSqiyAEVORyaCIqA9OYREBRQFBCUptKOogiCKPClC4j0Ir2IiPSmAqGXML/rfq7/7n83BMgsG7a9X9e1JDszOzuzs0vms8/z3BNmWZYlAAAAAIAUS5PyRQEAAAAAiiAFAAAAADYRpAAAAADAJoIUAAAAANhEkAIAAAAAmwhSAAAAAGATQQoAAAAAbCJIAQAAAIBNBCkAAAAAsIkgBQB38OGHH0rhwoUlbdq0UrZsWV9vTsiYP3++eb2joqIkLCxMzpw5c8+e+8knnzS31NaiRQuJiYlJ9ecBAHgfQQpAwJk0aZI5sXbc9ET7gQcekPbt28uJEye8+lwLFy6UHj16SNWqVWXixIkyaNAgr64fyfv777/lpZdekvTp08uoUaPkyy+/lOjoaAlEFy9elHfeeUeWLVvms23Q53f9zGTIkEGKFy8ub7/9tiQkJNzz7dm5c6fZpj///DNV/29wvfXq1UtC7bgDSF3hqbx+AEg1AwYMkEKFCsnly5fll19+kTFjxsj//d//yfbt282Jojf89NNPkiZNGhk/frxERER4ZZ24s/Xr18u5c+fk3XfflRo1akgg0xPq/v37m9/vRSvX7ehnRFvAzp8/b74kGDhwoHmPr1y50oSNexmk9DXR16NgwYKp9n+Dq5IlS0qoHncAqYMgBSBg1alTRypWrGh+f/XVVyVLliwybNgw+eGHH6Rx48Z3fRKkYezkyZOmVcRbIcqyLBP8dJ24NX3dVVxcnK83Jai88MILkjVrVvP766+/Lg0bNpSZM2fKmjVrJD4+3uP1Xr9+XW7cuOE3Xza4/t9wJ/p51O3WL0wAwA7+1wAQNKpVq2Z+7t+/3zntq6++kgoVKpjgkjlzZnn55Zfl0KFDbo/Tb4v12+qNGzfK448/bgLUW2+9Zb6h1+58Fy5ccHYP0q5DjhNHbS25//77JTIy0nyrro+5cuWK27p1+rPPPisLFiwwJ3a6HePGjTPdfXR906ZNM99a58mTRzJmzGhOdM+ePWvW06lTJ8mePbtpQWjZsuVN69Zt033WZXQbtKuWtjgk5dgGbbV7+OGHTVdIHfP1v//976ZldRxS586dzWN0nXnz5pVmzZrJX3/95VxGt6Nfv35SpEgRs0y+fPlM98ek23cr06dPdx4TPan/z3/+I0eOHHE7Hs2bNze/V6pUybxOOpbodn799Vdz8hwbG2ter+rVq5twkFy3L2196dKli2TLls10F/zXv/4lp06duuW6tfVGl+vYseNN8w4fPmzGzg0ePDjZx2rXNX0epcfZ8T7SLl+udP/r169vtl2X79atmyQmJroto0Hl448/lhIlSphjmCNHDnnttdfk9OnT4o3PzNWrV6Vv377m2GTKlMns82OPPSZLly69aZ90Hz766COzPY7PgLYyqd27d5v3sX7edDv1ff/jjz+6HYcXX3zR/P7UU085XxPXLnCjR482+6nrzZ07t7Rr184rY+Qcn7upU6eabo36udPPu6N7453em67j2m53zFJ63AEENlqkAASNffv2mZ/aMqW021KfPn3MWBttsdKT5U8++cSEJT3xdm3t0DE5eiKuQUtPnvQkVU8AP/vsM1m3bp188cUXZrkqVaqYn7q+yZMnmxPGrl27ytq1a83J9K5du+T777932649e/aYFjI96W3durU8+OCDznn6GD1p0/Ebv//+u9m+dOnSmW/H9QRZT7w0EOjJp3ZV0hNdBw1NerJZr149CQ8Pl9mzZ8sbb7xhTrj1xNOVrlu3tVWrViakTJgwwZwQ6kmjrsMRGPTEWffhlVdekfLly5sApSfBGhj0xFLXrc+noaxNmzZSrFgx2bZtmwwfPlx+++03mTVr1m2Pke6HhkINSLrvOqZtxIgRJtw4jsl///tf8xrpa+/ooqUn67eyY8cOs90aojTQ6eunYVUD2fLly6Vy5cpuy3fo0EHuu+8+Ewb1hFfDgI6v+/bbb5Ndv54oa9jS+driqcHJ4ZtvvjGtjE2aNEn2sXoyrcepbdu2Zh0NGjQw00uXLu1cRk++a9eubbZTw8nixYtl6NChZp/1cQ76/nG8fm+++aYJP59++ql53fT10/2+m8+Mhgl9n+t7Vd+n2rVSu7TqtulnIGmhFQ3y2pqj7wMNPBqc9FjoeEINKPqe1jCmXxZo4JgxY4Z5DfTzp9s/cuRI8+WDvoeU46e+5zV8aJdO3X/9/OhrqN09U7qf+mWEa/hXjpY4pV+CaCuUhh/9AkB/T8l7M6XHLCXHHUAQsAAgwEycONHS/74WL15snTp1yjp06JA1depUK0uWLFb69Omtw4cPW3/++aeVNm1aa+DAgW6P3bZtmxUeHu42/YknnjDrGzt27E3P1bx5cys6Otpt2ubNm83yr776qtv0bt26mek//fSTc1qBAgXMtPnz57stu3TpUjO9ZMmS1tWrV53TGzdubIWFhVl16tRxWz4+Pt6sy9XFixdv2t7atWtbhQsXdpvm2Iaff/7ZOe3kyZNWZGSk1bVrV+e0vn37muVmzpx503pv3Lhhfn755ZdWmjRprBUrVrjN19dOH7ty5UrrVnQ/s2fPbvb50qVLzulz5swxj9XnT3qM169fb91J/fr1rYiICGvfvn3OaUePHrUyZsxoPf744zets0aNGs79UZ07dzbvlTNnzri9J/TmsGDBAvPYefPmuT136dKl3ZZLjr5H9bH9+vVL9v2l8wYMGOA2vVy5claFChWc9/X11uWmTJnitpy+r5KbnpQ+ty63Z88esz379++3xo0bZ94DOXLksC5cuGBdv37dunLlitvjTp8+bea/8sorzmn6WF1XbGyseR+5ql69ulWqVCnr8uXLzmn6WlepUsUqWrSoc9r06dPNOvRz4ErXp8eyVq1aVmJionP6p59+apafMGHCbffTcYyTu7l+7vQz4vr5sfPeTOkxu91xBxAc6NoHIGDpN9b6za92LdOWJG050NYg/TZcx31o64m2Ruk3045bzpw5pWjRojd1V9Jv1PXb6JTQghZKu4e50pYpNXfuXLfp2qKi314nR7vNuX7Drt9wawuHtgi50unaJVG7FDq4jrNyfAP/xBNPyB9//GHuu9Juf9pq46Cvm7b66LIO2mJQpkwZ8w16Uo5CBNr1SVsOHnroIbfX1dFFLOnr6mrDhg1m7JO2mmmXL4e6deua9SV93VJCWwa0aIK2eGh3RYdcuXLJv//9b9NylrQqnbaguBZW0NdF13PgwIHbvte0i9mUKVOc07SoydatW00L5t3S8UqudJtcj42+7trdrmbNmm6vu7Yo6vv+dq+7Kz3meuz1PaktXNo9U1937d6mLW2OMU762fnnn3/M+01bZjdt2nTTunR8laP7mtLltXCFfua0Ncuxjdraq+//vXv33tRNLilt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",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"import seaborn as sns\n",
"import matplotlib.pyplot as plt\n",
"#replace nans in pareto front with 0\n",
"fig, ax = plt.subplots(figsize=(5,5))\n",
"sns.scatterplot(df[df['Pareto_Front']!=1], x='roc_auc_score', y='complexity_scorer', label='other', ax=ax)\n",
"sns.scatterplot(df[df['Pareto_Front']==1], x='roc_auc_score', y='complexity_scorer', label='Pareto Front', ax=ax)\n",
"ax.title.set_text('Performance of all pipelines')\n",
"#log scale y\n",
"ax.set_yscale('log')\n",
"plt.show()\n",
"\n",
"#replace nans in pareto front with 0\n",
"fig, ax = plt.subplots(figsize=(10,5))\n",
"sns.scatterplot(df[df['Pareto_Front']==1], x='roc_auc_score', y='complexity_scorer', label='Pareto Front', ax=ax)\n",
"ax.title.set_text('Performance of only the Pareto Front')\n",
"#log scale y\n",
"# ax.set_yscale('log')\n",
"plt.show()"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"