From 25f5f56697947e002937f81620ef58a31114208f Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 20:40:57 -0400 Subject: [PATCH 1/9] Update the driver for 0.8 release --- tpot/driver.py | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/tpot/driver.py b/tpot/driver.py index 0dfdbda4d..28c1b0324 100755 --- a/tpot/driver.py +++ b/tpot/driver.py @@ -228,10 +228,10 @@ def _get_arg_parser(): 'f1_micro, ' 'f1_samples, ' 'f1_weighted, ' - 'log_loss, ' - 'mean_absolute_error, ' - 'mean_squared_error, ' - 'median_absolute_error, ' + 'neg_log_loss, ' + 'neg_mean_absolute_error, ' + 'neg_mean_squared_error, ' + 'neg_median_absolute_error, ' 'precision, ' 'precision_macro, ' 'precision_micro, ' @@ -254,7 +254,7 @@ def _get_arg_parser(): default=5, type=int, help=( - 'Number of folds to evaluate each pipeline over in k-fold ' + 'Number of folds to evaluate each pipeline over in stratified k-fold ' 'cross-validation during the TPOT optimization process.' ) ) @@ -266,8 +266,8 @@ def _get_arg_parser(): default=1.0, type=float, help=( - 'Subsample ratio of the training instance. Setting it to 0.5 means that TPOT' - 'randomly collects half of training samples for pipeline optimization process.' + 'Subsample ratio of the training instance. Setting it to 0.5 means that TPOT ' + 'use a random subsample of half of training data for the pipeline optimization process.' ) ) @@ -327,12 +327,13 @@ def _get_arg_parser(): '-config', action='store', dest='CONFIG_FILE', - default='', + default=None, type=str, help=( 'Configuration file for customizing the operators and parameters ' - 'that TPOT uses in the optimization process. Must be a python ' - 'module containing a dict export named "tpot_config".' + 'that TPOT uses in the optimization process. Must be a Python ' + 'module containing a dict export named "tpot_config" or the name of ' + 'built-in configuration.' ) ) @@ -370,14 +371,14 @@ def _get_arg_parser(): def _print_args(args): print('\nTPOT settings:') - for arg, arg_val in args.__dict__.items(): + for arg, arg_val in sorted(args.__dict__.items()): if arg == 'DISABLE_UPDATE_CHECK': continue elif arg == 'SCORING_FN' and arg_val is None: if args.TPOT_MODE == 'classification': arg_val = 'accuracy' else: - arg_val = 'mean_squared_error' + arg_val = 'neg_mean_squared_error' elif arg == 'OFFSPRING_SIZE' and arg_val is None: arg_val = args.__dict__['POPULATION_SIZE'] else: @@ -419,7 +420,7 @@ def main(args): training_features, testing_features, training_target, testing_target = \ train_test_split(features, input_data[args.TARGET_NAME], random_state=args.RANDOM_STATE) tpot_type = TPOTClassifier if args.TPOT_MODE == 'classification' else TPOTRegressor - tpot = tpot_type( + tpot_obj = tpot_type( generations=args.GENERATIONS, population_size=args.POPULATION_SIZE, offspring_size=args.OFFSPRING_SIZE, @@ -437,29 +438,27 @@ def main(args): disable_update_check=args.DISABLE_UPDATE_CHECK ) - print('') - - tpot.fit(training_features, training_target) + tpot_obj.fit(training_features, training_target) - if args.VERBOSITY in [1, 2] and tpot._optimized_pipeline: - training_score = max([x.wvalues[1] for x in tpot._pareto_front.keys]) + if args.VERBOSITY in [1, 2] and tpot_obj._optimized_pipeline: + training_score = max([x.wvalues[1] for x in tpot_obj._pareto_front.keys]) print('\nTraining score: {}'.format(abs(training_score))) - print('Holdout score: {}'.format(tpot.score(testing_features, testing_target))) + print('Holdout score: {}'.format(tpot_obj.score(testing_features, testing_target))) - elif args.VERBOSITY >= 3 and tpot._pareto_front: + elif args.VERBOSITY >= 3 and tpot_obj._pareto_front: print('Final Pareto front testing scores:') - pipelines = zip(tpot._pareto_front.items, reversed(tpot._pareto_front.keys)) + pipelines = zip(tpot_obj._pareto_front.items, reversed(tpot_obj._pareto_front.keys)) for pipeline, pipeline_scores in pipelines: - tpot._fitted_pipeline = tpot._pareto_front_fitted_pipelines[str(pipeline)] + tpot_obj._fitted_pipeline = tpot_obj.pareto_front_fitted_pipelines_[str(pipeline)] print('{TRAIN_SCORE}\t{TEST_SCORE}\t{PIPELINE}'.format( TRAIN_SCORE=int(abs(pipeline_scores.wvalues[0])), - TEST_SCORE=tpot.score(testing_features, testing_target), + TEST_SCORE=tpot_obj.score(testing_features, testing_target), PIPELINE=pipeline ) ) if args.OUTPUT_FILE != '': - tpot.export(args.OUTPUT_FILE) + tpot_obj.export(args.OUTPUT_FILE) if __name__ == '__main__': From ce0d4e0445640d3366add945389f30326dbade56 Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 21:52:09 -0400 Subject: [PATCH 2/9] Fix unit test for the TPOT driver --- tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests.py b/tests.py index 1a802764a..3e44f01f4 100644 --- a/tests.py +++ b/tests.py @@ -180,7 +180,7 @@ def test_print_args(self): output = out.getvalue() expected_output = """ TPOT settings: -CONFIG_FILE\t=\t +CONFIG_FILE\t=\tNone CROSSOVER_RATE\t=\t0.1 GENERATIONS\t=\t100 INPUT_FILE\t=\ttests.csv From 2141989c154cb6f4189b18cbae07b8da1b335694 Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 22:01:05 -0400 Subject: [PATCH 3/9] Test Travis-CI setup with OS X build as well --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d01b217fb..1f2aea255 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,10 @@ env: # let's start simple: - PYTHON_VERSION="2.7" LATEST="true" - PYTHON_VERSION="3.5" LATEST="true" - - PYTHON_VERSION="3.6" COVERAGE="true" LATEST="true" "DEAP_VERSION=1.0.2" "XGBOOST_VERSION=0.6" + - PYTHON_VERSION="3.6" COVERAGE="true" LATEST="true" - PYTHON_VERSION="3.6" LATEST="true" + - os: osx + PYTHON_VERSION="3.6" LATEST="true" install: source ./ci/.travis_install.sh script: bash ./ci/.travis_test.sh after_success: From cfcb6e00972aab12a15ae623615f4aee98063ffa Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 22:02:40 -0400 Subject: [PATCH 4/9] Missing env variable? --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1f2aea255..5ae3e5165 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,7 @@ env: - PYTHON_VERSION="3.6" COVERAGE="true" LATEST="true" - PYTHON_VERSION="3.6" LATEST="true" - os: osx - PYTHON_VERSION="3.6" LATEST="true" + env: PYTHON_VERSION="3.6" LATEST="true" install: source ./ci/.travis_install.sh script: bash ./ci/.travis_test.sh after_success: From 87cc8f44e288b73660408ce1384d21c563d9f30a Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 22:04:05 -0400 Subject: [PATCH 5/9] Rework Travis-CI config --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5ae3e5165..fb1df4640 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ language: python virtualenv: system_site_packages: true +os: + - linux + - osx env: matrix: # let's start simple: @@ -8,8 +11,6 @@ env: - PYTHON_VERSION="3.5" LATEST="true" - PYTHON_VERSION="3.6" COVERAGE="true" LATEST="true" - PYTHON_VERSION="3.6" LATEST="true" - - os: osx - env: PYTHON_VERSION="3.6" LATEST="true" install: source ./ci/.travis_install.sh script: bash ./ci/.travis_test.sh after_success: From 981c74a29a509a53bf5d13426d0589a124c2d756 Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Thu, 1 Jun 2017 22:11:08 -0400 Subject: [PATCH 6/9] Remove OS X from the CI suite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … until we figure out what’s going on with the failed builds. --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fb1df4640..cc80f406d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: python virtualenv: system_site_packages: true -os: - - linux - - osx env: matrix: # let's start simple: From 9564a199bde317d60478200e53e234d9749ec2ea Mon Sep 17 00:00:00 2001 From: Weixuan Fu Date: Fri, 2 Jun 2017 07:25:40 -0400 Subject: [PATCH 7/9] fix issue 484 --- tests.py | 4 ++-- tpot/export_utils.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests.py b/tests.py index 3e44f01f4..4ae21b79e 100644 --- a/tests.py +++ b/tests.py @@ -1031,7 +1031,7 @@ def test_export_pipeline(): from sklearn.neighbors import KNeighborsClassifier from sklearn.pipeline import make_pipeline, make_union from sklearn.tree import DecisionTreeClassifier -from tpot.built_in_operators import StackingEstimator +from tpot.builtins import StackingEstimator # NOTE: Make sure that the class is labeled 'class' in the data file tpot_data = np.recfromcsv('PATH/TO/DATA/FILE', delimiter='COLUMN_SEPARATOR', dtype=np.float64) @@ -1136,7 +1136,7 @@ def test_export_pipeline_4(): from sklearn.neighbors import KNeighborsClassifier from sklearn.pipeline import make_pipeline, make_union from sklearn.tree import DecisionTreeClassifier -from tpot.built_in_operators import StackingEstimator +from tpot.builtins import StackingEstimator from sklearn.preprocessing import FunctionTransformer from copy import copy diff --git a/tpot/export_utils.py b/tpot/export_utils.py index 1cbd33158..f262ca1e2 100644 --- a/tpot/export_utils.py +++ b/tpot/export_utils.py @@ -205,7 +205,7 @@ def _starting_imports(operators, operators_used): return { 'sklearn.model_selection': ['train_test_split'], 'sklearn.pipeline': ['make_pipeline', 'make_union'], - 'tpot.built_in_operators': ['StackingEstimator'], + 'tpot.builtins': ['StackingEstimator'], } elif num_op > 1: return { From f06785c67baf8f753c70ea8e8c935a1c95e691ce Mon Sep 17 00:00:00 2001 From: weixuanfu2016 Date: Fri, 2 Jun 2017 10:24:24 -0400 Subject: [PATCH 8/9] Add a unit test for issue 484 --- tests.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests.py b/tests.py index 4ae21b79e..22d709129 100644 --- a/tests.py +++ b/tests.py @@ -947,6 +947,35 @@ def test_generate_import_code(): """ assert expected_code == generate_import_code(pipeline, tpot_obj.operators) + +def test_generate_import_code_2(): + """Assert that generate_import_code() returns the correct set of dependancies and dependancies are importable.""" + tpot_obj = TPOTClassifier() + pipeline_string = ( + 'KNeighborsClassifier(CombineDFs(' + 'DecisionTreeClassifier(input_matrix, DecisionTreeClassifier__criterion=gini, ' + 'DecisionTreeClassifier__max_depth=8,DecisionTreeClassifier__min_samples_leaf=5,' + 'DecisionTreeClassifier__min_samples_split=5), ZeroCount(input_matrix))' + 'KNeighborsClassifier__n_neighbors=10, ' + 'KNeighborsClassifier__p=1,KNeighborsClassifier__weights=uniform' + ) + + pipeline = creator.Individual.from_string(pipeline_string, tpot_obj._pset) + + import_code = generate_import_code(pipeline, tpot_obj.operators) + + expected_code = """import numpy as np + +from sklearn.model_selection import train_test_split +from sklearn.neighbors import KNeighborsClassifier +from sklearn.pipeline import make_pipeline, make_union +from sklearn.tree import DecisionTreeClassifier +from tpot.builtins import StackingEstimator, ZeroCount +""" + exec(import_code) # should not raise error + assert expected_code == import_code + + def test_PolynomialFeatures_exception(): """Assert that TPOT allows only one PolynomialFeatures operator in a pipeline""" tpot_obj = TPOTClassifier() From 884820e92fbd8a0eb95214c6d00ed4f65711caf3 Mon Sep 17 00:00:00 2001 From: Randy Olson Date: Fri, 2 Jun 2017 11:11:24 -0400 Subject: [PATCH 9/9] Minor version update for hot patch --- tpot/_version.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tpot/_version.py b/tpot/_version.py index 2270d3b87..823e511a2 100644 --- a/tpot/_version.py +++ b/tpot/_version.py @@ -19,4 +19,4 @@ """ -__version__ = '0.8.0' +__version__ = '0.8.1'