diff --git a/.gitignore b/.gitignore index 234fd5d7..bca7f873 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ *.pyc .pytest_cache/ -TPOT2.egg-info +TPOT.egg-info TPOT.egg-info *.tar.gz *.pkl diff --git a/README.md b/README.md index e05b407e..346f6b88 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,9 @@
-![Tests](https://github.com/EpistasisLab/tpot2/actions/workflows/tests.yml/badge.svg) -[![PyPI Downloads](https://img.shields.io/pypi/dm/tpot2?label=pypi%20downloads)](https://pypi.org/project/TPOT2) -[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/tpot2?label=conda%20downloads)](https://anaconda.org/conda-forge/tpot2) +![Tests](https://github.com/EpistasisLab/tpot/actions/workflows/tests.yml/badge.svg) +[![PyPI Downloads](https://img.shields.io/pypi/dm/tpot?label=pypi%20downloads)](https://pypi.org/project/TPOT) +[![Conda Downloads](https://img.shields.io/conda/dn/conda-forge/tpot?label=conda%20downloads)](https://anaconda.org/conda-forge/tpot) TPOT stands for Tree-based Pipeline Optimization Tool. TPOT is a Python Automated Machine Learning tool that optimizes machine learning pipelines using genetic programming. Consider TPOT your Data Science Assistant. @@ -39,7 +39,7 @@ The original version of TPOT was primarily developed at the University of Pennsy ## License -Please see the [repository license](https://github.com/EpistasisLab/tpot2/blob/main/LICENSE) for the licensing and usage information for TPOT. +Please see the [repository license](https://github.com/EpistasisLab/tpot/blob/main/LICENSE) for the licensing and usage information for TPOT. Generally, we have licensed TPOT to make it as widely usable as possible. TPOT is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ License along with TPOT. If not, see . ## Documentation -[The documentation webpage can be found here.](https://epistasislab.github.io/tpot2/) +[The documentation webpage can be found here.](https://epistasislab.github.io/tpot/) We also recommend looking at the Tutorials folder for jupyter notebooks with examples and guides. diff --git a/Tutorial/1_Using_TPOT.ipynb b/Tutorial/1_Using_TPOT.ipynb index 92821ca1..74926c77 100644 --- a/Tutorial/1_Using_TPOT.ipynb +++ b/Tutorial/1_Using_TPOT.ipynb @@ -40,8 +40,8 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", - "from tpot2 import TPOTClassifier" + "import tpot\n", + "from tpot import TPOTClassifier" ] }, { @@ -73,7 +73,7 @@ "metadata": {}, "outputs": [], "source": [ - "from tpot2 import TPOTRegressor\n", + "from tpot import TPOTRegressor\n", "regression_optimizer = TPOTRegressor()" ] }, @@ -93,16 +93,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 6it [00:32, 5.39s/it]\n", - "/home/perib/miniconda3/envs/myenv/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:349: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", - " warnings.warn(\n" + "Generation: : 4it [00:30, 7.62s/it]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "auroc_score: 0.9907407407407408\n" + "auroc_score: 0.9960317460317459\n" ] } ], @@ -110,7 +108,7 @@ "import sklearn\n", "import sklearn.datasets\n", "import sklearn.metrics\n", - "import tpot2\n", + "import tpot\n", "\n", "classification_optimizer = TPOTClassifier(search_space=\"linear-light\", max_time_mins=30/60, n_jobs=30, cv=5)\n", "\n", @@ -129,19 +127,19 @@ "source": [ "## Scorers, Objective Functions, and multi objective optimization.\n", "\n", - "There are two ways of passing objectives into TPOT2. \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 TPOT2 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)). TPOT2 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", + "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 TPOT2 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", + "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, TPOT2 maximizes objective functions (this can be changed by `bigger_is_better=False`). Positive weights means that TPOT2 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", + "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',tpot2.objectives.complexity_scorer],\n", + " scorers=['roc_auc_ovr',tpot.objectives.complexity_scorer],\n", " scorers_weights=[1,-1],\n", "\n", "\n", @@ -149,7 +147,7 @@ "\n", " scorers=['roc_auc_ovr'],\n", " scorers_weights=[1],\n", - " other_objective_functions=[tpot2.objectives.number_of_leaves_objective],\n", + " other_objective_functions=[tpot.objectives.number_of_leaves_objective],\n", " other_objective_functions_weights=[-1],\n", "\n", "\n", @@ -163,15 +161,15 @@ "Scorers:\n", "| Function | Description |\n", "| :--- | :----: |\n", - "| tpot2.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", + "| 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", - "| tpot2.objectives.average_path_length | Computes the average shortest path from all nodes to the root/final estimator (only supported for GraphPipeline) |\n", - "| tpot2.objectives.number_of_leaves_objective | Calculates the number of leaves (input nodes) in a GraphPipeline |\n", - "| tpot2.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) |" + "| 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) |" ] }, { @@ -182,7 +180,7 @@ "\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 `tpot2.objectives.number_of_nodes_objective` or `tpot2.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", + "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." ] @@ -204,7 +202,7 @@ "\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 `tpot2.config.template_search_spaces.get_template_search_spaces` with `inner_predictios=False`. You can pass the resulting search space into the `search space` param. " + "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. " ] }, { @@ -213,9 +211,9 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", - "from tpot2.search_spaces.pipelines import SequentialPipeline\n", - "from tpot2.config import get_search_space\n", + "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", @@ -223,9 +221,9 @@ " get_search_space(\"classifiers\"),\n", "])\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " search_space = stc_search_space,\n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " classification = True,\n", " cv = 5,\n", @@ -249,9 +247,9 @@ "metadata": {}, "outputs": [], "source": [ - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " search_space = \"linear\",\n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " classification = True,\n", " cv = 5,\n", @@ -266,10 +264,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "The specific hyperparameter ranges used by TPOT can be found in files in the tpot2/config folder. The template search spaces listed above are defined in tpot2/config/template_search_spaces.py. Search spaces for individual models can be acquired in the tpot2/config/get_configspace.py file (`tpot2.config.get_search_space`). More details on customizing search spaces can be found in Tutorial 2.\n", + "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", - " `tpot2.config.template_search_spaces.get_template_search_spaces`\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", @@ -310,7 +308,7 @@ "metadata": {}, "outputs": [], "source": [ - "linear_with_cross_val_predict_sp = tpot2.config.template_search_spaces.get_template_search_spaces(search_space=\"linear\", classification=True, inner_predictors=True, cross_val_predict_cv=5)\n", + "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)" ] }, @@ -348,22 +346,20 @@ "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 15it [31:22, 125.48s/it]\n" + "Generation: : 2it [03:01, 90.79s/it]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "0.9999480161532774\n" + "0.9992949729502254\n" ] } ], "source": [ - "#my_analysis.py\n", - "\n", "from dask.distributed import Client, LocalCluster\n", - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", @@ -374,7 +370,7 @@ " 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 = tpot2.TPOTClassifier(n_jobs=4, max_time_mins=3, verbose=2, early_stop=3)\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", @@ -401,29 +397,25 @@ "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 6it [03:29, 34.94s/it]\n", - "/home/perib/miniconda3/envs/myenv/lib/python3.10/site-packages/sklearn/ensemble/_weight_boosting.py:527: FutureWarning: The SAMME.R algorithm (the default) is deprecated and will be removed in 1.6. Use the SAMME algorithm to circumvent this warning.\n", - " warnings.warn(\n" + "Generation: : 4it [01:38, 24.53s/it]\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "0.9985632183908046\n" + "0.9955242966751918\n" ] } ], "source": [ - "#my_analysis.py\n", - "\n", "from dask.distributed import Client, LocalCluster\n", - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", "\n", - "import tpot2.objectives\n", + "import tpot.objectives\n", "\n", "\n", "scorer = sklearn.metrics.get_scorer('roc_auc_ovr')\n", @@ -432,8 +424,8 @@ "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 = tpot2.TPOTClassifier(\n", - " scorers=[scorer, tpot2.objectives.complexity_scorer],\n", + "est = tpot.TPOTClassifier(\n", + " scorers=[scorer, tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", "\n", " search_space=\"linear\",\n", @@ -462,415 +454,12 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('passthrough', Passthrough()),\n",
-       "                ('selectfwe', SelectFwe(alpha=0.0012275167982)),\n",
+       "
Pipeline(steps=[('passthrough', Passthrough()),\n",
+       "                ('selectfwe', SelectFwe(alpha=0.0078121592703)),\n",
        "                ('featureunion-1',\n",
-       "                 FeatureUnion(transformer_list=[('skiptransformer',\n",
-       "                                                 SkipTransformer()),\n",
+       "                 FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                                 FeatureUnion(transformer_list=[('zerocount',\n",
+       "                                                                                 ZeroCount())])),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
        "                ('featureunion-2',\n",
@@ -879,12 +468,13 @@
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
        "                ('adaboostclassifier',\n",
-       "                 AdaBoostClassifier(learning_rate=0.9052253032837,\n",
-       "                                    n_estimators=273))])
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.
Passthrough()
SelectFwe(alpha=0.0078121592703)
FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                FeatureUnion(transformer_list=[('zerocount',\n",
+       "                                                                ZeroCount())])),\n",
+       "                               ('passthrough', Passthrough())])
ZeroCount()
Passthrough()
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
AdaBoostClassifier(learning_rate=0.8192422162344, n_estimators=446)
" ], "text/plain": [ "Pipeline(steps=[('passthrough', Passthrough()),\n", - " ('selectfwe', SelectFwe(alpha=0.0012275167982)),\n", + " ('selectfwe', SelectFwe(alpha=0.0078121592703)),\n", " ('featureunion-1',\n", - " FeatureUnion(transformer_list=[('skiptransformer',\n", - " SkipTransformer()),\n", + " FeatureUnion(transformer_list=[('featureunion',\n", + " FeatureUnion(transformer_list=[('zerocount',\n", + " ZeroCount())])),\n", " ('passthrough',\n", " Passthrough())])),\n", " ('featureunion-2',\n", @@ -912,8 +505,8 @@ " ('passthrough',\n", " Passthrough())])),\n", " ('adaboostclassifier',\n", - " AdaBoostClassifier(learning_rate=0.9052253032837,\n", - " n_estimators=273))])" + " AdaBoostClassifier(learning_rate=0.8192422162344,\n", + " n_estimators=446))])" ] }, "execution_count": 10, @@ -1021,7 +614,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -1061,17 +654,17 @@ " \n", " \n", " 0\n", - " 0.964012\n", - " 1745.5\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " NaN\n", + " NaN\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 0.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", - " None\n", + " 1.734975e+09\n", + " 1.734975e+09\n", + " INVALID\n", " NaN\n", - " (Normalizer(norm='l1'), SelectPercentile(perce...\n", + " (MinMaxScaler(), SelectFwe(alpha=0.03084215664...\n", " \n", " \n", " 1\n", @@ -1079,13 +672,13 @@ " NaN\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 0.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 1.734975e+09\n", + " 1.734975e+09\n", " INVALID\n", " NaN\n", - " (MaxAbsScaler(), SelectFromModel(estimator=Ext...\n", + " (MinMaxScaler(), SelectFwe(alpha=0.03260916505...\n", " \n", " \n", " 2\n", @@ -1093,41 +686,41 @@ " NaN\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 0.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 1.734975e+09\n", + " 1.734975e+09\n", " INVALID\n", " NaN\n", - " (MaxAbsScaler(), VarianceThreshold(threshold=0...\n", + " (Normalizer(norm='l1'), VarianceThreshold(thre...\n", " \n", " \n", " 3\n", + " 0.991827\n", + " 10703.0\n", " NaN\n", " NaN\n", - " NaN\n", - " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 0.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", - " INVALID\n", + " 1.734975e+09\n", + " 1.734975e+09\n", + " None\n", " NaN\n", - " (Normalizer(norm='l1'), RFE(estimator=ExtraTre...\n", + " (MaxAbsScaler(), Passthrough(), FeatureUnion(t...\n", " \n", " \n", " 4\n", - " 0.991667\n", - " 24030.0\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " NaN\n", + " NaN\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 0.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", - " None\n", + " 1.734975e+09\n", + " 1.734975e+09\n", + " INVALID\n", " NaN\n", - " (RobustScaler(quantile_range=(0.1798922078332,...\n", + " (StandardScaler(), VarianceThreshold(threshold...\n", " \n", " \n", " ...\n", @@ -1144,137 +737,137 @@ " ...\n", " \n", " \n", - " 345\n", - " 0.992793\n", - " 4374.0\n", - " (237, 237)\n", + " 245\n", + " 0.990522\n", + " 9.0\n", + " (155, 155)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", - " NaN\n", - " (Passthrough(), SelectFwe(alpha=0.022268001122...\n", + " 1.0\n", + " (StandardScaler(), SelectPercentile(percentile...\n", " \n", " \n", - " 346\n", - " 0.520972\n", - " 9.0\n", - " (128, 128)\n", - " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " 246\n", + " 0.949947\n", " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " (87, 17)\n", + " ind_crossover\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " NaN\n", - " (MaxAbsScaler(), RFE(estimator=ExtraTreesClass...\n", + " (MinMaxScaler(), VarianceThreshold(threshold=0...\n", " \n", " \n", - " 347\n", + " 247\n", " NaN\n", " NaN\n", - " (109, 85)\n", - " ind_crossover\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " (14, 14)\n", + " ind_mutate\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " INVALID\n", " NaN\n", - " (StandardScaler(), SelectPercentile(percentile...\n", + " (StandardScaler(), SelectFwe(alpha=0.002516980...\n", " \n", " \n", - " 348\n", - " 0.976466\n", - " 21.0\n", - " (296, 128)\n", - " ind_crossover , ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 248\n", + " 0.988965\n", + " 18.0\n", + " (199, 116)\n", + " ind_crossover\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " NaN\n", - " (Passthrough(), RFE(estimator=ExtraTreesClassi...\n", + " (MaxAbsScaler(), SelectFwe(alpha=0.00057053364...\n", " \n", " \n", - " 349\n", - " 0.990725\n", - " 14.0\n", - " (297, 213)\n", + " 249\n", + " 0.985246\n", + " 9.0\n", + " (68, 142)\n", " ind_crossover\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " NaN\n", - " (MinMaxScaler(), SelectFwe(alpha=0.00016890355...\n", + " (RobustScaler(quantile_range=(0.0518636631319,...\n", " \n", " \n", "\n", - "

350 rows × 11 columns

\n", + "

250 rows × 11 columns

\n", "" ], "text/plain": [ - " roc_auc_score complexity_scorer Parents Variation_Function \\\n", - "0 0.964012 1745.5 NaN NaN \n", - "1 NaN NaN NaN NaN \n", - "2 NaN NaN NaN NaN \n", - "3 NaN NaN NaN NaN \n", - "4 0.991667 24030.0 NaN NaN \n", - ".. ... ... ... ... \n", - "345 0.992793 4374.0 (237, 237) ind_mutate \n", - "346 0.520972 9.0 (128, 128) ind_mutate \n", - "347 NaN NaN (109, 85) ind_crossover \n", - "348 0.976466 21.0 (296, 128) ind_crossover , ind_mutate \n", - "349 0.990725 14.0 (297, 213) ind_crossover \n", + " roc_auc_score complexity_scorer Parents Variation_Function \\\n", + "0 NaN NaN NaN NaN \n", + "1 NaN NaN NaN NaN \n", + "2 NaN NaN NaN NaN \n", + "3 0.991827 10703.0 NaN NaN \n", + "4 NaN NaN NaN NaN \n", + ".. ... ... ... ... \n", + "245 0.990522 9.0 (155, 155) ind_mutate \n", + "246 0.949947 6.0 (87, 17) ind_crossover \n", + "247 NaN NaN (14, 14) ind_mutate \n", + "248 0.988965 18.0 (199, 116) ind_crossover \n", + "249 0.985246 9.0 (68, 142) ind_crossover \n", "\n", " Individual Generation \\\n", - "0 " ] @@ -1310,7 +903,7 @@ }, { "data": { - "image/png": "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9dfGGGN++eUX8+qrrxpJZuLEiWbDhg1mx44dl93n7t27TVBQkKlatapZuHChWbVqlXnwwQeNJDNp0iRHv9z3vFKlSqZPnz5m1apV5t133zUVKlQw1atXN+fPn3f07du3r6lYsaLj+UcffWQkmTVr1jgde9WqVUaSWbVq1WXr27Ztm6lSpYpp1KiR4zzatm3bNdf09ttvG5vNZu6++26zfPly87///c90797deHh4mM8///yK7/u+ffuMJDNlyhSn9u+//95IMr179zbGGDNhwgQzffp0s2rVKrNu3Trz2muvmcqVK5t27do5va5v377Gy8vLVKpUycTHx5svvvjCfPbZZ/k+P670nhw+fNiUK1fOlClTxrz22msmISHBDB482EgyTzzxxBXHaczf53vdunVNVlaW0yM7O/uKtaenp5sGDRqYgIAA89///tesXr3ajB071nh6eppu3bo5HSP376xp06bmvffeM5988olp27at8fT0NHv37jXGGHPgwAEzZMgQI8ksX77cMc7U1NSrjgFA0UDYAlAs5YatjRs3mqysLHPq1CmzcuVKU6ZMGRMUFGQOHTpkNmzYYCSZqVOnOr32wIEDxs/Pz4wYMcLR1qZNGyPJfPHFF3mO1bdvXxMQEODUlpCQYCSZyZMnO7UvXbrUKewZ83fY8vDwMHv27HHqm/tL9l133eXUHhcXZySZoUOHOrXffffdpnTp0pd9T7Kzs01WVpZZuHCh8fDwMMePH88zvm+//dbpNXXq1DGdO3d2PH/uuecuGSgu9O677xpJZtmyZU7tmzdvNpLMrFmzrlhjZGSkqV+/vuMXX2OMOXXqlAkLCzMtWrRwtOW+P++///5l95frgQceMD4+Pmb//v1O7V27djX+/v7m5MmTTvu8+Bfn9957z0gyGzZscLRdHLays7NNlSpVTM+ePfMco2rVqiYnJ+eKNdatW9e0adMmT3t+azpz5owpXbp0nvMlOzvbNGzY0DRt2vSKx88NW5MmTTJZWVnm3LlzZuvWrea22267bFjMyckxWVlZJjEx0Ugy33//vWNb3759jSTz5ptvOr3mWs6Py70no0aNuuT5+sQTTxibzZbnZ+liuef7xY8+ffpcsfbXXnvNSDLvvfeeU/ukSZOMJLN69WpHmyQTHh5u0tLSHG2HDh0yJUqUMPHx8Y62KVOmGElm3759V6wZ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pJEjR2r69Olat26datWqpTJlykiSQkJCHLNoAAAAcL9gX68rbg+6yvbCRti6AeRnetSqsLVy5UoFBgbq/PnzysrKUs+ePTVjxgxJ0nfffafx48crOTlZx48fV05OjiRp//79qlOnjmMfTZo0cfx5586dOnfunCN85crMzFSjRo0uW8fevXuVlZWlli1bOtq8vLzUtGlT7dq164pj6NOnj8aMGeN4nhvgLq5Nknbt2qWePXs6tbVs2VIvvfSSsrOz5eHhIUlq0KCBY7vNZlNERITTJZQAAACwXmigt1pXD9VXl/hduXX1UIUG3tgrEhK2bgCFOT3arl07zZ49W15eXoqMjJSX19//O3DmzBl16tRJnTp10qJFi1SmTBnt379fnTt3zrPQREBAgOPPuYFs1apVKleunFM/Hx+fy9ZhjJH0d7C5uP3itovZ7XZVq1btktsurO1y+8s99oVy34dcNpvNMTYAAAAUDLu/t168t4FGLfvBKXC1rh6qSfc2uOGXfyds3QAKc3o0ICDgkkFl9+7dOnr0qF588UVFRUVJkrZs2XLV/dWpU0c+Pj7av3+/2rRpc8k+3t5//1BkZ2c72qpVqyZvb2+tX79evXv3liRlZWVpy5YtiouLu9ZhXbG+9evXO7UlJSWpRo0ajlmtq7lU/QAAALBGZEk/zXiwkY6eztSpc1kK8vVSaGDR+J4twtYN4EacHq1QoYK8vb01Y8YMPf7449q+fbsmTJhw1dcFBQVp+PDheuqpp5STk6NWrVopLS1NSUlJCgwMVN++fVWxYkXZbDatXLlS3bp1k5+fnwIDA/XEE0/oX//6l0qXLq0KFSpo8uTJOnv2rB555BG3jWvYsGG67bbbNGHCBPXq1UsbNmzQzJkzNWvWrHzvIywsTH5+fkpISFD58uXl6+sru93uthoBAADgzO5fNMLVxViN8AaQOz3aunqoU3thTo+WKVNGCxYs0Pvvv686deroxRdf1H//+998vXbChAl65plnFB8fr9q1a6tz58763//+51gyvVy5cnr22Wc1atQohYeHa/DgwZKkF198Uffee69iYmJ066236pdfftFnn32mUqVKuW1ct956q9577z0tWbJE9erV0zPPPKPnnnvukqssXo6np6deeeUVzZkzR5GRkXnuAQMAAAAkyWYudcMK8khLS5PdbldqaqqCg4Odtp07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mBilpKTIbrerQYMGSkhIUMeOHSVJI0aMUHp6ugYOHKgTJ06oWbNmWr16tYKCghz7mD59ujw9PXX//fcrPT1d7du314IFC+Th4eHos3jxYg0dOtSxamGPHj00c+bM664fAAAAAC7Hpe/Zuvvuu3X33XcrNjbWgpJuTHzPFgAAAAAp/9ngmme2JKlr164aPXq0tm/frsaNGysgIMBpe48ePVzZLQAAAAAUGy7NbJUocfl1NWw2m7Kzs6+rqBsRM1sAAAAAJItntnJyclwuDAAAAABuBte99Pu5c+fcUQcAAAAAFCsuha3s7GxNmDBB5cqVU2BgoH799VdJ0tixYzVv3jy3FggAAAAARZFLYeuFF17QggULNHnyZHl7ezva69evrzfeeMNtxQEAAABAUeVS2Fq4cKFef/119enTx+n7rBo0aKDdu3e7rTgAAAAAKKpcClt//vmnqlWrlqc9JydHWVlZ110UAAAAABR1LoWtunXr6uuvv87T/v7776tRo0bXXRQAAAAAFHUuLf0+btw4xcTE6M8//1ROTo6WL1+uPXv2aOHChVq5cqW7awQAAACAIselma277rpLS5cu1SeffCKbzaZnnnlGu3bt0v/+9z917NjR3TUCAAAAQJFzzTNb58+f1wsvvKCHH35YiYmJVtQEAAAAAEXeNc9seXp6asqUKcrOzraiHgAAAAAoFly6jLBDhw5at26dm0sBAAAAgOLDpQUyunbtqtGjR2v79u1q3LixAgICnLb36NHDLcUBAAAAQFFlM8aYa31RiRKXnxCz2WzF8hLDtLQ02e12paamKjg4uLDLAQAAAFBI8psNXJrZysnJcbkwAAAAALgZuHTPFgAAAADgylwOW4mJibrrrrtUrVo1Va9eXT169NDXX3/tztoAAAAAoMhyKWwtWrRIHTp0kL+/v4YOHarBgwfLz89P7du31zvvvOPuGgEAAACgyHFpgYzatWtrwIABeuqpp5zap02bprlz52rXrl1uK/BGwQIZAAAAAKT8ZwOXZrZ+/fVX3XXXXXnae/TooX379rmySwAAAAAoVlwKW1FRUfriiy/ytH/xxReKioq67qIAAAAAoKhzaen3YcOGaejQoUpOTlaLFi1ks9m0fv16LViwQC+//LK7awQAAACAIselsPXEE08oIiJCU6dO1XvvvSfp7/u4li5dqp49e7q1QAAAAAAoilxaIONmxAIZAAAAACSLF8jYvHmzvv322zzt3377rbZs2eLKLgEAAACgWHEpbA0aNEgHDhzI0/7nn39q0KBB110UAAAAABR1LoWtnTt36tZbb83T3qhRI+3cufO6iwIAAACAos6lsOXj46O//vorT3tKSoo8PV1acwMAAAAAihWXwlbHjh01evRopaamOtpOnjypf//73+rYsaPbigMAAACAosqlaaipU6eqdevWqlixoho1aiRJSk5OVnh4uN5++223FggAAAAARZFLYatcuXL64YcftHjxYn3//ffy8/NTv3799OCDD8rLy8vdNQIAAABAkePyDVYBAQEaMGCAO2sBAAAAgGLDpXu23nrrLa1atcrxfMSIESpZsqRatGih33//3W3FAQAAAEBR5VLYmjhxovz8/CRJGzZs0MyZMzV58mSFhobqqaeecmuBAAAAAFAUuXQZ4YEDB1StWjVJ0ooVK3TfffdpwIABatmypdq2bevO+gAAAACgSHJpZiswMFDHjh2TJK1evVodOnSQJPn6+io9Pd191QEAAABAEeXSzFbHjh316KOPqlGjRvrpp5905513SpJ27NihSpUqubM+AAAAACiSXJrZevXVVxUdHa0jR45o2bJlCgkJkSRt3bpVDz74oFsLBAAAAICiyGaMMVbtfODAgXruuecUGhpq1SEKTFpamux2u1JTUxUcHFzY5QAAAAAoJPnNBi7NbOXXokWLlJaWZuUhAAAAAOCGZGnYsnDSDAAAAABuaJaGLQAAAAC4WRG2AAAAAMAChC0AAAAAsABhCwAAAAAsYGnYeuihh1gmHQAAAMBNyaWwValSJT333HPav3//FfvNnj27WHzHFgAAAABcK5fC1rBhw/TRRx+pSpUq6tixo5YsWaKMjAx31wYAAAAARZZLYWvIkCHaunWrtm7dqjp16mjo0KEqW7asBg8erG3btrm7RgAAAAAocmzGDd88nJWVpVmzZmnkyJHKyspSvXr19OSTT6pfv36y2WzuqLPQpaWlyW63KzU1lfvQAAAAgJtYfrOB5/UcJCsrSx9++KHmz5+vNWvWqHnz5nrkkUd08OBBjRkzRp9//rneeeed6zkEAAAAABRJLoWtbdu2af78+Xr33Xfl4eGhmJgYTZ8+XbVq1XL06dSpk1q3bu22QgEAAACgKHEpbN12223q2LGjZs+e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/nnFxsbKbrerf//+kqSkpCS1bt1afn5+ioqK0tChQ3XmzJl8vV8AAPfwLOwCAAA3p7feektPPPGEvvnmGx09elSdOnVSbGysFi5cqN27d6t///7y9fXV+PHjJUmjR4/W3LlzNX36dLVq1UopKSnavXt3vo4VFBSkBQsWKDIyUj/++KP69++voKAgjRgxIt/1unr8V155RR9//LHee+89VahQQQcOHNCBAwck/R3gunbtqlOnTmnRokWqWrWqdu7cKQ8PD0nS1q1bdf/992v8+PHq1auXkpKSNHDgQIWEhCg2NtZxjClTpmjs2LH6z3/+I0n68ccf1blzZ02YMEHz5s3TkSNHNHjwYA0ePFjz58/P95gBANfHZowxhV0EAODm0rZtW6Wmpuq7776TJI0ZM0bLli3Trl27ZLPZJEmzZs3SyJEjlZqaqjNnzqhMmTKaOXOmHn300es+/pQpU7R06VJt2bJF0t8zWydPntSKFSscfeLi4pScnKx169bp1KlTLh9/6NCh2rFjhz7//HPH2HKtXr1aXbt21a5du1SjRo08r+3Tp4+OHDmi1atXO9pGjBihVatWaceOHZL+ntlq1KiRPvzwQ0eff/7zn/Lz89OcOXMcbevXr1ebNm105swZ+fr6XtMYAACu4TJCAEChaNKkiePPu3btUnR0tFMYadmypU6fPq0//vhDu3btUkZGhtq3b+/SsT744AO1atVKERERCgwM1NixY7V///58v/56jh8bG6vk5GTVrFlTQ4cOdQpOycnJKl++/CWDVu5xW7Zs6dTWsmVL/fzzz8rOzna0XfheSn/PiC1YsECBgYGOR+fOnZWTk6N9+/Zd8xgAAK4hbAEACkVAQIDjz8aYPLM+uRde2Gw2+fn5uXycjRs36oEHHlDXrl21cuVKfffddxozZozTQhIlSpTQxRd6XHhP1/Uc/9Zbb9W+ffs0YcIEpaen6/7779d9992Xr/1e6X250IXvpfT35YmPPfaYkpOTHY/vv/9eP//8s6pWreryWAAA14awBQAodHXq1FFSUpJTkEhKSlJQUJDKlSun6tWry8/PT1988cU17/ubb75RxYoVNWbMGDVp0kTVq1fX77//7tSnTJkySklJcWpLTk52/Pl6ji9JwcHB6tWrl+bOnaulS5dq2bJlOn78uBo0aKA//vhDP/300yVfV6dOHa1fv96pLSkpSTVq1HDc13Upt956q3bs2KFq1arleXh7e7s0BgDAtSNsAQAK3cCBA3XgwAENGTJEu3fv1kcffaRx48bp6aefVokSJeTr66uRI0dqxIgRWrhwofbu3auNGzdq3rx5V913tWrVtH//fi1ZskR79+7VK6+84nR/kyTdcccd2rJlixYuXKiff/5Z48aN0/bt2x3br+f406dP15IlS7R792799NNPev/99xUREaGSJUuqTZs2at26te69916tWbNG+/bt06effqqEhARJ0rBhw/TFF19owoQJ+umnn/TWW29p5syZGj58+BWPOXLkSG3YsEGDBg1ScnKyfv75Z3388ccaMmTIVesFALiRAQCggLVp08Y8+eSTTm3r1q0zt912m/H29jYRERFm5MiRJisry7E9OzvbPP/886ZixYrGy8vLVKhQwUycODFfx/vXv/5lQkJCTGBgoOnVq5eZPn26sdvtTn2eeeYZEx4ebux2u3nqqafM4MGDTZs2ba77+K+//rq55ZZbTEBAgAkODjbt27c327Ztc2w/duyY6devnwkJCTG+vr6mXr16ZuXKlY7tH3zwgalTp47jmFOmTHHaf8WKFc306dPzHHfTpk2mY8eOJjAw0AQEBJgGDRqYF154IV/vFwDAPViNEAAAAAAswGWEAAAAAGABwhYAoEibOHGi0xLnFz66du1a7I8PALhxcRkhAKBIO378uI4fP37JbX5+fipXrlyxPj4A4MZF2AIAAAAAC3AZIQAAAABYgLAFAAAAABYgbAEAAACABQhbAAAAAGABwhYAAAAAWICwBQAAAAAWIGwBAAAAgAX+L0tOnNeXC7TMAAAAAElFTkSuQmCC", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA1sAAAHWCAYAAACBjZMqAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAABcxUlEQVR4nO3dd3gU5f7+8XsT0sMGgRQCodfQpChGpCiRiPEoCCKI9KKYiPSAhaYSRQVBpShK8AhHQYoUBekKREA0iDQRooCQgEISaur8/uCX/bKGEpYMae/Xde11zDPPPPOZ3cme3MzMMxbDMAwBAAAAAPKUU34XAAAAAABFEWELAAAAAExA2AIAAAAAExC2AAAAAMAEhC0AAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsA8sBbb72lqlWrytnZWXfeeWd+l1NsrFq1Snfeeafc3d1lsViUlJR027bdunVrtW7d2vTt9OrVS97e3qZvBwCQ9whbAIqkmJgYWSwW28vd3V01a9ZUZGSkEhMT83Rb3377rUaOHKnmzZtrzpw5mjhxYp6Oj6v7559/1LlzZ3l4eOiDDz7Qf//7X3l5eeV3WQ65cOGCxo0bp40bN+ZbDePGjbP7nfH09FRwcLBefvllpaSk3PZ69u7dq3HjxumPP/7I03H//d1w5WvUqFF5uq0bKQifOwBzlcjvAgDATBMmTFCVKlV06dIlbd68WTNmzNDXX3+tX3/9VZ6ennmyjfXr18vJyUkff/yxXF1d82RM3NiOHTt09uxZvfrqqwoNDc3vcm7JhQsXNH78eEm6LWfLrmfGjBny9vbWuXPn9O233+r111/X+vXrtWXLFlkslttWx969ezV+/Hi1bt1alStXzvPxs78brlSvXr083871FKTPHYA5CFsAirR27dqpadOmkqR+/fqpTJkymjx5sr766it17dr1lsa+cOGCPD09dfLkSXl4eORZ0DIMQ5cuXZKHh0eejFdUnTx5UpJUqlSp/C2kiOnUqZPKli0rSXr22WfVsWNHLV68WD/88INCQkIcHjcjI0NZWVkF5h8krvxuuJFLly7J1dVVTk5cEATg5vCtAaBYeeCBByRJ8fHxtrbPPvtMTZo0kYeHh0qXLq0uXbro6NGjduu1bt1a9erV086dO9WyZUt5enrqxRdflMVi0Zw5c3T+/HnbpUgxMTGSLv9x+eqrr6patWpyc3NT5cqV9eKLLyo1NdVu7MqVK+uRRx7R6tWr1bRpU3l4eGjWrFnauHGjLBaLFixYoPHjx6t8+fIqWbKkOnXqpOTkZKWmpmrw4MHy8/OTt7e3evfunWPsOXPm6IEHHpCfn5/c3NwUHBysGTNm5HhfsmvYvHmz7r77brm7u6tq1ar69NNPc/RNSkrSkCFDVLlyZbm5ualChQrq0aOH/v77b1uf1NRUjR07VtWrV5ebm5uCgoI0cuTIHPVdy8KFC22fSdmyZfX000/rr7/+svs8evbsKUm66667ZLFY1KtXr+uO+fPPP6tdu3ayWq3y9vZWmzZt9MMPP9j1yb7EbMuWLRo6dKh8fX3l5eWlDh066NSpU9cc+9y5c/Ly8tILL7yQY9mxY8fk7Oys6Ojoq677xx9/yNfXV5I0fvx423E0btw4u35//fWX2rdvL29vb/n6+mr48OHKzMy065OVlaV3331XdevWlbu7u/z9/fXMM8/ozJkz131vrufK35m0tDSNGTNGTZo0kY+Pj7y8vNSiRQtt2LAhxz5ZLBa9/fbbevfdd22/A3v37pUk7d+/X506dVLp0qXl7u6upk2batmyZbb1Y2Ji9MQTT0iS7r//ftt7cuXldtOnT1fdunXl5uamwMBARURE5Mk9e9m/d59//rlefvlllS9fXp6enrZLKW90bEr/d5/d9T6z3H7uAAo3zmwBKFYOHTokSSpTpowk6fXXX9crr7yizp07q1+/fjp16pTee+89tWzZUj///LPdWZN//vlH7dq1U5cuXfT000/L399fTZs21Ycffqjt27dr9uzZkqR7771X0uUzaXPnzlWnTp00bNgwbdu2TdHR0dq3b5+WLFliV9eBAwfUtWtXPfPMM+rfv79q1aplWxYdHS0PDw+NGjVKv//+u9577z25uLjIyclJZ86c0bhx4/TDDz8oJiZGVapU0ZgxY2zrzpgxQ3Xr1tWjjz6qEiVKaPny5XruueeUlZWliIgIuxp+//13derUSX379lXPnj31ySefqFevXmrSpInq1q0r6XKoaNGihfbt26c+ffqocePG+vvvv7Vs2TIdO3ZMZcuWVVZWlh599FFt3rxZAwYMUJ06dbR7925NmTJFv/32m5YuXXrdzygmJka9e/fWXXfdpejoaCUmJmrq1KnasmWL7TN56aWXVKtWLX344Ye2y8GqVat2zTH37NmjFi1ayGq1auTIkXJxcdGsWbPUunVrbdq0Sc2aNbPr//zzz+uOO+7Q2LFj9ccff+jdd99VZGSkvvjii6uO7+3trQ4dOuiLL77Q5MmT5ezsbFv2v//9T4ZhqFu3bldd19fXVzNmzNDAgQPVoUMHPf7445KkBg0a2PpkZmYqLCxMzZo109tvv621a9fqnXfeUbVq1TRw4EBbv2eeecb2/g0aNEjx8fF6//339fPPP2vLli1ycXG57nt/NVf+zqSkpGj27Nnq2rWr+vfvr7Nnz+rjjz9WWFiYtm/fnmNymDlz5ujSpUsaMGCA3NzcVLp0ae3Zs0fNmzdX+fLlNWrUKHl5eWnBggVq3769Fi1apA4dOqhly5YaNGiQpk2bphdffFF16tSRJNv/jhs3TuPHj1doaKgGDhyoAwcOaMaMGdqxY0eu9zM5OdnuHwgk2c7oSdKrr74qV1dXDR8+XKmpqXJ1dc3VsZntRp9Zbj53AEWAAQBF0Jw5cwxJxtq1a41Tp04ZR48eNT7//HOjTJkyhoeHh3Hs2DHjjz/+MJydnY3XX3/dbt3du3cbJUqUsGtv1aqVIcmYOXNmjm317NnT8PLysmuLi4szJBn9+vWzax8+fLghyVi/fr2trVKlSoYkY9WqVXZ9N2zYYEgy6tWrZ6Slpdnau3btalgsFqNdu3Z2/UNCQoxKlSrZtV24cCFHvWFhYUbVqlXt2rJr+O6772xtJ0+eNNzc3Ixhw4bZ2saMGWNIMhYvXpxj3KysLMMwDOO///2v4eTkZHz//fd2y2fOnGlIMrZs2ZJj3WxpaWmGn5+fUa9ePePixYu29hUrVhiSjDFjxtjasj/jHTt2XHO8bO3btzdcXV2NQ4cO2dqOHz9ulCxZ0mjZsmWOMUNDQ237YxiGMWTIEMPZ2dlISkqytbVq1cpo1aqV7efVq1cbkoxvvvnGbtsNGjSw63c1p06dMiQZY8eOzbGsZ8+ehiRjwoQJdu2NGjUymjRpYvv5+++/NyQZ8+bNs+u3atWqq7b/29ixYw1JxoEDB4xTp04Z8fHxxqxZsww3NzfD39/fOH/+vJGRkWGkpqbarXfmzBnD39/f6NOnj60tPj7ekGRYrVbj5MmTdv3btGlj1K9f37h06ZKtLSsry7j33nuNGjVq2NoWLlxoSDI2bNhgt/7JkycNV1dXo23btkZmZqat/f333zckGZ988sl19zP7M77ayzD+7/euatWqdr8/N3Ns5vYzu97nDqBo4DJCAEVaaGiofH19FRQUpC5dusjb21tLlixR+fLltXjxYmVlZalz5876+++/ba+AgADVqFEjx6VRbm5u6t27d662+/XXX0uShg4datc+bNgwSdLKlSvt2qtUqaKwsLCrjtWjRw+7f6lv1qyZDMNQnz597Po1a9ZMR48eVUZGhq3tyvu+sv8lv1WrVjp8+LCSk5Pt1g8ODlaLFi1sP/v6+qpWrVo6fPiwrW3RokVq2LChOnTokKPO7MkTFi5cqDp16qh27dp272v25Wj/fl+v9OOPP+rkyZN67rnn5O7ubmsPDw9X7dq1c7xvuZGZmalvv/1W7du3V9WqVW3t5cqV01NPPaXNmzfnmG1vwIABdpNBtGjRQpmZmfrzzz+vuZ3Q0FAFBgZq3rx5trZff/1Vv/zyi55++umbrvvfnn32WbufW7RoYffZLFy4UD4+PnrwwQft3vcmTZrI29v7uu/7lWrVqiVfX19VqVJFzzzzjKpXr66VK1fK09NTzs7OtnuusrKydPr0aWVkZKhp06b66aefcozVsWNH26VyknT69GmtX79enTt31tmzZ201/vPPPwoLC9PBgwdzXJL3b2vXrlVaWpoGDx5sdw9V//79ZbVac32MfPDBB1qzZo3d60o9e/a0+/1x5Ni80WcGoOjjMkIARdoHH3ygmjVrqkSJEvL391etWrVsf6AdPHhQhmGoRo0aV13335cilS9fPtc39//5559ycnJS9erV7doDAgJUqlSpHH+0/3tWtCtVrFjR7mcfHx9JUlBQUI72rKwsJScn2y6T3LJli8aOHavY2FhduHDBrn9ycrJtrKttR5LuuOMOu/t9Dh06pI4dO16zVuny+7pv3z67P7KvlD2xxdVkvy9XXkaZrXbt2tq8efN1t301p06d0oULF646Zp06dZSVlaWjR4/aLpWUcr4Xd9xxhyRd994nJycndevWTTNmzLBNnjJv3jy5u7vb7j9ylLu7e47389+fzcGDB5WcnCw/P7+rjnG99/1KixYtktVqlYuLiypUqJDj8sy5c+fqnXfe0f79+5Wenm5rv9ox/O+233//XYZh6JVXXtErr7xyzTrLly9/zfqudYy4urqqatWq1w3EV7r77ruvO0HGv2u/2WMzN58ZgKKPsAWgSLveH1RZWVmyWCz65ptv7O6xyfbvB8k6MjtgbqfKvt7YV6vteu2GYUi6HIzatGmj2rVra/LkyQoKCpKrq6u+/vprTZkyRVlZWTc1Xm5lZWWpfv36mjx58lWX/zskFkSOvhc9evTQW2+9paVLl6pr166aP3++HnnkEbtQm5f1XCkrK0t+fn52Z9audK3w+28tW7a0u3fpSp999pl69eql9u3ba8SIEfLz87NN/pF9b9eV/n1cZx9zw4cPv+aZ3H//A0V+udXZQHPzmQEo+ghbAIqtatWqyTAMValSRTVr1szTsStVqqSsrCwdPHjQdlO/JCUmJiopKUmVKlXK0+1dzfLly5Wamqply5bZnanJ7eVkV1OtWjX9+uuvN+yza9cutWnT5qafy5T9vhw4cMB22WG2AwcOOPS++fr6ytPTUwcOHMixbP/+/XJycsqzAFivXj01atRI8+bNU4UKFXTkyBG99957N1wvL55fVa1aNa1du1bNmzc37bEBX375papWrarFixfb1Tx27NhcrZ99GaeLi8sNn412rffkymPkystC09LSFB8fb9oz18w4Nm/nc8sA5A/u2QJQbD3++ONydnbW+PHjc5yxMAxD//zzj8NjP/zww5Kkd9991649+2xPeHi4w2PnVva/rF+5b8nJyZozZ47DY3bs2FG7du3KMZvildvp3Lmz/vrrL3300Uc5+ly8eFHnz5+/5vhNmzaVn5+fZs6caTdN/DfffKN9+/Y59L45Ozurbdu2+uqrr/THH3/Y2hMTEzV//nzdd999slqtNz3utXTv3l3ffvut3n33XZUpU0bt2rW74TrZD9i+lanLO3furMzMTL366qs5lmVkZOTJtOhXO6a2bdum2NjYXK3v5+en1q1ba9asWTpx4kSO5VdOr+/l5SUp53sSGhoqV1dXTZs2za6Ojz/+WMnJyab9bplxbObF5w6gYOPMFoBiq1q1anrttdc0evRo/fHHH2rfvr1Kliyp+Ph4LVmyRAMGDNDw4cMdGrthw4bq2bOnPvzwQyUlJalVq1bavn275s6dq/bt2+v+++/P473JqW3btnJ1ddV//vMfPfPMMzp37pw++ugj+fn5XfUP3dwYMWKEvvzySz3xxBPq06ePmjRpotOnT2vZsmWaOXOmGjZsqO7du2vBggV6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rp1GjRql3bt3q0mTJvLy8rJb/uijj+ZJcQAAAABQWFkMwzBudiUnp2ufELNYLMrMzLylogqilJQU+fj4KDk5WVarNb/LAQAAAJBPcpsNHDqzlZWV5XBhAAAAAFAcOHTPFgAAAADg+hwOW5s2bdJ//vMfVa9eXdWrV9ejjz6q77//Pi9rAwAAAIBCy6Gw9dlnnyk0NFSenp4aNGiQBg0aJA8PD7Vp00bz58/P6xoBAAAAoNBxaIKMOnXqaMCAARoyZIhd++TJk/XRRx9p3759eVZgQcEEGQAAAACk3GcDh85sHT58WP/5z39ytD/66KOKj493ZEgAAAAAKFIcCltBQUFat25djva1a9cqKCjolosCAAAAgMLOoanfhw0bpkGDBikuLk733nuvJGnLli2KiYnR1KlT87RAAAAAACiMHApbAwcOVEBAgN555x0tWLBA0uX7uL744gs99thjeVogAAAAABRGDk2QURwxQQYAAAAAyeQJMnbs2KFt27blaN+2bZt+/PFHR4YEAAAAgCLFobAVERGho0eP5mj/66+/FBERcctFAQAAAEBh51DY2rt3rxo3bpyjvVGjRtq7d+8tFwUAAAAAhZ1DYcvNzU2JiYk52k+cOKESJRyacwMAAAAAihSHwlbbtm01evRoJScn29qSkpL04osv6sEHH8yz4gAAAACgsHLoNNTbb7+tli1bqlKlSmrUqJEkKS4uTv7+/vrvf/+bpwUCAAAAQGHkUNgqX768fvnlF82bN0+7du2Sh4eHevfura5du8rFxSWvawQAAACAQsehywglycvLSwMGDNAHH3ygt99+Wz169LjloPXGG2/IYrFo8ODBtrZLly4pIiJCZcqUkbe3tzp27JjjfrEjR44oPDxcnp6e8vPz04gRI5SRkWHXZ+PGjWrcuLHc3NxUvXp1xcTE3FKtAAAAAHA9DoWtuXPnauXKlbafR44cqVKlSunee+/Vn3/+6VAhO3bs0KxZs9SgQQO79iFDhmj58uVauHChNm3apOPHj+vxxx+3Lc/MzFR4eLjS0tK0detWzZ07VzExMRozZoytT3x8vMLDw3X//fcrLi5OgwcPVr9+/bR69WqHagUAAACAG7EYhmHc7Eq1atXSjBkz9MADDyg2NlZt2rTRu+++qxUrVqhEiRJavHjxTY137tw5NW7cWNOnT9drr72mO++8U+++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UqVKRq9evYxt27YZhw8fNlavXm38/vvvt2u3UICZccydPHnSOHHihO21Zs0aQ5KxYcOG27RXKOjMOO5ef/11o0yZMsaKFSuM+Ph4Y+HChYa3t7cxderU27VbKODMOO46d+5sBAcHG5s2bTIOHjxojB071rBarcaxY8du126hiCBsAbfB3XffbURERNh+zszMNAIDA43o6Oir9i9Xrpzx/vvv27U9/vjjRrdu3Ww/R0VFGffdd585BaPQM+OY+7cXXnjBqFatmpGVlZU3RaPQM+O4Cw8PN/r06XPdPije8vq4u3DhguHs7GysWLHCrk/jxo2Nl156KY+rR1HHZYSAydLS0rRz506Fhoba2pycnBQaGqrY2NirrpOamip3d3e7Ng8PD23evNn287Jly9S0aVM98cQT8vPzU6NGjfTRRx+ZsxMoVMw65v69jc8++0x9+vSRxWLJu+JRaJl13N17771at26dfvvtN0nSrl27tHnzZrVr186EvUBhY8Zxl5GRoczMzJv6TgSuhbAFmOzvv/9WZmam/P397dr9/f2VkJBw1XXCwsI0efJkHTx4UFlZWVqzZo0WL16sEydO2PocPnxYM2bMUI0aNbR69WoNHDhQgwYN0ty5c03dHxR8Zh1zV1q6dKmSkpLUq1evvC4fhZRZx92oUaPUpUsX1a5dWy4uLmrUqJEGDx6sbt26mbo/KBzMOO5KliypkJAQvfrqqzp+/LgyMzP12WefKTY29prficC1ELaAAmjq1KmqUaOGateuLVdXV0VGRqp3795ycvq/X9msrCw1btxYEydOVKNGjTRgwAD1799fM2fOzMfKUVjl5pi70scff6x27dopMDDwNleKoiQ3x92CBQs0b948zZ8/Xz/99JPmzp2rt99+m39YgsNyc9z997//lWEYKl++vNzc3DRt2jR17dr1mt+JwLVwxAAmK1u2rJydnZWYmGjXnpiYqICAgKuu4+vrq6VLl+r8+fP6888/tX//fnl7e6tq1aq2PuXKlVNwcLDdenXq1NGRI0fyfidQqJh1zGX7888/tXbtWvXr18+U+lE4mXXcjRgxwnZ2q379+urevbuGDBmi6OhoU/cHhYNZx121atW0adMmnTt3TkePHtX27duVnp5+1e9E4HoIW4DJXF1d1aRJE61bt87WlpWVpXXr1ikkJOS667q7u6t8+fLKyMjQokWL9Nhjj9mWNW/eXAcOHLDr/9tvv6lSpUp5uwModMw65rLNmTNHfn5+Cg8Pz/PaUXiZddxduHAhx9kEZ2dnZWVl5e0OoFAy+/vOy8tL5cqV05kzZ7R69eqr9gGuK79n6ACKg88//9xwc3MzYmJijL179xoDBgwwSpUqZSQkJBiGYRjdu3c3Ro0aZev/ww8/GIsWLTIOHTpkfPfdd8YDDzxgVKlSxThz5oytz/bt240SJUoYr7/+unHw4EFj3rx5hqenp/HZZ5/d7t1DAWTGMWcYl2f5qlixohEVFXU7dweFhBnHXc+ePY3y5cvbpn5fvHixUbZsWWPkyJG3e/dQQJlx3K1atcr45ptvjMOHDxvffvut0bBhQ6NZs2ZGWlra7d49FHKELeA2ee+994yKFSsarq6uxt1332388MMPtmWtWrUyevbsaft548aNRp06dQw3NzejTJkyRvfu3Y2//vorx5jLly836tWrZ7i5uRm1a9c2Pvzww9uxKygkzDjmVq9ebUgyDhw4cDt2AYVQXh93KSkpxgsvvGBUrFjRcHd3N6pWrWq89NJLRmpq6u3aJRQCeX3cffHFF0bVqlUNV1dXIyAgwIiIiDCSkpJu1+6gCLEYBo9gBwAAAIC8xj1bAAAAAGACwhYAAAAAmICwBQAAAAAmIGwBAAAAgAkIWwAAAABgAsIWAAAAAJiAsAUAAAAAJiBsAQAAAIAJCFsAAAAAYALCFgAAAACYgLAFAMhXaWlp+V1CkcF7CQAFC2ELAHBbtW7dWpGRkRo8eLDKli2rsLAwbdq0SXfffbfc3NxUrlw5jRo1ShkZGbZ1srKyNGnSJFWvXl1ubm6qWLGiXn/99VxtLyoqSjVr1pSnp6eqVq2qV155Renp6bblvXr1Uvv27e3WGTx4sFq3bn3L209LS1NkZKTKlSsnd3d3VapUSdHR0bblSUlJeuaZZ+Tv7y93d3fVq1dPK1assC1ftGiR6tatKzc3N1WuXFnvvPOO3fiVK1fWq6++qh49eshqtWrAgAGSpM2bN6tFixby8PBQUFCQBg0apPPnz+fq/QIA5J0S+V0AAKD4mTt3rgYOHKgtW7YoISFBDz/8sHr16qVPP/1U+/fvV//+/eXu7q5x48ZJkkaPHq2PPvpIU6ZM0X333acTJ05o//79udpWyZIlFRMTo8DAQO3evVv9+/dXyZIlNXLkyFzX6+j2p02bpmXLlmnBggWqWLGijh49qqNHj0q6HODatWuns2fP6rPPPlO1atW0d+9eOTs7S5J27typzp07a9y4cXryySe1detWPffccypTpox69epl28bbb7+tMWPGaOzYsZKkQ4cO6aGHHtJrr72mTz75RKdOnVJkZKQiIyM1Z86cXO8zAODWWQzDMPK7CABA8dG6dWulpKTop59+kiS99NJLWrRokfbt2yeLxSJJmj59uqKiopScnKzz58/L19dX77//vvr163fL23/77bf1+eef68cff5R0+cxWUlKSli5dauszePBgxcXFaePGjTp79qzD2x80aJD27NmjtWvX2vYt27fffqt27dpp3759qlmzZo51u3XrplOnTunbb7+1tY0cOVIrV67Unj17JF0+s9WoUSMtWbLE1qdfv35ydnbWrFmzbG2bN29Wq1atdP78ebm7u9/UPgAAHMdlhACA265Jkya2/963b59CQkLswkjz5s117tw5HTt2TPv27VNqaqratGnj0La++OILNW/eXAEBAfL29tbLL7+sI0eO5Hr9W9l+r169FBcXp1q1amnQoEF2wSkuLk4VKlS4atDK3m7z5s3t2po3b66DBw8qMzPT1ta0aVO7Prt27VJMTIy8vb1tr7CwMGVlZSk+Pv6m9wEA4DjCFgDgtvPy8sp1Xw8PD4e3Exsbq27duunhhx/WihUr9PPPP+ull16ym0jCyclJ/77I48p7um5l+40bN1Z8fLxeffVVXbx4UZ07d1anTp1uedwr/fu9PHfunJ555hnFxcXZXrt27dLBgwdVrVq1PNkmACB3CFsAgHxVp04dxcbG2gWeLVu2qGTJkqpQoYJq1KghDw8PrVu37qbH3rp1qypVqqSXXnpJTZs2VY0aNfTnn3/a9fH19dWJEyfs2uLi4mz/fSvblySr1aonn3xSH330kb744gstWrRIp0+fVoMGDXTs2DH99ttvV12vTp062rJli13bli1bVLNmTdt9XVfTuHFj7d27V9WrV8/xcnV1dWgfAACOIWwBAPLVc889p6NHj+r555/X/v379dVXX2ns2LEaOnSonJyc5O7urqioKI0cOVKffvqpDh06pB9++EEff/zxDceuUaOGjhw5os8//1yHDh3StGnT7O5vkqQHHnhAP/74oz799FMdPHhQY8eO1a+//mpbfivbnzx5sv73v/9p//79+u2337Rw4UIFBASoVKlSatWqlVq2bKmOHTtqzZo1io+P1zfffKNVq1ZJkoYNG6Z169bp1Vdf1W+//aa5c+fq/fff1/Dhw6+7zaioKG3dulWRkZGKi4vTwYMH9dVXXykyMvKG9QIA8pgBAMBt1KpVK+OFF16wa9u4caNx1113Ga6urkZAQIARFRVlpKen25ZnZmYar732mlGpUiXDxcXFqFixojFx4sRcbW/EiBFGmTJlDG9vb+PJJ580pkyZYvj4+Nj1GTNmjOHv72/4+PgYQ4YMMSIjI41WrVrd8vY//PBD48477zS8vLwMq9VqtGnTxvjpp59sy//55x+jd+/eRpkyZQx3d3ejXr16xooVK2zLv/zySyM4ONi2zbfeestu/EqVKhlTpkzJsd3t27cbDz74oOHt7W14eXkZDRo0MF5//fVcvV8AgLzDbIQAAAAAYAIuIwQAAAAAExC2AACF1sSJE+2mOL/y1a5duyK/fQBAwcZlhACAQuv06dM6ffr0VZd5eHiofPnyRXr7AICCjbAFAAAAACbgMkIAAAAAMAFhCwAAAABMQNgCAAAAABMQtgAAAADABIQtAAAAADABYQsAAAAATEDYAgAAAAAT/D90E6ElaC8OpAAAAABJRU5ErkJggg==", "text/plain": [ "
" ] @@ -1342,7 +935,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -1381,164 +974,155 @@ " \n", " \n", " \n", - " 330\n", - " 0.995556\n", - " 4373.0\n", - " (237, 52)\n", - " ind_crossover\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 226\n", + " 0.996974\n", + " 7141.0\n", + " (175, 167)\n", + " ind_mutate , ind_mutate , ind_crossover\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " 1.0\n", - " (Passthrough(), SelectFwe(alpha=0.001227516798...\n", + " (Passthrough(), SelectFwe(alpha=0.007812159270...\n", " \n", " \n", - " 144\n", - " 0.995000\n", - " 68.6\n", - " (61, 61)\n", + " 239\n", + " 0.996435\n", + " 33.9\n", + " (168, 168)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 2.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " 1.0\n", - " (RobustScaler(quantile_range=(0.2808423658106,...\n", + " (MaxAbsScaler(), SelectFwe(alpha=0.00199526767...\n", " \n", " \n", - " 320\n", - " 0.994059\n", - " 31.0\n", - " (184, 184)\n", + " 53\n", + " 0.994525\n", + " 31.3\n", + " (44, 44)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", - " None\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", " 1.0\n", - " (MaxAbsScaler(), SelectFwe(alpha=0.01352548659...\n", - " \n", - " \n", - " 161\n", - " 0.994028\n", - " 23.2\n", - " (123, 123)\n", - " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 3.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 1.734975e+09\n", + " 1.734975e+09\n", " None\n", " 1.0\n", - " (MaxAbsScaler(), SelectFromModel(estimator=Ext...\n", + " (MaxAbsScaler(), VarianceThreshold(threshold=0...\n", " \n", " \n", - " 297\n", - " 0.992577\n", - " 13.0\n", - " (193, 193)\n", - " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 5.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " 181\n", + " 0.991000\n", + " 18.0\n", + " (68, 85)\n", + " ind_crossover\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 3.0\n", + " 1.734975e+09\n", + " 1.734975e+09\n", " None\n", " 1.0\n", - " (MaxAbsScaler(), SelectFwe(alpha=0.00098089598...\n", + " (RobustScaler(quantile_range=(0.0518636631319,...\n", " \n", " \n", - " 306\n", - " 0.991165\n", - " 8.0\n", - " (167, 167)\n", + " 245\n", + " 0.990522\n", + " 9.0\n", + " (155, 155)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 6.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " 1.0\n", - " (MaxAbsScaler(), SelectFwe(alpha=0.00057722163...\n", + " (StandardScaler(), SelectPercentile(percentile...\n", " \n", " \n", - " 106\n", - " 0.965015\n", + " 237\n", + " 0.970314\n", " 7.0\n", - " (11, 85)\n", - " ind_crossover\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 2.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " (76, 76)\n", + " ind_mutate\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 4.0\n", + " 1.734976e+09\n", + " 1.734976e+09\n", " None\n", " 1.0\n", - " (StandardScaler(), SelectPercentile(percentile...\n", + " (MaxAbsScaler(), VarianceThreshold(threshold=0...\n", " \n", " \n", - " 195\n", - " 0.945486\n", + " 144\n", + " 0.952305\n", " 6.0\n", - " (25, 25)\n", + " (87, 87)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", - " 3.0\n", - " 1.727568e+09\n", - " 1.727568e+09\n", + " <tpot.search_spaces.pipelines.sequential.Seque...\n", + " 2.0\n", + " 1.734975e+09\n", + " 1.734975e+09\n", " None\n", " 1.0\n", - " (MaxAbsScaler(), SelectFwe(alpha=0.00098089598...\n", + " (StandardScaler(), VarianceThreshold(threshold...\n", " \n", " \n", "\n", "" ], "text/plain": [ - " roc_auc_score complexity_scorer Parents Variation_Function \\\n", - "330 0.995556 4373.0 (237, 52) ind_crossover \n", - "144 0.995000 68.6 (61, 61) ind_mutate \n", - "320 0.994059 31.0 (184, 184) ind_mutate \n", - "161 0.994028 23.2 (123, 123) ind_mutate \n", - "297 0.992577 13.0 (193, 193) ind_mutate \n", - "306 0.991165 8.0 (167, 167) ind_mutate \n", - "106 0.965015 7.0 (11, 85) ind_crossover \n", - "195 0.945486 6.0 (25, 25) ind_mutate \n", + " roc_auc_score complexity_scorer Parents \\\n", + "226 0.996974 7141.0 (175, 167) \n", + "239 0.996435 33.9 (168, 168) \n", + "53 0.994525 31.3 (44, 44) \n", + "181 0.991000 18.0 (68, 85) \n", + "245 0.990522 9.0 (155, 155) \n", + "237 0.970314 7.0 (76, 76) \n", + "144 0.952305 6.0 (87, 87) \n", + "\n", + " Variation_Function \\\n", + "226 ind_mutate , ind_mutate , ind_crossover \n", + "239 ind_mutate \n", + "53 ind_mutate \n", + "181 ind_crossover \n", + "245 ind_mutate \n", + "237 ind_mutate \n", + "144 ind_mutate \n", "\n", " Individual Generation \\\n", - "330 #sk-container-id-2 {\n", - " /* Definition of color scheme common for light and dark mode */\n", - " --sklearn-color-text: black;\n", - " --sklearn-color-line: gray;\n", - " /* Definition of color scheme for unfitted estimators */\n", - " --sklearn-color-unfitted-level-0: #fff5e6;\n", - " --sklearn-color-unfitted-level-1: #f6e4d2;\n", - " --sklearn-color-unfitted-level-2: #ffe0b3;\n", - " --sklearn-color-unfitted-level-3: chocolate;\n", - " /* Definition of color scheme for fitted estimators */\n", - " --sklearn-color-fitted-level-0: #f0f8ff;\n", - " --sklearn-color-fitted-level-1: #d4ebff;\n", - " --sklearn-color-fitted-level-2: #b3dbfd;\n", - " --sklearn-color-fitted-level-3: cornflowerblue;\n", - "\n", - " /* Specific color for light theme */\n", - " --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n", - " --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, white)));\n", - " --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, black)));\n", - " --sklearn-color-icon: #696969;\n", - "\n", - " @media (prefers-color-scheme: dark) {\n", - " /* Redefinition of color scheme for dark theme */\n", - " --sklearn-color-text-on-default-background: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n", - " --sklearn-color-background: var(--sg-background-color, var(--theme-background, var(--jp-layout-color0, #111)));\n", - " --sklearn-color-border-box: var(--sg-text-color, var(--theme-code-foreground, var(--jp-content-font-color1, white)));\n", - " --sklearn-color-icon: #878787;\n", - " }\n", - "}\n", - "\n", - "#sk-container-id-2 {\n", - " color: var(--sklearn-color-text);\n", - "}\n", - "\n", - "#sk-container-id-2 pre {\n", - " padding: 0;\n", - "}\n", - "\n", - "#sk-container-id-2 input.sk-hidden--visually {\n", - " border: 0;\n", - " clip: rect(1px 1px 1px 1px);\n", - " clip: rect(1px, 1px, 1px, 1px);\n", - " height: 1px;\n", - " margin: -1px;\n", - " overflow: hidden;\n", - " padding: 0;\n", - " position: absolute;\n", - " width: 1px;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-dashed-wrapped {\n", - " border: 1px dashed var(--sklearn-color-line);\n", - " margin: 0 0.4em 0.5em 0.4em;\n", - " box-sizing: border-box;\n", - " padding-bottom: 0.4em;\n", - " background-color: var(--sklearn-color-background);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-container {\n", - " /* jupyter's `normalize.less` sets `[hidden] { display: none; }`\n", - " but bootstrap.min.css set `[hidden] { display: none !important; }`\n", - " so we also need the `!important` here to be able to override the\n", - " default hidden behavior on the sphinx rendered scikit-learn.org.\n", - " See: https://github.com/scikit-learn/scikit-learn/issues/21755 */\n", - " display: inline-block !important;\n", - " position: relative;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-text-repr-fallback {\n", - " display: none;\n", - "}\n", - "\n", - "div.sk-parallel-item,\n", - "div.sk-serial,\n", - "div.sk-item {\n", - " /* draw centered vertical line to link estimators */\n", - " background-image: linear-gradient(var(--sklearn-color-text-on-default-background), var(--sklearn-color-text-on-default-background));\n", - " background-size: 2px 100%;\n", - " background-repeat: no-repeat;\n", - " background-position: center center;\n", - "}\n", - "\n", - "/* Parallel-specific style estimator block */\n", - "\n", - "#sk-container-id-2 div.sk-parallel-item::after {\n", - " content: \"\";\n", - " width: 100%;\n", - " border-bottom: 2px solid var(--sklearn-color-text-on-default-background);\n", - " flex-grow: 1;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-parallel {\n", - " display: flex;\n", - " align-items: stretch;\n", - " justify-content: center;\n", - " background-color: var(--sklearn-color-background);\n", - " position: relative;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-parallel-item {\n", - " display: flex;\n", - " flex-direction: column;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-parallel-item:first-child::after {\n", - " align-self: flex-end;\n", - " width: 50%;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-parallel-item:last-child::after {\n", - " align-self: flex-start;\n", - " width: 50%;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-parallel-item:only-child::after {\n", - " width: 0;\n", - "}\n", - "\n", - "/* Serial-specific style estimator block */\n", - "\n", - "#sk-container-id-2 div.sk-serial {\n", - " display: flex;\n", - " flex-direction: column;\n", - " align-items: center;\n", - " background-color: var(--sklearn-color-background);\n", - " padding-right: 1em;\n", - " padding-left: 1em;\n", - "}\n", - "\n", - "\n", - "/* Toggleable style: style used for estimator/Pipeline/ColumnTransformer box that is\n", - "clickable and can be expanded/collapsed.\n", - "- Pipeline and ColumnTransformer use this feature and define the default style\n", - "- Estimators will overwrite some part of the style using the `sk-estimator` class\n", - "*/\n", - "\n", - "/* Pipeline and ColumnTransformer style (default) */\n", - "\n", - "#sk-container-id-2 div.sk-toggleable {\n", - " /* Default theme specific background. It is overwritten whether we have a\n", - " specific estimator or a Pipeline/ColumnTransformer */\n", - " background-color: var(--sklearn-color-background);\n", - "}\n", - "\n", - "/* Toggleable label */\n", - "#sk-container-id-2 label.sk-toggleable__label {\n", - " cursor: pointer;\n", - " display: block;\n", - " width: 100%;\n", - " margin-bottom: 0;\n", - " padding: 0.5em;\n", - " box-sizing: border-box;\n", - " text-align: center;\n", - "}\n", - "\n", - "#sk-container-id-2 label.sk-toggleable__label-arrow:before {\n", - " /* Arrow on the left of the label */\n", - " content: \"▸\";\n", - " float: left;\n", - " margin-right: 0.25em;\n", - " color: var(--sklearn-color-icon);\n", - "}\n", - "\n", - "#sk-container-id-2 label.sk-toggleable__label-arrow:hover:before {\n", - " color: var(--sklearn-color-text);\n", - "}\n", - "\n", - "/* Toggleable content - dropdown */\n", - "\n", - "#sk-container-id-2 div.sk-toggleable__content {\n", - " max-height: 0;\n", - " max-width: 0;\n", - " overflow: hidden;\n", - " text-align: left;\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-0);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-toggleable__content.fitted {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-0);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-toggleable__content pre {\n", - " margin: 0.2em;\n", - " border-radius: 0.25em;\n", - " color: var(--sklearn-color-text);\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-0);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-toggleable__content.fitted pre {\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-fitted-level-0);\n", - "}\n", - "\n", - "#sk-container-id-2 input.sk-toggleable__control:checked~div.sk-toggleable__content {\n", - " /* Expand drop-down */\n", - " max-height: 200px;\n", - " max-width: 100%;\n", - " overflow: auto;\n", - "}\n", - "\n", - "#sk-container-id-2 input.sk-toggleable__control:checked~label.sk-toggleable__label-arrow:before {\n", - " content: \"▾\";\n", - "}\n", - "\n", - "/* Pipeline/ColumnTransformer-specific style */\n", - "\n", - "#sk-container-id-2 div.sk-label input.sk-toggleable__control:checked~label.sk-toggleable__label {\n", - " color: var(--sklearn-color-text);\n", - " background-color: var(--sklearn-color-unfitted-level-2);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-label.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n", - " background-color: var(--sklearn-color-fitted-level-2);\n", - "}\n", - "\n", - "/* Estimator-specific style */\n", - "\n", - "/* Colorize estimator box */\n", - "#sk-container-id-2 div.sk-estimator input.sk-toggleable__control:checked~label.sk-toggleable__label {\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-2);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-estimator.fitted input.sk-toggleable__control:checked~label.sk-toggleable__label {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-2);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-label label.sk-toggleable__label,\n", - "#sk-container-id-2 div.sk-label label {\n", - " /* The background is the default theme color */\n", - " color: var(--sklearn-color-text-on-default-background);\n", - "}\n", - "\n", - "/* On hover, darken the color of the background */\n", - "#sk-container-id-2 div.sk-label:hover label.sk-toggleable__label {\n", - " color: var(--sklearn-color-text);\n", - " background-color: var(--sklearn-color-unfitted-level-2);\n", - "}\n", - "\n", - "/* Label box, darken color on hover, fitted */\n", - "#sk-container-id-2 div.sk-label.fitted:hover label.sk-toggleable__label.fitted {\n", - " color: var(--sklearn-color-text);\n", - " background-color: var(--sklearn-color-fitted-level-2);\n", - "}\n", - "\n", - "/* Estimator label */\n", - "\n", - "#sk-container-id-2 div.sk-label label {\n", - " font-family: monospace;\n", - " font-weight: bold;\n", - " display: inline-block;\n", - " line-height: 1.2em;\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-label-container {\n", - " text-align: center;\n", - "}\n", - "\n", - "/* Estimator-specific */\n", - "#sk-container-id-2 div.sk-estimator {\n", - " font-family: monospace;\n", - " border: 1px dotted var(--sklearn-color-border-box);\n", - " border-radius: 0.25em;\n", - " box-sizing: border-box;\n", - " margin-bottom: 0.5em;\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-0);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-estimator.fitted {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-0);\n", - "}\n", - "\n", - "/* on hover */\n", - "#sk-container-id-2 div.sk-estimator:hover {\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-2);\n", - "}\n", - "\n", - "#sk-container-id-2 div.sk-estimator.fitted:hover {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-2);\n", - "}\n", - "\n", - "/* Specification for estimator info (e.g. \"i\" and \"?\") */\n", - "\n", - "/* Common style for \"i\" and \"?\" */\n", - "\n", - ".sk-estimator-doc-link,\n", - "a:link.sk-estimator-doc-link,\n", - "a:visited.sk-estimator-doc-link {\n", - " float: right;\n", - " font-size: smaller;\n", - " line-height: 1em;\n", - " font-family: monospace;\n", - " background-color: var(--sklearn-color-background);\n", - " border-radius: 1em;\n", - " height: 1em;\n", - " width: 1em;\n", - " text-decoration: none !important;\n", - " margin-left: 1ex;\n", - " /* unfitted */\n", - " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n", - " color: var(--sklearn-color-unfitted-level-1);\n", - "}\n", - "\n", - ".sk-estimator-doc-link.fitted,\n", - "a:link.sk-estimator-doc-link.fitted,\n", - "a:visited.sk-estimator-doc-link.fitted {\n", - " /* fitted */\n", - " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n", - " color: var(--sklearn-color-fitted-level-1);\n", - "}\n", - "\n", - "/* On hover */\n", - "div.sk-estimator:hover .sk-estimator-doc-link:hover,\n", - ".sk-estimator-doc-link:hover,\n", - "div.sk-label-container:hover .sk-estimator-doc-link:hover,\n", - ".sk-estimator-doc-link:hover {\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-3);\n", - " color: var(--sklearn-color-background);\n", - " text-decoration: none;\n", - "}\n", - "\n", - "div.sk-estimator.fitted:hover .sk-estimator-doc-link.fitted:hover,\n", - ".sk-estimator-doc-link.fitted:hover,\n", - "div.sk-label-container:hover .sk-estimator-doc-link.fitted:hover,\n", - ".sk-estimator-doc-link.fitted:hover {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-3);\n", - " color: var(--sklearn-color-background);\n", - " text-decoration: none;\n", - "}\n", - "\n", - "/* Span, style for the box shown on hovering the info icon */\n", - ".sk-estimator-doc-link span {\n", - " display: none;\n", - " z-index: 9999;\n", - " position: relative;\n", - " font-weight: normal;\n", - " right: .2ex;\n", - " padding: .5ex;\n", - " margin: .5ex;\n", - " width: min-content;\n", - " min-width: 20ex;\n", - " max-width: 50ex;\n", - " color: var(--sklearn-color-text);\n", - " box-shadow: 2pt 2pt 4pt #999;\n", - " /* unfitted */\n", - " background: var(--sklearn-color-unfitted-level-0);\n", - " border: .5pt solid var(--sklearn-color-unfitted-level-3);\n", - "}\n", - "\n", - ".sk-estimator-doc-link.fitted span {\n", - " /* fitted */\n", - " background: var(--sklearn-color-fitted-level-0);\n", - " border: var(--sklearn-color-fitted-level-3);\n", - "}\n", - "\n", - ".sk-estimator-doc-link:hover span {\n", - " display: block;\n", - "}\n", - "\n", - "/* \"?\"-specific style due to the `` HTML tag */\n", - "\n", - "#sk-container-id-2 a.estimator_doc_link {\n", - " float: right;\n", - " font-size: 1rem;\n", - " line-height: 1em;\n", - " font-family: monospace;\n", - " background-color: var(--sklearn-color-background);\n", - " border-radius: 1rem;\n", - " height: 1rem;\n", - " width: 1rem;\n", - " text-decoration: none;\n", - " /* unfitted */\n", - " color: var(--sklearn-color-unfitted-level-1);\n", - " border: var(--sklearn-color-unfitted-level-1) 1pt solid;\n", - "}\n", - "\n", - "#sk-container-id-2 a.estimator_doc_link.fitted {\n", - " /* fitted */\n", - " border: var(--sklearn-color-fitted-level-1) 1pt solid;\n", - " color: var(--sklearn-color-fitted-level-1);\n", - "}\n", - "\n", - "/* On hover */\n", - "#sk-container-id-2 a.estimator_doc_link:hover {\n", - " /* unfitted */\n", - " background-color: var(--sklearn-color-unfitted-level-3);\n", - " color: var(--sklearn-color-background);\n", - " text-decoration: none;\n", - "}\n", - "\n", - "#sk-container-id-2 a.estimator_doc_link.fitted:hover {\n", - " /* fitted */\n", - " background-color: var(--sklearn-color-fitted-level-3);\n", - "}\n", - "
Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n",
-       "                ('selectfwe', SelectFwe(alpha=0.0009808959816)),\n",
+       "
Pipeline(steps=[('standardscaler', StandardScaler()),\n",
+       "                ('variancethreshold',\n",
+       "                 VarianceThreshold(threshold=0.0001365003494)),\n",
        "                ('featureunion-1',\n",
        "                 FeatureUnion(transformer_list=[('skiptransformer',\n",
        "                                                 SkipTransformer()),\n",
@@ -1981,9 +1162,9 @@
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
        "                ('kneighborsclassifier',\n",
-       "                 KNeighborsClassifier(n_jobs=1, n_neighbors=1, p=1,\n",
-       "                                      weights='distance'))])
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.
StandardScaler()
VarianceThreshold(threshold=0.0001365003494)
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
KNeighborsClassifier(n_jobs=1, n_neighbors=1)
" ], "text/plain": [ - "Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n", - " ('selectfwe', SelectFwe(alpha=0.0009808959816)),\n", + "Pipeline(steps=[('standardscaler', StandardScaler()),\n", + " ('variancethreshold',\n", + " VarianceThreshold(threshold=0.0001365003494)),\n", " ('featureunion-1',\n", " FeatureUnion(transformer_list=[('skiptransformer',\n", " SkipTransformer()),\n", @@ -2014,11 +1195,10 @@ " ('passthrough',\n", " Passthrough())])),\n", " ('kneighborsclassifier',\n", - " KNeighborsClassifier(n_jobs=1, n_neighbors=1, p=1,\n", - " weights='distance'))])" + " KNeighborsClassifier(n_jobs=1, n_neighbors=1))])" ] }, - "execution_count": 17, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -2043,12 +1223,12 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 17, "metadata": {}, "outputs": [ { "data": { - "image/png": "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MWPGVPg726dPH78+nKsItIyMDPXq1UsxMTFq0aKFhg0bpu3bt/v14e/qL0cAC0KvvPKKJk2apOnTp2vz5s269NJLNXDgQBUUFFg9NNRjXbp0UXFxsfn44osvzNcee+wxZWZm6plnntEnn3yili1b6uqrr9aRI0csHDHqg2PHjql79+565plnTvt6Vc7NSZMm6fXXX9eqVau0YcMGHT16VIMHD5bH46mtw0A9cLZzVZKuueYav7+zq1ev9nudcxWBtm7dOo0fP14ff/yxcnJyVFZWprS0NB07dszsw9/VGmAg6Fx88cVGenq6X1vnzp2NqVOnWjQi1HezZs0yunfvftrXvF6v0bJlS+ORRx4x206cOGHExsYazz33XC2NEDAMScbrr79uPq/Kufnjjz8aDofDWLVqldmnqKjICAsLM955551aGzvql/8+Vw3DMG699VZj6NChlb6HcxVW2LdvnyHJWLdunWEY/F2tKayABZnS0lLl5+crLS3Nrz0tLU25ubkWjQqQdu7cqdatWyspKUmjRo3Srl27JEnffvut9u7d63fORkZG6vLLL+echaWqcm7m5+fL7Xb79WndurW6du3K+Yta9/7776tFixY6//zzNW7cOO3bt898jXMVVjh8+LAkqWnTppL4u1pTCGBBZv/+/fJ4PIqPj/drj4+P1969ey0aFeq73r17a/ny5VqzZo0WLVqkvXv3ql+/fjpw4IB5XnLOIthU5dzcu3evIiIi1KRJk0r7ALVh4MCBeumll/Tee+9p/vz5+uSTT/TrX/9aLpdLEucqap9hGJo8ebIuueQSde3aVRJ/V2tKuNUDwOnZbDa/54ZhVGgDasvAgQPNn7t166a+ffuqQ4cOWrZsmXmROOcsgtW5nJucv6htI0eONH/u2rWrevbsqYSEBP3973/XiBEjKn0f5yoCZcKECfr888+1YcOGCq/xd/WXYQUsyMTFxclut1f4fwj27dtX4f9tAKzSsGFDdevWTTt37jR3Q+ScRbCpyrnZsmVLlZaW6tChQ5X2AazQqlUrJSQkaOfOnZI4V1G77r77br311ltau3at2rZta7bzd7VmEMCCTEREhFJSUpSTk+PXnpOTo379+lk0KsCfy+XStm3b1KpVKyUlJally5Z+52xpaanWrVvHOQtLVeXcTElJkcPh8OtTXFysrVu3cv7CUgcOHFBhYaFatWoliXMVtcMwDE2YMEGvvfaa3nvvPSUlJfm9zt/VmkEJYhCaPHmyRo8erZ49e6pv377Kzs5WQUGB0tPTrR4a6qn7779fQ4YMUfv27bVv3z499NBDKikp0a233iqbzaZJkyZp3rx56tixozp27Kh58+apQYMGuummm6weOkLc0aNH9fXXX5vPv/32W23ZskVNmzZV+/btz3puxsbG6rbbbtN9992nZs2aqWnTprr//vvVrVs3XXXVVVYdFkLQmc7Vpk2bavbs2frNb36jVq1aaffu3XrggQcUFxen4cOHS+JcRe0YP368Xn75Zb355puKiYkxV7piY2PldDqr9G8+52oVWLb/Is7o2WefNRISEoyIiAijR48e5vafgBVGjhxptGrVynA4HEbr1q2NESNGGF9++aX5utfrNWbNmmW0bNnSiIyMNC677DLjiy++sHDEqC/Wrl1rSKrwuPXWWw3DqNq5+dNPPxkTJkwwmjZtajidTmPw4MFGQUGBBUeDUHamc/X48eNGWlqa0bx5c8PhcBjt27c3br311grnIecqAu1056gkY+nSpWYf/q7+cjbDMIzaj30AAAAAUP9wDRgAAAAA1BICGAAAAADUEgIYAAAAANQSAhgAAAAA1BICGAAAAADUEgIYAAAAANQSAhgAAAAA1BICGAAAAADUEgIYACDozJ49WxdeeKFl3z9z5kzdcccdln1/TXj//fdls9n0448/nrXvF198obZt2+rYsWOBHxgA1HMEMABArbLZbGd8jBkzRvfff7/+9a9/WTK+//znP3rqqaf0wAMPWPL9VujWrZsuvvhiPfHEE1YPBQBCHgEMAFCriouLzceTTz6pRo0a+bU99dRTio6OVrNmzSwZ3/PPP6++ffsqMTHRku+3ytixY5WVlSWPx2P1UAAgpBHAAAC1qmXLluYjNjZWNputQtt/lyCOGTNGw4YN07x58xQfH6/GjRtrzpw5Kisr0x/+8Ac1bdpUbdu21ZIlS/y+q6ioSCNHjlSTJk3UrFkzDR06VLt37z7j+FatWqXrrrvOr+1vf/ubunXrJqfTqWbNmumqq67yK9dbunSpkpOTFRUVpc6dO2vBggV+7//uu+80atQoNW3aVA0bNlTPnj21ceNG8/WsrCx16NBBERER6tSpk1asWOH3fpvNpsWLF2v48OFq0KCBOnbsqLfeesuvz+rVq3X++efL6XSqf//+FY5zz549GjJkiJo0aaKGDRuqS5cuWr16tfn6gAEDdODAAa1bt+6M/30AAL8MAQwAUCe89957+v777/XBBx8oMzNTs2fP1uDBg9WkSRNt3LhR6enpSk9PV2FhoSTp+PHj6t+/v6Kjo/XBBx9ow4YNio6O1jXXXKPS0tLTfsehQ4e0detW9ezZ02wrLi7WjTfeqN/97nfatm2b3n//fY0YMUKGYUiSFi1apOnTp+vhhx/Wtm3bNG/ePM2cOVPLli2TJB09elSXX365vv/+e7311lv67LPPNGXKFHm9XknS66+/rokTJ+q+++7T1q1bdeedd2rs2LFau3at39jmzJmjG264QZ9//rkGDRqkm2++WQcPHpQkFRYWasSIERo0aJC2bNmi22+/XVOnTvV7//jx4+VyufTBBx/oiy++0KOPPqro6Gjz9YiICHXv3l3r16//Jb8mAMDZGAAAWGTp0qVGbGxshfZZs2YZ3bt3N5/feuutRkJCguHxeMy2Tp06GZdeeqn5vKyszGjYsKGxcuVKwzAM4/nnnzc6depkeL1es4/L5TKcTqexZs2a045n8+bNhiSjoKDAbMvPzzckGbt37z7te9q1a2e8/PLLfm0PPvig0bdvX8MwDGPhwoVGTEyMceDAgdO+v1+/fsa4ceP82q6//npj0KBB5nNJxowZM8znR48eNWw2m/GPf/zDMAzDmDZtmpGcnOx3rH/84x8NScahQ4cMwzCMbt26GbNnzz7tGHyGDx9ujBkz5ox9AAC/DCtgAIA6oUuXLgoLO/XPVnx8vLp162Y+t9vtatasmfbt2ydJys/P19dff62YmBhFR0crOjpaTZs21YkTJ/TNN9+c9jt++uknSVJUVJTZ1r17d1155ZXq1q2brr/+ei1atEiHDh2SJP3www8qLCzUbbfdZn5HdHS0HnroIfM7tmzZoosuukhNmzY97Xdu27ZNqampfm2pqanatm2bX9uvfvUr8+eGDRsqJibGPNZt27apT58+stlsZp++ffv6vf+ee+7RQw89pNTUVM2aNUuff/55hbE4nU4dP378tOMEANSMcKsHAABAVTgcDr/nNpvttG2+0j6v16uUlBS99NJLFT6refPmp/2OuLg4SeWliL4+drtdOTk5ys3N1bvvvqunn35a06dP18aNG9WgQQNJ5WWIvXv39vssu90uqTzUnM3Pg5MkGYZRoe1Mx2qcLIc8k9tvv10DBgzQ3//+d7377rvKyMjQ/Pnzdffdd5t9Dh48qA4dOpz1swAA544VMABASOrRo4d27typFi1a6H/+53/8HrGxsad9T4cOHdSoUSN99dVXfu02m02pqamaM2eONm/erIiICL3++uuKj49XmzZttGvXrgrfkZSUJKl85WrLli3m9Vr/LTk5WRs2bPBry83NVXJycpWP9YILLtDHH3/s1/bfzyWpXbt2Sk9P12uvvab77rtPixYt8nt969atuuiii6r8vQCA6iOAAQBC0s0336y4uDgNHTpU69ev17fffqt169Zp4sSJ+u677077nrCwMF111VV+gWjjxo2aN2+eNm3apIKCAr322mv64YcfzIA0e/ZsZWRk6KmnntKOHTv0xRdfaOnSpcrMzJQk3XjjjWrZsqWGDRumDz/8ULt27dKrr76qjz76SJL0hz/8QS+88IKee+457dy5U5mZmXrttdd0//33V/lY09PT9c0332jy5Mnavn27Xn75Zb3wwgt+fSZNmqQ1a9bo22+/1aeffqr33nvPL+Tt3r1bRUVFuuqqq6r8vQCA6iOAAQBCUoMGDfTBBx+offv2GjFihJKTk/W73/1OP/30kxo1alTp++644w6tWrXKLO9r1KiRPvjgAw0aNEjnn3++ZsyYofnz52vgwIGSykv7Fi9erBdeeEHdunXT5ZdfrhdeeMFcAYuIiNC7776rFi1aaNCgQerWrZseeeQRs0Rx2LBheuqpp/T444+rS5cuWrhwoZYuXaorrriiysfavn17vfrqq3r77bfVvXt3Pffcc5o3b55fH4/Ho/Hjxys5OVnXXHONOnXq5Ldd/sqVK5WWlqaEhIQqfy8AoPpsRlUKxwEAqCcMw1CfPn00adIk3XjjjVYPp1a4XC517NhRK1eurLAhCACgZrECBgDAz9hsNmVnZ6usrMzqodSaPXv2aPr06YQvAKgFrIABAAAAQC1hBQwAAAAAagkBDAAAAABqCQEMAAAAAGoJAQwAAAAAagkBDAAAAABqCQEMAAAAAGoJAQwAAAAAagkBDAAAAABqCQEMAAAAAGrJ/wd7rerqyZ4ueAAAAABJRU5ErkJggg==", + "image/png": "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jZPCKcieeeYZq3Xr1lZ4eLjVo0cP65NPPnE6JBhMUrWPF1980T7n8OHD1v333281adLEioqKsm666SZr586dzgWNM8J/F07cR6iNd955x7rooosst9ttdejQwZo5c2bA6z6fzxo/fryVkJBgud1u69prr7U2bNjgULQwUVlZmTVq1CirdevWVkREhHXeeedZ48aNsyoqKuxzuI/w3xYvXlxtPjR06FDLsmp3z+zdu9caOHCgFR0dbcXGxlqZmZnWgQMHghqny7K+t5UzAAAAAOAErHECAAAAgBpQOAEAAABADSicAAAAAKAGFE4AAAAAUAMKJwAAAACoAYUTAAAAANSAwgkAAAAAakDhBAAAAAA1oHACAATNHXfcoRtvvNGxzx88eLAef/xxxz4/GGbPnq34+PhanZubm6suXbrI5/PVb1AAAAonAEDtuFyuUz4effRRPfXUU5o9e7Yj8a1Zs0YLFizQyJEjHfl8J/Tp00eNGjXSK6+84nQoAHDWC3M6AADAmWHnzp32f8+dO1cTJkzQhg0b7GPR0dGKjo52IjRJ0jPPPKNbbrnF0RiccMcdd+jpp5/W4MGDnQ4FAM5qjDgBAGolMTHRfsTFxcnlcgUci46OPmGq3lVXXaUHHnhAo0ePVpMmTZSQkKDnn39e5eXlyszMVExMjM4//3y99957AZ+1du1aXX/99YqOjlZCQoIGDx6sPXv2nDQ2r9erN998U/379w84/uc//1nt2rVTRESEEhIS9D//8z/2az6fT9nZ2Wrbtq0iIyOVmpqqN998M+D6devW6ec//7liY2MVExOjK664Ql999ZV9/aRJk9SqVSu53W516dJFubm59rXffPONXC6X5s2bp6uvvlpRUVFKTU1Vfn5+wGfMnj1brVu3VlRUlG666Sbt3bs34PU1a9bo6quvVkxMjGJjY9WtWzetWrXKfr1///5atWqVHRcAoH5QOAEA6tVLL72kZs2aacWKFXrggQd033336ZZbbtFll12m1atXq3fv3ho8eLAOHTokSdq/f7+uueYade3aVatWrVJubq5KSkr0q1/96qSf8dlnn6m0tFTdu3e3j61atUojR47UpEmTtGHDBuXm5upnP/uZ/Xp2drbmzJmjnJwcrVu3TmPGjNHtt9+uDz/8UJK0fft2/exnP5Pb7daiRYtUUFCgO++8U1VVVZKkp556SlOnTtUf//hHffbZZ8rIyNAvfvELbdq0KSC2cePG6Te/+Y0KCwt1wQUXaODAgfZ7LF++XHfddZdGjBihwsJCXX311fr9738fcP2gQYPUqlUrrVy5UgUFBXrooYfUqFEj+/XWrVsrISFBH3/88Q/5eQAAtWUBAFBHL774ohUXF3fC8aFDh1o33HCD/fzKK6+0Lr/8cvt5VVWV1bhxY2vw4MH2sZ07d1qSrPz8fMuyLGvy5MlW7969A95327ZtliRrw4YN1cbzz3/+0woNDbV8Pp997B//+IcVGxtrlZWVnXD+kSNHrKioKGvZsmUBx++66y5r4MCBlmVZ1tixY622bdtaHo+n2s9s2bKl9dhjjwUc++lPf2rdf//9lmVZ1pYtWyxJ1l//+lf79XXr1lmSrPXr11uWZVkDBw60+vbtG/AeAwYMCPjbxsTEWLNnz642Br+uXbtajz766CnPAQD8OIw4AQDq1cUXX2z/d2hoqJo2barOnTvbxxISEiRJu3btknR0atrixYvtNVPR0dHq0KGDJJ10Otrhw4fldrvlcrnsY9ddd53atGmj8847T4MHD9Yrr7xij2pt3rxZhw4d0nXXXRfwOXPmzLE/o7CwUFdccUXA6I5fWVmZduzYoV69egUc79Wrl9avX3/S79+iRYuA77p+/Xr17Nkz4Py0tLSA51lZWbr77ruVnp6uJ554otq/QWRkpP3dAAD1g+YQAIB69d+Fh8vlCjjmL3b8LbUPHjyo/v37a8qUKSe8l7/w+G/NmjXToUOH5PF4FB4eLkmKiYnR6tWrtWTJEn3wwQeaMGGCHn30Ua1cuVIHDx6UJM2fP19JSUkB7+V2uyUdLUaC4VTftTYeffRR3XbbbZo/f77ee+89TZw4Ua+99ppuuukm+5x9+/bp3HPPDUq8AIDqMeIEADDKJZdconXr1iklJUXnn39+wKNx48bVXtOlSxdJ0hdffBFwPCwsTOnp6XryySf12Wef6ZtvvtGiRYvUqVMnud1uFRUVnfAZycnJko6OFH388ceqrKw84fNiY2PVsmVL/ec//wk4/p///EedOnWq9Xft2LGjli9fHnDsk08+OeG8Cy64QGPGjNEHH3ygm2++WS+++KL92pEjR/TVV1+pa9eutf5cAEDdUTgBAIwyfPhw7du3TwMHDtTKlSv11Vdf6f3331dmZqa8Xm+115x77rm65JJLtHTpUvvYu+++q6efflqFhYXaunWr5syZI5/Pp/bt2ysmJka/+c1vNGbMGL300kv66quvtHr1aj3zzDN66aWXJEkjRoxQWVmZbr31Vq1atUqbNm3Syy+/bLdg/+1vf6spU6Zo7ty52rBhgx566CEVFhZq1KhRtf6uI0eOVG5urv74xz9q06ZNevbZZwM68x0+fFgjRozQkiVLtHXrVv3nP//RypUr1bFjR/ucTz75RG63+4QpfgCA4KJwAgAYxT+S4/V61bt3b3Xu3FmjR49WfHy8QkJO/s/W3XffHbARbHx8vObNm6drrrlGHTt2VE5Ojl599VVdeOGFkqTJkydr/Pjxys7OVseOHdWnTx/Nnz9fbdu2lSQ1bdpUixYt0sGDB3XllVeqW7duev755+2pdyNHjlRWVpZ+/etfq3PnzsrNzdXbb7+tdu3a1fq7XnrppXr++ef11FNPKTU1VR988IEeeeQR+/XQ0FDt3btXQ4YM0QUXXKBf/epXuv766/V///d/9jmvvvqqBg0apKioqFp/LgCg7lyWZVlOBwEAwI91+PBhtW/fXnPnzm0woy979uxR+/bttWrVKrvgAwDUD0acAABnhcjISM2ZM+eUG+Webb755hv9+c9/pmgCgNOAEScAAAAAqAEjTgAAAABQAwonAAAAAKgBhRMAAAAA1IDCCQAAAABqQOEEAAAAADWgcAIAAACAGlA4AQAAAEANKJwAAAAAoAYUTgAAAABQg/8HrqvMuJc1hsYAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -2161,7 +1341,7 @@ "metadata": {}, "outputs": [], "source": [ - "from tpot2 import TPOTClassifier\n", + "from tpot import TPOTClassifier\n", "from tempfile import mkdtemp\n", "from joblib import Memory\n", "from shutil import rmtree\n", @@ -2231,7 +1411,7 @@ "* Why are my TPOT runs not reproducible when random_state is set?\n", " * Check that `periodic_checkpoint_folder` is set correctly. If this is set to a non-empty folder, TPOT will continue training from the checkpoint rather than start a new run from scratch. For TPOT runs to be reproducible, they have to have the same starting points.\n", " * If using custom search spaces, pass in a fixed `random_state` value into the configspace of the scikit-learn modules that utilize them. TPOT does not check whether estimators do or do not take in a random state value (See Tutorial 2).\n", - " * If using the pre-built search spaces provided by TPOT, make sure to pass in `random_state` to `tpot2.config.get_configspace` or `tpot2.config.template_search_spaces.get_template_search_spaces`. This ensures all estimators that support it get a fixed random_state value. (See Tutorial 2).\n", + " * If using the pre-built search spaces provided by TPOT, make sure to pass in `random_state` to `tpot.config.get_configspace` or `tpot.config.template_search_spaces.get_template_search_spaces`. This ensures all estimators that support it get a fixed random_state value. (See Tutorial 2).\n", " * If using custom Node and Pipeline types, ensure all random decisions utilize the rng parameter passed into the mutation/crossover functions.\n", " * If `max_eval_time_mins` is set, TPOT will terminate pipelines that exceed this time limit. If the pipeline evaluation happens to be very similar to the time limit, small random fluctuations in CPU allocation may cause a given pipeline to be evaluated in one run but not another. This slightly different result would throw off the random number generator throughout the rest of the run. Setting `max_eval_time_mins` to None or a higher value may prevent this edge case.\n", " * If using `TPOTEstimatorSteadyState` with `n_jobs`>1, it is also possible that random fluctuations in CPU allocation slightly change the order in which pipelines are evaluated, which will affect the downstream results. `TPOTEstimatorSteadyState` is more reliably reproducible when `n_jobs=1` (This is not an issue for the default `TPOTEstimator`, `TPOTClassifier`, `TPOTRegressor` as they used a batched generational approach where execution order does not impact results).\n", @@ -2250,33 +1430,33 @@ "source": [ "# More Options\n", "\n", - "`tpot2.TPOTClassifier` and `tpot2.TPOTRegressor` have a simplified set of hyperparameters with default values set for classification and regression problems. Currently, both of these use the standard evolutionary algorithm in the `tpot2.TPOTEstimator` class. If you want more control, you can look into either the `tpot2.TPOTEstimator` or `tpot2.TPOTEstimatorSteadyState` class.\n", + "`tpot.TPOTClassifier` and `tpot.TPOTRegressor` have a simplified set of hyperparameters with default values set for classification and regression problems. Currently, both of these use the standard evolutionary algorithm in the `tpot.TPOTEstimator` class. If you want more control, you can look into either the `tpot.TPOTEstimator` or `tpot.TPOTEstimatorSteadyState` class.\n", "\n", - "There are two evolutionary algorithms built into TPOT2, which corresponds to two different estimator classes.\n", + "There are two evolutionary algorithms built into TPOT, which corresponds to two different estimator classes.\n", "\n", - "1. The `tpot2.TPOTEstimator` uses a standard evolutionary algorithm that evaluates exactly population_size individuals each generation. This is similar to the algorithm in TPOT1. The next generation does not start until the previous is completely finished evaluating. This leads to underutilized CPU time as the cores are waiting for the last individuals to finish training, but may preserve diversity in the population. \n", + "1. The `tpot.TPOTEstimator` uses a standard evolutionary algorithm that evaluates exactly population_size individuals each generation. This is similar to the algorithm in TPOT1. The next generation does not start until the previous is completely finished evaluating. This leads to underutilized CPU time as the cores are waiting for the last individuals to finish training, but may preserve diversity in the population. \n", "\n", - "2. The `tpot2.TPOTEstimatorSteadyState` differs in that it will generate and evaluate the next individual as soon as an individual finishes the evaluation. The number of individuals being evaluated is determined by the n_jobs parameter. There is no longer a concept of generations. The population_size parameter now refers to the size of the list of evaluated parents. When an individual is evaluated, the selection method updates the list of parents. This allows more efficient utilization when using multiple cores.\n" + "2. The `tpot.TPOTEstimatorSteadyState` differs in that it will generate and evaluate the next individual as soon as an individual finishes the evaluation. The number of individuals being evaluated is determined by the n_jobs parameter. There is no longer a concept of generations. The population_size parameter now refers to the size of the list of evaluated parents. When an individual is evaluated, the selection method updates the list of parents. This allows more efficient utilization when using multiple cores.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "### tpot2.TPOTEstimatorSteadyState" + "### tpot.TPOTEstimatorSteadyState" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Evaluations: : 113it [00:21, 5.15it/s]\n", - "/home/perib/miniconda3/envs/myenv/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:349: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", + "Evaluations: : 134it [01:00, 2.22it/s]\n", + "/Users/matsumoton/miniconda3/envs/tpot2_310/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", " warnings.warn(\n" ] }, @@ -2284,26 +1464,26 @@ "name": "stdout", "output_type": "stream", "text": [ - "0.9957890070921986\n" + "0.99812734082397\n" ] } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "\n", "\n", - "graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", ")\n", "\n", - "est = tpot2.TPOTEstimatorSteadyState( \n", + "est = tpot.TPOTEstimatorSteadyState( \n", " search_space = graph_search_space,\n", - " scorers=['roc_auc_ovr',tpot2.objectives.complexity_scorer],\n", + " scorers=['roc_auc_ovr',tpot.objectives.complexity_scorer],\n", " scorers_weights=[1,-1],\n", "\n", "\n", @@ -2347,7 +1527,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### tpot2.TPOTEstimator" + "### tpot.TPOTEstimator" ] }, { @@ -2356,11 +1536,11 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "\n", - "est = tpot2.TPOTEstimator( \n", + "est = tpot.TPOTEstimator( \n", " search_space = graph_search_space,\n", " max_time_mins=10,\n", " scorers=['roc_auc_ovr'], #scorers can be a list of strings or a list of scorers. These get evaluated during cross validation. \n", @@ -2396,7 +1576,7 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.metrics\n", "import sklearn.datasets\n", @@ -2405,7 +1585,7 @@ "X, y = sklearn.datasets.load_diabetes(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", - "est = tpot2.tpot_estimator.templates.TPOTRegressor(n_jobs=4, max_time_mins=30, verbose=2, cv=5, early_stop=5)\n", + "est = tpot.tpot_estimator.templates.TPOTRegressor(n_jobs=4, max_time_mins=30, verbose=2, cv=5, early_stop=5)\n", "est.fit(X_train, y_train)\n", "\n", "print(scorer(est, X_test, y_test))" @@ -2414,7 +1594,7 @@ ], "metadata": { "kernelspec": { - "display_name": "tpot_dev", + "display_name": "tpot2_310", "language": "python", "name": "python3" }, @@ -2428,14 +1608,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.10.13" }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "7fe1fe9ef32cd5efd76326a08046147513534f0dd2318301a1a96ae9071c1c4e" - } - } + "orig_nbformat": 4 }, "nbformat": 4, "nbformat_minor": 2 diff --git a/Tutorial/2_Search_Spaces.ipynb b/Tutorial/2_Search_Spaces.ipynb index ed04898a..6f3ec8e5 100644 --- a/Tutorial/2_Search_Spaces.ipynb +++ b/Tutorial/2_Search_Spaces.ipynb @@ -28,7 +28,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -36,429 +36,22 @@ "output_type": "stream", "text": [ "sampled hyperparameters\n", - "{'bootstrap': False, 'criterion': 'entropy', 'max_features': 0.1574830347299, 'min_samples_leaf': 10, 'min_samples_split': 6, 'n_estimators': 128}\n" + "{'bootstrap': True, 'criterion': 'gini', 'max_features': 0.02047915524, 'min_samples_leaf': 7, 'min_samples_split': 6, 'n_estimators': 128}\n" ] }, { "data": { "text/html": [ - "
RandomForestClassifier(bootstrap=False, criterion='entropy',\n",
-       "                       max_features=0.1574830347299, min_samples_leaf=10,\n",
-       "                       min_samples_split=6, n_estimators=128)
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.
" + "
RandomForestClassifier(max_features=0.02047915524, min_samples_leaf=7,\n",
+       "                       min_samples_split=6, n_estimators=128)
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": [ - "RandomForestClassifier(bootstrap=False, criterion='entropy',\n", - " max_features=0.1574830347299, min_samples_leaf=10,\n", + "RandomForestClassifier(max_features=0.02047915524, min_samples_leaf=7,\n", " min_samples_split=6, n_estimators=128)" ] }, - "execution_count": 1, + "execution_count": 2, "metadata": {}, "output_type": "execute_result" } @@ -467,7 +60,7 @@ "from ConfigSpace import ConfigurationSpace\n", "from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal\n", "from sklearn.ensemble import RandomForestClassifier\n", - "import tpot2\n", + "import tpot\n", "import numpy as np\n", "import sklearn\n", "import sklearn.datasets\n", @@ -501,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -509,429 +102,22 @@ "output_type": "stream", "text": [ "sampled hyperparameters\n", - "{'bootstrap': True, 'criterion': 'entropy', 'max_features': 0.2601475241557, 'min_samples_leaf': 17, 'min_samples_split': 3, 'n_estimators': 128}\n" + "{'bootstrap': False, 'criterion': 'gini', 'max_features': 0.9535953592513, 'min_samples_leaf': 12, 'min_samples_split': 2, 'n_estimators': 128}\n" ] }, { "data": { "text/html": [ - "
RandomForestClassifier(criterion='entropy', max_features=0.2601475241557,\n",
-       "                       min_samples_leaf=17, min_samples_split=3,\n",
-       "                       n_estimators=128)
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.
" + "
RandomForestClassifier(bootstrap=False, max_features=0.9535953592513,\n",
+       "                       min_samples_leaf=12, n_estimators=128)
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": [ - "RandomForestClassifier(criterion='entropy', max_features=0.2601475241557,\n", - " min_samples_leaf=17, min_samples_split=3,\n", - " n_estimators=128)" + "RandomForestClassifier(bootstrap=False, max_features=0.9535953592513,\n", + " min_samples_leaf=12, n_estimators=128)" ] }, - "execution_count": 2, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -1013,11 +199,11 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", + "import tpot\n", "from ConfigSpace import ConfigurationSpace\n", "from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal\n", "from sklearn.neighbors import KNeighborsClassifier\n", @@ -1034,7 +220,7 @@ ")\n", "\n", "\n", - "knn_node = tpot2.search_spaces.nodes.EstimatorNode(\n", + "knn_node = tpot.search_spaces.nodes.EstimatorNode(\n", " method = KNeighborsClassifier,\n", " space = knn_configspace,\n", ")" @@ -1049,16 +235,16 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 4, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -1070,7 +256,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -1078,7 +264,7 @@ "output_type": "stream", "text": [ "sampled hyperparameters\n", - "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 9, 'p': 1, 'weights': 'uniform'}\n" + "{'metric': 'minkowski', 'n_jobs': 1, 'n_neighbors': 8, 'p': 2, 'weights': 'uniform'}\n" ] } ], @@ -1096,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -1104,7 +290,7 @@ "output_type": "stream", "text": [ "mutated hyperparameters\n", - "{'metric': 'minkowski', 'n_jobs': 1, 'n_neighbors': 3, 'p': 3, 'weights': 'distance'}\n" + "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 2, 'p': 2, 'weights': 'uniform'}\n" ] } ], @@ -1118,12 +304,12 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In TPOT2, crossover only modifies the individual calling the crossover function, the second individual remains the same" + "In TPOT, crossover only modifies the individual calling the crossover function, the second individual remains the same" ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -1131,14 +317,14 @@ "output_type": "stream", "text": [ "original hyperparameters for individual 1\n", - "{'metric': 'minkowski', 'n_jobs': 1, 'n_neighbors': 6, 'p': 2, 'weights': 'distance'}\n", + "{'metric': 'minkowski', 'n_jobs': 1, 'n_neighbors': 8, 'p': 2, 'weights': 'uniform'}\n", "original hyperparameters for individual 2\n", - "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 4, 'p': 2, 'weights': 'uniform'}\n", + "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 6, 'p': 1, 'weights': 'distance'}\n", "\n", "post crossover hyperparameters for individual 1\n", - "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 6, 'p': 2, 'weights': 'uniform'}\n", + "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 6, 'p': 2, 'weights': 'distance'}\n", "post crossover hyperparameters for individual 2\n", - "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 4, 'p': 2, 'weights': 'uniform'}\n" + "{'metric': 'euclidean', 'n_jobs': 1, 'n_neighbors': 6, 'p': 1, 'weights': 'distance'}\n" ] } ], @@ -1171,423 +357,22 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=6)
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.
" + "
KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=6,\n",
+       "                     weights='distance')
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": [ - "KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=6)" + "KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=6,\n", + " weights='distance')" ] }, - "execution_count": 8, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -1606,429 +391,25 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 10, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
KNeighborsClassifier(n_neighbors=10)
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.
" + "
KNeighborsClassifier(n_neighbors=10)
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": [ "KNeighborsClassifier(n_neighbors=10)" ] }, - "execution_count": 9, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import tpot2\n", + "import tpot\n", "from ConfigSpace import ConfigurationSpace\n", "from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal\n", "from sklearn.neighbors import KNeighborsClassifier\n", @@ -2038,7 +419,7 @@ " 'n_neighbors':10,\n", "}\n", "\n", - "knn_node = tpot2.search_spaces.nodes.EstimatorNode(\n", + "knn_node = tpot.search_spaces.nodes.EstimatorNode(\n", " method = KNeighborsClassifier,\n", " space = space,\n", ")\n", @@ -2075,22 +456,22 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 10, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import tpot2\n", + "import tpot\n", "from ConfigSpace import ConfigurationSpace\n", "from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal\n", "from sklearn.neighbors import KNeighborsClassifier\n", @@ -2131,22 +512,22 @@ " }\n", " )\n", "\n", - "knn_node = tpot2.search_spaces.nodes.EstimatorNode(\n", + "knn_node = tpot.search_spaces.nodes.EstimatorNode(\n", " method = KNeighborsClassifier,\n", " space = knn_configspace,\n", ")\n", "\n", - "lr_node = tpot2.search_spaces.nodes.EstimatorNode(\n", + "lr_node = tpot.search_spaces.nodes.EstimatorNode(\n", " method = LogisticRegression,\n", " space = lr_configspace,\n", ")\n", "\n", - "dt_node = tpot2.search_spaces.nodes.EstimatorNode(\n", + "dt_node = tpot.search_spaces.nodes.EstimatorNode(\n", " method = DecisionTreeClassifier,\n", " space = dt_configspace,\n", ")\n", "\n", - "classifier_node = tpot2.search_spaces.pipelines.ChoicePipeline(\n", + "classifier_node = tpot.search_spaces.pipelines.ChoicePipeline(\n", " search_spaces=[\n", " knn_node,\n", " lr_node,\n", @@ -2155,17 +536,17 @@ ")\n", "\n", "\n", - "tpot2.search_spaces.pipelines.ChoicePipeline(\n", + "tpot.search_spaces.pipelines.ChoicePipeline(\n", " search_spaces = [\n", - " tpot2.search_spaces.nodes.EstimatorNode(\n", + " tpot.search_spaces.nodes.EstimatorNode(\n", " method = KNeighborsClassifier,\n", " space = knn_configspace,\n", " ),\n", - " tpot2.search_spaces.nodes.EstimatorNode(\n", + " tpot.search_spaces.nodes.EstimatorNode(\n", " method = LogisticRegression,\n", " space = lr_configspace,\n", " ),\n", - " tpot2.search_spaces.nodes.EstimatorNode(\n", + " tpot.search_spaces.nodes.EstimatorNode(\n", " method = DecisionTreeClassifier,\n", " space = dt_configspace,\n", " ),\n", @@ -2182,7 +563,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -2195,420 +576,13 @@ { "data": { "text/html": [ - "
LogisticRegression(C=0.0008500633703, class_weight='balanced', max_iter=1000,\n",
-       "                   n_jobs=1, penalty='l1', solver='saga')
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.
" + "
KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=3, p=1)
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": [ - "LogisticRegression(C=0.0008500633703, class_weight='balanced', max_iter=1000,\n", - " n_jobs=1, penalty='l1', solver='saga')" + "KNeighborsClassifier(metric='euclidean', n_jobs=1, n_neighbors=3, p=1)" ] }, - "execution_count": 11, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -2622,7 +596,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -2635,420 +609,13 @@ { "data": { "text/html": [ - "
LogisticRegression(C=0.1054489422979, class_weight='balanced', max_iter=1000,\n",
-       "                   n_jobs=1, penalty='l1', solver='liblinear')
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.
" + "
KNeighborsClassifier(n_jobs=1, n_neighbors=3, p=1, weights='distance')
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": [ - "LogisticRegression(C=0.1054489422979, class_weight='balanced', max_iter=1000,\n", - " n_jobs=1, penalty='l1', solver='liblinear')" + "KNeighborsClassifier(n_jobs=1, n_neighbors=3, p=1, weights='distance')" ] }, - "execution_count": 12, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -3070,7 +637,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "TPOT2 also comes with predefined hyperparameter search spaces. The current search spaces were adapted from a combination of the original TPOT package as well as the search spaces used in [AutoSklearn](https://github.com/automl/auto-sklearn/tree/development/autosklearn/pipeline/components). The helper function `tpot2.config.get_search_space` takes in a string or a list of strings, and returns either a EstimatorNode or a ChoicePipeline (including all methods in the list), respectively. \n", + "TPOT also comes with predefined hyperparameter search spaces. The current search spaces were adapted from a combination of the original TPOT package as well as the search spaces used in [AutoSklearn](https://github.com/automl/auto-sklearn/tree/development/autosklearn/pipeline/components). The helper function `tpot.config.get_search_space` takes in a string or a list of strings, and returns either a EstimatorNode or a ChoicePipeline (including all methods in the list), respectively. \n", "\n", "| String | Corresponding Method |\n", "| --- | ----- |\n", @@ -3096,8 +663,8 @@ "| DecisionTreeRegressor | |\n", "| KNeighborsRegressor | |\n", "| XGBRegressor | |\n", - "| ZeroCount | |\n", - "| ColumnOneHotEncoder | |\n", + "| ZeroCount | |\n", + "| ColumnOneHotEncoder | |\n", "| Binarizer | |\n", "| FastICA | |\n", "| FeatureAgglomeration | |\n", @@ -3130,38 +697,38 @@ "| GaussianProcessRegressor | |\n", "| HistGradientBoostingClassifier | |\n", "| HistGradientBoostingRegressor | |\n", - "| AddTransformer | |\n", - "| mul_neg_1_Transformer | |\n", - "| MulTransformer | |\n", - "| SafeReciprocalTransformer | |\n", - "| EQTransformer | |\n", - "| NETransformer | |\n", - "| GETransformer | |\n", - "| GTTransformer | |\n", - "| LETransformer | |\n", - "| LTTransformer | |\n", - "| MinTransformer | |\n", - "| MaxTransformer | |\n", - "| ZeroTransformer | |\n", - "| OneTransformer | |\n", - "| NTransformer | |\n", + "| AddTransformer | |\n", + "| mul_neg_1_Transformer | |\n", + "| MulTransformer | |\n", + "| SafeReciprocalTransformer | |\n", + "| EQTransformer | |\n", + "| NETransformer | |\n", + "| GETransformer | |\n", + "| GTTransformer | |\n", + "| LETransformer | |\n", + "| LTTransformer | |\n", + "| MinTransformer | |\n", + "| MaxTransformer | |\n", + "| ZeroTransformer | |\n", + "| OneTransformer | |\n", + "| NTransformer | |\n", "| PowerTransformer | |\n", "| QuantileTransformer | |\n", "| ARDRegression | |\n", "| QuadraticDiscriminantAnalysis | |\n", "| PassiveAggressiveClassifier | |\n", "| LinearDiscriminantAnalysis | |\n", - "| DominantEncoder | |\n", - "| RecessiveEncoder | |\n", - "| HeterosisEncoder | |\n", - "| UnderDominanceEncoder | |\n", - "| OverDominanceEncoder | |\n", + "| DominantEncoder | |\n", + "| RecessiveEncoder | |\n", + "| HeterosisEncoder | |\n", + "| UnderDominanceEncoder | |\n", + "| OverDominanceEncoder | |\n", "| GaussianProcessClassifier | |\n", "| BaggingClassifier | |\n", "| LGBMRegressor | |\n", - "| Passthrough | |\n", - "| SkipTransformer | |\n", - "| PassKBinsDiscretizer | |\n", + "| Passthrough | |\n", + "| SkipTransformer | |\n", + "| PassKBinsDiscretizer | |\n", "| SimpleImputer | |\n", "| IterativeImputer | |\n", "| KNNImputer | |\n", @@ -3226,7 +793,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -3239,424 +806,23 @@ { "data": { "text/html": [ - "
KNeighborsClassifier(n_jobs=1, n_neighbors=55, weights='distance')
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.
" + "
LogisticRegression(C=1.1466569941096, class_weight='balanced', max_iter=1000,\n",
+       "                   n_jobs=1, penalty='l1', solver='saga')
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": [ - "KNeighborsClassifier(n_jobs=1, n_neighbors=55, weights='distance')" + "LogisticRegression(C=1.1466569941096, class_weight='balanced', max_iter=1000,\n", + " n_jobs=1, penalty='l1', solver='saga')" ] }, - "execution_count": 13, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#same pipeline search space as before.\n", - "classifier_choice = tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"])\n", + "classifier_choice = tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"])\n", "\n", "print(\"sampled pipeline 1\")\n", "classifier_choice.generate().export_pipeline()" @@ -3664,7 +830,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -3677,420 +843,19 @@ { "data": { "text/html": [ - "
LogisticRegression(C=0.012915602763, l1_ratio=0.2577823332886, max_iter=1000,\n",
-       "                   n_jobs=1, penalty='elasticnet', solver='saga')
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.
" + "
LogisticRegression(C=0.017696063854, class_weight='balanced',\n",
+       "                   l1_ratio=0.8704814185204, max_iter=1000, n_jobs=1,\n",
+       "                   penalty='elasticnet', solver='saga')
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": [ - "LogisticRegression(C=0.012915602763, l1_ratio=0.2577823332886, max_iter=1000,\n", - " n_jobs=1, penalty='elasticnet', solver='saga')" + "LogisticRegression(C=0.017696063854, class_weight='balanced',\n", + " l1_ratio=0.8704814185204, max_iter=1000, n_jobs=1,\n", + " penalty='elasticnet', solver='saga')" ] }, - "execution_count": 14, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -4102,7 +867,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -4115,430 +880,20 @@ { "data": { "text/html": [ - "
SGDClassifier(alpha=0.0038384092036, class_weight='balanced',\n",
-       "              eta0=0.7197535254246, l1_ratio=0.8816063677431,\n",
-       "              loss='modified_huber', n_jobs=1, penalty='elasticnet')
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.
" + "
DecisionTreeClassifier(max_depth=10, min_samples_leaf=14, min_samples_split=17)
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": [ - "SGDClassifier(alpha=0.0038384092036, class_weight='balanced',\n", - " eta0=0.7197535254246, l1_ratio=0.8816063677431,\n", - " loss='modified_huber', n_jobs=1, penalty='elasticnet')" + "DecisionTreeClassifier(max_depth=10, min_samples_leaf=14, min_samples_split=17)" ] }, - "execution_count": 15, + "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#search space for all classifiers\n", - "classifier_choice = tpot2.config.get_search_space(\"classifiers\")\n", + "classifier_choice = tpot.config.get_search_space(\"classifiers\")\n", "\n", "print(\"sampled pipeline 1\")\n", "classifier_choice.generate().export_pipeline()" @@ -4546,7 +901,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 19, "metadata": {}, "outputs": [ { @@ -4559,417 +914,16 @@ { "data": { "text/html": [ - "
KNeighborsClassifier(n_jobs=1, n_neighbors=1, p=1, weights='distance')
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.
" + "
DecisionTreeClassifier(class_weight='balanced', max_depth=17,\n",
+       "                       min_samples_leaf=12, min_samples_split=5)
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": [ - "KNeighborsClassifier(n_jobs=1, n_neighbors=1, p=1, weights='distance')" + "DecisionTreeClassifier(class_weight='balanced', max_depth=17,\n", + " min_samples_leaf=12, min_samples_split=5)" ] }, - "execution_count": 16, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" } @@ -4989,435 +943,34 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
RandomForestClassifier(bootstrap=False, criterion='entropy',\n",
-       "                       max_features=0.0121463021153, min_samples_leaf=10,\n",
-       "                       min_samples_split=14, n_estimators=128, random_state=1)
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.
" + "
RandomForestClassifier(bootstrap=False, class_weight='balanced',\n",
+       "                       criterion='entropy', max_features=0.0247126034535,\n",
+       "                       min_samples_leaf=18, min_samples_split=13,\n",
+       "                       n_estimators=128, n_jobs=1, random_state=1)
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": [ - "RandomForestClassifier(bootstrap=False, criterion='entropy',\n", - " max_features=0.0121463021153, min_samples_leaf=10,\n", - " min_samples_split=14, n_estimators=128, random_state=1)" + "RandomForestClassifier(bootstrap=False, class_weight='balanced',\n", + " criterion='entropy', max_features=0.0247126034535,\n", + " min_samples_leaf=18, min_samples_split=13,\n", + " n_estimators=128, n_jobs=1, random_state=1)" ] }, - "execution_count": 17, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "reproducible_random_forest = tpot2.config.get_search_space(\"RandomForestClassifier\", random_state=1)\n", + "reproducible_random_forest = tpot.config.get_search_space(\"RandomForestClassifier\", random_state=1)\n", "reproducible_random_forest.generate().export_pipeline()" ] }, @@ -5432,7 +985,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -5445,450 +998,39 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('variancethreshold',\n",
-       "                 VarianceThreshold(threshold=0.0008293708451)),\n",
-       "                ('pca', PCA(n_components=0.5048643890372)),\n",
+       "
Pipeline(steps=[('variancethreshold',\n",
+       "                 VarianceThreshold(threshold=0.0749859461475)),\n",
+       "                ('pca', PCA(n_components=0.5413241473625)),\n",
        "                ('logisticregression',\n",
-       "                 LogisticRegression(C=7.7606337566295, class_weight='balanced',\n",
-       "                                    l1_ratio=0.123465163557, max_iter=1000,\n",
-       "                                    n_jobs=1, penalty='elasticnet',\n",
-       "                                    solver='saga'))])
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.
VarianceThreshold(threshold=0.0749859461475)
PCA(n_components=0.5413241473625)
LogisticRegression(C=0.0276080227073, max_iter=1000, n_jobs=1, penalty='l1',\n",
+       "                   solver='saga')
" ], "text/plain": [ "Pipeline(steps=[('variancethreshold',\n", - " VarianceThreshold(threshold=0.0008293708451)),\n", - " ('pca', PCA(n_components=0.5048643890372)),\n", + " VarianceThreshold(threshold=0.0749859461475)),\n", + " ('pca', PCA(n_components=0.5413241473625)),\n", " ('logisticregression',\n", - " LogisticRegression(C=7.7606337566295, class_weight='balanced',\n", - " l1_ratio=0.123465163557, max_iter=1000,\n", - " n_jobs=1, penalty='elasticnet',\n", - " solver='saga'))])" + " LogisticRegression(C=0.0276080227073, max_iter=1000, n_jobs=1,\n", + " penalty='l1', solver='saga'))])" ] }, - "execution_count": 18, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "selector_choicepipeline = tpot2.config.get_search_space(\"VarianceThreshold\")\n", - "transformer_choicepipeline = tpot2.config.get_search_space(\"PCA\")\n", - "classifier_choicepipeline = tpot2.config.get_search_space(\"LogisticRegression\")\n", + "selector_choicepipeline = tpot.config.get_search_space(\"VarianceThreshold\")\n", + "transformer_choicepipeline = tpot.config.get_search_space(\"PCA\")\n", + "classifier_choicepipeline = tpot.config.get_search_space(\"LogisticRegression\")\n", "\n", - "stc_pipeline = tpot2.search_spaces.pipelines.SequentialPipeline([\n", + "stc_pipeline = tpot.search_spaces.pipelines.SequentialPipeline([\n", " selector_choicepipeline,\n", " transformer_choicepipeline,\n", " classifier_choicepipeline,\n", @@ -5909,7 +1051,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -5922,449 +1064,35 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('variancethreshold',\n",
-       "                 VarianceThreshold(threshold=0.1215210592814)),\n",
-       "                ('fastica', FastICA(n_components=83)),\n",
-       "                ('baggingclassifier',\n",
-       "                 BaggingClassifier(bootstrap_features=True,\n",
-       "                                   max_features=0.9057563115025,\n",
-       "                                   max_samples=0.2313759070451, n_estimators=89,\n",
-       "                                   n_jobs=1))])
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.
" + "
Pipeline(steps=[('selectpercentile',\n",
+       "                 SelectPercentile(percentile=17.7371542950383)),\n",
+       "                ('pca', PCA(n_components=0.8858710545855)),\n",
+       "                ('quadraticdiscriminantanalysis',\n",
+       "                 QuadraticDiscriminantAnalysis(reg_param=0.0849090389922))])
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=[('variancethreshold',\n", - " VarianceThreshold(threshold=0.1215210592814)),\n", - " ('fastica', FastICA(n_components=83)),\n", - " ('baggingclassifier',\n", - " BaggingClassifier(bootstrap_features=True,\n", - " max_features=0.9057563115025,\n", - " max_samples=0.2313759070451, n_estimators=89,\n", - " n_jobs=1))])" + "Pipeline(steps=[('selectpercentile',\n", + " SelectPercentile(percentile=17.7371542950383)),\n", + " ('pca', PCA(n_components=0.8858710545855)),\n", + " ('quadraticdiscriminantanalysis',\n", + " QuadraticDiscriminantAnalysis(reg_param=0.0849090389922))])" ] }, - "execution_count": 19, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "selector_choicepipeline = tpot2.config.get_search_space(\"selectors\")\n", - "transformer_choicepipeline = tpot2.config.get_search_space(\"transformers\")\n", - "classifier_choicepipeline = tpot2.config.get_search_space(\"classifiers\")\n", + "selector_choicepipeline = tpot.config.get_search_space(\"selectors\")\n", + "transformer_choicepipeline = tpot.config.get_search_space(\"transformers\")\n", + "classifier_choicepipeline = tpot.config.get_search_space(\"classifiers\")\n", "\n", - "stc_pipeline = tpot2.search_spaces.pipelines.SequentialPipeline([\n", + "stc_pipeline = tpot.search_spaces.pipelines.SequentialPipeline([\n", " selector_choicepipeline,\n", " transformer_choicepipeline,\n", " classifier_choicepipeline,\n", @@ -6376,7 +1104,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -6389,438 +1117,36 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('selectpercentile',\n",
-       "                 SelectPercentile(percentile=25.1697450346144)),\n",
-       "                ('kbinsdiscretizer',\n",
-       "                 KBinsDiscretizer(encode='onehot-dense', n_bins=40,\n",
-       "                                  strategy='uniform')),\n",
-       "                ('lineardiscriminantanalysis',\n",
-       "                 LinearDiscriminantAnalysis(shrinkage=0.755769834898,\n",
-       "                                            solver='eigen'))])
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.
" + "
Pipeline(steps=[('selectfwe', SelectFwe(alpha=0.011428629553)),\n",
+       "                ('pca', PCA(n_components=0.5305969871753)),\n",
+       "                ('mlpclassifier',\n",
+       "                 MLPClassifier(activation='logistic', alpha=0.0165088486659,\n",
+       "                               hidden_layer_sizes=[374, 374, 374],\n",
+       "                               learning_rate='adaptive',\n",
+       "                               learning_rate_init=0.0023488711584,\n",
+       "                               n_iter_no_change=32))])
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=[('selectpercentile',\n", - " SelectPercentile(percentile=25.1697450346144)),\n", - " ('kbinsdiscretizer',\n", - " KBinsDiscretizer(encode='onehot-dense', n_bins=40,\n", - " strategy='uniform')),\n", - " ('lineardiscriminantanalysis',\n", - " LinearDiscriminantAnalysis(shrinkage=0.755769834898,\n", - " solver='eigen'))])" + "Pipeline(steps=[('selectfwe', SelectFwe(alpha=0.011428629553)),\n", + " ('pca', PCA(n_components=0.5305969871753)),\n", + " ('mlpclassifier',\n", + " MLPClassifier(activation='logistic', alpha=0.0165088486659,\n", + " hidden_layer_sizes=[374, 374, 374],\n", + " learning_rate='adaptive',\n", + " learning_rate_init=0.0023488711584,\n", + " n_iter_no_change=32))])" ] }, - "execution_count": 20, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -6841,7 +1167,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -6854,442 +1180,71 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('rbfsampler',\n",
-       "                 RBFSampler(gamma=0.1991726671256, n_components=7)),\n",
-       "                ('zerocount', ZeroCount()),\n",
-       "                ('binarizer', Binarizer(threshold=0.5354245073766))])
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.
" + "
Pipeline(steps=[('rfe',\n",
+       "                 RFE(estimator=ExtraTreesClassifier(criterion='entropy',\n",
+       "                                                    max_features=0.9131397098206,\n",
+       "                                                    min_samples_leaf=7,\n",
+       "                                                    min_samples_split=14,\n",
+       "                                                    n_jobs=1),\n",
+       "                     step=0.9655184110041)),\n",
+       "                ('quantiletransformer',\n",
+       "                 QuantileTransformer(n_quantiles=375,\n",
+       "                                     output_distribution='normal')),\n",
+       "                ('robustscaler',\n",
+       "                 RobustScaler(quantile_range=(0.2586783562495,\n",
+       "                                              0.973809923005)))])
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=[('rbfsampler',\n", - " RBFSampler(gamma=0.1991726671256, n_components=7)),\n", - " ('zerocount', ZeroCount()),\n", - " ('binarizer', Binarizer(threshold=0.5354245073766))])" + "Pipeline(steps=[('rfe',\n", + " RFE(estimator=ExtraTreesClassifier(criterion='entropy',\n", + " max_features=0.9131397098206,\n", + " min_samples_leaf=7,\n", + " min_samples_split=14,\n", + " n_jobs=1),\n", + " step=0.9655184110041)),\n", + " ('quantiletransformer',\n", + " QuantileTransformer(n_quantiles=375,\n", + " output_distribution='normal')),\n", + " ('robustscaler',\n", + " RobustScaler(quantile_range=(0.2586783562495,\n", + " 0.973809923005)))])" ] }, - "execution_count": 21, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import tpot2.config\n", + "import tpot.config\n", "\n", "\n", - "linear_feature_engineering = tpot2.search_spaces.pipelines.DynamicLinearPipeline(search_space = tpot2.config.get_search_space([\"all_transformers\",\"selectors_classification\"]), max_length=10)\n", + "linear_feature_engineering = tpot.search_spaces.pipelines.DynamicLinearPipeline(search_space = tpot.config.get_search_space([\"all_transformers\",\"selectors_classification\"]), max_length=10)\n", "print(\"sampled pipeline\")\n", "linear_feature_engineering.generate().export_pipeline()" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -7302,420 +1257,22 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('selectfwe', SelectFwe(alpha=0.0014251225737)),\n",
-       "                ('powertransformer', PowerTransformer())])
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.
" + "
Pipeline(steps=[('kbinsdiscretizer',\n",
+       "                 KBinsDiscretizer(encode='onehot-dense', n_bins=77)),\n",
+       "                ('zerocount', ZeroCount()),\n",
+       "                ('columnonehotencoder', ColumnOneHotEncoder())])
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=[('selectfwe', SelectFwe(alpha=0.0014251225737)),\n", - " ('powertransformer', PowerTransformer())])" + "Pipeline(steps=[('kbinsdiscretizer',\n", + " KBinsDiscretizer(encode='onehot-dense', n_bins=77)),\n", + " ('zerocount', ZeroCount()),\n", + " ('columnonehotencoder', ColumnOneHotEncoder())])" ] }, - "execution_count": 22, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -7727,7 +1284,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -7740,450 +1297,85 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('pipeline',\n",
-       "                 Pipeline(steps=[('nystroem',\n",
-       "                                  Nystroem(gamma=0.3480554902065,\n",
-       "                                           kernel='sigmoid', n_components=20)),\n",
-       "                                 ('binarizer',\n",
-       "                                  Binarizer(threshold=0.6696149189758)),\n",
-       "                                 ('minmaxscaler', MinMaxScaler())])),\n",
-       "                ('multinomialnb', MultinomialNB(alpha=0.0016967794962))])
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.
" + "
Pipeline(steps=[('pipeline',\n",
+       "                 Pipeline(steps=[('rfe',\n",
+       "                                  RFE(estimator=ExtraTreesClassifier(bootstrap=True,\n",
+       "                                                                     class_weight='balanced',\n",
+       "                                                                     criterion='entropy',\n",
+       "                                                                     max_features=0.3615719366658,\n",
+       "                                                                     min_samples_leaf=15,\n",
+       "                                                                     min_samples_split=15,\n",
+       "                                                                     n_jobs=1),\n",
+       "                                      step=0.2728695142659)),\n",
+       "                                 ('standardscaler', StandardScaler())])),\n",
+       "                ('decisiontreeclassifier',\n",
+       "                 DecisionTreeClassifier(criterion='entropy', max_depth=1,\n",
+       "                                        max_features='sqrt',\n",
+       "                                        min_samples_leaf=15,\n",
+       "                                        min_samples_split=6))])
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=[('pipeline',\n", - " Pipeline(steps=[('nystroem',\n", - " Nystroem(gamma=0.3480554902065,\n", - " kernel='sigmoid', n_components=20)),\n", - " ('binarizer',\n", - " Binarizer(threshold=0.6696149189758)),\n", - " ('minmaxscaler', MinMaxScaler())])),\n", - " ('multinomialnb', MultinomialNB(alpha=0.0016967794962))])" + " Pipeline(steps=[('rfe',\n", + " RFE(estimator=ExtraTreesClassifier(bootstrap=True,\n", + " class_weight='balanced',\n", + " criterion='entropy',\n", + " max_features=0.3615719366658,\n", + " min_samples_leaf=15,\n", + " min_samples_split=15,\n", + " n_jobs=1),\n", + " step=0.2728695142659)),\n", + " ('standardscaler', StandardScaler())])),\n", + " ('decisiontreeclassifier',\n", + " DecisionTreeClassifier(criterion='entropy', max_depth=1,\n", + " max_features='sqrt',\n", + " min_samples_leaf=15,\n", + " min_samples_split=6))])" ] }, - "execution_count": 23, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "full_search_space = tpot2.search_spaces.pipelines.SequentialPipeline([\n", + "full_search_space = tpot.search_spaces.pipelines.SequentialPipeline([\n", " linear_feature_engineering,\n", - " tpot2.config.get_search_space(\"classifiers\"),\n", + " tpot.config.get_search_space(\"classifiers\"),\n", "])\n", "\n", "print(\"sampled pipeline\")\n", @@ -8192,7 +1384,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 28, "metadata": {}, "outputs": [ { @@ -8205,441 +1397,33 @@ { "data": { "text/html": [ - "
Pipeline(steps=[('pipeline',\n",
-       "                 Pipeline(steps=[('zerocount', ZeroCount()),\n",
-       "                                 ('variancethreshold',\n",
-       "                                  VarianceThreshold(threshold=0.0020422211173)),\n",
-       "                                 ('binarizer',\n",
-       "                                  Binarizer(threshold=0.9681763702))])),\n",
-       "                ('bernoullinb',\n",
-       "                 BernoulliNB(alpha=0.0816524714629, fit_prior=False))])
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.
" + "
Pipeline(steps=[('pipeline',\n",
+       "                 Pipeline(steps=[('maxabsscaler-1', MaxAbsScaler()),\n",
+       "                                 ('powertransformer', PowerTransformer()),\n",
+       "                                 ('maxabsscaler-2', MaxAbsScaler())])),\n",
+       "                ('adaboostclassifier',\n",
+       "                 AdaBoostClassifier(learning_rate=1.8111334984721,\n",
+       "                                    n_estimators=437))])
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=[('pipeline',\n", - " Pipeline(steps=[('zerocount', ZeroCount()),\n", - " ('variancethreshold',\n", - " VarianceThreshold(threshold=0.0020422211173)),\n", - " ('binarizer',\n", - " Binarizer(threshold=0.9681763702))])),\n", - " ('bernoullinb',\n", - " BernoulliNB(alpha=0.0816524714629, fit_prior=False))])" + " Pipeline(steps=[('maxabsscaler-1', MaxAbsScaler()),\n", + " ('powertransformer', PowerTransformer()),\n", + " ('maxabsscaler-2', MaxAbsScaler())])),\n", + " ('adaboostclassifier',\n", + " AdaBoostClassifier(learning_rate=1.8111334984721,\n", + " n_estimators=437))])" ] }, - "execution_count": 24, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -8660,440 +1444,36 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('fastica',\n",
-       "                                FastICA(algorithm='deflation',\n",
-       "                                        n_components=66)),\n",
-       "                               ('passthrough', Passthrough())])
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.
" + "
FeatureUnion(transformer_list=[('kbinsdiscretizer',\n",
+       "                                KBinsDiscretizer(encode='onehot-dense',\n",
+       "                                                 n_bins=4, strategy='kmeans')),\n",
+       "                               ('passthrough', Passthrough())])
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": [ - "FeatureUnion(transformer_list=[('fastica',\n", - " FastICA(algorithm='deflation',\n", - " n_components=66)),\n", + "FeatureUnion(transformer_list=[('kbinsdiscretizer',\n", + " KBinsDiscretizer(encode='onehot-dense',\n", + " n_bins=4, strategy='kmeans')),\n", " ('passthrough', Passthrough())])" ] }, - "execution_count": 25, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "transform_and_passthrough = tpot2.search_spaces.pipelines.UnionPipeline([\n", - " tpot2.config.get_search_space(\"transformers\"),\n", - " tpot2.config.get_search_space(\"Passthrough\"),\n", + "transform_and_passthrough = tpot.search_spaces.pipelines.UnionPipeline([\n", + " tpot.config.get_search_space(\"transformers\"),\n", + " tpot.config.get_search_space(\"Passthrough\"),\n", "])\n", "\n", "transform_and_passthrough.generate().export_pipeline()" @@ -9108,461 +1488,63 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 30, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('variancethreshold',\n",
-       "                 VarianceThreshold(threshold=0.0009494718313)),\n",
+       "
Pipeline(steps=[('selectpercentile',\n",
+       "                 SelectPercentile(percentile=23.1558575415017)),\n",
        "                ('featureunion',\n",
-       "                 FeatureUnion(transformer_list=[('binarizer',\n",
-       "                                                 Binarizer(threshold=0.8136655878085)),\n",
+       "                 FeatureUnion(transformer_list=[('powertransformer',\n",
+       "                                                 PowerTransformer()),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
-       "                ('adaboostclassifier',\n",
-       "                 AdaBoostClassifier(learning_rate=0.1727096029044,\n",
-       "                                    n_estimators=446))])
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.
SelectPercentile(percentile=23.1558575415017)
FeatureUnion(transformer_list=[('powertransformer', PowerTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
PowerTransformer()
Passthrough()
RandomForestClassifier(max_features=0.0771674508583, min_samples_leaf=18,\n",
+       "                       min_samples_split=20, n_estimators=128, n_jobs=1)
" ], "text/plain": [ - "Pipeline(steps=[('variancethreshold',\n", - " VarianceThreshold(threshold=0.0009494718313)),\n", + "Pipeline(steps=[('selectpercentile',\n", + " SelectPercentile(percentile=23.1558575415017)),\n", " ('featureunion',\n", - " FeatureUnion(transformer_list=[('binarizer',\n", - " Binarizer(threshold=0.8136655878085)),\n", + " FeatureUnion(transformer_list=[('powertransformer',\n", + " PowerTransformer()),\n", " ('passthrough',\n", " Passthrough())])),\n", - " ('adaboostclassifier',\n", - " AdaBoostClassifier(learning_rate=0.1727096029044,\n", - " n_estimators=446))])" + " ('randomforestclassifier',\n", + " RandomForestClassifier(max_features=0.0771674508583,\n", + " min_samples_leaf=18,\n", + " min_samples_split=20, n_estimators=128,\n", + " n_jobs=1))])" ] }, - "execution_count": 26, + "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "stc_pipeline2 = tpot2.search_spaces.pipelines.SequentialPipeline([\n", - " tpot2.config.get_search_space(\"selectors\"),\n", + "stc_pipeline2 = tpot.search_spaces.pipelines.SequentialPipeline([\n", + " tpot.config.get_search_space(\"selectors\"),\n", " transform_and_passthrough,\n", - " tpot2.config.get_search_space(\"classifiers\"),\n", + " tpot.config.get_search_space(\"classifiers\"),\n", "])\n", "\n", "stc_pipeline2.generate().export_pipeline()" @@ -9577,484 +1559,86 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 31, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('featureunion',\n",
+       "
Pipeline(steps=[('featureunion',\n",
        "                 FeatureUnion(transformer_list=[('pipeline-1',\n",
        "                                                 Pipeline(steps=[('variancethreshold',\n",
-       "                                                                  VarianceThreshold(threshold=0.1996640297479)),\n",
-       "                                                                 ('powertransformer',\n",
-       "                                                                  PowerTransformer())])),\n",
+       "                                                                  VarianceThreshold(threshold=0.0175436295121)),\n",
+       "                                                                 ('zerocount',\n",
+       "                                                                  ZeroCount())])),\n",
        "                                                ('pipeline-2',\n",
-       "                                                 Pipeline(steps=[('selectfwe',\n",
-       "                                                                  SelectFwe(alpha=0.0045323854667)),\n",
-       "                                                                 ('fastica',\n",
-       "                                                                  FastICA(n_components=34))]))])),\n",
-       "                ('quadraticdiscriminantanalysis',\n",
-       "                 QuadraticDiscriminantAnalysis(reg_param=0.8833282196313))])
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.
VarianceThreshold(threshold=0.0175436295121)
ZeroCount()
VarianceThreshold(threshold=0.0060477871847)
PCA(n_components=0.9796517989842)
DecisionTreeClassifier(max_depth=9, max_features='log2', min_samples_leaf=7,\n",
+       "                       min_samples_split=7)
" ], "text/plain": [ "Pipeline(steps=[('featureunion',\n", " FeatureUnion(transformer_list=[('pipeline-1',\n", " Pipeline(steps=[('variancethreshold',\n", - " VarianceThreshold(threshold=0.1996640297479)),\n", - " ('powertransformer',\n", - " PowerTransformer())])),\n", + " VarianceThreshold(threshold=0.0175436295121)),\n", + " ('zerocount',\n", + " ZeroCount())])),\n", " ('pipeline-2',\n", - " Pipeline(steps=[('selectfwe',\n", - " SelectFwe(alpha=0.0045323854667)),\n", - " ('fastica',\n", - " FastICA(n_components=34))]))])),\n", - " ('quadraticdiscriminantanalysis',\n", - " QuadraticDiscriminantAnalysis(reg_param=0.8833282196313))])" + " Pipeline(steps=[('variancethreshold',\n", + " VarianceThreshold(threshold=0.0060477871847)),\n", + " ('pca',\n", + " PCA(n_components=0.9796517989842))]))])),\n", + " ('decisiontreeclassifier',\n", + " DecisionTreeClassifier(max_depth=9, max_features='log2',\n", + " min_samples_leaf=7,\n", + " min_samples_split=7))])" ] }, - "execution_count": 27, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "st_pipeline = tpot2.search_spaces.pipelines.SequentialPipeline([\n", - " tpot2.config.get_search_space(\"selectors\"),\n", - " tpot2.config.get_search_space(\"transformers\"),\n", + "st_pipeline = tpot.search_spaces.pipelines.SequentialPipeline([\n", + " tpot.config.get_search_space(\"selectors\"),\n", + " tpot.config.get_search_space(\"transformers\"),\n", "])\n", "\n", - "branched_pipeline = tpot2.search_spaces.pipelines.SequentialPipeline([\n", - " tpot2.search_spaces.pipelines.UnionPipeline([\n", + "branched_pipeline = tpot.search_spaces.pipelines.SequentialPipeline([\n", + " tpot.search_spaces.pipelines.UnionPipeline([\n", " st_pipeline,\n", " st_pipeline,\n", " ]),\n", - " tpot2.config.get_search_space(\"classifiers\"),\n", + " tpot.config.get_search_space(\"classifiers\"),\n", "])\n", "\n", "branched_pipeline.generate().export_pipeline()" @@ -10075,432 +1659,46 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 32, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('zerocount', ZeroCount()),\n",
-       "                               ('powertransformer', PowerTransformer())])
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.
" + "
FeatureUnion(transformer_list=[('kbinsdiscretizer',\n",
+       "                                KBinsDiscretizer(encode='onehot-dense',\n",
+       "                                                 n_bins=17,\n",
+       "                                                 strategy='uniform')),\n",
+       "                               ('rbfsampler',\n",
+       "                                RBFSampler(gamma=0.6920878537418,\n",
+       "                                           n_components=6)),\n",
+       "                               ('zerocount', ZeroCount())])
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": [ - "FeatureUnion(transformer_list=[('zerocount', ZeroCount()),\n", - " ('powertransformer', PowerTransformer())])" + "FeatureUnion(transformer_list=[('kbinsdiscretizer',\n", + " KBinsDiscretizer(encode='onehot-dense',\n", + " n_bins=17,\n", + " strategy='uniform')),\n", + " ('rbfsampler',\n", + " RBFSampler(gamma=0.6920878537418,\n", + " n_components=6)),\n", + " ('zerocount', ZeroCount())])" ] }, - "execution_count": 28, + "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "dynamic_transformers = tpot2.search_spaces.pipelines.DynamicUnionPipeline(tpot2.config.get_search_space(\"transformers\"), max_estimators=4)\n", + "dynamic_transformers = tpot.search_spaces.pipelines.DynamicUnionPipeline(tpot.config.get_search_space(\"transformers\"), max_estimators=4)\n", "dynamic_transformers.generate().export_pipeline()" ] }, @@ -10513,440 +1711,36 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 33, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                FeatureUnion(transformer_list=[('powertransformer',\n",
-       "                                                                PowerTransformer())])),\n",
-       "                               ('passthrough', Passthrough())])
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.
" + "
FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                FeatureUnion(transformer_list=[('columnonehotencoder',\n",
+       "                                                                ColumnOneHotEncoder())])),\n",
+       "                               ('passthrough', Passthrough())])
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": [ "FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('powertransformer',\n", - " PowerTransformer())])),\n", + " FeatureUnion(transformer_list=[('columnonehotencoder',\n", + " ColumnOneHotEncoder())])),\n", " ('passthrough', Passthrough())])" ] }, - "execution_count": 29, + "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "dynamic_transformers_with_passthrough = tpot2.search_spaces.pipelines.UnionPipeline([\n", + "dynamic_transformers_with_passthrough = tpot.search_spaces.pipelines.UnionPipeline([\n", " dynamic_transformers,\n", - " tpot2.config.get_search_space(\"Passthrough\")],\n", + " tpot.config.get_search_space(\"Passthrough\")],\n", " )\n", "\n", "dynamic_transformers_with_passthrough.generate().export_pipeline()" @@ -10954,470 +1748,67 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 39, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('selectpercentile',\n",
-       "                 SelectPercentile(percentile=3.5688237635159)),\n",
+       "
Pipeline(steps=[('variancethreshold',\n",
+       "                 VarianceThreshold(threshold=0.0061334954052)),\n",
        "                ('featureunion',\n",
        "                 FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                                 FeatureUnion(transformer_list=[('featureagglomeration',\n",
-       "                                                                                 FeatureAgglomeration(n_clusters=28,\n",
-       "                                                                                                      pooling_func=<function max at 0x78ec455b4e30>))])),\n",
+       "                                                 FeatureUnion(transformer_list=[('powertransformer',\n",
+       "                                                                                 PowerTransformer()),\n",
+       "                                                                                ('quantiletransformer',\n",
+       "                                                                                 QuantileTransformer(n_quantiles=952,\n",
+       "                                                                                                     output_distribution='normal'))])),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
-       "                ('logisticregression',\n",
-       "                 LogisticRegression(C=9762.07332929782, max_iter=1000, n_jobs=1,\n",
-       "                                    solver='saga'))])
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.
VarianceThreshold(threshold=0.0061334954052)
FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                FeatureUnion(transformer_list=[('powertransformer',\n",
+       "                                                                PowerTransformer()),\n",
+       "                                                               ('quantiletransformer',\n",
+       "                                                                QuantileTransformer(n_quantiles=952,\n",
+       "                                                                                    output_distribution='normal'))])),\n",
+       "                               ('passthrough', Passthrough())])
PowerTransformer()
QuantileTransformer(n_quantiles=952, output_distribution='normal')
Passthrough()
GaussianNB()
" ], "text/plain": [ - "Pipeline(steps=[('selectpercentile',\n", - " SelectPercentile(percentile=3.5688237635159)),\n", + "Pipeline(steps=[('variancethreshold',\n", + " VarianceThreshold(threshold=0.0061334954052)),\n", " ('featureunion',\n", " FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('featureagglomeration',\n", - " FeatureAgglomeration(n_clusters=28,\n", - " pooling_func=))])),\n", + " FeatureUnion(transformer_list=[('powertransformer',\n", + " PowerTransformer()),\n", + " ('quantiletransformer',\n", + " QuantileTransformer(n_quantiles=952,\n", + " output_distribution='normal'))])),\n", " ('passthrough',\n", " Passthrough())])),\n", - " ('logisticregression',\n", - " LogisticRegression(C=9762.07332929782, max_iter=1000, n_jobs=1,\n", - " solver='saga'))])" + " ('gaussiannb', GaussianNB())])" ] }, - "execution_count": 30, + "execution_count": 39, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "stc_pipeline3 = tpot2.search_spaces.pipelines.SequentialPipeline([\n", - " tpot2.config.get_search_space(\"selectors\"),\n", + "stc_pipeline3 = tpot.search_spaces.pipelines.SequentialPipeline([\n", + " tpot.config.get_search_space(\"selectors\"),\n", " dynamic_transformers_with_passthrough,\n", - " tpot2.config.get_search_space(\"classifiers\"),\n", + " tpot.config.get_search_space(\"classifiers\"),\n", "])\n", "\n", "stc_pipeline3.generate().export_pipeline()" @@ -11436,426 +1827,25 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 40, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
ExtraTreesClassifier(class_weight='balanced', max_features=0.6642237575313,\n",
-       "                     min_samples_leaf=17, min_samples_split=3, n_jobs=1)
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.
" + "
ExtraTreesClassifier(bootstrap=True, criterion='entropy',\n",
+       "                     max_features=0.4414978244072, min_samples_leaf=19,\n",
+       "                     min_samples_split=5, n_jobs=1)
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": [ - "ExtraTreesClassifier(class_weight='balanced', max_features=0.6642237575313,\n", - " min_samples_leaf=17, min_samples_split=3, n_jobs=1)" + "ExtraTreesClassifier(bootstrap=True, criterion='entropy',\n", + " max_features=0.4414978244072, min_samples_leaf=19,\n", + " min_samples_split=5, n_jobs=1)" ] }, - "execution_count": 31, + "execution_count": 40, "metadata": {}, "output_type": "execute_result" } @@ -11867,448 +1857,44 @@ " }\n", " )\n", "\n", - "extratrees_estimator_node = tpot2.config.get_search_space(\"ExtraTreesClassifier\") #this exports an ExtraTreesClassifier node\n", + "extratrees_estimator_node = tpot.config.get_search_space(\"ExtraTreesClassifier\") #this exports an ExtraTreesClassifier node\n", "extratrees_estimator_node.generate().export_pipeline()" ] }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 41, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
SelectFromModel(estimator=ExtraTreesClassifier(bootstrap=True,\n",
-       "                                               class_weight='balanced',\n",
-       "                                               max_features=0.3007313724684,\n",
-       "                                               min_samples_leaf=12,\n",
-       "                                               min_samples_split=17, n_jobs=1),\n",
-       "                threshold=0.0048046738992)
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.
" + "
SelectFromModel(estimator=ExtraTreesClassifier(class_weight='balanced',\n",
+       "                                               criterion='entropy',\n",
+       "                                               max_features=0.7142154671055,\n",
+       "                                               min_samples_leaf=10,\n",
+       "                                               min_samples_split=14, n_jobs=1),\n",
+       "                threshold=0.0006148231618)
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": [ - "SelectFromModel(estimator=ExtraTreesClassifier(bootstrap=True,\n", - " class_weight='balanced',\n", - " max_features=0.3007313724684,\n", - " min_samples_leaf=12,\n", - " min_samples_split=17, n_jobs=1),\n", - " threshold=0.0048046738992)" + "SelectFromModel(estimator=ExtraTreesClassifier(class_weight='balanced',\n", + " criterion='entropy',\n", + " max_features=0.7142154671055,\n", + " min_samples_leaf=10,\n", + " min_samples_split=14, n_jobs=1),\n", + " threshold=0.0006148231618)" ] }, - "execution_count": 32, + "execution_count": 41, "metadata": {}, "output_type": "execute_result" } @@ -12317,7 +1903,7 @@ "from sklearn.ensemble import ExtraTreesClassifier\n", "from sklearn.feature_selection import SelectFromModel\n", "\n", - "select_from_model_wrapper_searchspace = tpot2.search_spaces.pipelines.WrapperPipeline(\n", + "select_from_model_wrapper_searchspace = tpot.search_spaces.pipelines.WrapperPipeline(\n", " method=SelectFromModel,\n", " space = SelectFromModel_configspace_part,\n", " estimator_search_space= extratrees_estimator_node,\n", @@ -12334,7 +1920,7 @@ "\n", "Sklearn Pipelines only allow classifiers/regressors as the final step. All other steps are expected to implement a transform function. We can get around this by wrapping it in another transformer class that returns the output of predict or predict_proba inside the transform() function.\n", "\n", - "To wrap classifiers as transfomers, you can use the following class: `tpot2.builtin_modules.EstimatorTransformer`. You can specify whether to pass the outputs of predict, predict_proba, or decision function with the `method` parameter. \n", + "To wrap classifiers as transfomers, you can use the following class: `tpot.builtin_modules.EstimatorTransformer`. You can specify whether to pass the outputs of predict, predict_proba, or decision function with the `method` parameter. \n", "\n", "#### cross_val_predict_cv\n", "\n", @@ -12347,438 +1933,37 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
EstimatorTransformer(estimator=SVC(C=140.9223338924506, gamma=0.0007253447995,\n",
-       "                                   max_iter=3000, probability=True,\n",
-       "                                   shrinking=False))
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.
" + "
EstimatorTransformer(estimator=LogisticRegression(C=26041.760435900884,\n",
+       "                                                  class_weight='balanced',\n",
+       "                                                  max_iter=1000, n_jobs=1,\n",
+       "                                                  solver='saga'))
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": [ - "EstimatorTransformer(estimator=SVC(C=140.9223338924506, gamma=0.0007253447995,\n", - " max_iter=3000, probability=True,\n", - " shrinking=False))" + "EstimatorTransformer(estimator=LogisticRegression(C=26041.760435900884,\n", + " class_weight='balanced',\n", + " max_iter=1000, n_jobs=1,\n", + " solver='saga'))" ] }, - "execution_count": 33, + "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "classifiers = tpot2.config.get_search_space(\"classifiers\")\n", - "wrapped_estimators = tpot2.search_spaces.pipelines.WrapperPipeline(tpot2.builtin_modules.EstimatorTransformer, {}, classifiers)\n", + "classifiers = tpot.config.get_search_space(\"classifiers\")\n", + "wrapped_estimators = tpot.search_spaces.pipelines.WrapperPipeline(tpot.builtin_modules.EstimatorTransformer, {}, classifiers)\n", "\n", "est = wrapped_estimators.generate().export_pipeline() #returns an estimator with a transform function\n", "est" @@ -12786,20 +1971,20 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 43, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[0.5 , 0.5 ],\n", - " [0.50964815, 0.49035185],\n", - " [0.50681558, 0.49318442],\n", - " [0.51565809, 0.48434191],\n", - " [0.52006004, 0.47993996]])" + "array([[0.37946644, 0.62053356],\n", + " [0.31827888, 0.68172112],\n", + " [0.28322725, 0.71677275],\n", + " [0.60434582, 0.39565418],\n", + " [0.65940485, 0.34059515]])" ] }, - "execution_count": 34, + "execution_count": 43, "metadata": {}, "output_type": "execute_result" } @@ -12820,27 +2005,27 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "array([[0],\n", - " [0],\n", + "array([[1],\n", + " [1],\n", " [1],\n", " [1],\n", " [1]])" ] }, - "execution_count": 35, + "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "classifiers = tpot2.config.get_search_space(\"classifiers\")\n", - "wrapped_estimators_cv = tpot2.search_spaces.pipelines.WrapperPipeline(tpot2.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':10, 'method':'predict'}, classifiers)\n", + "classifiers = tpot.config.get_search_space(\"classifiers\")\n", + "wrapped_estimators_cv = tpot.search_spaces.pipelines.WrapperPipeline(tpot.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':10, 'method':'predict'}, classifiers)\n", "est = wrapped_estimators_cv.generate().export_pipeline() #returns an estimator with a transform function\n", "est.fit_transform(X, y)[0:5]" ] @@ -12854,571 +2039,128 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 45, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('normalizer', Normalizer(norm='max')),\n",
+       "
Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n",
        "                ('featureunion-1',\n",
        "                 FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                                 FeatureUnion(transformer_list=[('rbfsampler',\n",
-       "                                                                                 RBFSampler(gamma=0.7809991844556,\n",
-       "                                                                                            n_components=50)),\n",
-       "                                                                                ('columnonehotencoder',\n",
-       "                                                                                 ColumnOneHotEncoder()),\n",
-       "                                                                                ('nystroem',\n",
-       "                                                                                 Nystroem(gamma=0.3179172515929,\n",
-       "                                                                                          kernel='additive_chi2',\n",
-       "                                                                                          n_components=80))])),\n",
-       "                                                ('...\n",
-       "                                                                                                                              class_weight='balanced',\n",
-       "                                                                                                                              eta0=0.4039854095517,\n",
-       "                                                                                                                              l1_ratio=0.0336982783886,\n",
-       "                                                                                                                              learning_rate='constant',\n",
-       "                                                                                                                              loss='modified_huber',\n",
-       "                                                                                                                              n_jobs=1,\n",
-       "                                                                                                                              penalty='elasticnet'),\n",
-       "                                                                                                      method='predict'))])),\n",
-       "                                                ('passthrough',\n",
-       "                                                 Passthrough())])),\n",
-       "                ('mlpclassifier',\n",
-       "                 MLPClassifier(alpha=0.0867902302825, hidden_layer_sizes=[35],\n",
-       "                               learning_rate='invscaling',\n",
-       "                               learning_rate_init=0.0152961651727,\n",
-       "                               n_iter_no_change=32))])
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.
MLPClassifier(alpha=0.0749450324783, hidden_layer_sizes=[418, 418, 418],\n",
+       "              learning_rate_init=0.0055186230368, n_iter_no_change=32)
MLPClassifier(alpha=0.0749450324783, hidden_layer_sizes=[418, 418, 418],\n",
+       "              learning_rate_init=0.0055186230368, n_iter_no_change=32)
Passthrough()
XGBClassifier(base_score=None, booster=None, callbacks=None,\n",
+       "              colsample_bylevel=None, colsample_bynode=None,\n",
+       "              colsample_bytree=None, device=None, early_stopping_rounds=None,\n",
+       "              enable_categorical=False, eval_metric=None, feature_types=None,\n",
+       "              gamma=0.0095679856018, grow_policy=None, importance_type=None,\n",
+       "              interaction_constraints=None, learning_rate=0.0037432296142,\n",
+       "              max_bin=None, max_cat_threshold=None, max_cat_to_onehot=None,\n",
+       "              max_delta_step=None, max_depth=12, max_leaves=None,\n",
+       "              min_child_weight=2, missing=nan, monotone_constraints=None,\n",
+       "              multi_strategy=None, n_estimators=100, n_jobs=1, nthread=1,\n",
+       "              num_parallel_tree=None, ...)
" ], "text/plain": [ - "Pipeline(steps=[('normalizer', Normalizer(norm='max')),\n", + "Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n", " ('featureunion-1',\n", " FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('rbfsampler',\n", - " RBFSampler(gamma=0.7809991844556,\n", - " n_components=50)),\n", - " ('columnonehotencoder',\n", - " ColumnOneHotEncoder()),\n", - " ('nystroem',\n", - " Nystroem(gamma=0.3179172515929,\n", - " kernel='additive_chi2',\n", - " n_components=80))])),\n", - " ('...\n", - " class_weight='balanced',\n", - " eta0=0.4039854095517,\n", - " l1_ratio=0.0336982783886,\n", - " learning_rate='constant',\n", - " loss='modified_huber',\n", - " n_jobs=1,\n", - " penalty='elasticnet'),\n", - " method='predict'))])),\n", - " ('passthrough',\n", - " Passthrough())])),\n", - " ('mlpclassifier',\n", - " MLPClassifier(alpha=0.0867902302825, hidden_layer_sizes=[35],\n", - " learning_rate='invscaling',\n", - " learning_rate_init=0.0152961651727,\n", - " n_iter_no_change=32))])" + " FeatureUnion(transformer_list=[('kbinsdiscretizer-1',\n", + " KBinsDiscretizer(encode='onehot-dense',\n", + " n_bins=62)),\n", + " ('kbinsdiscretizer-2',\n", + " KBinsDiscretizer(encode='onehot-dense',\n", + " strategy='kmeans')),\n", + " ('fastica',\n", + " FastICA(n_components=39))])),\n", + " ('passthroug...\n", + " feature_types=None, gamma=0.0095679856018,\n", + " grow_policy=None, importance_type=None,\n", + " interaction_constraints=None,\n", + " learning_rate=0.0037432296142, max_bin=None,\n", + " max_cat_threshold=None, max_cat_to_onehot=None,\n", + " max_delta_step=None, max_depth=12,\n", + " max_leaves=None, min_child_weight=2, missing=nan,\n", + " monotone_constraints=None, multi_strategy=None,\n", + " n_estimators=100, n_jobs=1, nthread=1,\n", + " num_parallel_tree=None, ...))])" ] }, - "execution_count": 36, + "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "dynamic_wrapped_classifiers_with_passthrough = tpot2.search_spaces.pipelines.UnionPipeline([\n", - " tpot2.search_spaces.pipelines.DynamicUnionPipeline(wrapped_estimators_cv, max_estimators=4),\n", - " tpot2.config.get_search_space(\"Passthrough\")\n", + "dynamic_wrapped_classifiers_with_passthrough = tpot.search_spaces.pipelines.UnionPipeline([\n", + " tpot.search_spaces.pipelines.DynamicUnionPipeline(wrapped_estimators_cv, max_estimators=4),\n", + " tpot.config.get_search_space(\"Passthrough\")\n", " ])\n", "\n", - "stc_pipeline4 = tpot2.search_spaces.pipelines.SequentialPipeline([\n", - " tpot2.config.get_search_space(\"scalers\"),\n", + "stc_pipeline4 = tpot.search_spaces.pipelines.SequentialPipeline([\n", + " tpot.config.get_search_space(\"scalers\"),\n", " dynamic_transformers_with_passthrough,\n", " dynamic_wrapped_classifiers_with_passthrough,\n", - " tpot2.config.get_search_space(\"classifiers\"),\n", + " tpot.config.get_search_space(\"classifiers\"),\n", "])\n", "\n", "stc_pipeline4.generate().export_pipeline()" @@ -13443,19 +2185,19 @@ "| cross_val_predict_cv | int, cross-validation generator or an iterable, optional | Determines the cross-validation splitting strategy used in inner classifiers or regressors. |\n", "| method | str, optional | The prediction method to use for the inner classifiers or regressors. If 'auto', it will try to use predict_proba, decision_function, or predict in that order. |\n", "\n", - "This search space exports a `tpot2.GraphPipeline`. This is similar to a scikit-learn Pipeline, but for directed acyclic graph pipelines. You can learn more about using this module in Tutorial 6." + "This search space exports a `tpot.GraphPipeline`. This is similar to a scikit-learn Pipeline, but for directed acyclic graph pipelines. You can learn more about using this module in Tutorial 6." ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 46, "metadata": {}, "outputs": [], "source": [ - "graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", ")\n", "\n", @@ -13464,12 +2206,12 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 47, "metadata": {}, "outputs": [ { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -13492,7 +2234,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -13622,7 +2364,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -13637,10 +2379,10 @@ } ], "source": [ - "tree_search_space = tpot2.search_spaces.pipelines.TreePipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + "tree_search_space = tpot.search_spaces.pipelines.TreePipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", ")\n", "\n", @@ -13655,7 +2397,7 @@ "source": [ "## Tips and Tricks\n", "\n", - "* Two very helpful transformers to use with search spaces are `tpot2.buildin_models.Passthrough` and `tpot2.builtin_models.SkipTransformer`. \n", + "* Two very helpful transformers to use with search spaces are `tpot.buildin_models.Passthrough` and `tpot.builtin_models.SkipTransformer`. \n", " Passthrough will simply pass through the exact inputs it receives into the next step. This is particularly useful inside UnionSearchSpace as it allows for both the transformed data as well as the original data to be passed into the next step.\n", " SkipTransformer will always return nothing. This is helpful when inside a union with Passthrough and an optional second method. For example, if you are unsure of whether or not you will need a transformer, you can have SkipTransformer be one option that will skip the transformation step if selected." ] @@ -13669,451 +2411,41 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                FeatureUnion(transformer_list=[('kbinsdiscretizer',\n",
-       "                                                                KBinsDiscretizer(encode='onehot-dense',\n",
-       "                                                                                 n_bins=9,\n",
-       "                                                                                 strategy='uniform')),\n",
-       "                                                               ('quantiletransformer',\n",
-       "                                                                QuantileTransformer(n_quantiles=697))])),\n",
-       "                               ('passthrough', Passthrough())])
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.
" + "
FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                FeatureUnion(transformer_list=[('columnonehotencoder',\n",
+       "                                                                ColumnOneHotEncoder()),\n",
+       "                                                               ('zerocount',\n",
+       "                                                                ZeroCount())])),\n",
+       "                               ('passthrough', Passthrough())])
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": [ "FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('kbinsdiscretizer',\n", - " KBinsDiscretizer(encode='onehot-dense',\n", - " n_bins=9,\n", - " strategy='uniform')),\n", - " ('quantiletransformer',\n", - " QuantileTransformer(n_quantiles=697))])),\n", + " FeatureUnion(transformer_list=[('columnonehotencoder',\n", + " ColumnOneHotEncoder()),\n", + " ('zerocount',\n", + " ZeroCount())])),\n", " ('passthrough', Passthrough())])" ] }, - "execution_count": 41, + "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from tpot2.search_spaces.pipelines import *\n", - "from tpot2.config import get_search_space\n", + "from tpot.search_spaces.pipelines import *\n", + "from tpot.config import get_search_space\n", "\n", "#This FeatureUnion layer will always have at least one transformer selected and will always have one passthrough\n", "transformers_with_passthrough = UnionPipeline([\n", @@ -14134,432 +2466,37 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('featureunion',\n",
+       "
FeatureUnion(transformer_list=[('featureunion',\n",
        "                                FeatureUnion(transformer_list=[('quantiletransformer',\n",
-       "                                                                QuantileTransformer(n_quantiles=842))])),\n",
-       "                               ('passthrough', Passthrough())])
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.
QuantileTransformer(n_quantiles=177)
RBFSampler(gamma=0.995621869472, n_components=36)
Passthrough()
" ], "text/plain": [ "FeatureUnion(transformer_list=[('featureunion',\n", " FeatureUnion(transformer_list=[('quantiletransformer',\n", - " QuantileTransformer(n_quantiles=842))])),\n", + " QuantileTransformer(n_quantiles=177)),\n", + " ('rbfsampler',\n", + " RBFSampler(gamma=0.995621869472,\n", + " n_components=36))])),\n", " ('passthrough', Passthrough())])" ] }, - "execution_count": 42, + "execution_count": 49, "metadata": {}, "output_type": "execute_result" } @@ -14579,456 +2516,60 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 50, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
FeatureUnion(transformer_list=[('featureunion',\n",
+       "
FeatureUnion(transformer_list=[('featureunion',\n",
        "                                FeatureUnion(transformer_list=[('estimatortransformer-1',\n",
-       "                                                                EstimatorTransformer(estimator=LogisticRegression(C=3553.613707181859,\n",
-       "                                                                                                                  max_iter=1000,\n",
-       "                                                                                                                  n_jobs=1,\n",
-       "                                                                                                                  solver='saga'))),\n",
+       "                                                                EstimatorTransformer(estimator=BernoulliNB(alpha=0.0226401717754,\n",
+       "                                                                                                           fit_prior=False))),\n",
        "                                                               ('estimatortransformer-2',\n",
-       "                                                                EstimatorTransformer(estimator=GaussianNB())),\n",
+       "                                                                EstimatorTransformer(estimator=LGBMClassifier(boosting_type='dart',\n",
+       "                                                                                                              max_depth=5,\n",
+       "                                                                                                              n_estimators=49,\n",
+       "                                                                                                              n_jobs=1,\n",
+       "                                                                                                              num_leaves=174,\n",
+       "                                                                                                              verbose=-1))),\n",
        "                                                               ('estimatortransformer-3',\n",
-       "                                                                EstimatorTransformer(estimator=MultinomialNB(alpha=0.0128552259108,\n",
-       "                                                                                                             fit_prior=False)))])),\n",
-       "                               ('passthrough', Passthrough())])
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.
BernoulliNB(alpha=0.0226401717754, fit_prior=False)
BernoulliNB(alpha=0.0226401717754, fit_prior=False)
LGBMClassifier(boosting_type='dart', max_depth=5, n_estimators=49, n_jobs=1,\n",
+       "               num_leaves=174, verbose=-1)
LGBMClassifier(boosting_type='dart', max_depth=5, n_estimators=49, n_jobs=1,\n",
+       "               num_leaves=174, verbose=-1)
QuadraticDiscriminantAnalysis(reg_param=0.6913442155341)
QuadraticDiscriminantAnalysis(reg_param=0.6913442155341)
Passthrough()
" ], "text/plain": [ "FeatureUnion(transformer_list=[('featureunion',\n", " FeatureUnion(transformer_list=[('estimatortransformer-1',\n", - " EstimatorTransformer(estimator=LogisticRegression(C=3553.613707181859,\n", - " max_iter=1000,\n", - " n_jobs=1,\n", - " solver='saga'))),\n", + " EstimatorTransformer(estimator=BernoulliNB(alpha=0.0226401717754,\n", + " fit_prior=False))),\n", " ('estimatortransformer-2',\n", - " EstimatorTransformer(estimator=GaussianNB())),\n", + " EstimatorTransformer(estimator=LGBMClassifier(boosting_type='dart',\n", + " max_depth=5,\n", + " n_estimators=49,\n", + " n_jobs=1,\n", + " num_leaves=174,\n", + " verbose=-1))),\n", " ('estimatortransformer-3',\n", - " EstimatorTransformer(estimator=MultinomialNB(alpha=0.0128552259108,\n", - " fit_prior=False)))])),\n", + " EstimatorTransformer(estimator=QuadraticDiscriminantAnalysis(reg_param=0.6913442155341)))])),\n", " ('passthrough', Passthrough())])" ] }, - "execution_count": 43, + "execution_count": 50, "metadata": {}, "output_type": "execute_result" } @@ -15047,417 +2588,13 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 51, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('normalizer', Normalizer(norm='max')),\n",
+       "
Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n",
        "                ('featureunion-1',\n",
        "                 FeatureUnion(transformer_list=[('featureunion',\n",
        "                                                 FeatureUnion(transformer_list=[('columnonehotencoder',\n",
@@ -15469,11 +2606,10 @@
        "                                                 SkipTransformer()),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
-       "                ('baggingclassifier',\n",
-       "                 BaggingClassifier(bootstrap_features=True,\n",
-       "                                   max_features=0.6083887402217,\n",
-       "                                   max_samples=0.440010144908, n_estimators=24,\n",
-       "                                   n_jobs=1, oob_score=True))])
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.
ColumnOneHotEncoder()
Passthrough()
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
LGBMClassifier(boosting_type='dart', max_depth=2, n_estimators=47, n_jobs=1,\n",
+       "               num_leaves=103, verbose=-1)
" ], "text/plain": [ - "Pipeline(steps=[('normalizer', Normalizer(norm='max')),\n", + "Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n", " ('featureunion-1',\n", " FeatureUnion(transformer_list=[('featureunion',\n", " FeatureUnion(transformer_list=[('columnonehotencoder',\n", @@ -15510,14 +2644,13 @@ " SkipTransformer()),\n", " ('passthrough',\n", " Passthrough())])),\n", - " ('baggingclassifier',\n", - " BaggingClassifier(bootstrap_features=True,\n", - " max_features=0.6083887402217,\n", - " max_samples=0.440010144908, n_estimators=24,\n", - " n_jobs=1, oob_score=True))])" + " ('lgbmclassifier',\n", + " LGBMClassifier(boosting_type='dart', max_depth=2,\n", + " n_estimators=47, n_jobs=1, num_leaves=103,\n", + " verbose=-1))])" ] }, - "execution_count": 44, + "execution_count": 51, "metadata": {}, "output_type": "execute_result" } @@ -15549,9 +2682,9 @@ "| 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", - "Rather than create your own search space, you can simply pass the string into the `search_space` param. Alternatively, you can access tpot2.config.`template_search_spaces.get_template_search_spaces` directly which offers a few more customizable options for each template including `cross_val_predict_cv` and whether or not stacked classifiers/regressors are allowed. Or you can copy the code and customize it manually!\n", + "Rather than create your own search space, you can simply pass the string into the `search_space` param. Alternatively, you can access tpot.config.`template_search_spaces.get_template_search_spaces` directly which offers a few more customizable options for each template including `cross_val_predict_cv` and whether or not stacked classifiers/regressors are allowed. Or you can copy the code and customize it manually!\n", "\n", - " `tpot2.config.template_search_spaces.get_template_search_spaces`\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", @@ -15582,537 +2715,138 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 53, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('passthrough', Passthrough()),\n",
-       "                ('variancethreshold',\n",
-       "                 VarianceThreshold(threshold=0.0014368451974)),\n",
+       "
Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n",
+       "                ('selectfrommodel',\n",
+       "                 SelectFromModel(estimator=ExtraTreesClassifier(class_weight='balanced',\n",
+       "                                                                max_features=0.2467678448354,\n",
+       "                                                                min_samples_leaf=4,\n",
+       "                                                                min_samples_split=9,\n",
+       "                                                                n_jobs=1),\n",
+       "                                 threshold=0.0021738791638)),\n",
        "                ('featureunion-1',\n",
        "                 FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                                 FeatureUnion(transformer_list=[('powertransformer',\n",
-       "                                                                                 PowerTransformer()),\n",
-       "                                                                                ('nystroem',\n",
-       "                                                                                 Nystroem(gamma=0.8842695866347,\n",
-       "                                                                                          kernel='sigmoid',\n",
-       "                                                                                          n_components=7))])),\n",
-       "                                                ('passthrough',\n",
-       "                                                 Passth...\n",
-       "                 FeatureUnion(transformer_list=[('featureunion',\n",
+       "                                                 FeatureUnion(transformer_list=[('columnon...\n",
        "                                                 FeatureUnion(transformer_list=[('estimatortransformer',\n",
        "                                                                                 EstimatorTransformer(cross_val_predict_cv=5,\n",
-       "                                                                                                      estimator=BaggingClassifier(bootstrap=False,\n",
-       "                                                                                                                                  max_features=0.2031842311627,\n",
-       "                                                                                                                                  max_samples=0.4743985327407,\n",
-       "                                                                                                                                  n_estimators=89,\n",
-       "                                                                                                                                  n_jobs=1)))])),\n",
+       "                                                                                                      estimator=DecisionTreeClassifier(class_weight='balanced',\n",
+       "                                                                                                                                       max_depth=8,\n",
+       "                                                                                                                                       max_features='sqrt',\n",
+       "                                                                                                                                       min_samples_leaf=11,\n",
+       "                                                                                                                                       min_samples_split=4)))])),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
-       "                ('bernoullinb', BernoulliNB(alpha=4.2777686142181))])
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.
DecisionTreeClassifier(class_weight='balanced', max_depth=8,\n",
+       "                       max_features='sqrt', min_samples_leaf=11,\n",
+       "                       min_samples_split=4)
DecisionTreeClassifier(class_weight='balanced', max_depth=8,\n",
+       "                       max_features='sqrt', min_samples_leaf=11,\n",
+       "                       min_samples_split=4)
Passthrough()
LogisticRegression(C=54.4375368217274, class_weight='balanced', max_iter=1000,\n",
+       "                   n_jobs=1, penalty='l1', solver='saga')
" ], "text/plain": [ - "Pipeline(steps=[('passthrough', Passthrough()),\n", - " ('variancethreshold',\n", - " VarianceThreshold(threshold=0.0014368451974)),\n", + "Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n", + " ('selectfrommodel',\n", + " SelectFromModel(estimator=ExtraTreesClassifier(class_weight='balanced',\n", + " max_features=0.2467678448354,\n", + " min_samples_leaf=4,\n", + " min_samples_split=9,\n", + " n_jobs=1),\n", + " threshold=0.0021738791638)),\n", " ('featureunion-1',\n", " FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('powertransformer',\n", - " PowerTransformer()),\n", - " ('nystroem',\n", - " Nystroem(gamma=0.8842695866347,\n", - " kernel='sigmoid',\n", - " n_components=7))])),\n", - " ('passthrough',\n", - " Passth...\n", - " FeatureUnion(transformer_list=[('featureunion',\n", + " FeatureUnion(transformer_list=[('columnon...\n", " FeatureUnion(transformer_list=[('estimatortransformer',\n", " EstimatorTransformer(cross_val_predict_cv=5,\n", - " estimator=BaggingClassifier(bootstrap=False,\n", - " max_features=0.2031842311627,\n", - " max_samples=0.4743985327407,\n", - " n_estimators=89,\n", - " n_jobs=1)))])),\n", + " estimator=DecisionTreeClassifier(class_weight='balanced',\n", + " max_depth=8,\n", + " max_features='sqrt',\n", + " min_samples_leaf=11,\n", + " min_samples_split=4)))])),\n", " ('passthrough',\n", " Passthrough())])),\n", - " ('bernoullinb', BernoulliNB(alpha=4.2777686142181))])" + " ('logisticregression',\n", + " LogisticRegression(C=54.4375368217274, class_weight='balanced',\n", + " max_iter=1000, n_jobs=1, penalty='l1',\n", + " solver='saga'))])" ] }, - "execution_count": 45, + "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "linear_search_space = tpot2.config.template_search_spaces.get_template_search_spaces(\"linear\", inner_predictors=True, cross_val_predict_cv=5)\n", + "linear_search_space = tpot.config.template_search_spaces.get_template_search_spaces(\"linear\", inner_predictors=True, cross_val_predict_cv=5)\n", "linear_search_space.generate().export_pipeline()" ] }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 54, "metadata": {}, "outputs": [], "source": [ - "linear_search_space = tpot2.config.template_search_spaces.get_template_search_spaces(\"linear\", inner_predictors=True, cross_val_predict_cv=5)\n", - "linear_est = tpot2.TPOTEstimator(\n", + "linear_search_space = tpot.config.template_search_spaces.get_template_search_spaces(\"linear\", inner_predictors=True, cross_val_predict_cv=5)\n", + "linear_est = tpot.TPOTEstimator(\n", " search_space = linear_search_space,\n", - " scorers=['roc_auc_ovr',tpot2.objectives.complexity_scorer],\n", + " scorers=['roc_auc_ovr',tpot.objectives.complexity_scorer],\n", " scorers_weights=[1,-1],\n", " classification=True,\n", " verbose=1,\n", " )\n", "\n", "#alternatively, you can use the template search space to generate a pipeline\n", - "linear_est = tpot2.TPOTEstimator(\n", + "linear_est = tpot.TPOTEstimator(\n", " search_space = \"linear\",\n", - " scorers=['roc_auc_ovr',tpot2.objectives.complexity_scorer],\n", + " scorers=['roc_auc_ovr',tpot.objectives.complexity_scorer],\n", " scorers_weights=[1,-1],\n", " n_jobs=32,\n", " classification=True,\n", @@ -16131,7 +2865,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 55, "metadata": {}, "outputs": [], "source": [ @@ -16151,450 +2885,46 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 57, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 8it [01:44, 13.07s/it]\n", - "/home/perib/miniconda3/envs/myenv/lib/python3.10/site-packages/sklearn/preprocessing/_data.py:2785: UserWarning: n_quantiles (911) is greater than the total number of samples (284). n_quantiles is set to n_samples.\n", + "Generation: : 4it [01:14, 18.59s/it]\n", + "/Users/matsumoton/miniconda3/envs/tpot2_310/lib/python3.10/site-packages/sklearn/preprocessing/_data.py:2667: UserWarning: n_quantiles (583) is greater than the total number of samples (284). n_quantiles is set to n_samples.\n", " warnings.warn(\n" ] }, { "data": { "text/html": [ - "
TPOTEstimator(classification=True, cv=5, early_stop=2, max_time_mins=10,\n",
+       "
TPOTEstimator(classification=True, cv=5, early_stop=2, max_time_mins=10,\n",
        "              n_jobs=4,\n",
        "              scorers=['roc_auc_ovr',\n",
-       "                       <function complexity_scorer at 0x78eb3afa4160>],\n",
+       "                       <function complexity_scorer at 0x1596f5900>],\n",
        "              scorers_weights=[1.0, -1.0],\n",
-       "              search_space=<tpot2.search_spaces.pipelines.sequential.SequentialPipeline object at 0x78eb39022d10>,\n",
-       "              verbose=2)
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": [ "TPOTEstimator(classification=True, cv=5, early_stop=2, max_time_mins=10,\n", " n_jobs=4,\n", " scorers=['roc_auc_ovr',\n", - " ],\n", + " ],\n", " scorers_weights=[1.0, -1.0],\n", - " search_space=,\n", + " search_space=,\n", " verbose=2)" ] }, - "execution_count": 48, + "execution_count": 57, "metadata": {}, "output_type": "execute_result" } @@ -16603,8 +2933,8 @@ "selected_search_space = all_search_spaces[\"stc_pipeline\"] #change this to select a different search space\n", "\n", "\n", - "est = tpot2.TPOTEstimator(\n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + "est = tpot.TPOTEstimator(\n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " classification = True,\n", " cv = 5,\n", @@ -16621,14 +2951,14 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 58, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "auroc score 0.9899335933382524\n" + "auroc score 0.9949070671007035\n" ] } ], @@ -16642,445 +2972,52 @@ }, { "cell_type": "code", - "execution_count": 50, + "execution_count": 59, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('selectfwe', SelectFwe(alpha=0.0336222333869)),\n",
-       "                ('quantiletransformer',\n",
-       "                 QuantileTransformer(n_quantiles=911,\n",
-       "                                     output_distribution='normal')),\n",
-       "                ('quadraticdiscriminantanalysis',\n",
-       "                 QuadraticDiscriminantAnalysis(reg_param=0.3209042101754))])
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.
" + "
Pipeline(steps=[('selectpercentile',\n",
+       "                 SelectPercentile(percentile=76.8135147746577)),\n",
+       "                ('quantiletransformer', QuantileTransformer(n_quantiles=583)),\n",
+       "                ('mlpclassifier',\n",
+       "                 MLPClassifier(alpha=0.0030912429015,\n",
+       "                               hidden_layer_sizes=[125, 125, 125],\n",
+       "                               learning_rate='adaptive',\n",
+       "                               learning_rate_init=0.0176311093579,\n",
+       "                               n_iter_no_change=32))])
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=[('selectfwe', SelectFwe(alpha=0.0336222333869)),\n", - " ('quantiletransformer',\n", - " QuantileTransformer(n_quantiles=911,\n", - " output_distribution='normal')),\n", - " ('quadraticdiscriminantanalysis',\n", - " QuadraticDiscriminantAnalysis(reg_param=0.3209042101754))])" + "Pipeline(steps=[('selectpercentile',\n", + " SelectPercentile(percentile=76.8135147746577)),\n", + " ('quantiletransformer', QuantileTransformer(n_quantiles=583)),\n", + " ('mlpclassifier',\n", + " MLPClassifier(alpha=0.0030912429015,\n", + " hidden_layer_sizes=[125, 125, 125],\n", + " learning_rate='adaptive',\n", + " learning_rate_init=0.0176311093579,\n", + " n_iter_no_change=32))])" ] }, - "execution_count": 50, + "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "#plot the best pipeline\n", - "if isinstance(est.fitted_pipeline_, tpot2.GraphPipeline):\n", + "if isinstance(est.fitted_pipeline_, tpot.GraphPipeline):\n", " est.fitted_pipeline_.plot()\n", " \n", "est.fitted_pipeline_" @@ -17097,7 +3034,7 @@ }, { "cell_type": "code", - "execution_count": 51, + "execution_count": 60, "metadata": {}, "outputs": [ { @@ -17106,7 +3043,7 @@ "0.04690299241236334" ] }, - "execution_count": 51, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -17115,7 +3052,7 @@ "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", - "import tpot2\n", + "import tpot\n", "\n", "#in practice, cross validation is likely better, but this simple example is fine for demonstration purposes\n", "def rmse_obective(est, X, missing_add=.2, rng=1, fitted=False):\n", @@ -17141,435 +3078,53 @@ }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 61, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
KNNImputer(n_neighbors=99, weights='distance')
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.
" + "
IterativeImputer(estimator=ExtraTreesRegressor(bootstrap=True,\n",
+       "                                               criterion='friedman_mse',\n",
+       "                                               max_features=0.4319398243887,\n",
+       "                                               min_samples_leaf=18,\n",
+       "                                               min_samples_split=21, n_jobs=1),\n",
+       "                 imputation_order='random', initial_strategy='most_frequent',\n",
+       "                 n_nearest_features=2)
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": [ - "KNNImputer(n_neighbors=99, weights='distance')" + "IterativeImputer(estimator=ExtraTreesRegressor(bootstrap=True,\n", + " criterion='friedman_mse',\n", + " max_features=0.4319398243887,\n", + " min_samples_leaf=18,\n", + " min_samples_split=21, n_jobs=1),\n", + " imputation_order='random', initial_strategy='most_frequent',\n", + " n_nearest_features=2)" ] }, - "execution_count": 52, + "execution_count": 61, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "import tpot2.search_spaces\n", + "import tpot.search_spaces\n", "from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal\n", "\n", "#set up an imputation search space that includes simple imputer, knn imputer, and iterative imputer (with an optimized ExtraTreesRegressor)\n", "\n", - "simple_imputer = tpot2.config.get_search_space(\"SimpleImputer\")\n", - "knn_imputer = tpot2.config.get_search_space(\"KNNImputer\")\n", + "simple_imputer = tpot.config.get_search_space(\"SimpleImputer\")\n", + "knn_imputer = tpot.config.get_search_space(\"KNNImputer\")\n", "\n", "space = ConfigurationSpace({ 'initial_strategy' : Categorical('initial_strategy', \n", " ['mean', 'median', \n", @@ -17582,15 +3137,15 @@ "})\n", "\n", "# This optimizes both the iterative imputer parameters and the ExtraTreesRegressor parameters\n", - "iterative_imputer_sp = tpot2.search_spaces.pipelines.WrapperPipeline(\n", + "iterative_imputer_sp = tpot.search_spaces.pipelines.WrapperPipeline(\n", " method = sklearn.impute.IterativeImputer,\n", " space = space,\n", - " estimator_search_space = tpot2.config.get_search_space(\"ExtraTreesRegressor\"),\n", + " estimator_search_space = tpot.config.get_search_space(\"ExtraTreesRegressor\"),\n", ")\n", "#this is equivalent to\n", - "# iterative_imputer_sp = tpot2.config.get_search_space(\"IterativeImputer_learned_estimators\")\n", + "# iterative_imputer_sp = tpot.config.get_search_space(\"IterativeImputer_learned_estimators\")\n", "\n", - "imputation_search_space = tpot2.search_spaces.pipelines.ChoicePipeline(\n", + "imputation_search_space = tpot.search_spaces.pipelines.ChoicePipeline(\n", " search_spaces = [simple_imputer, knn_imputer, iterative_imputer_sp],\n", ")\n", "imputation_search_space.generate().export_pipeline()" @@ -17598,16 +3153,16 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 62, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/home/perib/Projects/common/Projects/TPOT_Dev/tpot2/tpot2/tpot_estimator/estimator.py:504: UserWarning: Labels are not encoded as ints from 0 to N. For compatibility with some classifiers such as sklearn, TPOT has encoded y with the sklearn LabelEncoder. When using pipelines outside the main TPOT estimator class, you can encode the labels with est.label_encoder_\n", + "/Users/matsumoton/Git/tpot2/tpot/tpot_estimator/estimator.py:534: UserWarning: Labels are not encoded as ints from 0 to N. For compatibility with some classifiers such as sklearn, TPOT has encoded y with the sklearn LabelEncoder. When using pipelines outside the main TPOT estimator class, you can encode the labels with est.label_encoder_\n", " warnings.warn(\"Labels are not encoded as ints from 0 to N. For compatibility with some classifiers such as sklearn, TPOT has encoded y with the sklearn LabelEncoder. When using pipelines outside the main TPOT estimator class, you can encode the labels with est.label_encoder_\")\n", - "Generation: : 1it [00:24, 24.65s/it]" + "Generation: : 1it [00:20, 20.06s/it]" ] }, { @@ -17615,14 +3170,14 @@ "output_type": "stream", "text": [ "Generation: 1\n", - "Best rmse score: 0.034633208054417206\n" + "Best rmse score: 0.03477479002890079\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 2it [00:47, 23.42s/it]" + "Generation: : 2it [00:40, 20.01s/it]" ] }, { @@ -17630,14 +3185,14 @@ "output_type": "stream", "text": [ "Generation: 2\n", - "Best rmse score: 0.034633208054417206\n" + "Best rmse score: 0.03477479002890079\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 3it [01:12, 24.23s/it]" + "Generation: : 3it [01:10, 24.70s/it]" ] }, { @@ -17645,14 +3200,14 @@ "output_type": "stream", "text": [ "Generation: 3\n", - "Best rmse score: 0.03429318271103084\n" + "Best rmse score: 0.03426605985084626\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 3it [01:40, 33.47s/it]" + "Generation: : 3it [01:39, 33.02s/it]" ] }, { @@ -17660,7 +3215,7 @@ "output_type": "stream", "text": [ "Generation: 4\n", - "Best rmse score: 0.03429318271103084\n", + "Best rmse score: 0.03426605985084626\n", "Early stop\n" ] }, @@ -17674,415 +3229,12 @@ { "data": { "text/html": [ - "
TPOTEstimator(classification=True, early_stop=2, max_eval_time_mins=300,\n",
+       "
TPOTEstimator(classification=True, early_stop=2, max_eval_time_mins=300,\n",
        "              max_time_mins=10, n_jobs=20, objective_function_names=['rmse'],\n",
-       "              other_objective_functions=[functools.partial(<function rmse_obective at 0x78eb3890c700>, X=array([[ 0.03807591,  0.05068012,  0.06169621, ..., -0.00259226,\n",
+       "              other_objective_functions=[functools.partial(<function rmse_obective at 0x34e15d900>, X=array([[ 0.03807591,  0.05068012,  0.06169621, ..., -0.00259226,\n",
        "         0.01990749, -0.01764613],\n",
-       "       [-0.00188202, -0.04464164, -0.05147406, ..., -0.0394933...\n",
+       "       [-0.00188202, -0.04464164, -0.05147406, ..., -0.03949338,\n",
+       "        -...\n",
        "        -0.04688253,  0.01549073],\n",
        "       [-0.04547248, -0.04464164,  0.03906215, ...,  0.02655962,\n",
        "         0.04452873, -0.02593034],\n",
@@ -18090,12 +3242,13 @@
        "        -0.00422151,  0.00306441]]), missing_add=0.2)],\n",
        "              other_objective_functions_weights=[-1], scorers=[],\n",
        "              scorers_weights=[],\n",
-       "              search_space=<tpot2.search_spaces.pipelines.choice.ChoicePipeline object at 0x78eb37c9f250>,\n",
-       "              verbose=3)
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": [ "TPOTEstimator(classification=True, early_stop=2, max_eval_time_mins=300,\n", " max_time_mins=10, n_jobs=20, objective_function_names=['rmse'],\n", - " other_objective_functions=[functools.partial(, X=array([[ 0.03807591, 0.05068012, 0.06169621, ..., -0.00259226,\n", + " other_objective_functions=[functools.partial(, X=array([[ 0.03807591, 0.05068012, 0.06169621, ..., -0.00259226,\n", " 0.01990749, -0.01764613],\n", - " [-0.00188202, -0.04464164, -0.05147406, ..., -0.0394933...\n", + " [-0.00188202, -0.04464164, -0.05147406, ..., -0.03949338,\n", + " -...\n", " -0.04688253, 0.01549073],\n", " [-0.04547248, -0.04464164, 0.03906215, ..., 0.02655962,\n", " 0.04452873, -0.02593034],\n", @@ -18119,11 +3273,11 @@ " -0.00422151, 0.00306441]]), missing_add=0.2)],\n", " other_objective_functions_weights=[-1], scorers=[],\n", " scorers_weights=[],\n", - " search_space=,\n", + " search_space=,\n", " verbose=3)" ] }, - "execution_count": 54, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -18133,7 +3287,7 @@ "\n", "final_objective = partial(rmse_obective, X=X, missing_add=.2)\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " scorers = [],\n", " scorers_weights = [],\n", " other_objective_functions = [final_objective],\n", @@ -18153,14 +3307,14 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "final rmse score 0.028453289651831883\n" + "final rmse score 0.030640000771615945\n" ] } ], @@ -18172,432 +3326,30 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 64, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
IterativeImputer(estimator=ExtraTreesRegressor(max_features=0.7116178998798,\n",
-       "                                               min_samples_split=16),\n",
-       "                 imputation_order='descending', initial_strategy='median',\n",
-       "                 n_nearest_features=10)
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.
" + "
IterativeImputer(estimator=ExtraTreesRegressor(max_features=0.7142652800679,\n",
+       "                                               min_samples_leaf=2,\n",
+       "                                               min_samples_split=20, n_jobs=1),\n",
+       "                 imputation_order='random', n_nearest_features=9)
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": [ - "IterativeImputer(estimator=ExtraTreesRegressor(max_features=0.7116178998798,\n", - " min_samples_split=16),\n", - " imputation_order='descending', initial_strategy='median',\n", - " n_nearest_features=10)" + "IterativeImputer(estimator=ExtraTreesRegressor(max_features=0.7142652800679,\n", + " min_samples_leaf=2,\n", + " min_samples_split=20, n_jobs=1),\n", + " imputation_order='random', n_nearest_features=9)" ] }, - "execution_count": 56, + "execution_count": 64, "metadata": {}, "output_type": "execute_result" } @@ -18615,453 +3367,47 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 65, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Generation: : 3it [01:30, 30.21s/it]\n", - "/home/perib/miniconda3/envs/myenv/lib/python3.10/site-packages/sklearn/discriminant_analysis.py:947: UserWarning: Variables are collinear\n", - " warnings.warn(\"Variables are collinear\")\n", - "/home/perib/miniconda3/envs/myenv/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", + "Generation: : 11it [10:00, 54.61s/it]\n", + "/Users/matsumoton/miniconda3/envs/tpot2_310/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", " warnings.warn(\n" ] }, { "data": { "text/html": [ - "
TPOTEstimator(classification=True, cv=5, early_stop=2, max_eval_time_mins=300,\n",
+       "
TPOTEstimator(classification=True, cv=5, max_eval_time_mins=300,\n",
        "              max_time_mins=10, n_jobs=20, scorers=['roc_auc'],\n",
        "              scorers_weights=[1],\n",
-       "              search_space=<tpot2.search_spaces.pipelines.sequential.SequentialPipeline object at 0x78eb2654aec0>,\n",
-       "              verbose=2)
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": [ - "TPOTEstimator(classification=True, cv=5, early_stop=2, max_eval_time_mins=300,\n", + "TPOTEstimator(classification=True, cv=5, max_eval_time_mins=300,\n", " max_time_mins=10, n_jobs=20, scorers=['roc_auc'],\n", " scorers_weights=[1],\n", - " search_space=,\n", + " search_space=,\n", " verbose=2)" ] }, - "execution_count": 57, + "execution_count": 65, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from tpot2.search_spaces.pipelines import *\n", - "from tpot2.config import get_search_space\n", + "from tpot.search_spaces.pipelines import *\n", + "from tpot.config import get_search_space\n", "\n", "selectors = get_search_space([\"selectors_classification\", \"Passthrough\"])\n", "estimators = get_search_space([\"classifiers\"])\n", @@ -19069,7 +3415,7 @@ "\n", "# this allows us to wrap the classifiers in the EstimatorTransformer\n", "# this is necessary so that classifiers can be used inside of sklearn pipelines\n", - "wrapped_estimators = WrapperPipeline(tpot2.builtin_modules.EstimatorTransformer, {}, estimators)\n", + "wrapped_estimators = WrapperPipeline(tpot.builtin_modules.EstimatorTransformer, {}, estimators)\n", "\n", "scalers = get_search_space([\"scalers\",\"Passthrough\"])\n", "\n", @@ -19099,7 +3445,7 @@ " estimators,\n", " ])\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " scorers = [\"roc_auc\"],\n", " scorers_weights = [1],\n", " classification = True,\n", @@ -19116,507 +3462,70 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 66, "metadata": {}, "outputs": [ { "data": { "text/html": [ - "
Pipeline(steps=[('standardscaler', StandardScaler()),\n",
-       "                ('passthrough', Passthrough()),\n",
+       "
Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n",
+       "                ('variancethreshold',\n",
+       "                 VarianceThreshold(threshold=0.000155199293)),\n",
        "                ('featureunion-1',\n",
-       "                 FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                                 FeatureUnion(transformer_list=[('columnonehotencoder',\n",
-       "                                                                                 ColumnOneHotEncoder())])),\n",
+       "                 FeatureUnion(transformer_list=[('skiptransformer',\n",
+       "                                                 SkipTransformer()),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
        "                ('featureunion-2',\n",
-       "                 FeatureUnion(transformer_list=[('featureunion',\n",
-       "                                                 FeatureUnion(transformer_...\n",
-       "                                                                                ('estimatortransformer-2',\n",
-       "                                                                                 EstimatorTransformer(estimator=DecisionTreeClassifier(max_depth=16,\n",
-       "                                                                                                                                       max_features='log2',\n",
-       "                                                                                                                                       min_samples_leaf=9,\n",
-       "                                                                                                                                       min_samples_split=7)))])),\n",
+       "                 FeatureUnion(transformer_list=[('skiptransformer',\n",
+       "                                                 SkipTransformer()),\n",
        "                                                ('passthrough',\n",
        "                                                 Passthrough())])),\n",
-       "                ('mlpclassifier',\n",
-       "                 MLPClassifier(activation='tanh', alpha=0.0015036151556,\n",
-       "                               hidden_layer_sizes=[435],\n",
-       "                               learning_rate='adaptive',\n",
-       "                               learning_rate_init=0.0002156053435,\n",
-       "                               n_iter_no_change=32))])
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.
MaxAbsScaler()
VarianceThreshold(threshold=0.000155199293)
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
FeatureUnion(transformer_list=[('skiptransformer', SkipTransformer()),\n",
+       "                               ('passthrough', Passthrough())])
SkipTransformer()
Passthrough()
LogisticRegression(C=33.705420509428, l1_ratio=0.5608877560576, max_iter=1000,\n",
+       "                   n_jobs=1, penalty='elasticnet', solver='saga')
" ], "text/plain": [ - "Pipeline(steps=[('standardscaler', StandardScaler()),\n", - " ('passthrough', Passthrough()),\n", + "Pipeline(steps=[('maxabsscaler', MaxAbsScaler()),\n", + " ('variancethreshold',\n", + " VarianceThreshold(threshold=0.000155199293)),\n", " ('featureunion-1',\n", - " FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_list=[('columnonehotencoder',\n", - " ColumnOneHotEncoder())])),\n", + " FeatureUnion(transformer_list=[('skiptransformer',\n", + " SkipTransformer()),\n", " ('passthrough',\n", " Passthrough())])),\n", " ('featureunion-2',\n", - " FeatureUnion(transformer_list=[('featureunion',\n", - " FeatureUnion(transformer_...\n", - " ('estimatortransformer-2',\n", - " EstimatorTransformer(estimator=DecisionTreeClassifier(max_depth=16,\n", - " max_features='log2',\n", - " min_samples_leaf=9,\n", - " min_samples_split=7)))])),\n", + " FeatureUnion(transformer_list=[('skiptransformer',\n", + " SkipTransformer()),\n", " ('passthrough',\n", " Passthrough())])),\n", - " ('mlpclassifier',\n", - " MLPClassifier(activation='tanh', alpha=0.0015036151556,\n", - " hidden_layer_sizes=[435],\n", - " learning_rate='adaptive',\n", - " learning_rate_init=0.0002156053435,\n", - " n_iter_no_change=32))])" + " ('logisticregression',\n", + " LogisticRegression(C=33.705420509428, l1_ratio=0.5608877560576,\n", + " max_iter=1000, n_jobs=1,\n", + " penalty='elasticnet', solver='saga'))])" ] }, - "execution_count": 58, + "execution_count": 66, "metadata": {}, "output_type": "execute_result" } @@ -19628,7 +3537,7 @@ ], "metadata": { "kernelspec": { - "display_name": "myenv", + "display_name": "tpot2_310", "language": "python", "name": "python3" }, @@ -19642,7 +3551,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.14" + "version": "3.10.13" } }, "nbformat": 4, diff --git a/Tutorial/3_Feature_Set_Selector.ipynb b/Tutorial/3_Feature_Set_Selector.ipynb index 5b76ba4e..ec8e9afe 100644 --- a/Tutorial/3_Feature_Set_Selector.ipynb +++ b/Tutorial/3_Feature_Set_Selector.ipynb @@ -4,9 +4,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Genetic Feature Selection nodes in TPOT2\n", + "# Genetic Feature Selection nodes in TPOT\n", "\n", - "TPOT2 can use evolutionary algorithms to optimize feature selection simultaneously with pipeline optimization. It includes two node search spaces with different feature selection strategies: FSSNode and GeneticFeatureSelectorNode. \n", + "TPOT can use evolutionary algorithms to optimize feature selection simultaneously with pipeline optimization. It includes two node search spaces with different feature selection strategies: FSSNode and GeneticFeatureSelectorNode. \n", "\n", "1. FSSNode - (Feature Set Selector) This node is useful if you have a list of predefined feature sets you want to select from. Each FeatureSetSelector Node will select a single group of features to be passed to the next step in the pipeline. Note that FSSNode does not create its own subset of features and does not mix/match multiple predefined feature sets.\n", "\n", @@ -16,9 +16,9 @@ "\n", "It may also be beneficial to pair these search spaces with a secondary objective function to minimize complexity. That would encourage TPOT to try to produce the simplest pipeline with the fewest number of features.\n", "\n", - "tpot2.objectives.number_of_nodes_objective - This can be used as an other_objective_function that counts the number of nodes.\n", + "tpot.objectives.number_of_nodes_objective - This can be used as an other_objective_function that counts the number of nodes.\n", "\n", - "tpot2.objectives.complexity_scorer - This is a scorer that tries to count the total number of learned parameters (number of coefficients, number of nodes in decision trees, etc.).\n" + "tpot.objectives.complexity_scorer - This is a scorer that tries to count the total number of learned parameters (number of coefficients, number of nodes in decision trees, etc.).\n" ] }, { @@ -75,7 +75,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "#make a dataframe with columns a,b,c,d,e,f\n", @@ -84,7 +84,7 @@ "data = np.repeat([np.arange(6)],10,0)\n", "\n", "df = pd.DataFrame(data,columns=['a','b','c','d','e','f'])\n", - "fss = tpot2.builtin_modules.FeatureSetSelector(name='test',sel_subset=['a','b','c'])\n", + "fss = tpot.builtin_modules.FeatureSetSelector(name='test',sel_subset=['a','b','c'])\n", "\n", "print(\"original DataFrame\")\n", "print(df)\n", @@ -296,18 +296,18 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", "import pandas as pd\n", - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", - "from tpot2.search_spaces.nodes import *\n", - "from tpot2.search_spaces.pipelines import *\n", - "from tpot2.config import get_search_space\n", + "from tpot.search_spaces.nodes import *\n", + "from tpot.search_spaces.pipelines import *\n", + "from tpot.config import get_search_space\n", "\n", "\n", "X, y = sklearn.datasets.make_classification(n_samples=1000, n_features=6, n_informative=6, n_redundant=0, n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)\n", @@ -1817,8 +1817,8 @@ "fss_and_classifier_search_space = SequentialPipeline([fss_search_space, classification_search_space])\n", "\n", "\n", - "est = tpot2.TPOTEstimator(generations=5, \n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + "est = tpot.TPOTEstimator(generations=5, \n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " n_jobs=32,\n", " classification=True,\n", @@ -3841,10 +3841,10 @@ } ], "source": [ - "graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", " leaf_search_space = fss_search_space,\n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", " max_size = 10,\n", ")\n", "\n", @@ -3881,7 +3881,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", @@ -3889,8 +3889,8 @@ "\n", "final_classification_search_space = SequentialPipeline([dynamic_fss_space, classification_search_space])\n", "\n", - "est = tpot2.TPOTEstimator(generations=5, \n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + "est = tpot.TPOTEstimator(generations=5, \n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " n_jobs=32,\n", " classification=True,\n", @@ -4938,13 +4938,13 @@ } ], "source": [ - "linear_search_space = tpot2.config.template_search_spaces.get_template_search_spaces(\"linear\", classification=True)\n", + "linear_seatpot.onfig.ttpot.config.template_search_spaces.get_template_search_spaces(\"linear\", classification=True)\n", "fss_and_linear_search_space = SequentialPipeline([fss_search_space, linear_search_space])\n", "\n", - "# est = tpot2.TPOTEstimator( \n", + "# est = tpot.TPOTEstimator( \n", "# population_size=32,\n", "# generations=10, \n", - "# scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + "# scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", "# scorers_weights=[1.0, -1.0],\n", "# other_objective_functions=[number_of_selected_features],\n", "# other_objective_functions_weights = [-1],\n", @@ -4975,9 +4975,9 @@ "outputs": [], "source": [ "dynamic_transformers = DynamicUnionPipeline(get_search_space(\"all_transformers\"), max_estimators=4)\n", - "dynamic_transformers_with_passthrough = tpot2.search_spaces.pipelines.UnionPipeline([\n", + "dynamic_transformers_with_passthrough = tpot.search_spaces.pipelines.UnionPipeline([\n", " dynamic_transformers,\n", - " tpot2.config.get_search_space(\"Passthrough\")],\n", + " tpot.config.get_search_space(\"Passthrough\")],\n", " )\n", "multi_step_engineering = DynamicLinearPipeline(dynamic_transformers_with_passthrough, max_length=4)\n", "fss_engineering_search_space = SequentialPipeline([fss_search_space, multi_step_engineering])\n", @@ -5683,7 +5683,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LogisticRegression\n", @@ -5694,7 +5694,7 @@ " \"group_three\" : ['g','h','i'],\n", " }\n", "\n", - "fss_search_space = tpot2.search_spaces.nodes.FSSNode(subsets=subsets)\n", + "fss_search_space = tpot.search_spaces.nodes.FSSNode(subsets=subsets)\n", "\n", "selector = fss_search_space.generate(rng=1).export_pipeline()\n", "selector.set_output(transform=\"pandas\")\n", @@ -5835,7 +5835,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LogisticRegression\n", @@ -5843,7 +5843,7 @@ "\n", "subsets = [['a','b','c'],['d','e','f'],['g','h','i']]\n", "\n", - "fss_search_space = tpot2.search_spaces.nodes.FSSNode(subsets=subsets)\n", + "fss_search_space = tpot.search_spaces.nodes.FSSNode(subsets=subsets)\n", "\n", "selector = fss_search_space.generate(rng=1).export_pipeline()\n", "selector.set_output(transform=\"pandas\")\n", @@ -5986,7 +5986,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LogisticRegression\n", @@ -6000,7 +6000,7 @@ "three,g,h,i\n", "'''\n", "\n", - "fss_search_space = tpot2.search_spaces.nodes.FSSNode(subsets=subsets)\n", + "fss_search_space = tpot.search_spaces.nodes.FSSNode(subsets=subsets)\n", "\n", "selector = fss_search_space.generate(rng=1).export_pipeline()\n", "selector.set_output(transform=\"pandas\")\n", @@ -6041,7 +6041,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", @@ -6079,7 +6079,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LogisticRegression\n", @@ -6090,7 +6090,7 @@ " \"group_three\" : [6,7,8],\n", " }\n", "\n", - "fss_search_space = tpot2.search_spaces.nodes.FSSNode(subsets=subsets)\n", + "fss_search_space = tpot.search_spaces.nodes.FSSNode(subsets=subsets)\n", "selector = fss_search_space.generate(rng=1).export_pipeline()\n", "selector.fit(X_train)\n", "selector.transform(X_train)" @@ -6102,7 +6102,7 @@ "hash": "57aedbec84c390a3287b44649e400696ed2b6dcd408c8519583e8e995dbe6e9b" }, "kernelspec": { - "display_name": "Python 3.10.12 ('tpot2env2')", + "display_name": "Python 3.10.12 ('tpotenv2')", "language": "python", "name": "python3" }, diff --git a/Tutorial/4_Genetic_Feature_Selection.ipynb b/Tutorial/4_Genetic_Feature_Selection.ipynb index 7f3f0254..21177a72 100644 --- a/Tutorial/4_Genetic_Feature_Selection.ipynb +++ b/Tutorial/4_Genetic_Feature_Selection.ipynb @@ -160,21 +160,21 @@ } ], "source": [ - "import tpot2\n", - "from tpot2.search_spaces.nodes import *\n", - "from tpot2.search_spaces.pipelines import *\n", - "import tpot2\n", + "import tpot\n", + "from tpot.search_spaces.nodes import *\n", + "from tpot.search_spaces.pipelines import *\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", "import pandas as pd\n", - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", - "from tpot2.search_spaces.nodes import *\n", - "from tpot2.search_spaces.pipelines import *\n", - "from tpot2.config import get_search_space\n", + "from tpot.search_spaces.nodes import *\n", + "from tpot.search_spaces.pipelines import *\n", + "from tpot.config import get_search_space\n", "\n", "\n", "X, y = sklearn.datasets.make_classification(n_samples=1000, n_features=6, n_informative=6, n_redundant=0, n_repeated=0, n_classes=2, n_clusters_per_class=2, weights=None, flip_y=0.01, class_sep=1.0, hypercube=True, shift=0.0, scale=1.0, shuffle=True, random_state=None)\n", @@ -565,20 +565,20 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "import numpy as np\n", - "from tpot2.search_spaces.nodes import *\n", - "from tpot2.search_spaces.pipelines import *\n", + "from tpot.search_spaces.nodes import *\n", + "from tpot.search_spaces.pipelines import *\n", "\n", "gfs_sp = GeneticFeatureSelectorNode(n_features=X.shape[1])\n", "classifiers_sp = get_search_space('RandomForestClassifier')\n", "final_classification_search_space = SequentialPipeline([gfs_sp, classifiers_sp])\n", "\n", - "est = tpot2.TPOTEstimator( population_size=32,\n", + "est = tpot.TPOTEstimator( population_size=32,\n", " generations=10, \n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " n_jobs=32,\n", " classification=True,\n", @@ -1103,10 +1103,10 @@ "classifiers_sp = get_search_space('RandomForestClassifier')\n", "final_classification_search_space = SequentialPipeline([gfs_sp, classifiers_sp])\n", "\n", - "est = tpot2.TPOTEstimator( \n", + "est = tpot.TPOTEstimator( \n", " population_size=32,\n", " generations=10, \n", - " scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + " scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", " scorers_weights=[1.0, -1.0],\n", " other_objective_functions=[number_of_selected_features],\n", " other_objective_functions_weights = [-1],\n", @@ -1717,13 +1717,13 @@ } ], "source": [ - "linear_search_space = tpot2.config.template_search_spaces.get_template_search_spaces(\"linear\", classification=True)\n", + "linear_search_space = tpot.config.template_search_spaces.get_template_search_spaces(\"linear\", classification=True)\n", "gfs_and_linear_search_space = SequentialPipeline([gfs_sp, linear_search_space])\n", "\n", - "# est = tpot2.TPOTEstimator( \n", + "# est = tpot.TPOTEstimator( \n", "# population_size=32,\n", "# generations=10, \n", - "# scorers=[\"roc_auc_ovr\", tpot2.objectives.complexity_scorer],\n", + "# scorers=[\"roc_auc_ovr\", tpot.objectives.complexity_scorer],\n", "# scorers_weights=[1.0, -1.0],\n", "# other_objective_functions=[number_of_selected_features],\n", "# other_objective_functions_weights = [-1],\n", @@ -2291,9 +2291,9 @@ ], "source": [ "dynamic_transformers = DynamicUnionPipeline(get_search_space(\"all_transformers\"), max_estimators=4)\n", - "dynamic_transformers_with_passthrough = tpot2.search_spaces.pipelines.UnionPipeline([\n", + "dynamic_transformers_with_passthrough = tpot.search_spaces.pipelines.UnionPipeline([\n", " dynamic_transformers,\n", - " tpot2.config.get_search_space(\"Passthrough\")],\n", + " tpot.config.get_search_space(\"Passthrough\")],\n", " )\n", "multi_step_engineering = DynamicLinearPipeline(dynamic_transformers_with_passthrough, max_length=4)\n", "gfs_engineering_search_space = SequentialPipeline([gfs_sp, multi_step_engineering])\n", @@ -2308,7 +2308,7 @@ ], "metadata": { "kernelspec": { - "display_name": "tpot2env", + "display_name": "tpotenv", "language": "python", "name": "python3" }, diff --git a/Tutorial/5_GraphPipeline.ipynb b/Tutorial/5_GraphPipeline.ipynb index 59c24969..fe612909 100644 --- a/Tutorial/5_GraphPipeline.ipynb +++ b/Tutorial/5_GraphPipeline.ipynb @@ -7,7 +7,7 @@ "source": [ "# GraphPipeline\n", "\n", - "GraphPipelines (`tpot2.GraphPipeline`) work similarly to the scikit-learn Pipeline class. Rather than provide a list of steps, in GraphPipeline you provide a directed acyclic graph (`networkx.DiGraph`) of steps using networkx. In GraphPipeline, parents get their inputs from their children (i.e the leafs get the raw inputs (X,y), and the roots are the final classifiers/regressors). \n", + "GraphPipelines (`tpot.GraphPipeline`) work similarly to the scikit-learn Pipeline class. Rather than provide a list of steps, in GraphPipeline you provide a directed acyclic graph (`networkx.DiGraph`) of steps using networkx. In GraphPipeline, parents get their inputs from their children (i.e the leafs get the raw inputs (X,y), and the roots are the final classifiers/regressors). \n", "\n", "The label of the nodes can be anything, but must unique per instance of an sklearn estimator. Each node has an attribute called \"instance\" for the instance of the scikit-learn estimator.\n", "\n", @@ -68,7 +68,7 @@ "from sklearn.model_selection import train_test_split\n", "from sklearn.pipeline import Pipeline\n", "import networkx as nx\n", - "from tpot2 import GraphPipeline\n", + "from tpot import GraphPipeline\n", "import sklearn.metrics\n", "\n", "X, y = make_classification(random_state=0)\n", diff --git a/Tutorial/6_Symbolic_Regression_and_Classification.ipynb b/Tutorial/6_Symbolic_Regression_and_Classification.ipynb index a5e04777..9438084e 100644 --- a/Tutorial/6_Symbolic_Regression_and_Classification.ipynb +++ b/Tutorial/6_Symbolic_Regression_and_Classification.ipynb @@ -21,10 +21,10 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", - "from tpot2.search_spaces.pipelines import GraphSearchPipeline\n", - "from tpot2.search_spaces.nodes import FSSNode\n", - "from tpot2.config import get_search_space\n", + "import tpot\n", + "from tpot.search_spaces.pipelines import GraphSearchPipeline\n", + "from tpot.search_spaces.nodes import FSSNode\n", + "from tpot.config import get_search_space\n", "import sklearn.datasets\n", "from sklearn.linear_model import LogisticRegression\n", "from sklearn.model_selection import train_test_split\n", @@ -114,11 +114,11 @@ } ], "source": [ - "est = tpot2.TPOTEstimator( generations=20, \n", + "est = tpot.TPOTEstimator( generations=20, \n", " max_time_mins=None,\n", " scorers=['roc_auc_ovr'],\n", " scorers_weights=[1],\n", - " other_objective_functions=[tpot2.objectives.number_of_nodes_objective],\n", + " other_objective_functions=[tpot.objectives.number_of_nodes_objective],\n", " other_objective_functions_weights=[-1],\n", " n_jobs=32,\n", " classification=True,\n", @@ -219,25 +219,25 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn.datasets\n", "\n", "scorer = sklearn.metrics.get_scorer('neg_mean_squared_error')\n", "X, y = sklearn.datasets.load_diabetes(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", - "graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", - " root_search_space= tpot2.config.get_search_space(\"SGDRegressor\"),\n", - " leaf_search_space = tpot2.search_spaces.nodes.FSSNode(subsets=X_train.shape[1]), \n", - " inner_search_space = tpot2.config.get_search_space([\"arithmatic\"]),\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", + " root_search_space= tpot.config.get_search_space(\"SGDRegressor\"),\n", + " leaf_search_space = tpot.search_spaces.nodes.FSSNode(subsets=X_train.shape[1]), \n", + " inner_search_space = tpot.config.get_search_space([\"arithmatic\"]),\n", " max_size = 10,\n", ")\n", "\n", - "est = tpot2.TPOTEstimator( generations=20, \n", + "est = tpot.TPOTEstimator( generations=20, \n", " max_time_mins=None,\n", " scorers=['neg_mean_squared_error'],\n", " scorers_weights=[1],\n", - " other_objective_functions=[tpot2.objectives.number_of_nodes_objective],\n", + " other_objective_functions=[tpot.objectives.number_of_nodes_objective],\n", " other_objective_functions_weights=[-1],\n", " n_jobs=32,\n", " classification=False,\n", diff --git a/Tutorial/7_dask_parallelization.ipynb b/Tutorial/7_dask_parallelization.ipynb index 1004245d..22cf72f0 100644 --- a/Tutorial/7_dask_parallelization.ipynb +++ b/Tutorial/7_dask_parallelization.ipynb @@ -7,14 +7,14 @@ "source": [ "# Parallelization\n", "\n", - "This tutorial covers advanced setups for parallelizing TPOT2 with Dask. If you just want to parallelize TPOT2 within a single computer with multiple processes, set the n_jobs parameter to the number of threads you want to use and skip this tutorial. \n", + "This tutorial covers advanced setups for parallelizing TPOT with Dask. If you just want to parallelize TPOT within a single computer with multiple processes, set the n_jobs parameter to the number of threads you want to use and skip this tutorial. \n", "\n", - "TPOT2 uses Dask for parallelization and defaults to using a dask.distributed.LocalCluster for local parallelization. A user can pass in a custom Dask client or cluster for advanced usage. For example, a multi-node parallelization is possible using the dask-jobqueue package.\n", + "TPOT uses Dask for parallelization and defaults to using a dask.distributed.LocalCluster for local parallelization. A user can pass in a custom Dask client or cluster for advanced usage. For example, a multi-node parallelization is possible using the dask-jobqueue package.\n", "\n", "\n", - "TPOT2 can be easily parallelized on a local computer by setting the n_jobs and memory_limit parameters.\n", + "TPOT can be easily parallelized on a local computer by setting the n_jobs and memory_limit parameters.\n", "\n", - "`n_jobs` dictates how many dask workers to launch. In TPOT2 this corresponds to the number of pipelines to evaluate in parallel.\n", + "`n_jobs` dictates how many dask workers to launch. In TPOT this corresponds to the number of pipelines to evaluate in parallel.\n", "\n", "`memory_limit` is the amount of RAM to use per worker. " ] @@ -24,7 +24,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### TPOT2 with Python Scripts\n", + "### TPOT with Python Scripts\n", "\n", "When running tpot from an .py script, it is important to protect code with `if __name__==\"__main__\":`\n", "\n", @@ -41,11 +41,11 @@ "output_type": "stream", "text": [ "Generation: 100%|██████████| 5/5 [00:11<00:00, 2.24s/it]\n", - "/home/ribeirop/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 8\n", + "/home/ribeirop/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 8\n", " warnings.warn(\n", - "/home/ribeirop/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:128: ConvergenceWarning: FastICA did not converge. Consider increasing tolerance or the maximum number of iterations.\n", + "/home/ribeirop/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:128: ConvergenceWarning: FastICA did not converge. Consider increasing tolerance or the maximum number of iterations.\n", " warnings.warn(\n", - "/home/ribeirop/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", + "/home/ribeirop/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", " warnings.warn(\n" ] }, @@ -58,7 +58,7 @@ } ], "source": [ - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", @@ -67,14 +67,14 @@ "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", - "graph_search_space = tpot2.search_spaces.pipelines.GraphPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", " )\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " scorers = [\"roc_auc_ovr\"],\n", " scorers_weights = [1],\n", " classification = True,\n", @@ -97,7 +97,7 @@ "source": [ "## Manual Dask Clients and Dashboard\n", "\n", - "You can also manually initialize a dask client. This can be useful to gain additional control over the parallelization, debugging, as well as viewing a dashboard of the live performance of TPOT2.\n", + "You can also manually initialize a dask client. This can be useful to gain additional control over the parallelization, debugging, as well as viewing a dashboard of the live performance of TPOT.\n", "\n", "You can find more details in the official [documentation here.](https://docs.dask.org/en/stable/)\n", "\n", @@ -173,7 +173,7 @@ "output_type": "stream", "text": [ "Generation: 100%|██████████| 5/5 [00:13<00:00, 2.62s/it]\n", - "/home/ribeirop/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", + "/home/ribeirop/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", " warnings.warn(\n" ] }, @@ -186,14 +186,14 @@ } ], "source": [ - "graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + "graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", " )\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " client = client,\n", " scorers = [\"roc_auc_ovr\"],\n", " scorers_weights = [1],\n", @@ -207,7 +207,7 @@ "\n", "\n", "# this is equivalent to: \n", - "# est = tpot2.TPOTClassifier(population_size= 8, generations=5, n_jobs=4, memory_limit=\"4GB\", verbose=1)\n", + "# est = tpot.TPOTClassifier(population_size= 8, generations=5, n_jobs=4, memory_limit=\"4GB\", verbose=1)\n", "est.fit(X_train, y_train)\n", "print(scorer(est, X_test, y_test))\n", "\n", @@ -236,7 +236,7 @@ "output_type": "stream", "text": [ "Generation: 100%|██████████| 5/5 [00:16<00:00, 3.33s/it]\n", - "/home/ribeirop/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", + "/home/ribeirop/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/linear_model/_sag.py:350: ConvergenceWarning: The max_iter was reached which means the coef_ did not converge\n", " warnings.warn(\n" ] }, @@ -250,7 +250,7 @@ ], "source": [ "from dask.distributed import Client, LocalCluster\n", - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", @@ -268,14 +268,14 @@ " threads_per_worker=1,\n", " memory_limit='4GB',\n", ") as cluster, Client(cluster) as client:\n", - " graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + " graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", " )\n", "\n", - " est = tpot2.TPOTEstimator(\n", + " est = tpot.TPOTEstimator(\n", " client = client,\n", " scorers = [\"roc_auc_ovr\"],\n", " scorers_weights = [1],\n", @@ -299,7 +299,7 @@ "\n", "Dask can parallelize across multiple nodes via job queueing systems. This is done using the Dask-Jobqueue package. More information can be found in the official [documentation here.]( https://jobqueue.dask.org/en/latest/)\n", "\n", - "To parallelize TPOT2 with Dask-Jobqueue, simply pass in a client based on a Jobqueue cluster with desired settings into the client parameter. Each job will evaluate a single pipeline.\n", + "To parallelize TPOT with Dask-Jobqueue, simply pass in a client based on a Jobqueue cluster with desired settings into the client parameter. Each job will evaluate a single pipeline.\n", "\n", "Note that TPOT will ignore n_jobs and memory_limit as these should be set inside the Dask cluster. \n", "\n", @@ -318,7 +318,7 @@ "import sklearn.datasets\n", "import sklearn.metrics\n", "import sklearn.model_selection\n", - "import tpot2\n", + "import tpot\n", "from dask_jobqueue import SGECluster # or SLURMCluster, PBSCluster, etc. Replace SGE with your scheduler.\n", "import os\n", "\n", @@ -343,14 +343,14 @@ " 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", - " graph_search_space = tpot2.search_spaces.pipelines.GraphPipeline(\n", - " root_search_space= tpot2.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", - " leaf_search_space = tpot2.config.get_search_space(\"selectors\"), \n", - " inner_search_space = tpot2.config.get_search_space([\"transformers\"]),\n", + " graph_search_space = tpot.search_spaces.pipelines.GraphPipeline(\n", + " root_search_space= tpot.config.get_search_space([\"KNeighborsClassifier\", \"LogisticRegression\", \"DecisionTreeClassifier\"]),\n", + " leaf_search_space = tpot.config.get_search_space(\"selectors\"), \n", + " inner_search_space = tpot.config.get_search_space([\"transformers\"]),\n", " max_size = 10,\n", " )\n", "\n", - " est = tpot2.TPOTEstimator(\n", + " est = tpot.TPOTEstimator(\n", " client = client,\n", " scorers = [\"roc_auc\"],\n", " scorers_weights = [1],\n", @@ -363,7 +363,7 @@ " )\n", " est.fit(X_train, y_train)\n", " # this is equivalent to: \n", - " # est = tpot2.TPOTClassifier(population_size= 8, generations=5, n_jobs=4, memory_limit=\"4GB\", verbose=1)\n", + " # est = tpot.TPOTClassifier(population_size= 8, generations=5, n_jobs=4, memory_limit=\"4GB\", verbose=1)\n", " est.fit(X_train, y_train)\n", " print(scorer(est, X_test, y_test))\n", "\n", diff --git a/Tutorial/8_SH_and_cv_early_pruning.ipynb b/Tutorial/8_SH_and_cv_early_pruning.ipynb index df8cbd0c..0a24c33b 100644 --- a/Tutorial/8_SH_and_cv_early_pruning.ipynb +++ b/Tutorial/8_SH_and_cv_early_pruning.ipynb @@ -65,7 +65,7 @@ "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", - "import tpot2\n", + "import tpot\n", "\n", "population_size=30\n", "initial_population_size=100\n", @@ -81,8 +81,8 @@ "fig, ax1 = plt.subplots()\n", "ax2 = ax1.twinx()\n", "\n", - "interpolated_values_population = tpot2.utils.beta_interpolation(start=initial_population_size, end=population_size, n=generations_until_end_population, n_steps=stepwise_steps, scale=population_scaling)\n", - "interpolated_values_budget = tpot2.utils.beta_interpolation(start=budget_range[0], end=budget_range[1], n=generations_until_end_budget, n_steps=stepwise_steps, scale=budget_scaling)\n", + "interpolated_values_population = tpot.utils.beta_interpolation(start=initial_population_size, end=population_size, n=generations_until_end_population, n_steps=stepwise_steps, scale=population_scaling)\n", + "interpolated_values_budget = tpot.utils.beta_interpolation(start=budget_range[0], end=budget_range[1], n=generations_until_end_budget, n_steps=stepwise_steps, scale=budget_scaling)\n", "ax1.step(list(range(len(interpolated_values_population))), interpolated_values_population, label=f\"population size\")\n", "ax2.step(list(range(len(interpolated_values_budget))), interpolated_values_budget, label=f\"budget\", color='r')\n", "ax1.set_xlabel(\"generation\")\n", @@ -103,12 +103,12 @@ "# A Graph pipeline starting with at least one selector as a leaf, potentially followed by a series\n", "# of stacking classifiers or transformers, and ending with a classifier. The graph will have at most 15 nodes and a max depth of 6.\n", "\n", - "import tpot2\n", + "import tpot\n", "import sklearn\n", "import sklearn.datasets\n", "import numpy as np\n", "import time\n", - "import tpot2\n", + "import tpot\n", "import pandas as pd\n", "import numpy as np\n", "from sklearn.linear_model import LogisticRegression\n", @@ -119,7 +119,7 @@ "scorer = sklearn.metrics.make_scorer(sklearn.metrics.roc_auc_score, needs_proba=True, multi_class='ovr')\n", "\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " generations=50,\n", " max_time_mins=None,\n", " scorers=['roc_auc_ovr'],\n", @@ -210,7 +210,7 @@ ], "source": [ "import matplotlib.pyplot as plt\n", - "import tpot2\n", + "import tpot\n", "import time\n", "import sklearn\n", "import sklearn.datasets\n", @@ -222,7 +222,7 @@ "#Population and budget use stepwise\n", "fig, ax1 = plt.subplots()\n", "\n", - "interpolated_values = tpot2.utils.beta_interpolation(start=threshold_evaluation_pruning[0], end=threshold_evaluation_pruning[-1], n=cv, n_steps=cv, scale=threshold_evaluation_scaling)\n", + "interpolated_values = tpot.utils.beta_interpolation(start=threshold_evaluation_pruning[0], end=threshold_evaluation_pruning[-1], n=cv, n_steps=cv, scale=threshold_evaluation_scaling)\n", "ax1.step(list(range(len(interpolated_values))), interpolated_values, label=f\"threshold\")\n", "ax1.set_xlabel(\"fold\")\n", "ax1.set_ylabel(\"percentile\")\n", @@ -236,10 +236,10 @@ "metadata": {}, "outputs": [], "source": [ - "import tpot2\n", - "from tpot2.search_spaces.pipelines import *\n", - "from tpot2.search_spaces.nodes import *\n", - "from tpot2.config.get_configspace import get_search_space\n", + "import tpot\n", + "from tpot.search_spaces.pipelines import *\n", + "from tpot.search_spaces.nodes import *\n", + "from tpot.config.get_configspace import get_search_space\n", "import sklearn.model_selection\n", "import sklearn\n", "\n", @@ -275,14 +275,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "/home/ribeirop/common/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/metrics/_scorer.py:548: FutureWarning: The `needs_threshold` and `needs_proba` parameter are deprecated in version 1.4 and will be removed in 1.6. You can either let `response_method` be `None` or set it to `predict` to preserve the same behaviour.\n", + "/home/ribeirop/common/miniconda3/envs/tpotenv/lib/python3.10/site-packages/sklearn/metrics/_scorer.py:548: FutureWarning: The `needs_threshold` and `needs_proba` parameter are deprecated in version 1.4 and will be removed in 1.6. You can either let `response_method` be `None` or set it to `predict` to preserve the same behaviour.\n", " warnings.warn(\n" ] } ], "source": [ "import matplotlib.pyplot as plt\n", - "import tpot2\n", + "import tpot\n", "import time\n", "import sklearn\n", "import sklearn.datasets\n", @@ -292,7 +292,7 @@ "X, y = sklearn.datasets.make_classification(n_samples=5000, n_features=20, n_classes=5, random_state=1, n_informative=15, n_redundant=5, n_repeated=0, n_clusters_per_class=3, class_sep=.8)\n", "X_train, X_test, y_train, y_test = sklearn.model_selection.train_test_split(X, y, random_state=1)\n", "\n", - "# search_space = tpot2.config.template_search_spaces.get_template_search_spaces(\"linear\",inner_predictors=False, random_state=42)\n" + "# search_space = tpot.config.template_search_spaces.get_template_search_spaces(\"linear\",inner_predictors=False, random_state=42)\n" ] }, { @@ -468,7 +468,7 @@ ], "source": [ "# no pruning\n", - "est = tpot2.TPOTEstimator( \n", + "est = tpot.TPOTEstimator( \n", " generations=10,\n", " max_time_mins=None,\n", " scorers=['roc_auc_ovr'],\n", @@ -649,9 +649,9 @@ "output_type": "stream", "text": [ "\n", - "/home/ribeirop/common/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 16\n", + "/home/ribeirop/common/miniconda3/envs/tpotnv/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 16\n", " warnings.warn(\n", - "/home/ribeirop/common/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:128: ConvergenceWarning: FastICA did not converge. Consider increasing tolerance or the maximum number of iterations.\n", + "/home/ribeirop/common/miniconda3/envs/tpotnv/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:128: ConvergenceWarning: FastICA did not converge. Consider increasing tolerance or the maximum number of iterations.\n", " warnings.warn(\n" ] }, @@ -665,15 +665,15 @@ } ], "source": [ - "import tpot2.config\n", - "import tpot2.config.template_search_spaces\n", - "import tpot2.search_spaces\n", + "import tpot.config\n", + "import tpot.config.template_search_spaces\n", + "import tpot.search_spaces\n", "\n", "\n", "\n", - "# search_space = tpot2.config.get_search_space([\"RandomForestClassifier\"])\n", + "# search_space = tpot.config.get_search_space([\"RandomForestClassifier\"])\n", "\n", - "est = tpot2.TPOTEstimator( \n", + "est = tpot.TPOTEstimator( \n", " generations=10,\n", " max_time_mins=None,\n", " scorers=['roc_auc_ovr'],\n", @@ -715,7 +715,7 @@ ], "source": [ "import matplotlib.pyplot as plt\n", - "import tpot2\n", + "import tpot\n", "\n", "selection_evaluation_pruning = [.9, .3]\n", "selection_evaluation_scaling = .2\n", @@ -723,7 +723,7 @@ "#Population and budget use stepwise\n", "fig, ax1 = plt.subplots()\n", "\n", - "interpolated_values = tpot2.utils.beta_interpolation(start=selection_evaluation_pruning[0], end=selection_evaluation_pruning[-1], n=cv, n_steps=cv, scale=selection_evaluation_scaling)\n", + "interpolated_values = tpot.utils.beta_interpolation(start=selection_evaluation_pruning[0], end=selection_evaluation_pruning[-1], n=cv, n_steps=cv, scale=selection_evaluation_scaling)\n", "ax1.step(list(range(len(interpolated_values))), interpolated_values, label=f\"threshold\")\n", "ax1.set_xlabel(\"fold\")\n", "ax1.set_ylabel(\"percent to select\")\n", @@ -891,7 +891,7 @@ "output_type": "stream", "text": [ "\n", - "/home/ribeirop/common/miniconda3/envs/tpot2env/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 20\n", + "/home/ribeirop/common/miniconda3/envs/tpotnv/lib/python3.10/site-packages/sklearn/decomposition/_fastica.py:595: UserWarning: n_components is too large: it will be set to 20\n", " warnings.warn(\n" ] }, @@ -905,7 +905,7 @@ } ], "source": [ - "est = tpot2.TPOTEstimator( \n", + "est = tpot.TPOTEstimator( \n", " generations=10,\n", " max_time_mins=None,\n", " scorers=['roc_auc_ovr'],\n", @@ -983,7 +983,7 @@ " 0.848068\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 0.0\n", " 0.846478\n", " 1.727821e+09\n", @@ -1006,7 +1006,7 @@ " 0.831502\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 0.0\n", " 0.817219\n", " 1.727822e+09\n", @@ -1029,7 +1029,7 @@ " 0.830374\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 0.0\n", " 0.817150\n", " 1.727822e+09\n", @@ -1052,7 +1052,7 @@ " 0.850091\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 0.0\n", " 0.843524\n", " 1.727821e+09\n", @@ -1075,7 +1075,7 @@ " 0.855569\n", " NaN\n", " NaN\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 0.0\n", " 0.847828\n", " 1.727821e+09\n", @@ -1121,7 +1121,7 @@ " 0.821990\n", " (742, 742)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 9.0\n", " 0.813408\n", " 1.727823e+09\n", @@ -1144,7 +1144,7 @@ " 0.899339\n", " (100, 100)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 9.0\n", " 0.893247\n", " 1.727823e+09\n", @@ -1167,7 +1167,7 @@ " 0.870868\n", " (179, 14)\n", " ind_crossover\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 9.0\n", " 0.871226\n", " 1.727823e+09\n", @@ -1190,7 +1190,7 @@ " 0.815212\n", " (362, 362)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 9.0\n", " 0.830802\n", " 1.727823e+09\n", @@ -1213,7 +1213,7 @@ " 0.865588\n", " (670, 670)\n", " ind_mutate\n", - " <tpot2.search_spaces.pipelines.sequential.Sequ...\n", + " <tpot.search_spaces.pipelines.sequential.Sequ...\n", " 9.0\n", " 0.867900\n", " 1.727823e+09\n", @@ -1251,17 +1251,17 @@ "995 0.865588 (670, 670) ind_mutate \n", "\n", " Individual Generation \\\n", - "1
TPOTEstimator(classification=True, generations=2, max_eval_time_mins=300,\n",
        "              n_jobs=10, population_size=10, scorers=['roc_auc'],\n",
        "              scorers_weights=[1],\n",
-       "              search_space=<tpot2.search_spaces.pipelines.sequential.SequentialPipeline object at 0x7d34ec1efbb0>,\n",
+       "              search_space=<tpot.search_spaces.pipelines.sequential.SequentialPipeline object at 0x7d34ec1efbb0>,\n",
        "              verbose=5)
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": [ "TPOTEstimator(classification=True, generations=2, max_eval_time_mins=300,\n", " n_jobs=10, population_size=10, scorers=['roc_auc'],\n", " scorers_weights=[1],\n", - " search_space=,\n", + " search_space=,\n", " verbose=5)" ] }, @@ -1312,7 +1312,7 @@ "\n", "\n", "\n", - "est = tpot2.TPOTEstimator(\n", + "est = tpot.TPOTEstimator(\n", " scorers = [\"roc_auc\"],\n", " scorers_weights = [1],\n", " classification = True,\n", diff --git a/docs/contribute.md b/docs/contribute.md index d2c44afa..9be6f44e 100644 --- a/docs/contribute.md +++ b/docs/contribute.md @@ -4,11 +4,11 @@ We welcome you to check the existing issues for bugs or enhancements to work on. # Contribution Guide -We welcome you to [check the existing issues](https://github.com/EpistasisLab/tpot2/issues/) for bugs or enhancements to work on. If you have an idea for an extension to TPOT, please [file a new issue](https://github.com/EpistasisLab/tpot2/issues/new) so we can discuss it. +We welcome you to [check the existing issues](https://github.com/EpistasisLab/tpot/issues/) for bugs or enhancements to work on. If you have an idea for an extension to TPOT, please [file a new issue](https://github.com/EpistasisLab/tpot/issues/new) so we can discuss it. ## Project layout -The latest stable release of TPOT is on the [main branch](https://github.com/EpistasisLab/tpot2/tree/main), whereas the latest version of TPOT in development is on the [development branch](https://github.com/EpistasisLab/tpot2/tree/dev). Make sure you are looking at and working on the correct branch if you're looking to contribute code. +The latest stable release of TPOT is on the [main branch](https://github.com/EpistasisLab/tpot/tree/main), whereas the latest version of TPOT in development is on the [development branch](https://github.com/EpistasisLab/tpot/tree/dev). Make sure you are looking at and working on the correct branch if you're looking to contribute code. In terms of directory structure: @@ -23,10 +23,10 @@ Make sure to familiarize yourself with the project layout before making any majo ## How to contribute The preferred way to contribute to TPOT is to fork the -[main repository](https://github.com/EpistasisLab/tpot2/) on +[main repository](https://github.com/EpistasisLab/tpot/) on GitHub: -1. Fork the [project repository](https://github.com/EpistasisLab/tpot2): +1. Fork the [project repository](https://github.com/EpistasisLab/tpot): click on the 'Fork' button near the top of the page. This creates a copy of the code under your account on the GitHub server. @@ -70,13 +70,13 @@ Before you submit a pull request for your contribution, please work through this If your contribution changes TPOT in any way: -* Update the [documentation](https://github.com/EpistasisLab/tpot2/tree/main/docs) so all of your changes are reflected there. +* Update the [documentation](https://github.com/EpistasisLab/tpot/tree/main/docs) so all of your changes are reflected there. -* Update the [README](https://github.com/EpistasisLab/tpot2/blob/main/README.md) if anything there has changed. +* Update the [README](https://github.com/EpistasisLab/tpot/blob/main/README.md) if anything there has changed. If your contribution involves any code changes: -* Update the [project unit tests](https://github.com/EpistasisLab/tpot2/tree/main/tpot2/tests) to test your code changes. +* Update the [project unit tests](https://github.com/EpistasisLab/tpot/tree/main/tpot/tests) to test your code changes. * Make sure that your code is properly commented with [docstrings](https://www.python.org/dev/peps/pep-0257/) and comments explaining your rationale behind non-obvious coding practices. diff --git a/docs/scripts/build_docs_sources.sh b/docs/scripts/build_docs_sources.sh index 52089cf7..d79423b8 100644 --- a/docs/scripts/build_docs_sources.sh +++ b/docs/scripts/build_docs_sources.sh @@ -22,4 +22,4 @@ function iterate_files() { done } -iterate_files "tpot2" +iterate_files "tpot" diff --git a/docs/tpot_api/classifier.md b/docs/tpot_api/classifier.md index b8d81f66..68cb90bc 100644 --- a/docs/tpot_api/classifier.md +++ b/docs/tpot_api/classifier.md @@ -1 +1 @@ -::: tpot2.tpot_estimator.templates.tpottemplates.TPOTClassifier \ No newline at end of file +::: tpot.tpot_estimator.templates.tpottemplates.TPOTClassifier \ No newline at end of file diff --git a/docs/tpot_api/estimator.md b/docs/tpot_api/estimator.md index d18b41c9..acb729c2 100644 --- a/docs/tpot_api/estimator.md +++ b/docs/tpot_api/estimator.md @@ -1 +1 @@ -::: tpot2.tpot_estimator.estimator \ No newline at end of file +::: tpot.tpot_estimator.estimator \ No newline at end of file diff --git a/docs/tpot_api/regressor.md b/docs/tpot_api/regressor.md index 5013fbef..fc1c5802 100644 --- a/docs/tpot_api/regressor.md +++ b/docs/tpot_api/regressor.md @@ -1 +1 @@ -::: tpot2.tpot_estimator.templates.tpottemplates.TPOTRegressor \ No newline at end of file +::: tpot.tpot_estimator.templates.tpottemplates.TPOTRegressor \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 4d280443..42772c7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,13 +3,13 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" [tool.pytest.ini_options] -addopts = "--cov=tpot2" +addopts = "--cov=tpot" testpaths = [ - "tpot2/tests", + "tpot/tests", ] [tool.mypy] -mypy_path = "tpot2" +mypy_path = "tpot" check_untyped_defs = true disallow_any_generics = true ignore_missing_imports = true diff --git a/setup.cfg b/setup.cfg index d79a5b86..a619924a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -7,7 +7,7 @@ testing = tox>=3.24 [options.package_data] -tpot2 = py.typed +tpot = py.typed [flake8] max-line-length = 120 \ No newline at end of file diff --git a/setup.py b/setup.py index b1d194f8..a5c1dbf1 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ def calculate_version(): - initpy = open('tpot2/_version.py').read().split('\n') + initpy = open('tpot/_version.py').read().split('\n') version = list(filter(lambda x: '__version__' in x, initpy))[0].split('\'')[1] return version @@ -13,14 +13,14 @@ def calculate_version(): package_version = calculate_version() setup( - name='TPOT2', + name='TPOT', python_requires='>=3.10, <3.12', #for configspace compatibility version=package_version, author='Pedro Ribeiro', packages=find_packages(), - url='https://github.com/EpistasisLab/tpot2', + url='https://github.com/EpistasisLab/tpot', license='GNU/LGPLv3', #TODO - entry_points={'console_scripts': ['tpot2=tpot2:main', ]}, + entry_points={'console_scripts': ['tpot=tpot:main', ]}, description=('Tree-based Pipeline Optimization Tool'), long_description=''' A Python tool that automatically creates and optimizes machine learning pipelines using genetic programming. diff --git a/tpot2/__init__.py b/tpot/__init__.py similarity index 98% rename from tpot2/__init__.py rename to tpot/__init__.py index da5e74bf..7c0e715a 100644 --- a/tpot2/__init__.py +++ b/tpot/__init__.py @@ -55,4 +55,4 @@ from update_checker import update_check from ._version import __version__ -update_check("tpot2",__version__) \ No newline at end of file +update_check("tpot",__version__) \ No newline at end of file diff --git a/tpot2/_version.py b/tpot/_version.py similarity index 98% rename from tpot2/_version.py rename to tpot/_version.py index 94760e75..3b7e1f42 100644 --- a/tpot2/_version.py +++ b/tpot/_version.py @@ -32,4 +32,4 @@ License along with TPOT. If not, see . """ -__version__ = '0.1.8a0' +__version__ = '1.0.0' diff --git a/tpot2/builtin_modules/__init__.py b/tpot/builtin_modules/__init__.py similarity index 100% rename from tpot2/builtin_modules/__init__.py rename to tpot/builtin_modules/__init__.py diff --git a/tpot2/builtin_modules/arithmetictransformer.py b/tpot/builtin_modules/arithmetictransformer.py similarity index 100% rename from tpot2/builtin_modules/arithmetictransformer.py rename to tpot/builtin_modules/arithmetictransformer.py diff --git a/tpot2/builtin_modules/column_one_hot_encoder.py b/tpot/builtin_modules/column_one_hot_encoder.py similarity index 100% rename from tpot2/builtin_modules/column_one_hot_encoder.py rename to tpot/builtin_modules/column_one_hot_encoder.py diff --git a/tpot2/builtin_modules/estimatortransformer.py b/tpot/builtin_modules/estimatortransformer.py similarity index 100% rename from tpot2/builtin_modules/estimatortransformer.py rename to tpot/builtin_modules/estimatortransformer.py diff --git a/tpot2/builtin_modules/feature_encoding_frequency_selector.py b/tpot/builtin_modules/feature_encoding_frequency_selector.py similarity index 100% rename from tpot2/builtin_modules/feature_encoding_frequency_selector.py rename to tpot/builtin_modules/feature_encoding_frequency_selector.py diff --git a/tpot2/builtin_modules/feature_set_selector.py b/tpot/builtin_modules/feature_set_selector.py similarity index 100% rename from tpot2/builtin_modules/feature_set_selector.py rename to tpot/builtin_modules/feature_set_selector.py diff --git a/tpot2/builtin_modules/feature_transformers.py b/tpot/builtin_modules/feature_transformers.py similarity index 100% rename from tpot2/builtin_modules/feature_transformers.py rename to tpot/builtin_modules/feature_transformers.py diff --git a/tpot2/builtin_modules/genetic_encoders.py b/tpot/builtin_modules/genetic_encoders.py similarity index 100% rename from tpot2/builtin_modules/genetic_encoders.py rename to tpot/builtin_modules/genetic_encoders.py diff --git a/tpot2/builtin_modules/imputer.py b/tpot/builtin_modules/imputer.py similarity index 100% rename from tpot2/builtin_modules/imputer.py rename to tpot/builtin_modules/imputer.py diff --git a/tpot2/builtin_modules/nn.py b/tpot/builtin_modules/nn.py similarity index 100% rename from tpot2/builtin_modules/nn.py rename to tpot/builtin_modules/nn.py diff --git a/tpot2/builtin_modules/passkbinsdiscretizer.py b/tpot/builtin_modules/passkbinsdiscretizer.py similarity index 100% rename from tpot2/builtin_modules/passkbinsdiscretizer.py rename to tpot/builtin_modules/passkbinsdiscretizer.py diff --git a/tpot2/builtin_modules/passthrough.py b/tpot/builtin_modules/passthrough.py similarity index 100% rename from tpot2/builtin_modules/passthrough.py rename to tpot/builtin_modules/passthrough.py diff --git a/tpot2/builtin_modules/tests/feature_set_selector_tests.py b/tpot/builtin_modules/tests/feature_set_selector_tests.py similarity index 98% rename from tpot2/builtin_modules/tests/feature_set_selector_tests.py rename to tpot/builtin_modules/tests/feature_set_selector_tests.py index 1164adf7..2aa9527e 100644 --- a/tpot2/builtin_modules/tests/feature_set_selector_tests.py +++ b/tpot/builtin_modules/tests/feature_set_selector_tests.py @@ -36,7 +36,7 @@ import numpy as np import pandas as pd -from tpot2.config.custom_modules import FeatureSetSelector +from tpot.config.custom_modules import FeatureSetSelector from nose.tools import assert_raises test_data = pd.read_csv("tests/tests.csv") diff --git a/tpot2/builtin_modules/zero_count.py b/tpot/builtin_modules/zero_count.py similarity index 100% rename from tpot2/builtin_modules/zero_count.py rename to tpot/builtin_modules/zero_count.py diff --git a/tpot2/config/__init__.py b/tpot/config/__init__.py similarity index 100% rename from tpot2/config/__init__.py rename to tpot/config/__init__.py diff --git a/tpot2/config/autoqtl_builtins.py b/tpot/config/autoqtl_builtins.py similarity index 94% rename from tpot2/config/autoqtl_builtins.py rename to tpot/config/autoqtl_builtins.py index 9b9b8961..6bdf7980 100644 --- a/tpot2/config/autoqtl_builtins.py +++ b/tpot/config/autoqtl_builtins.py @@ -32,8 +32,8 @@ License along with TPOT. If not, see . """ -from tpot2.builtin_modules import genetic_encoders -from tpot2.builtin_modules import feature_encoding_frequency_selector +from tpot.builtin_modules import genetic_encoders +from tpot.builtin_modules import feature_encoding_frequency_selector import sklearn import numpy as np diff --git a/tpot2/config/classifiers.py b/tpot/config/classifiers.py similarity index 100% rename from tpot2/config/classifiers.py rename to tpot/config/classifiers.py diff --git a/tpot2/config/classifiers_sklearnex.py b/tpot/config/classifiers_sklearnex.py similarity index 100% rename from tpot2/config/classifiers_sklearnex.py rename to tpot/config/classifiers_sklearnex.py diff --git a/tpot2/config/get_configspace.py b/tpot/config/get_configspace.py similarity index 98% rename from tpot2/config/get_configspace.py rename to tpot/config/get_configspace.py index 898cdb75..2ba7aad9 100644 --- a/tpot2/config/get_configspace.py +++ b/tpot/config/get_configspace.py @@ -57,11 +57,11 @@ from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal #autoqtl_builtins -from tpot2.builtin_modules import genetic_encoders, feature_encoding_frequency_selector -from tpot2.builtin_modules import AddTransformer, mul_neg_1_Transformer, MulTransformer, SafeReciprocalTransformer, EQTransformer, NETransformer, GETransformer, GTTransformer, LETransformer, LTTransformer, MinTransformer, MaxTransformer, ZeroTransformer, OneTransformer, NTransformer -from tpot2.builtin_modules.genetic_encoders import DominantEncoder, RecessiveEncoder, HeterosisEncoder, UnderDominanceEncoder, OverDominanceEncoder -from tpot2.builtin_modules import ZeroCount, ColumnOneHotEncoder, PassKBinsDiscretizer -from tpot2.builtin_modules import Passthrough, SkipTransformer +from tpot.builtin_modules import genetic_encoders, feature_encoding_frequency_selector +from tpot.builtin_modules import AddTransformer, mul_neg_1_Transformer, MulTransformer, SafeReciprocalTransformer, EQTransformer, NETransformer, GETransformer, GTTransformer, LETransformer, LTTransformer, MinTransformer, MaxTransformer, ZeroTransformer, OneTransformer, NTransformer +from tpot.builtin_modules.genetic_encoders import DominantEncoder, RecessiveEncoder, HeterosisEncoder, UnderDominanceEncoder, OverDominanceEncoder +from tpot.builtin_modules import ZeroCount, ColumnOneHotEncoder, PassKBinsDiscretizer +from tpot.builtin_modules import Passthrough, SkipTransformer from sklearn.linear_model import SGDClassifier, LogisticRegression, SGDRegressor, Ridge, Lasso, ElasticNet, Lars, LassoLars, LassoLarsCV, RidgeCV, ElasticNetCV, PassiveAggressiveClassifier, ARDRegression from sklearn.ensemble import BaggingClassifier, RandomForestClassifier, ExtraTreesClassifier, GradientBoostingClassifier, ExtraTreesRegressor, ExtraTreesClassifier, AdaBoostRegressor, AdaBoostClassifier, GradientBoostingRegressor,RandomForestRegressor, BaggingRegressor, ExtraTreesRegressor, HistGradientBoostingClassifier, HistGradientBoostingRegressor from sklearn.neural_network import MLPClassifier, MLPRegressor diff --git a/tpot2/config/imputers.py b/tpot/config/imputers.py similarity index 100% rename from tpot2/config/imputers.py rename to tpot/config/imputers.py diff --git a/tpot2/config/mdr_configs.py b/tpot/config/mdr_configs.py similarity index 100% rename from tpot2/config/mdr_configs.py rename to tpot/config/mdr_configs.py diff --git a/tpot2/config/regressors.py b/tpot/config/regressors.py similarity index 100% rename from tpot2/config/regressors.py rename to tpot/config/regressors.py diff --git a/tpot2/config/regressors_sklearnex.py b/tpot/config/regressors_sklearnex.py similarity index 100% rename from tpot2/config/regressors_sklearnex.py rename to tpot/config/regressors_sklearnex.py diff --git a/tpot2/config/selectors.py b/tpot/config/selectors.py similarity index 100% rename from tpot2/config/selectors.py rename to tpot/config/selectors.py diff --git a/tpot2/config/special_configs.py b/tpot/config/special_configs.py similarity index 85% rename from tpot2/config/special_configs.py rename to tpot/config/special_configs.py index 19c1dff8..b8d7f81b 100644 --- a/tpot2/config/special_configs.py +++ b/tpot/config/special_configs.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -from tpot2.builtin_modules import ArithmeticTransformer, FeatureSetSelector +from tpot.builtin_modules import ArithmeticTransformer, FeatureSetSelector from functools import partial import pandas as pd import numpy as np -from tpot2.builtin_modules import AddTransformer, mul_neg_1_Transformer, MulTransformer, SafeReciprocalTransformer, EQTransformer, NETransformer, GETransformer, GTTransformer, LETransformer, LTTransformer, MinTransformer, MaxTransformer, ZeroTransformer, OneTransformer, NTransformer +from tpot.builtin_modules import AddTransformer, mul_neg_1_Transformer, MulTransformer, SafeReciprocalTransformer, EQTransformer, NETransformer, GETransformer, GTTransformer, LETransformer, LTTransformer, MinTransformer, MaxTransformer, ZeroTransformer, OneTransformer, NTransformer from ConfigSpace import ConfigurationSpace from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal diff --git a/tpot2/config/template_search_spaces.py b/tpot/config/template_search_spaces.py similarity index 85% rename from tpot2/config/template_search_spaces.py rename to tpot/config/template_search_spaces.py index 69e658d9..56aa5c77 100644 --- a/tpot2/config/template_search_spaces.py +++ b/tpot/config/template_search_spaces.py @@ -32,9 +32,9 @@ License along with TPOT. If not, see . """ -import tpot2 -from tpot2.search_spaces.pipelines import * -from tpot2.search_spaces.nodes import * +import tpot +from tpot.search_spaces.pipelines import * +from tpot.search_spaces.nodes import * from .get_configspace import get_search_space import sklearn.model_selection import sklearn @@ -51,7 +51,7 @@ def get_linear_search_space(classification=True, inner_predictors=True, cross_va # this allows us to wrap the classifiers in the EstimatorTransformer # this is necessary so that classifiers can be used inside of sklearn pipelines - wrapped_estimators = WrapperPipeline(tpot2.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':cross_val_predict_cv}, estimators) + wrapped_estimators = WrapperPipeline(tpot.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':cross_val_predict_cv}, estimators) scalers = get_search_space(["scalers","Passthrough"], **get_search_space_params) @@ -95,24 +95,24 @@ def get_graph_search_space(classification=True, inner_predictors=True, cross_val if classification: root_search_space = get_search_space(["classifiers"], **get_search_space_params) - inner_search_space = tpot2.config.get_search_space(["transformers","scalers","selectors_classification"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["transformers","scalers","selectors_classification"],**get_search_space_params) else: root_search_space = get_search_space(["regressors"], **get_search_space_params) if classification: if inner_predictors: - inner_search_space = tpot2.config.get_search_space(["classifiers","transformers","scalers","selectors_classification"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["classifiers","transformers","scalers","selectors_classification"],**get_search_space_params) else: - inner_search_space = tpot2.config.get_search_space(["transformers","scalers","selectors_classification"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["transformers","scalers","selectors_classification"],**get_search_space_params) else: if inner_predictors: - inner_search_space = tpot2.config.get_search_space(["regressors", "transformers","scalers","selectors_regression"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["regressors", "transformers","scalers","selectors_regression"],**get_search_space_params) else: - inner_search_space = tpot2.config.get_search_space(["transformers","scalers","selectors_regression"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["transformers","scalers","selectors_regression"],**get_search_space_params) - search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline( + search_space = tpot.search_spaces.pipelines.GraphSearchPipeline( root_search_space= root_search_space, leaf_search_space = None, inner_search_space = inner_search_space, @@ -133,17 +133,17 @@ def get_graph_search_space_light(classification=True, inner_predictors=True, cro if classification: if inner_predictors: - inner_search_space = tpot2.config.get_search_space(['BernoulliNB', 'DecisionTreeClassifier', 'GaussianNB', 'KNeighborsClassifier', 'LogisticRegression', 'MultinomialNB',"transformers","scalers","SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(['BernoulliNB', 'DecisionTreeClassifier', 'GaussianNB', 'KNeighborsClassifier', 'LogisticRegression', 'MultinomialNB',"transformers","scalers","SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) else: - inner_search_space = tpot2.config.get_search_space(["transformers","scalers","SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["transformers","scalers","SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) else: if inner_predictors: - inner_search_space = tpot2.config.get_search_space(["RidgeCV", "LinearSVR", "LassoLarsCV", "KNeighborsRegressor", "DecisionTreeRegressor", "ElasticNetCV", "transformers","scalers", "SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["RidgeCV", "LinearSVR", "LassoLarsCV", "KNeighborsRegressor", "DecisionTreeRegressor", "ElasticNetCV", "transformers","scalers", "SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) else: - inner_search_space = tpot2.config.get_search_space(["transformers", "scalers", "SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) + inner_search_space = tpot.config.get_search_space(["transformers", "scalers", "SelectFwe", "SelectPercentile", "VarianceThreshold"],**get_search_space_params) - search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline( + search_space = tpot.search_spaces.pipelines.GraphSearchPipeline( root_search_space= root_search_space, leaf_search_space = None, inner_search_space = inner_search_space, @@ -165,7 +165,7 @@ def get_light_search_space(classification=True, inner_predictors=False, cross_va # this allows us to wrap the classifiers in the EstimatorTransformer # this is necessary so that classifiers can be used inside of sklearn pipelines - wrapped_estimators = WrapperPipeline(tpot2.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':cross_val_predict_cv}, estimators) + wrapped_estimators = WrapperPipeline(tpot.builtin_modules.EstimatorTransformer, {'cross_val_predict_cv':cross_val_predict_cv}, estimators) scalers = get_search_space(["scalers","Passthrough"], **get_search_space_params) diff --git a/tpot2/config/tests/__init__.py b/tpot/config/tests/__init__.py similarity index 100% rename from tpot2/config/tests/__init__.py rename to tpot/config/tests/__init__.py diff --git a/tpot2/config/tests/test_get_configspace.py b/tpot/config/tests/test_get_configspace.py similarity index 73% rename from tpot2/config/tests/test_get_configspace.py rename to tpot/config/tests/test_get_configspace.py index ae9af09a..17ac866a 100644 --- a/tpot2/config/tests/test_get_configspace.py +++ b/tpot/config/tests/test_get_configspace.py @@ -1,10 +1,10 @@ import pytest -import tpot2 +import tpot from sklearn.datasets import load_iris import random import sklearn -import tpot2.config +import tpot.config from ..get_configspace import STRING_TO_CLASS, GROUPNAMES @@ -17,7 +17,7 @@ def test_loop_through_all_hyperparameters(): for class_name, _ in STRING_TO_CLASS.items(): print(class_name) - estnode_gen = tpot2.config.get_search_space(class_name, n_classes=n_classes, n_samples=n_samples, n_features=n_features, random_state=random_state) + estnode_gen = tpot.config.get_search_space(class_name, n_classes=n_classes, n_samples=n_samples, n_features=n_features, random_state=random_state) #generate 100 random hyperparameters and make sure they are all valid for i in range(25): @@ -34,7 +34,7 @@ def test_loop_through_groupnames(): for groupname, group in GROUPNAMES.items(): for class_name in group: print(class_name) - estnode_gen = tpot2.config.get_search_space(class_name, n_classes=n_classes, n_samples=n_samples, n_features=n_features, random_state=random_state) + estnode_gen = tpot.config.get_search_space(class_name, n_classes=n_classes, n_samples=n_samples, n_features=n_features, random_state=random_state) #generate 10 random hyperparameters and make sure they are all valid for i in range(25): diff --git a/tpot2/config/transformers.py b/tpot/config/transformers.py similarity index 100% rename from tpot2/config/transformers.py rename to tpot/config/transformers.py diff --git a/tpot2/evolvers/__init__.py b/tpot/evolvers/__init__.py similarity index 100% rename from tpot2/evolvers/__init__.py rename to tpot/evolvers/__init__.py diff --git a/tpot2/evolvers/base_evolver.py b/tpot/evolvers/base_evolver.py similarity index 97% rename from tpot2/evolvers/base_evolver.py rename to tpot/evolvers/base_evolver.py index 7b1c50f9..9bdd416d 100644 --- a/tpot2/evolvers/base_evolver.py +++ b/tpot/evolvers/base_evolver.py @@ -35,10 +35,10 @@ #All abstract methods in the Evolutionary_Optimization module from abc import abstractmethod -import tpot2 +import tpot import typing import tqdm -from tpot2 import BaseIndividual +from tpot import BaseIndividual import time import numpy as np import copy @@ -50,9 +50,9 @@ import distributed from dask.distributed import Client from dask.distributed import LocalCluster -from tpot2.selectors import survival_select_NSGA2, tournament_selection_dominated +from tpot.selectors import survival_select_NSGA2, tournament_selection_dominated import math -from tpot2.utils.utils import get_thresholds, beta_interpolation, remove_items, equalize_list +from tpot.utils.utils import get_thresholds, beta_interpolation, remove_items, equalize_list # Evolvers allow you to pass in custom mutation and crossover functions. By default, # the evolver will just use these functions to call ind.mutate or ind.crossover @@ -432,7 +432,7 @@ def __init__( self, if self.budget_range is not None: init_names = init_names + ["Budget"] if self.population is None: - self.population = tpot2.Population(column_names=init_names) + self.population = tpot.Population(column_names=init_names) initial_population = [next(self.individual_generator) for _ in range(self.cur_population_size)] self.population.add_to_population(initial_population, self.rng) self.population.update_column(self.population.population, column_names="Generation", data=self.generation) @@ -580,7 +580,7 @@ def optimize(self, generations=None): self._client.close() self._cluster.close() - tpot2.utils.get_pareto_frontier(self.population.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) + tpot.utils.get_pareto_frontier(self.population.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) def step(self,): """ @@ -714,7 +714,7 @@ def evaluate_population_full(self, budget=None): if parallel_timeout < 0: parallel_timeout = 10 - scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(individuals_to_evaluate, self.objective_functions, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, budget=budget, n_expected_columns=len(self.objective_names), client=self._client, scheduled_timeout_time=self.scheduled_timeout_time, **self.objective_kwargs) + scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(individuals_to_evaluate, self.objective_functions, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, budget=budget, n_expected_columns=len(self.objective_names), client=self._client, scheduled_timeout_time=self.scheduled_timeout_time, **self.objective_kwargs) self.population.update_column(individuals_to_evaluate, column_names=self.objective_names, data=scores) if budget is not None: @@ -785,7 +785,7 @@ def evaluate_population_selection_early_stop(self,survival_counts, thresholds=No Budget to use when evaluating individuals. Use is dependent on the objective functions. (In TPOTEstimator this corresponds to the percentage of the data to sample.) """ - survival_selector = tpot2.selectors.survival_select_NSGA2 + survival_selector = tpot.selectors.survival_select_NSGA2 ################ @@ -820,7 +820,7 @@ def evaluate_population_selection_early_stop(self,survival_counts, thresholds=No if parallel_timeout < 0: parallel_timeout = 10 - scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(individual_list=unevaluated_individuals_this_step, + scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(individual_list=unevaluated_individuals_this_step, objective_list=self.objective_functions, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, diff --git a/tpot2/evolvers/steady_state_evolver.py b/tpot/evolvers/steady_state_evolver.py similarity index 97% rename from tpot2/evolvers/steady_state_evolver.py rename to tpot/evolvers/steady_state_evolver.py index 2cd2cc74..7ba20a76 100644 --- a/tpot2/evolvers/steady_state_evolver.py +++ b/tpot/evolvers/steady_state_evolver.py @@ -33,7 +33,7 @@ """ #All abstract methods in the Evolutionary_Optimization module -import tpot2 +import tpot import typing import tqdm import time @@ -44,9 +44,9 @@ import distributed from dask.distributed import Client from dask.distributed import LocalCluster -from tpot2.selectors import survival_select_NSGA2, tournament_selection_dominated +from tpot.selectors import survival_select_NSGA2, tournament_selection_dominated import math -from tpot2.utils.utils import get_thresholds, beta_interpolation, remove_items, equalize_list +from tpot.utils.utils import get_thresholds, beta_interpolation, remove_items, equalize_list import dask import warnings @@ -342,7 +342,7 @@ def __init__( self, if self.budget_range is not None: init_names = init_names + ["Budget"] if self.population is None: - self.population = tpot2.Population(column_names=init_names) + self.population = tpot.Population(column_names=init_names) initial_population = [next(self.individual_generator) for _ in range(self.initial_population_size)] self.population.add_to_population(initial_population, rng=self.rng) @@ -403,7 +403,7 @@ def optimize(self): for individual in individuals_to_evaluate: if len(submitted_futures) >= self.max_queue_size: break - future = self._client.submit(tpot2.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) + future = self._client.submit(tpot.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) submitted_futures[future] = {"individual": individual, "time": time.time(), @@ -569,7 +569,7 @@ def optimize(self): individuals_to_evaluate = [ind for ind in individuals_to_evaluate if ind.unique_id() not in submitted_inds] for individual in individuals_to_evaluate: if self.max_queue_size > len(submitted_futures): - future = self._client.submit(tpot2.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) + future = self._client.submit(tpot.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) submitted_futures[future] = {"individual": individual, "time": time.time(), @@ -687,7 +687,7 @@ def optimize(self): individuals_to_evaluate = [ind for ind in individuals_to_evaluate if ind.unique_id() not in submitted_inds] for individual in individuals_to_evaluate: if self.max_queue_size > len(submitted_futures): - future = self._client.submit(tpot2.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) + future = self._client.submit(tpot.utils.eval_utils.eval_objective_list, individual, self.objective_functions, verbose=self.verbose, timeout=self.max_eval_time_mins*60,**self.objective_kwargs) submitted_futures[future] = {"individual": individual, "time": time.time(), @@ -726,7 +726,7 @@ def optimize(self): self._client.close() self._cluster.close() - tpot2.utils.get_pareto_frontier(self.population.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) + tpot.utils.get_pareto_frontier(self.population.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) def get_unevaluated_individuals(self, column_names, budget=None, individual_list=None): diff --git a/tpot2/graphsklearn.py b/tpot/graphsklearn.py similarity index 100% rename from tpot2/graphsklearn.py rename to tpot/graphsklearn.py diff --git a/tpot2/individual.py b/tpot/individual.py similarity index 100% rename from tpot2/individual.py rename to tpot/individual.py diff --git a/tpot2/logbook.py b/tpot/logbook.py similarity index 100% rename from tpot2/logbook.py rename to tpot/logbook.py diff --git a/tpot2/objectives/__init__.py b/tpot/objectives/__init__.py similarity index 100% rename from tpot2/objectives/__init__.py rename to tpot/objectives/__init__.py diff --git a/tpot2/objectives/average_path_length.py b/tpot/objectives/average_path_length.py similarity index 100% rename from tpot2/objectives/average_path_length.py rename to tpot/objectives/average_path_length.py diff --git a/tpot2/objectives/complexity.py b/tpot/objectives/complexity.py similarity index 99% rename from tpot2/objectives/complexity.py rename to tpot/objectives/complexity.py index a5ff3a8b..43c3131d 100644 --- a/tpot2/objectives/complexity.py +++ b/tpot/objectives/complexity.py @@ -32,7 +32,7 @@ License along with TPOT. If not, see . """ -from tpot2 import GraphPipeline +from tpot import GraphPipeline import numpy as np import sklearn import warnings diff --git a/tpot2/objectives/number_of_leaves.py b/tpot/objectives/number_of_leaves.py similarity index 100% rename from tpot2/objectives/number_of_leaves.py rename to tpot/objectives/number_of_leaves.py diff --git a/tpot2/objectives/number_of_nodes.py b/tpot/objectives/number_of_nodes.py similarity index 100% rename from tpot2/objectives/number_of_nodes.py rename to tpot/objectives/number_of_nodes.py diff --git a/tpot2/objectives/tests/test_complexity_objective.py b/tpot/objectives/tests/test_complexity_objective.py similarity index 100% rename from tpot2/objectives/tests/test_complexity_objective.py rename to tpot/objectives/tests/test_complexity_objective.py diff --git a/tpot2/objectives/tests/test_number_of_nodes.py b/tpot/objectives/tests/test_number_of_nodes.py similarity index 79% rename from tpot2/objectives/tests/test_number_of_nodes.py rename to tpot/objectives/tests/test_number_of_nodes.py index cfb94726..d13e186d 100644 --- a/tpot2/objectives/tests/test_number_of_nodes.py +++ b/tpot/objectives/tests/test_number_of_nodes.py @@ -1,5 +1,5 @@ import pytest -import tpot2 +import tpot from sklearn.datasets import load_iris import random import sklearn @@ -11,8 +11,8 @@ from sklearn.model_selection import train_test_split from sklearn.pipeline import Pipeline import networkx as nx -import tpot2 -from tpot2 import GraphPipeline +import tpot +from tpot import GraphPipeline import sklearn.metrics def test_number_of_nodes_objective_Graphpipeline(): @@ -30,17 +30,17 @@ def test_number_of_nodes_objective_Graphpipeline(): est = GraphPipeline(g) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(est) == 4 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(est) == 4 def test_number_of_nodes_objective_Pipeline(): pipe = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(pipe) == 2 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(pipe) == 2 def test_number_of_nodes_objective_not_pipeline_or_graphpipeline(): - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(SVC()) == 1 - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(StandardScaler()) == 1 - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(LogisticRegression()) == 1 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(SVC()) == 1 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(StandardScaler()) == 1 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(LogisticRegression()) == 1 def test_number_of_nodes_objective_pipeline_in_graphpipeline(): g = nx.DiGraph() @@ -52,7 +52,7 @@ def test_number_of_nodes_objective_pipeline_in_graphpipeline(): est = GraphPipeline(g) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(est) == 3 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(est) == 3 def test_number_of_nodes_objective_graphpipeline_in_pipeline(): pipe = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) @@ -73,7 +73,7 @@ def test_number_of_nodes_objective_graphpipeline_in_pipeline(): pipe.steps.append(("graphpipe", est)) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(pipe) == 6 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(pipe) == 6 def test_number_of_nodes_objective_graphpipeline_in_graphpipeline(): @@ -105,11 +105,11 @@ def test_number_of_nodes_objective_graphpipeline_in_graphpipeline(): est2 = GraphPipeline(g2) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(est2) == 7 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(est2) == 7 def test_number_of_nodes_objective_pipeline_in_pipeline(): pipe = Pipeline([("scaler", StandardScaler()), ("svc", SVC())]) pipe2 = Pipeline([("pipe", pipe), ("svc", SVC())]) - assert tpot2.objectives.number_of_nodes.number_of_nodes_objective(pipe2) == 3 + assert tpot.objectives.number_of_nodes.number_of_nodes_objective(pipe2) == 3 diff --git a/tpot2/old_config_utils/__init__.py b/tpot/old_config_utils/__init__.py similarity index 100% rename from tpot2/old_config_utils/__init__.py rename to tpot/old_config_utils/__init__.py diff --git a/tpot2/old_config_utils/old_config_utils.py b/tpot/old_config_utils/old_config_utils.py similarity index 93% rename from tpot2/old_config_utils/old_config_utils.py rename to tpot/old_config_utils/old_config_utils.py index 4903e33a..fd12ed71 100644 --- a/tpot2/old_config_utils/old_config_utils.py +++ b/tpot/old_config_utils/old_config_utils.py @@ -72,7 +72,7 @@ def hyperparameter_parser(hdict, function_params_conversion_dict): def get_node_space(module_string, params): """ - Create the search space for a single node in the TPOT2 config. + Create the search space for a single node in the TPOT config. Parameters ---------- @@ -160,12 +160,12 @@ def get_node_space(module_string, params): def convert_config_dict_to_list(config_dict): """ - Takes in a TPOT2 config dictionary and returns a list of search spaces (EstimatorNode, WrapperPipeline) + Takes in a TPOT config dictionary and returns a list of search spaces (EstimatorNode, WrapperPipeline) Parameters ---------- config_dict : dict - The dictionary representation of the TPOT2 config. + The dictionary representation of the TPOT config. Returns ------- @@ -180,13 +180,13 @@ def convert_config_dict_to_list(config_dict): def convert_config_dict_to_choicepipeline(config_dict): """ - Takes in a TPOT2 config dictionary and returns a ChoicePipeline search space that represents the config_dict. + Takes in a TPOT config dictionary and returns a ChoicePipeline search space that represents the config_dict. This space will sample from all included modules in the config_dict. Parameters ---------- config_dict : dict - The dictionary representation of the TPOT2 config. + The dictionary representation of the TPOT config. Returns ------- @@ -201,14 +201,14 @@ def convert_config_dict_to_choicepipeline(config_dict): #Note doesn't convert estimators so they passthrough inputs like in TPOT1 def convert_config_dict_to_graphpipeline(config_dict): """ - Takes in a TPOT2 config dictionary and returns a GraphSearchPipeline search space that represents the config_dict. + Takes in a TPOT config dictionary and returns a GraphSearchPipeline search space that represents the config_dict. This space will sample from all included modules in the config_dict. It will also identify classifiers/regressors to set the search space for the root node. Note doesn't convert estimators so they passthrough inputs like in TPOT1 Parameters ---------- config_dict : dict - The dictionary representation of the TPOT2 config. + The dictionary representation of the TPOT config. Returns ------- @@ -243,14 +243,14 @@ def convert_config_dict_to_graphpipeline(config_dict): #Note doesn't convert estimators so they passthrough inputs like in TPOT1 def convert_config_dict_to_linearpipeline(config_dict): """ - Takes in a TPOT2 config dictionary and returns a GraphSearchPipeline search space that represents the config_dict. + Takes in a TPOT config dictionary and returns a GraphSearchPipeline search space that represents the config_dict. This space will sample from all included modules in the config_dict. It will also identify classifiers/regressors to set the search space for the root node. Note doesn't convert estimators so they passthrough inputs like in TPOT1 Parameters ---------- config_dict : dict - The dictionary representation of the TPOT2 config. + The dictionary representation of the TPOT config. Returns ------- diff --git a/tpot2/population.py b/tpot/population.py similarity index 99% rename from tpot2/population.py rename to tpot/population.py index f19660cf..baf7fdf7 100644 --- a/tpot2/population.py +++ b/tpot/population.py @@ -36,8 +36,8 @@ import copy import copy import typing -import tpot2 -from tpot2 import BaseIndividual +import tpot +from tpot import BaseIndividual from traitlets import Bool import collections import pandas as pd diff --git a/tpot2/search_spaces/__init__.py b/tpot/search_spaces/__init__.py similarity index 100% rename from tpot2/search_spaces/__init__.py rename to tpot/search_spaces/__init__.py diff --git a/tpot2/search_spaces/base.py b/tpot/search_spaces/base.py similarity index 96% rename from tpot2/search_spaces/base.py rename to tpot/search_spaces/base.py index de0e660d..0a224d6d 100644 --- a/tpot2/search_spaces/base.py +++ b/tpot/search_spaces/base.py @@ -32,7 +32,7 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import sklearn from sklearn.base import BaseEstimator import sklearn @@ -42,7 +42,7 @@ -class SklearnIndividual(tpot2.BaseIndividual): +class SklearnIndividual(tpot.BaseIndividual): def __init_subclass__(cls): cls.crossover = cls.validate_same_type(cls.crossover) @@ -95,7 +95,7 @@ def get_size(self): return 1 @final - def export_flattened_graphpipeline(self, **graphpipeline_kwargs) -> tpot2.GraphPipeline: + def export_flattened_graphpipeline(self, **graphpipeline_kwargs) -> tpot.GraphPipeline: return flatten_to_graphpipeline(self.export_pipeline(), **graphpipeline_kwargs) class SearchSpace(): @@ -163,7 +163,7 @@ def flatten_estimator(est): return graph def flatten_any(est): - if isinstance(est, tpot2.GraphPipeline): + if isinstance(est, tpot.GraphPipeline): return flatten_graphpipeline(est) elif isinstance(est, sklearn.pipeline.Pipeline): return flatten_pipeline(est) @@ -193,4 +193,4 @@ def flatten_to_graphpipeline(est, **graphpipeline_kwargs): for label, instance in label_to_instance.items(): flattened_full_graph.nodes[label]["instance"] = instance - return tpot2.GraphPipeline(flattened_full_graph, **graphpipeline_kwargs) \ No newline at end of file + return tpot.GraphPipeline(flattened_full_graph, **graphpipeline_kwargs) \ No newline at end of file diff --git a/tpot2/search_spaces/graph_utils.py b/tpot/search_spaces/graph_utils.py similarity index 100% rename from tpot2/search_spaces/graph_utils.py rename to tpot/search_spaces/graph_utils.py diff --git a/tpot2/search_spaces/nodes/__init__.py b/tpot/search_spaces/nodes/__init__.py similarity index 100% rename from tpot2/search_spaces/nodes/__init__.py rename to tpot/search_spaces/nodes/__init__.py diff --git a/tpot2/search_spaces/nodes/estimator_node.py b/tpot/search_spaces/nodes/estimator_node.py similarity index 100% rename from tpot2/search_spaces/nodes/estimator_node.py rename to tpot/search_spaces/nodes/estimator_node.py diff --git a/tpot2/search_spaces/nodes/estimator_node_gradual.py b/tpot/search_spaces/nodes/estimator_node_gradual.py similarity index 99% rename from tpot2/search_spaces/nodes/estimator_node_gradual.py rename to tpot/search_spaces/nodes/estimator_node_gradual.py index dab7a49f..29ac6b0f 100644 --- a/tpot2/search_spaces/nodes/estimator_node_gradual.py +++ b/tpot/search_spaces/nodes/estimator_node_gradual.py @@ -35,7 +35,7 @@ # try https://automl.github.io/ConfigSpace/main/api/hyperparameters.html import numpy as np -from tpot2.search_spaces.base import SklearnIndividual, SearchSpace +from tpot.search_spaces.base import SklearnIndividual, SearchSpace from ConfigSpace import ConfigurationSpace from typing import final import ConfigSpace diff --git a/tpot2/search_spaces/nodes/fss_node.py b/tpot/search_spaces/nodes/fss_node.py similarity index 99% rename from tpot2/search_spaces/nodes/fss_node.py rename to tpot/search_spaces/nodes/fss_node.py index ada93cba..e57f1a94 100644 --- a/tpot2/search_spaces/nodes/fss_node.py +++ b/tpot/search_spaces/nodes/fss_node.py @@ -33,7 +33,7 @@ """ from numpy import iterable -import tpot2 +import tpot import numpy as np import sklearn import sklearn.datasets diff --git a/tpot2/search_spaces/nodes/genetic_feature_selection.py b/tpot/search_spaces/nodes/genetic_feature_selection.py similarity index 99% rename from tpot2/search_spaces/nodes/genetic_feature_selection.py rename to tpot/search_spaces/nodes/genetic_feature_selection.py index fb71a280..021a9fc4 100644 --- a/tpot2/search_spaces/nodes/genetic_feature_selection.py +++ b/tpot/search_spaces/nodes/genetic_feature_selection.py @@ -33,7 +33,7 @@ """ from numpy import iterable -import tpot2 +import tpot import numpy as np import sklearn import sklearn.datasets diff --git a/tpot2/search_spaces/pipelines/__init__.py b/tpot/search_spaces/pipelines/__init__.py similarity index 100% rename from tpot2/search_spaces/pipelines/__init__.py rename to tpot/search_spaces/pipelines/__init__.py diff --git a/tpot2/search_spaces/pipelines/choice.py b/tpot/search_spaces/pipelines/choice.py similarity index 98% rename from tpot2/search_spaces/pipelines/choice.py rename to tpot/search_spaces/pipelines/choice.py index dd7dfa90..524175fc 100644 --- a/tpot2/search_spaces/pipelines/choice.py +++ b/tpot/search_spaces/pipelines/choice.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/dynamic_linear.py b/tpot/search_spaces/pipelines/dynamic_linear.py similarity index 99% rename from tpot2/search_spaces/pipelines/dynamic_linear.py rename to tpot/search_spaces/pipelines/dynamic_linear.py index f82f2b24..3f53555e 100644 --- a/tpot2/search_spaces/pipelines/dynamic_linear.py +++ b/tpot/search_spaces/pipelines/dynamic_linear.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/dynamicunion.py b/tpot/search_spaces/pipelines/dynamicunion.py similarity index 99% rename from tpot2/search_spaces/pipelines/dynamicunion.py rename to tpot/search_spaces/pipelines/dynamicunion.py index dd664158..ab285fa1 100644 --- a/tpot2/search_spaces/pipelines/dynamicunion.py +++ b/tpot/search_spaces/pipelines/dynamicunion.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/graph.py b/tpot/search_spaces/pipelines/graph.py similarity index 99% rename from tpot2/search_spaces/pipelines/graph.py rename to tpot/search_spaces/pipelines/graph.py index 07bc80a9..84836b1c 100644 --- a/tpot2/search_spaces/pipelines/graph.py +++ b/tpot/search_spaces/pipelines/graph.py @@ -32,7 +32,7 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np from typing import Generator, List, Tuple, Union from ..base import SklearnIndividual, SearchSpace @@ -656,7 +656,7 @@ def export_pipeline(self, memory=None, **kwargs): for label, instance in label_to_instance.items(): estimator_graph.nodes[label]["instance"] = instance - return tpot2.GraphPipeline(graph=estimator_graph, memory=memory, use_label_encoder=self.use_label_encoder, method=self.method, cross_val_predict_cv=self.cross_val_predict_cv) + return tpot.GraphPipeline(graph=estimator_graph, memory=memory, use_label_encoder=self.use_label_encoder, method=self.method, cross_val_predict_cv=self.cross_val_predict_cv) def plot(self): diff --git a/tpot2/search_spaces/pipelines/sequential.py b/tpot/search_spaces/pipelines/sequential.py similarity index 99% rename from tpot2/search_spaces/pipelines/sequential.py rename to tpot/search_spaces/pipelines/sequential.py index 73ae4411..46bf97ed 100644 --- a/tpot2/search_spaces/pipelines/sequential.py +++ b/tpot/search_spaces/pipelines/sequential.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/tests/test_graphspace.py b/tpot/search_spaces/pipelines/tests/test_graphspace.py similarity index 82% rename from tpot2/search_spaces/pipelines/tests/test_graphspace.py rename to tpot/search_spaces/pipelines/tests/test_graphspace.py index ac35d0f9..f580c18a 100644 --- a/tpot2/search_spaces/pipelines/tests/test_graphspace.py +++ b/tpot/search_spaces/pipelines/tests/test_graphspace.py @@ -1,8 +1,8 @@ # Test all nodes have all dictionaries import pytest -import tpot2 +import tpot -import tpot2 +import tpot from ConfigSpace import ConfigurationSpace from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal from sklearn.neighbors import KNeighborsClassifier @@ -15,18 +15,18 @@ def test_merge_duplicate_nodes(): knn_configspace = {} standard_scaler_configspace = {} - knn_node = tpot2.search_spaces.nodes.EstimatorNode( + knn_node = tpot.search_spaces.nodes.EstimatorNode( method = KNeighborsClassifier, space = knn_configspace, ) - scaler_node = tpot2.search_spaces.nodes.EstimatorNode( + scaler_node = tpot.search_spaces.nodes.EstimatorNode( method = StandardScaler, space = standard_scaler_configspace, ) - graph_search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline( + graph_search_space = tpot.search_spaces.pipelines.GraphSearchPipeline( root_search_space= knn_node, leaf_search_space = scaler_node, inner_search_space = None, diff --git a/tpot2/search_spaces/pipelines/tree.py b/tpot/search_spaces/pipelines/tree.py similarity index 98% rename from tpot2/search_spaces/pipelines/tree.py rename to tpot/search_spaces/pipelines/tree.py index 1b825e71..7e2dc8f8 100644 --- a/tpot2/search_spaces/pipelines/tree.py +++ b/tpot/search_spaces/pipelines/tree.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/union.py b/tpot/search_spaces/pipelines/union.py similarity index 99% rename from tpot2/search_spaces/pipelines/union.py rename to tpot/search_spaces/pipelines/union.py index 299bb078..0fa4421f 100644 --- a/tpot2/search_spaces/pipelines/union.py +++ b/tpot/search_spaces/pipelines/union.py @@ -32,11 +32,11 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/pipelines/wrapper.py b/tpot/search_spaces/pipelines/wrapper.py similarity index 99% rename from tpot2/search_spaces/pipelines/wrapper.py rename to tpot/search_spaces/pipelines/wrapper.py index 72da82ca..df01ed6f 100644 --- a/tpot2/search_spaces/pipelines/wrapper.py +++ b/tpot/search_spaces/pipelines/wrapper.py @@ -36,7 +36,7 @@ import numpy as np import pandas as pd import sklearn -from tpot2 import config +from tpot import config from typing import Generator, List, Tuple, Union import random from ..base import SklearnIndividual, SearchSpace diff --git a/tpot2/search_spaces/tests/test_search_spaces.py b/tpot/search_spaces/tests/test_search_spaces.py similarity index 91% rename from tpot2/search_spaces/tests/test_search_spaces.py rename to tpot/search_spaces/tests/test_search_spaces.py index ff228ede..7759b549 100644 --- a/tpot2/search_spaces/tests/test_search_spaces.py +++ b/tpot/search_spaces/tests/test_search_spaces.py @@ -34,9 +34,9 @@ """ # Test all nodes have all dictionaries import pytest -import tpot2 +import tpot -import tpot2 +import tpot from ConfigSpace import ConfigurationSpace from ConfigSpace import ConfigurationSpace, Integer, Float, Categorical, Normal from sklearn.neighbors import KNeighborsClassifier @@ -49,7 +49,7 @@ def test_EstimatorNodeCrossover(): knn_configspace = {} standard_scaler_configspace = {} - knn_node = tpot2.search_spaces.nodes.EstimatorNode( + knn_node = tpot.search_spaces.nodes.EstimatorNode( method = KNeighborsClassifier, space = knn_configspace, ) @@ -64,8 +64,8 @@ def test_EstimatorNodeCrossover(): def test_ValueError_different_types(): - knn_node = tpot2.config.get_search_space(["KNeighborsClassifier"]) - sfm_wrapper_node = tpot2.config.get_search_space(["SelectFromModel_classification"]) + knn_node = tpot.config.get_search_space(["KNeighborsClassifier"]) + sfm_wrapper_node = tpot.config.get_search_space(["SelectFromModel_classification"]) for i in range(10): ind1 = knn_node.generate() diff --git a/tpot2/search_spaces/tuple_index.py b/tpot/search_spaces/tuple_index.py similarity index 100% rename from tpot2/search_spaces/tuple_index.py rename to tpot/search_spaces/tuple_index.py diff --git a/tpot2/selectors/__init__.py b/tpot/selectors/__init__.py similarity index 100% rename from tpot2/selectors/__init__.py rename to tpot/selectors/__init__.py diff --git a/tpot2/selectors/lexicase_selection.py b/tpot/selectors/lexicase_selection.py similarity index 100% rename from tpot2/selectors/lexicase_selection.py rename to tpot/selectors/lexicase_selection.py diff --git a/tpot2/selectors/map_elites_selection.py b/tpot/selectors/map_elites_selection.py similarity index 100% rename from tpot2/selectors/map_elites_selection.py rename to tpot/selectors/map_elites_selection.py diff --git a/tpot2/selectors/max_weighted_average_selector.py b/tpot/selectors/max_weighted_average_selector.py similarity index 100% rename from tpot2/selectors/max_weighted_average_selector.py rename to tpot/selectors/max_weighted_average_selector.py diff --git a/tpot2/selectors/nsgaii.py b/tpot/selectors/nsgaii.py similarity index 100% rename from tpot2/selectors/nsgaii.py rename to tpot/selectors/nsgaii.py diff --git a/tpot2/selectors/random_selector.py b/tpot/selectors/random_selector.py similarity index 100% rename from tpot2/selectors/random_selector.py rename to tpot/selectors/random_selector.py diff --git a/tpot2/selectors/tournament_selection.py b/tpot/selectors/tournament_selection.py similarity index 100% rename from tpot2/selectors/tournament_selection.py rename to tpot/selectors/tournament_selection.py diff --git a/tpot2/selectors/tournament_selection_dominated.py b/tpot/selectors/tournament_selection_dominated.py similarity index 100% rename from tpot2/selectors/tournament_selection_dominated.py rename to tpot/selectors/tournament_selection_dominated.py diff --git a/tpot2/tests/__init__.py b/tpot/tests/__init__.py similarity index 100% rename from tpot2/tests/__init__.py rename to tpot/tests/__init__.py diff --git a/tpot2/tests/conftest.py b/tpot/tests/conftest.py similarity index 100% rename from tpot2/tests/conftest.py rename to tpot/tests/conftest.py diff --git a/tpot2/tests/test_estimators.py b/tpot/tests/test_estimators.py similarity index 78% rename from tpot2/tests/test_estimators.py rename to tpot/tests/test_estimators.py index 9b394e5f..c85132a2 100644 --- a/tpot2/tests/test_estimators.py +++ b/tpot/tests/test_estimators.py @@ -33,7 +33,7 @@ """ import pytest -import tpot2 +import tpot from sklearn.datasets import load_iris import random import sklearn @@ -51,13 +51,13 @@ def tpot_estimator(): n_samples=100 n_features=100 - search_space = tpot2.search_spaces.pipelines.GraphSearchPipeline( - root_search_space= tpot2.config.get_search_space("classifiers", n_samples=n_samples, n_features=n_features, n_classes=n_classes), + search_space = tpot.search_spaces.pipelines.GraphSearchPipeline( + root_search_space= tpot.config.get_search_space("classifiers", n_samples=n_samples, n_features=n_features, n_classes=n_classes), leaf_search_space = None, - inner_search_space = tpot2.config.get_search_space(["selectors","transformers"],n_samples=n_samples, n_features=n_features, n_classes=n_classes), + inner_search_space = tpot.config.get_search_space(["selectors","transformers"],n_samples=n_samples, n_features=n_features, n_classes=n_classes), max_size = 10, ) - return tpot2.TPOTEstimator( + return tpot.TPOTEstimator( search_space=search_space, population_size=10, generations=2, @@ -73,11 +73,11 @@ def tpot_estimator(): @pytest.fixture def tpot_classifier(): - return tpot2.tpot_estimator.templates.TPOTClassifier(max_time_mins=10/60,verbose=0) + return tpot.tpot_estimator.templates.TPOTClassifier(max_time_mins=10/60,verbose=0) @pytest.fixture def tpot_regressor(): - return tpot2.tpot_estimator.templates.TPOTRegressor(max_time_mins=10/60,verbose=0) + return tpot.tpot_estimator.templates.TPOTRegressor(max_time_mins=10/60,verbose=0) @pytest.fixture @@ -95,31 +95,31 @@ def test_tpot_estimator_predict(tpot_estimator_with_pipeline,sample_dataset): def test_tpot_estimator_generations_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations="two", population_size=10, verbosity=2) + tpot.TPOTEstimator(generations="two", population_size=10, verbosity=2) def test_tpot_estimator_population_size_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size='ten', verbosity=2) + tpot.TPOTEstimator(generations=2, population_size='ten', verbosity=2) def test_tpot_estimator_verbosity_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size=10, verbosity='high') + tpot.TPOTEstimator(generations=2, population_size=10, verbosity='high') def test_tpot_estimator_scoring_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size=10, verbosity=2, scoring=0.5) + tpot.TPOTEstimator(generations=2, population_size=10, verbosity=2, scoring=0.5) def test_tpot_estimator_cv_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size=10, verbosity=2, cv='kfold') + tpot.TPOTEstimator(generations=2, population_size=10, verbosity=2, cv='kfold') def test_tpot_estimator_n_jobs_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size=10, verbosity=2, n_jobs='all') + tpot.TPOTEstimator(generations=2, population_size=10, verbosity=2, n_jobs='all') def test_tpot_estimator_config_dict_type(): with pytest.raises(TypeError): - tpot2.TPOTEstimator(generations=2, population_size=10, verbosity=2, config_dict='config') + tpot.TPOTEstimator(generations=2, population_size=10, verbosity=2, config_dict='config') diff --git a/tpot2/tests/test_hello_world.py b/tpot/tests/test_hello_world.py similarity index 100% rename from tpot2/tests/test_hello_world.py rename to tpot/tests/test_hello_world.py diff --git a/tpot2/tpot_estimator/__init__.py b/tpot/tpot_estimator/__init__.py similarity index 100% rename from tpot2/tpot_estimator/__init__.py rename to tpot/tpot_estimator/__init__.py diff --git a/tpot2/tpot_estimator/cross_val_utils.py b/tpot/tpot_estimator/cross_val_utils.py similarity index 100% rename from tpot2/tpot_estimator/cross_val_utils.py rename to tpot/tpot_estimator/cross_val_utils.py diff --git a/tpot2/tpot_estimator/estimator.py b/tpot/tpot_estimator/estimator.py similarity index 96% rename from tpot2/tpot_estimator/estimator.py rename to tpot/tpot_estimator/estimator.py index c71bc2ce..91745c53 100644 --- a/tpot2/tpot_estimator/estimator.py +++ b/tpot/tpot_estimator/estimator.py @@ -36,14 +36,14 @@ from sklearn.utils.metaestimators import available_if import numpy as np import sklearn.metrics -import tpot2.config +import tpot.config from sklearn.utils.validation import check_is_fitted -from tpot2.selectors import survival_select_NSGA2, tournament_selection_dominated +from tpot.selectors import survival_select_NSGA2, tournament_selection_dominated from sklearn.preprocessing import LabelEncoder import pandas as pd from sklearn.model_selection import train_test_split -import tpot2 +import tpot from dask.distributed import Client from dask.distributed import LocalCluster from sklearn.preprocessing import LabelEncoder @@ -478,7 +478,7 @@ def __init__(self, self._scorers = [sklearn.metrics.get_scorer(scoring) for scoring in self._scorers] self._scorers_early_stop_tol = self.scorers_early_stop_tol - self._evolver = tpot2.evolvers.BaseEvolver + self._evolver = tpot.evolvers.BaseEvolver self.objective_function_weights = [*scorers_weights, *other_objective_functions_weights] @@ -579,21 +579,21 @@ def fit(self, X, y): pipeline_steps = [] if self.categorical_features is not None: #if categorical features are specified, use those - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnSimpleImputer(self.categorical_features, strategy='most_frequent'))) - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) - pipeline_steps.append(("ColumnOneHotEncoder", tpot2.builtin_modules.ColumnOneHotEncoder(self.categorical_features, strategy='most_frequent'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnSimpleImputer(self.categorical_features, strategy='most_frequent'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) + pipeline_steps.append(("ColumnOneHotEncoder", tpot.builtin_modules.ColumnOneHotEncoder(self.categorical_features, strategy='most_frequent'))) else: if isinstance(X, pd.DataFrame): categorical_columns = X.select_dtypes(include=['object']).columns if len(categorical_columns) > 0: - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnSimpleImputer("categorical", strategy='most_frequent'))) - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) - pipeline_steps.append(("ColumnOneHotEncoder", tpot2.builtin_modules.ColumnOneHotEncoder("categorical", strategy='most_frequent'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnSimpleImputer("categorical", strategy='most_frequent'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) + pipeline_steps.append(("ColumnOneHotEncoder", tpot.builtin_modules.ColumnOneHotEncoder("categorical", strategy='most_frequent'))) else: - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) else: - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) self._preprocessing_pipeline = sklearn.pipeline.Pipeline(pipeline_steps) @@ -693,15 +693,15 @@ def objective_function(pipeline_individual, # } # ) - # imputation_search = tpot2.search_spaces.pipelines.ChoicePipeline([ - # tpot2.config.get_search_space("SimpleImputer"), - # tpot2.search_spaces.nodes.EstimatorNode(sklearn.impute.IterativeImputer, iterative_imputer_cs) + # imputation_search = tpot.search_spaces.pipelines.ChoicePipeline([ + # tpot.config.get_search_space("SimpleImputer"), + # tpot.search_spaces.nodes.EstimatorNode(sklearn.impute.IterativeImputer, iterative_imputer_cs) # ]) - # self.search_space_final = tpot2.search_spaces.pipelines.SequentialPipeline(search_spaces=[ imputation_search, self._search_space], memory="sklearn_pipeline_memory") + # self.search_space_final = tpot.search_spaces.pipelines.SequentialPipeline(search_spaces=[ imputation_search, self._search_space], memory="sklearn_pipeline_memory") # else: # self.search_space_final = self._search_space @@ -767,7 +767,7 @@ def ind_generator(rng): - tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) + tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) if validation_strategy == 'reshuffled': best_pareto_front_idx = list(self.pareto_front.index) @@ -806,7 +806,7 @@ def ind_generator(rng): )] objective_kwargs = {"X": X_future, "y": y_future} - val_scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) + val_scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) @@ -817,7 +817,7 @@ def ind_generator(rng): self.evaluated_individuals.loc[best_pareto_front_idx,'validation_end_times'] = end_times self.evaluated_individuals.loc[best_pareto_front_idx,'validation_eval_errors'] = eval_errors - self.evaluated_individuals["Validation_Pareto_Front"] = tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) + self.evaluated_individuals["Validation_Pareto_Front"] = tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) elif validation_strategy == 'split': @@ -860,7 +860,7 @@ def ind_generator(rng): **kwargs, )] - val_scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) + val_scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) @@ -871,7 +871,7 @@ def ind_generator(rng): self.evaluated_individuals.loc[best_pareto_front_idx,'validation_end_times'] = end_times self.evaluated_individuals.loc[best_pareto_front_idx,'validation_eval_errors'] = eval_errors - self.evaluated_individuals["Validation_Pareto_Front"] = tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) + self.evaluated_individuals["Validation_Pareto_Front"] = tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) else: self.objective_names_for_selection = self.objective_names diff --git a/tpot2/tpot_estimator/estimator_utils.py b/tpot/tpot_estimator/estimator_utils.py similarity index 99% rename from tpot2/tpot_estimator/estimator_utils.py rename to tpot/tpot_estimator/estimator_utils.py index d44de6dd..0db3a9ee 100644 --- a/tpot2/tpot_estimator/estimator_utils.py +++ b/tpot/tpot_estimator/estimator_utils.py @@ -35,7 +35,7 @@ import numpy as np import sklearn import sklearn.base -import tpot2 +import tpot import pandas as pd from .cross_val_utils import cross_val_score_objective diff --git a/tpot2/tpot_estimator/steady_state_estimator.py b/tpot/tpot_estimator/steady_state_estimator.py similarity index 95% rename from tpot2/tpot_estimator/steady_state_estimator.py rename to tpot/tpot_estimator/steady_state_estimator.py index c0ae3b3f..3135aa40 100644 --- a/tpot2/tpot_estimator/steady_state_estimator.py +++ b/tpot/tpot_estimator/steady_state_estimator.py @@ -36,14 +36,14 @@ from sklearn.utils.metaestimators import available_if import numpy as np import sklearn.metrics -import tpot2.config +import tpot.config from sklearn.utils.validation import check_is_fitted -from tpot2.selectors import survival_select_NSGA2, tournament_selection_dominated +from tpot.selectors import survival_select_NSGA2, tournament_selection_dominated from sklearn.preprocessing import LabelEncoder from sklearn.utils.multiclass import unique_labels import pandas as pd from sklearn.model_selection import train_test_split -import tpot2 +import tpot from dask.distributed import Client from dask.distributed import LocalCluster @@ -520,7 +520,7 @@ def __init__(self, self._scorers = [sklearn.metrics.get_scorer(scoring) for scoring in self._scorers] self._scorers_early_stop_tol = self.scorers_early_stop_tol - self._evolver = tpot2.evolvers.SteadyStateEvolver + self._evolver = tpot.evolvers.SteadyStateEvolver @@ -622,21 +622,21 @@ def fit(self, X, y): pipeline_steps = [] if self.categorical_features is not None: #if categorical features are specified, use those - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnSimpleImputer(self.categorical_features, strategy='most_frequent'))) - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnOneHotEncoder(self.categorical_features, strategy='most_frequent'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnSimpleImputer(self.categorical_features, strategy='most_frequent'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnOneHotEncoder(self.categorical_features, strategy='most_frequent'))) else: if isinstance(X, pd.DataFrame): categorical_columns = X.select_dtypes(include=['object']).columns if len(categorical_columns) > 0: - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnSimpleImputer("categorical", strategy='most_frequent'))) - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) - pipeline_steps.append(("impute_categorical", tpot2.builtin_modules.ColumnOneHotEncoder("categorical", strategy='most_frequent'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnSimpleImputer("categorical", strategy='most_frequent'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("numeric", strategy='mean'))) + pipeline_steps.append(("impute_categorical", tpot.builtin_modules.ColumnOneHotEncoder("categorical", strategy='most_frequent'))) else: - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) else: - pipeline_steps.append(("impute_numeric", tpot2.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) + pipeline_steps.append(("impute_numeric", tpot.builtin_modules.ColumnSimpleImputer("all", strategy='mean'))) self._preprocessing_pipeline = sklearn.pipeline.Pipeline(pipeline_steps) @@ -762,8 +762,8 @@ def ind_generator(rng): if self.optuna_optimize_pareto_front: pareto_front_inds = self.pareto_front['Individual'].values - all_graphs, all_scores = tpot2.individual_representations.graph_pipeline_individual.simple_parallel_optuna(pareto_front_inds, objective_function, self.objective_function_weights, _client, storage=self.optuna_storage, steps=self.optuna_optimize_pareto_front_trials, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, max_time_mins=self.optuna_optimize_pareto_front_timeout, **{"X": X, "y": y}) - all_scores = tpot2.utils.eval_utils.process_scores(all_scores, len(self.objective_function_weights)) + all_graphs, all_scores = tpot.individual_representations.graph_pipeline_individual.simple_parallel_optuna(pareto_front_inds, objective_function, self.objective_function_weights, _client, storage=self.optuna_storage, steps=self.optuna_optimize_pareto_front_trials, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, max_time_mins=self.optuna_optimize_pareto_front_timeout, **{"X": X, "y": y}) + all_scores = tpot.utils.eval_utils.process_scores(all_scores, len(self.objective_function_weights)) if len(all_graphs) > 0: df = pd.DataFrame(np.column_stack((all_graphs, all_scores,np.repeat("Optuna",len(all_graphs)))), columns=["Individual"] + self.objective_names +["Parents"]) @@ -774,7 +774,7 @@ def ind_generator(rng): else: print("WARNING NO OPTUNA TRIALS COMPLETED") - tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) + tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=self.objective_names, weights=self.objective_function_weights) if validation_strategy == 'reshuffled': best_pareto_front_idx = list(self.pareto_front.index) @@ -814,7 +814,7 @@ def ind_generator(rng): )] objective_kwargs = {"X": X_future, "y": y_future} - val_scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) + val_scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) val_objective_names = ['validation_'+name for name in self.objective_names] self.objective_names_for_selection = val_objective_names @@ -823,7 +823,7 @@ def ind_generator(rng): self.evaluated_individuals.loc[best_pareto_front_idx,'validation_end_times'] = end_times self.evaluated_individuals.loc[best_pareto_front_idx,'validation_eval_errors'] = eval_errors - self.evaluated_individuals["Validation_Pareto_Front"] = tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) + self.evaluated_individuals["Validation_Pareto_Front"] = tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) elif validation_strategy == 'split': @@ -864,7 +864,7 @@ def ind_generator(rng): **kwargs, )] - val_scores, start_times, end_times, eval_errors = tpot2.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) + val_scores, start_times, end_times, eval_errors = tpot.utils.eval_utils.parallel_eval_objective_list(best_pareto_front, val_objective_function_list, verbose=self.verbose, max_eval_time_mins=self.max_eval_time_mins, n_expected_columns=len(self.objective_names), client=_client, **objective_kwargs) @@ -875,7 +875,7 @@ def ind_generator(rng): self.evaluated_individuals.loc[best_pareto_front_idx,'validation_end_times'] = end_times self.evaluated_individuals.loc[best_pareto_front_idx,'validation_eval_errors'] = eval_errors - self.evaluated_individuals["Validation_Pareto_Front"] = tpot2.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) + self.evaluated_individuals["Validation_Pareto_Front"] = tpot.utils.get_pareto_frontier(self.evaluated_individuals, column_names=val_objective_names, weights=self.objective_function_weights) else: self.objective_names_for_selection = self.objective_names diff --git a/tpot2/tpot_estimator/templates/__init__.py b/tpot/tpot_estimator/templates/__init__.py similarity index 100% rename from tpot2/tpot_estimator/templates/__init__.py rename to tpot/tpot_estimator/templates/__init__.py diff --git a/tpot2/tpot_estimator/templates/tpot_autoimputer.py b/tpot/tpot_estimator/templates/tpot_autoimputer.py similarity index 100% rename from tpot2/tpot_estimator/templates/tpot_autoimputer.py rename to tpot/tpot_estimator/templates/tpot_autoimputer.py diff --git a/tpot2/tpot_estimator/templates/tpottemplates.py b/tpot/tpot_estimator/templates/tpottemplates.py similarity index 99% rename from tpot2/tpot_estimator/templates/tpottemplates.py rename to tpot/tpot_estimator/templates/tpottemplates.py index 3f87192e..303fbd9b 100644 --- a/tpot2/tpot_estimator/templates/tpottemplates.py +++ b/tpot/tpot_estimator/templates/tpottemplates.py @@ -32,12 +32,12 @@ License along with TPOT. If not, see . """ -import tpot2 +import tpot import numpy as np import pandas as pd from ..estimator import TPOTEstimator from sklearn.utils.validation import check_X_y, check_array, check_is_fitted -from tpot2.selectors import survival_select_NSGA2, tournament_selection_dominated +from tpot.selectors import survival_select_NSGA2, tournament_selection_dominated #TODO These do not follow sklearn conventions of __init__ from ...config.template_search_spaces import get_template_search_spaces diff --git a/tpot2/tpot_estimator/tests/__init__.py b/tpot/tpot_estimator/tests/__init__.py similarity index 100% rename from tpot2/tpot_estimator/tests/__init__.py rename to tpot/tpot_estimator/tests/__init__.py diff --git a/tpot2/tpot_estimator/tests/test_estimator_utils.py b/tpot/tpot_estimator/tests/test_estimator_utils.py similarity index 100% rename from tpot2/tpot_estimator/tests/test_estimator_utils.py rename to tpot/tpot_estimator/tests/test_estimator_utils.py diff --git a/tpot2/utils/__init__.py b/tpot/utils/__init__.py similarity index 97% rename from tpot2/utils/__init__.py rename to tpot/utils/__init__.py index a456d65a..41518787 100644 --- a/tpot2/utils/__init__.py +++ b/tpot/utils/__init__.py @@ -37,7 +37,7 @@ # If amltk is installed, import the parser try: - from .amltk_parser import tpot2_parser + from .amltk_parser import tpot_parser except ImportError: # Handle the case when amltk is not installed pass diff --git a/tpot2/utils/amltk_parser.py b/tpot/utils/amltk_parser.py similarity index 82% rename from tpot2/utils/amltk_parser.py rename to tpot/utils/amltk_parser.py index a6a18658..db6e62b8 100644 --- a/tpot2/utils/amltk_parser.py +++ b/tpot/utils/amltk_parser.py @@ -33,8 +33,8 @@ """ from amltk.pipeline import Choice, Component, Sequential, Node, Fixed, Split, Join, Searchable -from tpot2.search_spaces.pipelines import SequentialPipeline, ChoicePipeline, UnionPipeline -from tpot2.search_spaces.nodes import EstimatorNode +from tpot.search_spaces.pipelines import SequentialPipeline, ChoicePipeline, UnionPipeline +from tpot.search_spaces.nodes import EstimatorNode from ConfigSpace import ConfigurationSpace def component_to_estimatornode(component: Component) -> EstimatorNode: @@ -46,8 +46,8 @@ def component_to_estimatornode(component: Component) -> EstimatorNode: space_dict.update(component.config) space = ConfigurationSpace(component.space) - tpot2_sp = EstimatorNode(method=method, space=space) - return tpot2_sp + tpot_sp = EstimatorNode(method=method, space=space) + return tpot_sp def fixed_to_estimatornode(node: Fixed) -> EstimatorNode: method = node.item @@ -65,26 +65,26 @@ def fixed_to_estimatornode(node: Fixed) -> EstimatorNode: if node.config is not None: space_dict.update(node.config) - tpot2_sp = EstimatorNode(method=method, space=space_dict) - return tpot2_sp + tpot_sp = EstimatorNode(method=method, space=space_dict) + return tpot_sp def sequential_to_sequentialpipeline(sequential: Sequential) -> SequentialPipeline: - nodes = [tpot2_parser(node) for node in sequential.nodes] - tpot2_sp = SequentialPipeline(search_spaces=nodes) - return tpot2_sp + nodes = [tpot_parser(node) for node in sequential.nodes] + tpot_sp = SequentialPipeline(search_spaces=nodes) + return tpot_sp def choice_to_choicepipeline(choice: Choice) -> ChoicePipeline: - nodes = [tpot2_parser(node) for node in choice.nodes] - tpot2_sp = ChoicePipeline(search_spaces=nodes) - return tpot2_sp + nodes = [tpot_parser(node) for node in choice.nodes] + tpot_sp = ChoicePipeline(search_spaces=nodes) + return tpot_sp def split_to_unionpipeline(split: Split) -> UnionPipeline: - nodes = [tpot2_parser(node) for node in split.nodes] - tpot2_sp = UnionPipeline(search_spaces=nodes) - return tpot2_sp + nodes = [tpot_parser(node) for node in split.nodes] + tpot_sp = UnionPipeline(search_spaces=nodes) + return tpot_sp -def tpot2_parser( +def tpot_parser( node: Node, ): """ diff --git a/tpot2/utils/eval_utils.py b/tpot/utils/eval_utils.py similarity index 99% rename from tpot2/utils/eval_utils.py rename to tpot/utils/eval_utils.py index 7f93cef4..3aa9e1d7 100644 --- a/tpot2/utils/eval_utils.py +++ b/tpot/utils/eval_utils.py @@ -40,7 +40,7 @@ from collections.abc import Iterable import warnings from stopit import threading_timeoutable, TimeoutException -from tpot2.selectors import survival_select_NSGA2 +from tpot.selectors import survival_select_NSGA2 import time import dask import stopit diff --git a/tpot2/utils/utils.py b/tpot/utils/utils.py similarity index 98% rename from tpot2/utils/utils.py rename to tpot/utils/utils.py index 66483b65..dec14b43 100644 --- a/tpot2/utils/utils.py +++ b/tpot/utils/utils.py @@ -35,7 +35,7 @@ import numpy as np import scipy import statistics -import tpot2 +import tpot import pandas as pd @@ -147,7 +147,7 @@ def get_pareto_front(df, column_names, weights): indexes = dftmp[~dftmp[column_names].isna().any(axis=1)].index.values weighted_scores = df.loc[indexes][column_names].to_numpy() * weights - pareto_fronts = tpot2.selectors.nondominated_sorting(weighted_scores) + pareto_fronts = tpot.selectors.nondominated_sorting(weighted_scores) df = pd.DataFrame(index=df.index,columns=["Pareto_Front"], data=[])