From 3e23a3972eb0ba401dd4a98c54348c69900e5117 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Tue, 19 May 2020 15:22:10 -0700 Subject: [PATCH 01/21] feature: TensorFlow 2.2 support --- README.rst | 2 +- doc/using_tf.rst | 2 +- src/sagemaker/tensorflow/README.rst | 78 ++++++++++++++-------------- src/sagemaker/tensorflow/defaults.py | 2 +- tests/integ/test_tf_script_mode.py | 5 +- 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/README.rst b/README.rst index 3c4ba69c44..6e79461442 100644 --- a/README.rst +++ b/README.rst @@ -219,7 +219,7 @@ TensorFlow SageMaker Estimators By using TensorFlow SageMaker Estimators, you can train and host TensorFlow models on Amazon SageMaker. -Supported versions of TensorFlow: ``1.4.1``, ``1.5.0``, ``1.6.0``, ``1.7.0``, ``1.8.0``, ``1.9.0``, ``1.10.0``, ``1.11.0``, ``1.12.0``, ``1.13.1``, ``1.14.0``, ``1.15.0``, ``1.15.2``, ``2.0.0``, ``2.0.1``, ``2.1.0``. +Supported versions of TensorFlow: ``1.4.1``, ``1.5.0``, ``1.6.0``, ``1.7.0``, ``1.8.0``, ``1.9.0``, ``1.10.0``, ``1.11.0``, ``1.12.0``, ``1.13.1``, ``1.14.0``, ``1.15.0``, ``1.15.2``, ``2.0.0``, ``2.0.1``, ``2.1.0``, ``2.2.0``. Supported versions of TensorFlow for Elastic Inference: ``1.11.0``, ``1.12.0``, ``1.13.1``, ``1.14.0``, ``1.15.0``, ``2.0.0``. diff --git a/doc/using_tf.rst b/doc/using_tf.rst index 3a8fcd5186..66e4acc4e7 100644 --- a/doc/using_tf.rst +++ b/doc/using_tf.rst @@ -20,7 +20,7 @@ For general information about using the SageMaker Python SDK, see :ref:`overview .. contents:: -Supported versions of TensorFlow for Elastic Inference: ``1.11``, ``1.12``, ``1.13``, ``1.14``. +Supported versions of TensorFlow for Elastic Inference: ``1.11``, ``1.12``, ``1.13``, ``1.14``, ``1.15``, ``2.0``. ***************************** diff --git a/src/sagemaker/tensorflow/README.rst b/src/sagemaker/tensorflow/README.rst index 54781cf330..30841a5f1c 100644 --- a/src/sagemaker/tensorflow/README.rst +++ b/src/sagemaker/tensorflow/README.rst @@ -31,45 +31,47 @@ SageMaker TensorFlow Docker containers The latest containers include the following Python packages: -+--------------------------------+--------------------+---------------+ -| Dependencies | TF 1.15.2 | TF 2.1 | -+--------------------------------+--------------------+---------------+ -| awscli | 1.18.1 | 1.18.3 | -+--------------------------------+--------------------+---------------+ -| boto3 | 1.12.1 | 1.12.3 | -+--------------------------------+--------------------+---------------+ -| botocore | 1.15.1 | 1.15.3 | -+--------------------------------+--------------------+---------------+ -| h5py | 2.10.0 | 2.10.0 | -+--------------------------------+--------------------+---------------+ -| horovod | 0.18.2 | 0.18.2 | -+--------------------------------+--------------------+---------------+ -| keras | 2.3.1 | 2.3.1 | -+--------------------------------+--------------------+---------------+ -| mpi4py | 3.0.2 | 3.0.3 | -+--------------------------------+--------------------+---------------+ -| numpy | 1.18.1 | 1.18.1 | -+--------------------------------+--------------------+---------------+ -| pandas | 0.24.2 | 1.0.1 | -+--------------------------------+--------------------+---------------+ -| pip | 20.0.2 | 20.0.2 | -+--------------------------------+--------------------+---------------+ -| Pillow | 6.2.1 | 7.0.0 | -+--------------------------------+--------------------+---------------+ -| Python | 2.7, 3.6 or 3.7 | 2.7 or 3.6 | -+--------------------------------+--------------------+---------------+ -| requests | 2.22.0 | 2.22.0 | -+--------------------------------+--------------------+---------------+ -| sagemaker-containers | 2.7.0 | 2.8.0 | -+--------------------------------+--------------------+---------------+ -| sagemaker-tensorflow-container | 1.15.0.1.1.0 | 2.0.0.1.1.0 | -+--------------------------------+--------------------+---------------+ -| scipy | 1.2.2 | 1.4.1 | -+--------------------------------+--------------------+---------------+ -| tensorflow | 1.15.2 | 2.1.0 | -+--------------------------------+--------------------+---------------+ ++--------------------------------+--------------------+---------------+---------------+ +| Dependencies | TF 1.15.2 | TF 2.1 | TF 2.2 | ++--------------------------------+--------------------+---------------+---------------+ +| awscli | 1.18.1 | 1.18.3 | 1.18.63 | ++--------------------------------+--------------------+---------------+---------------+ +| boto3 | 1.12.1 | 1.12.3 | 1.13.3 | ++--------------------------------+--------------------+---------------+---------------+ +| botocore | 1.15.1 | 1.15.3 | 1.16.13 | ++--------------------------------+--------------------+---------------+---------------+ +| h5py | 2.10.0 | 2.10.0 | 2.10.0 | ++--------------------------------+--------------------+---------------+---------------+ +| horovod | 0.18.2 | 0.18.2 | 0.18.2 | ++--------------------------------+--------------------+---------------+---------------+ +| keras | 2.3.1 | 2.3.1 | 2.3.1 | ++--------------------------------+--------------------+---------------+---------------+ +| mpi4py | 3.0.2 | 3.0.3 | 3.0.3 | ++--------------------------------+--------------------+---------------+---------------+ +| numpy | 1.18.1 | 1.18.1 | 1.18.4 | ++--------------------------------+--------------------+---------------+---------------+ +| pandas | 0.24.2 | 1.0.1 | 1.0.3 | ++--------------------------------+--------------------+---------------+---------------+ +| pip | 20.0.2 | 20.0.2 | 20.0.2 | ++--------------------------------+--------------------+---------------+---------------+ +| Pillow | 6.2.1 | 7.0.0 | 7.1.2 | ++--------------------------------+--------------------+---------------+---------------+ +| Python | 2.7, 3.6 or 3.7 | 2.7 or 3.6 | 3.7 | ++--------------------------------+--------------------+---------------+---------------+ +| requests | 2.22.0 | 2.22.0 | 2.23.0 | ++--------------------------------+--------------------+---------------+---------------+ +| sagemaker-containers | 2.7.0 | 2.8.0 | N/A | ++--------------------------------+--------------------+---------------+---------------+ +| sagemaker-tensorflow-container | 1.15.0.1.1.0 | 2.0.0.1.1.0 | N/A | ++--------------------------------+--------------------+---------------+---------------+ +| sagemaker-tensorflow-training | N/A | N/A | 4.0.1 | ++--------------------------------+--------------------+---------------+---------------+ +| scipy | 1.2.2 | 1.4.1 | 1.4.1 | ++--------------------------------+--------------------+---------------+---------------+ +| tensorflow | 1.15.2 | 2.1.0 | 2.2.0 | ++--------------------------------+--------------------+---------------+---------------+ -Script Mode TensorFlow Docker images support Python 2.7 and Python 3.6, Python 3.7 for TensorFlow version 1.15.2. The Docker images extend Ubuntu 16.04. +Script Mode TensorFlow Docker images support Python 2.7 and Python 3.6, Python 3.7 for TensorFlow version 1.15.2 and 2.2.0. The Docker images extend Ubuntu 16.04. You can select version of TensorFlow by passing a ``framework_version`` keyword arg to the TensorFlow Estimator constructor. Currently supported versions are listed in the table above. You can also set ``framework_version`` to only specify major and minor version, e.g ``'1.6'``, which will cause your training script to be run on the latest supported patch version of that minor version, which in this example would be 1.6.0. Alternatively, you can build your own image by following the instructions in the SageMaker TensorFlow containers diff --git a/src/sagemaker/tensorflow/defaults.py b/src/sagemaker/tensorflow/defaults.py index 08d1c63a10..e3bc65e2a8 100644 --- a/src/sagemaker/tensorflow/defaults.py +++ b/src/sagemaker/tensorflow/defaults.py @@ -18,7 +18,7 @@ This is no longer updated so as to not break existing workflows. """ -LATEST_VERSION = "2.1.0" +LATEST_VERSION = "2.2.0" """The latest version of TensorFlow included in the SageMaker pre-built Docker images.""" LATEST_PY2_VERSION = "2.1.0" diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index a6326bccd9..c8db998a27 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -37,13 +37,12 @@ PARAMETER_SERVER_DISTRIBUTION = {"parameter_server": {"enabled": True}} MPI_DISTRIBUTION = {"mpi": {"enabled": True}} TAGS = [{"Key": "some-key", "Value": "some-value"}] +PY37_SUPPORTED_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] @pytest.fixture(scope="module") def py_version(tf_full_version): - return ( - "py37" if tf_full_version == TensorFlow._LATEST_1X_VERSION else tests.integ.PYTHON_VERSION - ) + return "py37" if tf_full_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION def test_mnist_with_checkpoint_config( From 1d66433d0047b8f6a4fc299770c4d2aae7e33001 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Wed, 20 May 2020 10:47:39 -0700 Subject: [PATCH 02/21] prevent TFS test pulling 2.2.0 images --- tests/integ/test_tfs.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index 4d070fac85..00a0c24ed6 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -26,6 +26,18 @@ from sagemaker.tensorflow.serving import Model, Predictor +LATEST_SERVING_VERSION = "2.1.0" + + +@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, LATEST_SERVING_VERSION]) +def tf_full_version(request): + tf_version = request.config.getoption("--tf-full-version") + if tf_version is None: + return request.param + else: + return tf_version + + @pytest.fixture(scope="module") def tfs_predictor(sagemaker_session, tf_full_version): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") From 98a0a5e49f9a8849be6124028aa0685b9c561aaf Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Wed, 20 May 2020 11:12:07 -0700 Subject: [PATCH 03/21] fix flake8 error --- tests/integ/test_tfs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index 00a0c24ed6..a5f7f8ae59 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -26,10 +26,11 @@ from sagemaker.tensorflow.serving import Model, Predictor +LATEST_1x_SERVING_VERSION = "1.5.2" LATEST_SERVING_VERSION = "2.1.0" -@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, LATEST_SERVING_VERSION]) +@pytest.fixture(scope="module", params=[LATEST_1x_SERVING_VERSION, LATEST_SERVING_VERSION]) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") if tf_version is None: From 7f44c656479c61627d262b0e7da2bd21b3c66f68 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Wed, 20 May 2020 20:34:20 -0700 Subject: [PATCH 04/21] update tfs test versions --- tests/integ/test_tfs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index a5f7f8ae59..fbacc06ac7 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -26,7 +26,7 @@ from sagemaker.tensorflow.serving import Model, Predictor -LATEST_1x_SERVING_VERSION = "1.5.2" +LATEST_1x_SERVING_VERSION = "1.15.2" LATEST_SERVING_VERSION = "2.1.0" From b33deb9f54a7f55c7e46f136c514e4b434732df1 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Wed, 20 May 2020 23:36:12 -0700 Subject: [PATCH 05/21] use tfs 2.1.0 in model monitor tests --- tests/integ/test_model_monitor.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/integ/test_model_monitor.py b/tests/integ/test_model_monitor.py index 338a676186..65e3f42f6d 100644 --- a/tests/integ/test_model_monitor.py +++ b/tests/integ/test_model_monitor.py @@ -86,6 +86,18 @@ FIVE_MINUTE_CRON_EXPRESSION = "cron(0/5 * ? * * *)" +LATEST_1x_SERVING_VERSION = "1.15.2" +LATEST_SERVING_VERSION = "2.1.0" + + +@pytest.fixture(scope="module", params=[LATEST_1x_SERVING_VERSION, LATEST_SERVING_VERSION]) +def tf_full_version(request): + tf_version = request.config.getoption("--tf-full-version") + if tf_version is None: + return request.param + else: + return tf_version + @pytest.fixture(scope="module") def predictor(sagemaker_session, tf_full_version): From 8da65097e8f00a47e31728119f85e3215abc15a4 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 01:23:34 -0700 Subject: [PATCH 06/21] distinguish tf and tfs latest versions in test --- src/sagemaker/tensorflow/defaults.py | 3 +++ tests/conftest.py | 4 +++- tests/integ/test_model_monitor.py | 12 ------------ tests/integ/test_tf_script_mode.py | 19 ++++++++++++++----- tests/integ/test_tfs.py | 13 ------------- 5 files changed, 20 insertions(+), 31 deletions(-) diff --git a/src/sagemaker/tensorflow/defaults.py b/src/sagemaker/tensorflow/defaults.py index e3bc65e2a8..b4f99d0e3c 100644 --- a/src/sagemaker/tensorflow/defaults.py +++ b/src/sagemaker/tensorflow/defaults.py @@ -21,4 +21,7 @@ LATEST_VERSION = "2.2.0" """The latest version of TensorFlow included in the SageMaker pre-built Docker images.""" +LATEST_SERVING_VERSION = "2.1.0" +"""The latest version of TensorFlow Serving included in the SageMaker pre-built Docker images.""" + LATEST_PY2_VERSION = "2.1.0" diff --git a/tests/conftest.py b/tests/conftest.py index b7cab1dd44..17cb1b34a0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -259,7 +259,9 @@ def sklearn_full_version(request): return request.config.getoption("--sklearn-full-version") -@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION]) +@pytest.fixture( + scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_SERVING_VERSION] +) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") if tf_version is None: diff --git a/tests/integ/test_model_monitor.py b/tests/integ/test_model_monitor.py index 65e3f42f6d..338a676186 100644 --- a/tests/integ/test_model_monitor.py +++ b/tests/integ/test_model_monitor.py @@ -86,18 +86,6 @@ FIVE_MINUTE_CRON_EXPRESSION = "cron(0/5 * ? * * *)" -LATEST_1x_SERVING_VERSION = "1.15.2" -LATEST_SERVING_VERSION = "2.1.0" - - -@pytest.fixture(scope="module", params=[LATEST_1x_SERVING_VERSION, LATEST_SERVING_VERSION]) -def tf_full_version(request): - tf_version = request.config.getoption("--tf-full-version") - if tf_version is None: - return request.param - else: - return tf_version - @pytest.fixture(scope="module") def predictor(sagemaker_session, tf_full_version): diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index c8db998a27..e049483267 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -40,13 +40,22 @@ PY37_SUPPORTED_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] +@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION]) +def tf_training_version(request): + tf_version = request.config.getoption("--tf-full-version") + if tf_version is None: + return request.param + else: + return tf_version + + @pytest.fixture(scope="module") def py_version(tf_full_version): return "py37" if tf_full_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION def test_mnist_with_checkpoint_config( - sagemaker_session, instance_type, tf_full_version, py_version + sagemaker_session, instance_type, tf_training_version, py_version ): checkpoint_s3_uri = "s3://{}/checkpoints/tf-{}".format( sagemaker_session.default_bucket(), sagemaker_timestamp() @@ -59,7 +68,7 @@ def test_mnist_with_checkpoint_config( train_instance_type=instance_type, sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_training_version, py_version=py_version, metric_definitions=[{"Name": "train:global_steps", "Regex": r"global_step\/sec:\s(.*)"}], checkpoint_s3_uri=checkpoint_s3_uri, @@ -132,7 +141,7 @@ def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): @pytest.mark.canary_quick -def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py_version): +def test_mnist_distributed(sagemaker_session, instance_type, tf_training_version, py_version): estimator = TensorFlow( entry_point=SCRIPT, role=ROLE, @@ -141,7 +150,7 @@ def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py sagemaker_session=sagemaker_session, py_version=py_version, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_training_version, distributions=PARAMETER_SERVER_DISTRIBUTION, ) inputs = estimator.sagemaker_session.upload_data( @@ -167,7 +176,7 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v sagemaker_session=sagemaker_session, script_mode=True, # testing py-sdk functionality, no need to run against all TF versions - framework_version=TensorFlow.LATEST_VERSION, + framework_version=TensorFlow.LATEST_SERVING_VERSION, tags=TAGS, ) inputs = estimator.sagemaker_session.upload_data( diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index fbacc06ac7..4d070fac85 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -26,19 +26,6 @@ from sagemaker.tensorflow.serving import Model, Predictor -LATEST_1x_SERVING_VERSION = "1.15.2" -LATEST_SERVING_VERSION = "2.1.0" - - -@pytest.fixture(scope="module", params=[LATEST_1x_SERVING_VERSION, LATEST_SERVING_VERSION]) -def tf_full_version(request): - tf_version = request.config.getoption("--tf-full-version") - if tf_version is None: - return request.param - else: - return tf_version - - @pytest.fixture(scope="module") def tfs_predictor(sagemaker_session, tf_full_version): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") From 4f857867e5eb1ec614334fc0f779c86e7e97c861 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 01:32:18 -0700 Subject: [PATCH 07/21] add latest serving version --- src/sagemaker/tensorflow/estimator.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sagemaker/tensorflow/estimator.py b/src/sagemaker/tensorflow/estimator.py index be238f4c9a..75eb411006 100644 --- a/src/sagemaker/tensorflow/estimator.py +++ b/src/sagemaker/tensorflow/estimator.py @@ -201,6 +201,7 @@ class TensorFlow(Framework): __framework_name__ = "tensorflow" LATEST_VERSION = defaults.LATEST_VERSION + LATEST_SERVING_VERSION = defaults.LATEST_SERVING_VERSION _LATEST_1X_VERSION = "1.15.2" From cb2a4891801ff4e5362ffe63b1e9fceb161dc638 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 09:00:10 -0700 Subject: [PATCH 08/21] let py_version pick up tf_training_version --- tests/integ/test_tf_script_mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index e049483267..211c74df28 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -50,7 +50,7 @@ def tf_training_version(request): @pytest.fixture(scope="module") -def py_version(tf_full_version): +def py_version(tf_training_version): return "py37" if tf_full_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION From ed177e80c9fecd18a547be1cdf9b8dbcfc5c1aaf Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 09:34:07 -0700 Subject: [PATCH 09/21] fix typo --- tests/integ/test_tf_script_mode.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index 211c74df28..bfd66be4dd 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -51,7 +51,7 @@ def tf_training_version(request): @pytest.fixture(scope="module") def py_version(tf_training_version): - return "py37" if tf_full_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION + return "py37" if tf_training_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION def test_mnist_with_checkpoint_config( From 0b77be7a0b151d58da529e671e051201c188d5d2 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 12:23:51 -0700 Subject: [PATCH 10/21] no py37 for tfs 2.1 --- tests/conftest.py | 2 +- tests/integ/test_tf_script_mode.py | 33 ++++++++++++++---------------- tests/integ/test_tfs.py | 19 +++++++++++------ tests/integ/test_transformer.py | 2 +- 4 files changed, 30 insertions(+), 26 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 3551724866..1e627dcef0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -260,7 +260,7 @@ def sklearn_full_version(request): @pytest.fixture( - scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_SERVING_VERSION] + scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] ) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index bfd66be4dd..5b9ecda023 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -37,25 +37,22 @@ PARAMETER_SERVER_DISTRIBUTION = {"parameter_server": {"enabled": True}} MPI_DISTRIBUTION = {"mpi": {"enabled": True}} TAGS = [{"Key": "some-key", "Value": "some-value"}] -PY37_SUPPORTED_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] -@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION]) -def tf_training_version(request): - tf_version = request.config.getoption("--tf-full-version") - if tf_version is None: - return request.param - else: - return tf_version +@pytest.fixture(scope="module") +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version @pytest.fixture(scope="module") -def py_version(tf_training_version): - return "py37" if tf_training_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION +def py_version(tf_full_version): + return "py37" if tf_full_version == tf_serving_version else tests.integ.PYTHON_VERSION def test_mnist_with_checkpoint_config( - sagemaker_session, instance_type, tf_training_version, py_version + sagemaker_session, instance_type, tf_full_version, py_version ): checkpoint_s3_uri = "s3://{}/checkpoints/tf-{}".format( sagemaker_session.default_bucket(), sagemaker_timestamp() @@ -68,7 +65,7 @@ def test_mnist_with_checkpoint_config( train_instance_type=instance_type, sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_training_version, + framework_version=tf_full_version, py_version=py_version, metric_definitions=[{"Name": "train:global_steps", "Regex": r"global_step\/sec:\s(.*)"}], checkpoint_s3_uri=checkpoint_s3_uri, @@ -99,7 +96,7 @@ def test_mnist_with_checkpoint_config( assert actual_training_checkpoint_config == expected_training_checkpoint_config -def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): +def test_server_side_encryption(sagemaker_session, tf_serving_version, py_version): with kms_utils.bucket_with_encryption(sagemaker_session, ROLE) as (bucket_with_kms, kms_key): output_path = os.path.join( bucket_with_kms, "test-server-side-encryption", time.strftime("%y%m%d-%H%M") @@ -113,7 +110,7 @@ def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): train_instance_type="ml.c5.xlarge", sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_serving_version, py_version=py_version, code_location=output_path, output_path=output_path, @@ -141,7 +138,7 @@ def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): @pytest.mark.canary_quick -def test_mnist_distributed(sagemaker_session, instance_type, tf_training_version, py_version): +def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py_version): estimator = TensorFlow( entry_point=SCRIPT, role=ROLE, @@ -150,7 +147,7 @@ def test_mnist_distributed(sagemaker_session, instance_type, tf_training_version sagemaker_session=sagemaker_session, py_version=py_version, script_mode=True, - framework_version=tf_training_version, + framework_version=tf_full_version, distributions=PARAMETER_SERVER_DISTRIBUTION, ) inputs = estimator.sagemaker_session.upload_data( @@ -208,7 +205,7 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v _assert_model_name_match(sagemaker_session.sagemaker_client, endpoint_name, model_name) -def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_full_version, py_version): +def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_serving_version, py_version): estimator = TensorFlow( entry_point="training.py", source_dir=TFS_RESOURCE_PATH, @@ -218,7 +215,7 @@ def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_full_ve py_version=py_version, sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_serving_version, tags=TAGS, ) diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index 4d070fac85..ffc260a4f9 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -27,7 +27,14 @@ @pytest.fixture(scope="module") -def tfs_predictor(sagemaker_session, tf_full_version): +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version + + +@pytest.fixture(scope="module") +def tfs_predictor(sagemaker_session, tf_serving_version): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( path=os.path.join(tests.integ.DATA_DIR, "tensorflow-serving-test-model.tar.gz"), @@ -37,7 +44,7 @@ def tfs_predictor(sagemaker_session, tf_full_version): model = Model( model_data=model_data, role="SageMakerRole", - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) predictor = model.deploy(1, "ml.c5.xlarge", endpoint_name=endpoint_name) @@ -54,7 +61,7 @@ def tar_dir(directory, tmpdir): @pytest.fixture def tfs_predictor_with_model_and_entry_point_same_tar( - sagemaker_local_session, tf_full_version, tmpdir + sagemaker_local_session, tf_serving_version, tmpdir ): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") @@ -65,7 +72,7 @@ def tfs_predictor_with_model_and_entry_point_same_tar( model = Model( model_data="file://" + model_tar, role="SageMakerRole", - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_local_session, ) predictor = model.deploy(1, "local", endpoint_name=endpoint_name) @@ -78,7 +85,7 @@ def tfs_predictor_with_model_and_entry_point_same_tar( @pytest.fixture(scope="module") def tfs_predictor_with_model_and_entry_point_and_dependencies( - sagemaker_local_session, tf_full_version + sagemaker_local_session, tf_serving_version ): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") @@ -98,7 +105,7 @@ def tfs_predictor_with_model_and_entry_point_and_dependencies( model_data=model_data, role="SageMakerRole", dependencies=dependencies, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_local_session, ) diff --git a/tests/integ/test_transformer.py b/tests/integ/test_transformer.py index 19bf38b4b5..1c167829fb 100644 --- a/tests/integ/test_transformer.py +++ b/tests/integ/test_transformer.py @@ -351,7 +351,7 @@ def test_transform_tf_kms_network_isolation(sagemaker_session, cpu_instance_type role="SageMakerRole", train_instance_count=1, train_instance_type=cpu_instance_type, - framework_version=TensorFlow.LATEST_VERSION, + framework_version=TensorFlow.LATEST_SERVING_VERSION, script_mode=True, py_version=PYTHON_VERSION, sagemaker_session=sagemaker_session, From 89bb6d6a2c3cc40e544c76a3cb5aaa74a3bdff96 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 12:30:10 -0700 Subject: [PATCH 11/21] fix black error --- tests/conftest.py | 4 +--- tests/integ/test_tf_script_mode.py | 4 +++- tests/integ/test_tfs.py | 1 + 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1e627dcef0..d5cfc3a8a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -259,9 +259,7 @@ def sklearn_full_version(request): return request.config.getoption("--sklearn-full-version") -@pytest.fixture( - scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] -) +@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION]) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") if tf_version is None: diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index 5b9ecda023..075129f3a1 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -205,7 +205,9 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v _assert_model_name_match(sagemaker_session.sagemaker_client, endpoint_name, model_name) -def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_serving_version, py_version): +def test_deploy_with_input_handlers( + sagemaker_session, instance_type, tf_serving_version, py_version +): estimator = TensorFlow( entry_point="training.py", source_dir=TFS_RESOURCE_PATH, diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index ffc260a4f9..4ed13966e5 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -23,6 +23,7 @@ import sagemaker.utils import tests.integ import tests.integ.timeout +from sagemaker.tensorflow import TensorFlow from sagemaker.tensorflow.serving import Model, Predictor From 40da47392fbbfa674f964b769420c74d49b820ea Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Wed, 20 May 2020 10:47:39 -0700 Subject: [PATCH 12/21] prevent tfs pulling 2.2 image --- CHANGELOG.md | 25 +++++++ README.rst | 2 +- VERSION | 2 +- doc/overview.rst | 20 ++++++ doc/using_tf.rst | 33 ++++++++- src/sagemaker/__init__.py | 9 +++ src/sagemaker/amazon/amazon_estimator.py | 5 ++ src/sagemaker/automl/automl.py | 2 +- src/sagemaker/estimator.py | 9 ++- src/sagemaker/fw_utils.py | 25 ++++++- src/sagemaker/inputs.py | 7 ++ src/sagemaker/model.py | 2 + src/sagemaker/mxnet/README.rst | 2 +- src/sagemaker/mxnet/estimator.py | 2 + src/sagemaker/s3.py | 31 +++++++++ src/sagemaker/session.py | 25 +++++++ src/sagemaker/tensorflow/defaults.py | 3 + src/sagemaker/tensorflow/estimator.py | 6 +- src/sagemaker/transformer.py | 1 + src/sagemaker/workflow/airflow.py | 74 ++++++++++++++++++++- tests/conftest.py | 2 +- tests/integ/test_airflow_config.py | 2 + tests/integ/test_experiments_analytics.py | 12 ++++ tests/integ/test_local_mode.py | 1 + tests/integ/test_tf_script_mode.py | 22 ++++-- tests/integ/test_tfs.py | 20 ++++-- tests/integ/test_transformer.py | 14 ++-- tests/unit/sagemaker/automl/test_auto_ml.py | 2 +- tests/unit/test_airflow.py | 18 ++++- tests/unit/test_amazon_estimator.py | 9 +++ tests/unit/test_fw_utils.py | 4 +- tests/unit/test_inputs.py | 7 +- tests/unit/test_mxnet.py | 4 +- tests/unit/test_s3.py | 6 +- 34 files changed, 367 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f75c84a56..28c9545108 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,30 @@ # Changelog +## v1.58.4 (2020-05-20) + +### Bug Fixes and Other Changes + + * update AutoML default max_candidate value to use the service default + * add describe_transform_job in session class + +### Documentation Changes + + * clarify support for requirements.txt in Tensorflow docs + +### Testing and Release Infrastructure + + * wait for DisassociateTrialComponent to take effect in experiment integ test cleanup + +## v1.58.3 (2020-05-19) + +### Bug Fixes and Other Changes + + * update DatasetFormat key name for sagemakerCaptureJson + +### Documentation Changes + + * update Processing job max_runtime_in_seconds docstring + ## v1.58.2.post0 (2020-05-18) ### Documentation Changes diff --git a/README.rst b/README.rst index 6e79461442..8d5e5aa893 100644 --- a/README.rst +++ b/README.rst @@ -205,7 +205,7 @@ By using MXNet SageMaker Estimators, you can train and host MXNet models on Amaz Supported versions of MXNet: ``0.12.1``, ``1.0.0``, ``1.1.0``, ``1.2.1``, ``1.3.0``, ``1.4.0``, ``1.4.1``, ``1.6.0``. -Supported versions of MXNet for Elastic Inference: ``1.3.0``, ``1.4.0``, ``1.4.1``. +Supported versions of MXNet for Elastic Inference: ``1.3.0``, ``1.4.0``, ``1.4.1``, ``1.5.1``. We recommend that you use the latest supported version, because that's where we focus most of our development efforts. diff --git a/VERSION b/VERSION index cf79ea5266..7d9a188f5d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.58.3.dev0 +1.58.5.dev0 diff --git a/doc/overview.rst b/doc/overview.rst index 6b5dfea711..84bae6b69e 100644 --- a/doc/overview.rst +++ b/doc/overview.rst @@ -732,6 +732,26 @@ You can install all necessary for this feature dependencies using pip: pip install 'sagemaker[local]' --upgrade +If you want to keep everything local, and not use Amazon S3 either, you can enable "local code" in one of two ways: + +- Create a file at ``~/.sagemaker/config.yaml`` that contains: + +.. code:: yaml + + local: + local_code: true + +- Create a ``LocalSession`` and configure it directly: + +.. code:: python + + from sagemaker.local import LocalSession + + sagemaker_session = LocalSession() + sagemaker_session.config = {'local': {'local_code': True}} + + # pass sagemaker_session to your estimator or model + We can take the example in `Using Estimators <#using-estimators>`__ , and use either ``local`` or ``local_gpu`` as the instance type. .. code:: python diff --git a/doc/using_tf.rst b/doc/using_tf.rst index 66e4acc4e7..a4482a241a 100644 --- a/doc/using_tf.rst +++ b/doc/using_tf.rst @@ -133,6 +133,34 @@ In your training script the channels will be stored in environment variables ``S ``output_path``. +Use third-party libraries +------------------------- + +If there are other packages you want to use with your script, you can use a ``requirements.txt`` to install other dependencies at runtime. + +For training, support for installing packages using ``requirements.txt`` varies by TensorFlow version as follows: + +- For TensorFlow 1.11 or newer using Script Mode without Horovod, TensorFlow 1.15.2 with Python 3.7 or newer, and TensorFlow 2.2 or newer: + - Include a ``requirements.txt`` file in the same directory as your training script. + - You must specify this directory using the ``source_dir`` argument when creating a TensorFlow estimator. +- For older versions of TensorFlow using Script Mode with Horovod: + - Write a shell script for your entry point that first calls ``pip install -r requirements.txt``, then runs your training script. + - For an example of using shell scripts, see `this example notebook `__. +- For older versions of TensorFlow using Legacy Mode: + - Specify the path to your ``requirements.txt`` file using the ``requirements_file`` argument. + +For serving, support for installing packages using ``requirements.txt`` varies by TensorFlow version as follows: + +- For TensorFlow 1.11 or newer: + - Include a ``requirements.txt`` file in the ``code`` directory. +- For older versions of TensorFlow: + - Specify the path to your ``requirements.txt`` file using the ``SAGEMAKER_REQUIREMENTS`` environment variable. + +A ``requirements.txt`` file is a text file that contains a list of items that are installed by using ``pip install``. +You can also specify the version of an item to install. +For information about the format of a ``requirements.txt`` file, see `Requirements Files `__ in the pip documentation. + + Create an Estimator =================== @@ -215,7 +243,7 @@ Calling ``fit`` starts a SageMaker training job. The training job will execute t - starts asynchronous training If the ``wait=False`` flag is passed to ``fit``, then it returns immediately. The training job continues running -asynchronously. Later, a Tensorflow estimator can be obtained by attaching to the existing training job. +asynchronously. Later, a TensorFlow estimator can be obtained by attaching to the existing training job. If the training job is not finished, it starts showing the standard output of training and wait until it completes. After attaching, the estimator can be deployed as usual. @@ -882,8 +910,7 @@ in the following code: You can also bring in external dependencies to help with your data processing. There are 2 ways to do this: -1. If you included ``requirements.txt`` in your ``source_dir`` or in - your dependencies, the container installs the Python dependencies at runtime using ``pip install -r``: +1. If your model archive contains ``code/requirements.txt``, the container will install the Python dependencies at runtime using ``pip install -r``. .. code:: diff --git a/src/sagemaker/__init__.py b/src/sagemaker/__init__.py index 6b35f5abb9..122e10e927 100644 --- a/src/sagemaker/__init__.py +++ b/src/sagemaker/__init__.py @@ -13,6 +13,8 @@ """Placeholder docstring""" from __future__ import absolute_import +import logging +import sys import importlib_metadata from sagemaker import estimator, parameter, tuner # noqa: F401 @@ -61,3 +63,10 @@ from sagemaker.automl.candidate_estimator import CandidateEstimator, CandidateStep # noqa: F401 __version__ = importlib_metadata.version("sagemaker") + +if sys.version[0] == "2": + logging.getLogger("sagemaker").warning( + "SageMaker Python SDK v2 will no longer support Python 2. " + "Please see https://github.com/aws/sagemaker-python-sdk/issues/1459 " + "for more information" + ) diff --git a/src/sagemaker/amazon/amazon_estimator.py b/src/sagemaker/amazon/amazon_estimator.py index 17f17f1a13..bf76d0a94d 100644 --- a/src/sagemaker/amazon/amazon_estimator.py +++ b/src/sagemaker/amazon/amazon_estimator.py @@ -616,6 +616,11 @@ def get_image_uri(region_name, repo_name, repo_version=1): repo_name: repo_version: """ + logger.warning( + "'get_image_uri' method will be deprecated in favor of 'ImageURIProvider' class " + "in SageMaker Python SDK v2." + ) + if repo_name == "xgboost": if not _is_latest_xgboost_version(repo_version): logging.warning( diff --git a/src/sagemaker/automl/automl.py b/src/sagemaker/automl/automl.py index ed9805f75e..794e03aee1 100644 --- a/src/sagemaker/automl/automl.py +++ b/src/sagemaker/automl/automl.py @@ -39,7 +39,7 @@ def __init__( encrypt_inter_container_traffic=False, vpc_config=None, problem_type=None, - max_candidates=500, + max_candidates=None, max_runtime_per_training_job_in_seconds=None, total_job_runtime_in_seconds=None, job_objective=None, diff --git a/src/sagemaker/estimator.py b/src/sagemaker/estimator.py index c556fb3f96..81d0b6ab01 100644 --- a/src/sagemaker/estimator.py +++ b/src/sagemaker/estimator.py @@ -39,6 +39,7 @@ UploadedCode, validate_source_dir, _region_supports_debugger, + parameter_v2_rename_warning, ) from sagemaker.job import _Job from sagemaker.local import LocalSession @@ -1273,6 +1274,7 @@ def __init__( https://docs.aws.amazon.com/sagemaker/latest/dg/API_AlgorithmSpecification.html#SageMaker-Type-AlgorithmSpecification-EnableSageMakerMetricsTimeSeries (default: ``None``). """ + logging.warning(parameter_v2_rename_warning("image_name", "image_uri")) self.image_name = image_name self.hyperparam_dict = hyperparameters.copy() if hyperparameters else {} super(Estimator, self).__init__( @@ -1637,6 +1639,8 @@ def __init__( self.container_log_level = container_log_level self.code_location = code_location self.image_name = image_name + if image_name is not None: + logging.warning(parameter_v2_rename_warning("image_name", "image_uri")) self.uploaded_code = None @@ -1722,11 +1726,14 @@ def _stage_user_code_in_s3(self): code_bucket = self.sagemaker_session.default_bucket() code_s3_prefix = "{}/{}".format(self._current_job_name, "source") kms_key = None - elif self.code_location is None: code_bucket, _ = parse_s3_url(self.output_path) code_s3_prefix = "{}/{}".format(self._current_job_name, "source") kms_key = self.output_kms_key + elif local_mode: + code_bucket, key_prefix = parse_s3_url(self.code_location) + code_s3_prefix = "/".join(filter(None, [key_prefix, self._current_job_name, "source"])) + kms_key = None else: code_bucket, key_prefix = parse_s3_url(self.code_location) code_s3_prefix = "/".join(filter(None, [key_prefix, self._current_job_name, "source"])) diff --git a/src/sagemaker/fw_utils.py b/src/sagemaker/fw_utils.py index 645a28f8f1..9141ae8c72 100644 --- a/src/sagemaker/fw_utils.py +++ b/src/sagemaker/fw_utils.py @@ -34,7 +34,10 @@ instantiated with positional or keyword arguments. """ -EMPTY_FRAMEWORK_VERSION_WARNING = "No framework_version specified, defaulting to version {}." +EMPTY_FRAMEWORK_VERSION_WARNING = ( + "No framework_version specified, defaulting to version {}. " + "framework_version will be required in SageMaker Python SDK v2." +) LATER_FRAMEWORK_VERSION_WARNING = ( "This is not the latest supported version. " "If you would like to use version {latest}, " @@ -52,6 +55,10 @@ "fully leverage all GPU cores; the parameter server will be configured to run " "only one worker per host regardless of the number of GPUs." ) +PARAMETER_V2_RENAME_WARNING = ( + "Parameter {v1_parameter_name} will be renamed to {v2_parameter_name} " + "in SageMaker Python SDK v2." +) EMPTY_FRAMEWORK_VERSION_ERROR = ( @@ -253,6 +260,11 @@ def create_image_uri( Returns: str: The appropriate image URI based on the given parameters. """ + logger.warning( + "'create_image_uri' will be deprecated in favor of 'ImageURIProvider' class " + "in SageMaker Python SDK v2." + ) + optimized_families = optimized_families or [] if py_version and py_version not in VALID_PY_VERSIONS: @@ -647,6 +659,17 @@ def python_deprecation_warning(framework, latest_supported_version): ) +def parameter_v2_rename_warning(v1_parameter_name, v2_parameter_name): + """ + Args: + v1_parameter_name: parameter name used in SageMaker Python SDK v1 + v2_parameter_name: parameter name used in SageMaker Python SDK v2 + """ + return PARAMETER_V2_RENAME_WARNING.format( + v1_parameter_name=v1_parameter_name, v2_parameter_name=v2_parameter_name + ) + + def _region_supports_debugger(region_name): """Returns boolean indicating whether the region supports Amazon SageMaker Debugger. diff --git a/src/sagemaker/inputs.py b/src/sagemaker/inputs.py index c6b0659c11..63dccb1555 100644 --- a/src/sagemaker/inputs.py +++ b/src/sagemaker/inputs.py @@ -13,9 +13,13 @@ """Amazon SageMaker channel configurations for S3 data sources and file system data sources""" from __future__ import absolute_import, print_function +import logging + FILE_SYSTEM_TYPES = ["FSxLustre", "EFS"] FILE_SYSTEM_ACCESS_MODES = ["ro", "rw"] +logger = logging.getLogger("sagemaker") + class s3_input(object): """Amazon SageMaker channel configurations for S3 data sources. @@ -76,6 +80,9 @@ def __init__( this channel. See the SageMaker API documentation for more info: https://docs.aws.amazon.com/sagemaker/latest/dg/API_ShuffleConfig.html """ + logger.warning( + "'s3_input' class will be renamed to 'TrainingInput' in SageMaker Python SDK v2." + ) self.config = { "DataSource": {"S3DataSource": {"S3DataType": s3_data_type, "S3Uri": s3_data}} diff --git a/src/sagemaker/model.py b/src/sagemaker/model.py index 94e1aaf3e5..e049b6d1f5 100644 --- a/src/sagemaker/model.py +++ b/src/sagemaker/model.py @@ -108,6 +108,8 @@ def __init__( model_kms_key (str): KMS key ARN used to encrypt the repacked model archive file if the model is repacked """ + LOGGER.warning(fw_utils.parameter_v2_rename_warning("image", "image_uri")) + self.model_data = model_data self.image = image self.role = role diff --git a/src/sagemaker/mxnet/README.rst b/src/sagemaker/mxnet/README.rst index 8da08ecd48..2368dcad58 100644 --- a/src/sagemaker/mxnet/README.rst +++ b/src/sagemaker/mxnet/README.rst @@ -6,7 +6,7 @@ With the SageMaker Python SDK, you can train and host MXNet models on Amazon Sag Supported versions of MXNet: ``0.12.1``, ``1.0.0``, ``1.1.0``, ``1.2.1``, ``1.3.0``, ``1.4.0``, ``1.4.1``, ``1.6.0``. -Supported versions of MXNet for Elastic Inference: ``1.3.0``, ``1.4.0``, ``1.4.1``. +Supported versions of MXNet for Elastic Inference: ``1.3.0``, ``1.4.0``, ``1.4.1``, ``1.5.1``. Supported versions of MXNet for Inferentia: ``1.5.1``. diff --git a/src/sagemaker/mxnet/estimator.py b/src/sagemaker/mxnet/estimator.py index 76575e65b4..2b0956f90c 100644 --- a/src/sagemaker/mxnet/estimator.py +++ b/src/sagemaker/mxnet/estimator.py @@ -21,6 +21,7 @@ framework_version_from_tag, empty_framework_version_warning, python_deprecation_warning, + parameter_v2_rename_warning, is_version_equal_or_higher, warn_if_parameter_server_with_multi_gpu, ) @@ -129,6 +130,7 @@ def __init__( ) if distributions is not None: + logger.warning(parameter_v2_rename_warning("distributions", "distribution")) train_instance_type = kwargs.get("train_instance_type") warn_if_parameter_server_with_multi_gpu( training_instance_type=train_instance_type, distributions=distributions diff --git a/src/sagemaker/s3.py b/src/sagemaker/s3.py index d81710c412..316b1e002f 100644 --- a/src/sagemaker/s3.py +++ b/src/sagemaker/s3.py @@ -13,11 +13,27 @@ """This module contains Enums and helper methods related to S3.""" from __future__ import print_function, absolute_import +import logging import os from six.moves.urllib.parse import urlparse from sagemaker.session import Session +logger = logging.getLogger("sagemaker") + +SESSION_V2_RENAME_MESSAGE = ( + "Parameter 'session' will be renamed to 'sagemaker_session' in SageMaker Python SDK v2." +) + + +def _session_v2_rename_warning(session): + """ + Args: + session (sagemaker.session.Session): + """ + if session is not None: + logger.warning(SESSION_V2_RENAME_MESSAGE) + def parse_s3_url(url): """Returns an (s3 bucket, key name/prefix) tuple from a url with an s3 @@ -54,6 +70,9 @@ def upload(local_path, desired_s3_uri, kms_key=None, session=None): The S3 uri of the uploaded file(s). """ + if session is not None: + _session_v2_rename_warning(session) + sagemaker_session = session or Session() bucket, key_prefix = parse_s3_url(url=desired_s3_uri) if kms_key is not None: @@ -80,6 +99,9 @@ def upload_string_as_file_body(body, desired_s3_uri=None, kms_key=None, session= str: The S3 uri of the uploaded file(s). """ + if session is not None: + _session_v2_rename_warning(session) + sagemaker_session = session or Session() bucket, key = parse_s3_url(desired_s3_uri) @@ -107,6 +129,9 @@ def download(s3_uri, local_path, kms_key=None, session=None): using the default AWS configuration chain. """ + if session is not None: + _session_v2_rename_warning(session) + sagemaker_session = session or Session() bucket, key_prefix = parse_s3_url(url=s3_uri) if kms_key is not None: @@ -131,6 +156,9 @@ def read_file(s3_uri, session=None): str: The body of the file. """ + if session is not None: + _session_v2_rename_warning(session) + sagemaker_session = session or Session() bucket, key_prefix = parse_s3_url(url=s3_uri) @@ -149,6 +177,9 @@ def list(s3_uri, session=None): [str]: The list of S3 URIs in the given S3 base uri. """ + if session is not None: + _session_v2_rename_warning(session) + sagemaker_session = session or Session() bucket, key_prefix = parse_s3_url(url=s3_uri) diff --git a/src/sagemaker/session.py b/src/sagemaker/session.py index 0dc5bf3161..c58801a886 100644 --- a/src/sagemaker/session.py +++ b/src/sagemaker/session.py @@ -181,6 +181,12 @@ def upload_data(self, path, bucket=None, key_prefix="data", extra_args=None): ``s3://{bucket name}/{key_prefix}``. """ # Generate a tuple for each file that we want to upload of the form (local_path, s3_key). + LOGGER.warning( + "'upload_data' method will be deprecated in favor of 'S3Uploader' class " + "(https://sagemaker.readthedocs.io/en/stable/s3.html#sagemaker.s3.S3Uploader) " + "in SageMaker Python SDK v2." + ) + files = [] key_suffix = None if os.path.isdir(path): @@ -230,6 +236,12 @@ def upload_string_as_file_body(self, body, bucket, key, kms_key=None): str: The S3 URI of the uploaded file. The URI format is: ``s3://{bucket name}/{key}``. """ + LOGGER.warning( + "'upload_string_as_file_body' method will be deprecated in favor of 'S3Uploader' class " + "(https://sagemaker.readthedocs.io/en/stable/s3.html#sagemaker.s3.S3Uploader) " + "in SageMaker Python SDK v2." + ) + if self.s3_resource is None: s3 = self.boto_session.resource("s3", region_name=self.boto_region_name) else: @@ -2573,6 +2585,18 @@ def wait_for_tuning_job(self, job, poll=5): self._check_job_status(job, desc, "HyperParameterTuningJobStatus") return desc + def describe_transform_job(self, job_name): + """Calls the DescribeTransformJob API for the given job name + and returns the response. + + Args: + job_name (str): The name of the transform job to describe. + + Returns: + dict: A dictionary response with the transform job description. + """ + return self.sagemaker_client.describe_transform_job(TransformJobName=job_name) + def wait_for_transform_job(self, job, poll=5): """Wait for an Amazon SageMaker transform job to complete. @@ -3311,6 +3335,7 @@ def get_execution_role(sagemaker_session=None): Returns: (str): The role ARN """ + if not sagemaker_session: sagemaker_session = Session() arn = sagemaker_session.get_caller_identity_arn() diff --git a/src/sagemaker/tensorflow/defaults.py b/src/sagemaker/tensorflow/defaults.py index e3bc65e2a8..b4f99d0e3c 100644 --- a/src/sagemaker/tensorflow/defaults.py +++ b/src/sagemaker/tensorflow/defaults.py @@ -21,4 +21,7 @@ LATEST_VERSION = "2.2.0" """The latest version of TensorFlow included in the SageMaker pre-built Docker images.""" +LATEST_SERVING_VERSION = "2.1.0" +"""The latest version of TensorFlow Serving included in the SageMaker pre-built Docker images.""" + LATEST_PY2_VERSION = "2.1.0" diff --git a/src/sagemaker/tensorflow/estimator.py b/src/sagemaker/tensorflow/estimator.py index be238f4c9a..fc3c52b200 100644 --- a/src/sagemaker/tensorflow/estimator.py +++ b/src/sagemaker/tensorflow/estimator.py @@ -201,6 +201,7 @@ class TensorFlow(Framework): __framework_name__ = "tensorflow" LATEST_VERSION = defaults.LATEST_VERSION + LATEST_SERVING_VERSION = defaults.LATEST_SERVING_VERSION _LATEST_1X_VERSION = "1.15.2" @@ -311,6 +312,7 @@ def __init__( ) if distributions is not None: + logger.warning(fw.parameter_v2_rename_warning("distribution", distributions)) train_instance_type = kwargs.get("train_instance_type") fw.warn_if_parameter_server_with_multi_gpu( training_instance_type=train_instance_type, distributions=distributions @@ -385,7 +387,9 @@ def _validate_args( if (not self._script_mode_enabled()) and self._only_script_mode_supported(): logger.warning( - "Legacy mode is deprecated in versions 1.13 and higher. Using script mode instead." + "Legacy mode is deprecated in versions 1.13 and higher. Using script mode instead. " + "Legacy mode and its training parameters will be deprecated in " + "SageMaker Python SDK v2. Please use TF 1.13 or higher and script mode." ) self.script_mode = True diff --git a/src/sagemaker/transformer.py b/src/sagemaker/transformer.py index 0603b8a579..95cbb2e634 100644 --- a/src/sagemaker/transformer.py +++ b/src/sagemaker/transformer.py @@ -135,6 +135,7 @@ def transform( * 'ManifestFile' - the S3 URI points to a single manifest file listing each S3 object to use as an input for the transform job. + content_type (str): MIME type of the input data (default: None). compression_type (str): Compression type of the input data, if compressed (default: None). Valid values: 'Gzip', None. diff --git a/src/sagemaker/workflow/airflow.py b/src/sagemaker/workflow/airflow.py index 6d663bad94..54ff0ee5df 100644 --- a/src/sagemaker/workflow/airflow.py +++ b/src/sagemaker/workflow/airflow.py @@ -671,6 +671,9 @@ def transform_config( compression_type=None, split_type=None, job_name=None, + input_filter=None, + output_filter=None, + join_source=None, ): """Export Airflow transform config from a SageMaker transformer @@ -686,6 +689,7 @@ def transform_config( * 'ManifestFile' - the S3 URI points to a single manifest file listing each S3 object to use as an input for the transform job. + content_type (str): MIME type of the input data (default: None). compression_type (str): Compression type of the input data, if compressed (default: None). Valid values: 'Gzip', None. @@ -693,6 +697,30 @@ def transform_config( 'None'). Valid values: 'None', 'Line', 'RecordIO', and 'TFRecord'. job_name (str): job name (default: None). If not specified, one will be generated. + input_filter (str): A JSONPath to select a portion of the input to + pass to the algorithm container for inference. If you omit the + field, it gets the value '$', representing the entire input. + For CSV data, each row is taken as a JSON array, + so only index-based JSONPaths can be applied, e.g. $[0], $[1:]. + CSV data should follow the `RFC format `_. + See `Supported JSONPath Operators + `_ + for a table of supported JSONPath operators. + For more information, see the SageMaker API documentation for + `CreateTransformJob + `_. + Some examples: "$[1:]", "$.features" (default: None). + output_filter (str): A JSONPath to select a portion of the + joined/original output to return as the output. + For more information, see the SageMaker API documentation for + `CreateTransformJob + `_. + Some examples: "$[1:]", "$.prediction" (default: None). + join_source (str): The source of data to be joined to the transform + output. It can be set to 'Input' meaning the entire input record + will be joined to the inference result. You can use OutputFilter + to select the useful portion before uploading to S3. (default: + None). Valid values: Input, None. Returns: dict: Transform config that can be directly used by @@ -723,6 +751,12 @@ def transform_config( "TransformResources": job_config["resource_config"], } + data_processing = sagemaker.transformer._TransformJob._prepare_data_processing( + input_filter, output_filter, join_source + ) + if data_processing is not None: + config["DataProcessing"] = data_processing + if transformer.strategy is not None: config["BatchStrategy"] = transformer.strategy @@ -768,6 +802,9 @@ def transform_config_from_estimator( model_server_workers=None, image=None, vpc_config_override=None, + input_filter=None, + output_filter=None, + join_source=None, ): """Export Airflow transform config from a SageMaker estimator @@ -836,9 +873,35 @@ def transform_config_from_estimator( image (str): An container image to use for deploying the model vpc_config_override (dict[str, list[str]]): Override for VpcConfig set on the model. Default: use subnets and security groups from this Estimator. + * 'Subnets' (list[str]): List of subnet ids. * 'SecurityGroupIds' (list[str]): List of security group ids. + input_filter (str): A JSONPath to select a portion of the input to + pass to the algorithm container for inference. If you omit the + field, it gets the value '$', representing the entire input. + For CSV data, each row is taken as a JSON array, + so only index-based JSONPaths can be applied, e.g. $[0], $[1:]. + CSV data should follow the `RFC format `_. + See `Supported JSONPath Operators + `_ + for a table of supported JSONPath operators. + For more information, see the SageMaker API documentation for + `CreateTransformJob + `_. + Some examples: "$[1:]", "$.features" (default: None). + output_filter (str): A JSONPath to select a portion of the + joined/original output to return as the output. + For more information, see the SageMaker API documentation for + `CreateTransformJob + `_. + Some examples: "$[1:]", "$.prediction" (default: None). + join_source (str): The source of data to be joined to the transform + output. It can be set to 'Input' meaning the entire input record + will be joined to the inference result. You can use OutputFilter + to select the useful portion before uploading to S3. (default: + None). Valid values: Input, None. + Returns: dict: Transform config that can be directly used by SageMakerTransformOperator in Airflow. @@ -891,7 +954,16 @@ def transform_config_from_estimator( transformer.model_name = model_base_config["ModelName"] transform_base_config = transform_config( - transformer, data, data_type, content_type, compression_type, split_type, job_name + transformer, + data, + data_type, + content_type, + compression_type, + split_type, + job_name, + input_filter, + output_filter, + join_source, ) config = {"Model": model_base_config, "Transform": transform_base_config} diff --git a/tests/conftest.py b/tests/conftest.py index b7cab1dd44..d5cfc3a8a8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -50,7 +50,7 @@ def pytest_addoption(parser): parser.addoption("--boto-config", action="store", default=None) parser.addoption("--chainer-full-version", action="store", default=Chainer.LATEST_VERSION) parser.addoption("--mxnet-full-version", action="store", default=MXNet.LATEST_VERSION) - parser.addoption("--ei-mxnet-full-version", action="store", default="1.4.1") + parser.addoption("--ei-mxnet-full-version", action="store", default="1.5.1") parser.addoption("--pytorch-full-version", action="store", default=PyTorch.LATEST_VERSION) parser.addoption( "--rl-coach-mxnet-full-version", diff --git a/tests/integ/test_airflow_config.py b/tests/integ/test_airflow_config.py index 25439f67af..1d60a4a3f5 100644 --- a/tests/integ/test_airflow_config.py +++ b/tests/integ/test_airflow_config.py @@ -682,6 +682,8 @@ def _build_airflow_workflow(estimator, instance_type, inputs=None, mini_batch_si instance_type=estimator.train_instance_type, data=inputs, content_type="text/csv", + input_filter="$", + output_filter="$", ) default_args = { diff --git a/tests/integ/test_experiments_analytics.py b/tests/integ/test_experiments_analytics.py index be0d0d39c6..80e9dfd3f9 100644 --- a/tests/integ/test_experiments_analytics.py +++ b/tests/integ/test_experiments_analytics.py @@ -138,6 +138,7 @@ def _delete_resources(sagemaker_client, experiment_name, trials): for trial, tc in trials.items(): with _ignore_resource_not_found(sagemaker_client): sagemaker_client.disassociate_trial_component(TrialName=trial, TrialComponentName=tc) + _wait_for_trial_component_disassociation(sagemaker_client, tc) with _ignore_resource_not_found(sagemaker_client): sagemaker_client.delete_trial_component(TrialComponentName=tc) @@ -155,3 +156,14 @@ def _ignore_resource_not_found(sagemaker_client): yield except sagemaker_client.exceptions.ResourceNotFound: pass + + +def _wait_for_trial_component_disassociation(sagemaker_client, tc): + # Sometimes it can take a bit of waiting for the trial component to be disassociated + for _ in range(5): + # Check that the trial component has been disassociated from the trial + trials = sagemaker_client.list_trials(TrialComponentName=tc)["TrialSummaries"] + if len(trials) == 0: + break + + time.sleep(1) diff --git a/tests/integ/test_local_mode.py b/tests/integ/test_local_mode.py index 215a3684d0..936928101d 100644 --- a/tests/integ/test_local_mode.py +++ b/tests/integ/test_local_mode.py @@ -361,6 +361,7 @@ def test_mxnet_training_failure(sagemaker_local_session, mxnet_full_version, tmp train_instance_count=1, train_instance_type="local", sagemaker_session=sagemaker_local_session, + code_location="s3://{}".format(sagemaker_local_session.default_bucket()), output_path="file://{}".format(tmpdir), ) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index c8db998a27..075129f3a1 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -37,12 +37,18 @@ PARAMETER_SERVER_DISTRIBUTION = {"parameter_server": {"enabled": True}} MPI_DISTRIBUTION = {"mpi": {"enabled": True}} TAGS = [{"Key": "some-key", "Value": "some-value"}] -PY37_SUPPORTED_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] + + +@pytest.fixture(scope="module") +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version @pytest.fixture(scope="module") def py_version(tf_full_version): - return "py37" if tf_full_version in PY37_SUPPORTED_VERSION else tests.integ.PYTHON_VERSION + return "py37" if tf_full_version == tf_serving_version else tests.integ.PYTHON_VERSION def test_mnist_with_checkpoint_config( @@ -90,7 +96,7 @@ def test_mnist_with_checkpoint_config( assert actual_training_checkpoint_config == expected_training_checkpoint_config -def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): +def test_server_side_encryption(sagemaker_session, tf_serving_version, py_version): with kms_utils.bucket_with_encryption(sagemaker_session, ROLE) as (bucket_with_kms, kms_key): output_path = os.path.join( bucket_with_kms, "test-server-side-encryption", time.strftime("%y%m%d-%H%M") @@ -104,7 +110,7 @@ def test_server_side_encryption(sagemaker_session, tf_full_version, py_version): train_instance_type="ml.c5.xlarge", sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_serving_version, py_version=py_version, code_location=output_path, output_path=output_path, @@ -167,7 +173,7 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v sagemaker_session=sagemaker_session, script_mode=True, # testing py-sdk functionality, no need to run against all TF versions - framework_version=TensorFlow.LATEST_VERSION, + framework_version=TensorFlow.LATEST_SERVING_VERSION, tags=TAGS, ) inputs = estimator.sagemaker_session.upload_data( @@ -199,7 +205,9 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v _assert_model_name_match(sagemaker_session.sagemaker_client, endpoint_name, model_name) -def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_full_version, py_version): +def test_deploy_with_input_handlers( + sagemaker_session, instance_type, tf_serving_version, py_version +): estimator = TensorFlow( entry_point="training.py", source_dir=TFS_RESOURCE_PATH, @@ -209,7 +217,7 @@ def test_deploy_with_input_handlers(sagemaker_session, instance_type, tf_full_ve py_version=py_version, sagemaker_session=sagemaker_session, script_mode=True, - framework_version=tf_full_version, + framework_version=tf_serving_version, tags=TAGS, ) diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index 4d070fac85..4ed13966e5 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -23,11 +23,19 @@ import sagemaker.utils import tests.integ import tests.integ.timeout +from sagemaker.tensorflow import TensorFlow from sagemaker.tensorflow.serving import Model, Predictor @pytest.fixture(scope="module") -def tfs_predictor(sagemaker_session, tf_full_version): +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version + + +@pytest.fixture(scope="module") +def tfs_predictor(sagemaker_session, tf_serving_version): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( path=os.path.join(tests.integ.DATA_DIR, "tensorflow-serving-test-model.tar.gz"), @@ -37,7 +45,7 @@ def tfs_predictor(sagemaker_session, tf_full_version): model = Model( model_data=model_data, role="SageMakerRole", - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) predictor = model.deploy(1, "ml.c5.xlarge", endpoint_name=endpoint_name) @@ -54,7 +62,7 @@ def tar_dir(directory, tmpdir): @pytest.fixture def tfs_predictor_with_model_and_entry_point_same_tar( - sagemaker_local_session, tf_full_version, tmpdir + sagemaker_local_session, tf_serving_version, tmpdir ): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") @@ -65,7 +73,7 @@ def tfs_predictor_with_model_and_entry_point_same_tar( model = Model( model_data="file://" + model_tar, role="SageMakerRole", - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_local_session, ) predictor = model.deploy(1, "local", endpoint_name=endpoint_name) @@ -78,7 +86,7 @@ def tfs_predictor_with_model_and_entry_point_same_tar( @pytest.fixture(scope="module") def tfs_predictor_with_model_and_entry_point_and_dependencies( - sagemaker_local_session, tf_full_version + sagemaker_local_session, tf_serving_version ): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") @@ -98,7 +106,7 @@ def tfs_predictor_with_model_and_entry_point_and_dependencies( model_data=model_data, role="SageMakerRole", dependencies=dependencies, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_local_session, ) diff --git a/tests/integ/test_transformer.py b/tests/integ/test_transformer.py index 8eec086a11..1c167829fb 100644 --- a/tests/integ/test_transformer.py +++ b/tests/integ/test_transformer.py @@ -97,8 +97,8 @@ def test_transform_mxnet( ): transformer.wait() - job_desc = transformer.sagemaker_session.sagemaker_client.describe_transform_job( - TransformJobName=transformer.latest_transform_job.name + job_desc = transformer.sagemaker_session.describe_transform_job( + job_name=transformer.latest_transform_job.name ) assert kms_key_arn == job_desc["TransformResources"]["VolumeKmsKeyId"] assert output_filter == job_desc["DataProcessing"]["OutputFilter"] @@ -323,8 +323,8 @@ def test_stop_transform_job(mxnet_estimator, mxnet_transform_input, cpu_instance transformer.stop_transform_job() - desc = transformer.latest_transform_job.sagemaker_session.sagemaker_client.describe_transform_job( - TransformJobName=latest_transform_job_name + desc = transformer.latest_transform_job.sagemaker_session.describe_transform_job( + job_name=latest_transform_job_name ) assert desc["TransformJobStatus"] == "Stopped" @@ -351,7 +351,7 @@ def test_transform_tf_kms_network_isolation(sagemaker_session, cpu_instance_type role="SageMakerRole", train_instance_count=1, train_instance_type=cpu_instance_type, - framework_version=TensorFlow.LATEST_VERSION, + framework_version=TensorFlow.LATEST_SERVING_VERSION, script_mode=True, py_version=PYTHON_VERSION, sagemaker_session=sagemaker_session, @@ -393,9 +393,7 @@ def test_transform_tf_kms_network_isolation(sagemaker_session, cpu_instance_type ) assert model_desc["EnableNetworkIsolation"] - job_desc = sagemaker_session.sagemaker_client.describe_transform_job( - TransformJobName=job_name - ) + job_desc = sagemaker_session.describe_transform_job(job_name=job_name) assert job_desc["TransformOutput"]["S3OutputPath"] == output_path assert job_desc["TransformOutput"]["KmsKeyId"] == kms_key assert job_desc["TransformResources"]["VolumeKmsKeyId"] == kms_key diff --git a/tests/unit/sagemaker/automl/test_auto_ml.py b/tests/unit/sagemaker/automl/test_auto_ml.py index c6b240e2b2..8ef0cd31da 100644 --- a/tests/unit/sagemaker/automl/test_auto_ml.py +++ b/tests/unit/sagemaker/automl/test_auto_ml.py @@ -32,7 +32,7 @@ DEFAULT_S3_INPUT_DATA = "s3://{}/data".format(BUCKET_NAME) DEFAULT_OUTPUT_PATH = "s3://{}/".format(BUCKET_NAME) LOCAL_DATA_PATH = "file://data" -DEFAULT_MAX_CANDIDATES = 500 +DEFAULT_MAX_CANDIDATES = None DEFAULT_JOB_NAME = "automl-{}".format(TIMESTAMP) JOB_NAME = "default-job-name" diff --git a/tests/unit/test_airflow.py b/tests/unit/test_airflow.py index 835929e750..b01835c1d3 100644 --- a/tests/unit/test_airflow.py +++ b/tests/unit/test_airflow.py @@ -10,7 +10,6 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. - from __future__ import absolute_import import pytest @@ -21,7 +20,6 @@ from sagemaker.amazon import amazon_estimator from sagemaker.amazon import knn, linear_learner, ntm, pca - REGION = "us-west-2" BUCKET_NAME = "output" TIME_STAMP = "1111" @@ -1162,6 +1160,9 @@ def test_transform_config(sagemaker_session): content_type="{{ content_type }}", compression_type="{{ compression_type }}", split_type="{{ split_type }}", + input_filter="{{ input_filter }}", + output_filter="{{ output_filter }}", + join_source="{{ join_source }}", ) expected_config = { "TransformJobName": "tensorflow-transform-%s" % TIME_STAMP, @@ -1190,6 +1191,11 @@ def test_transform_config(sagemaker_session): "MaxPayloadInMB": "{{ max_payload }}", "Environment": {"{{ key }}": "{{ value }}"}, "Tags": [{"{{ key }}": "{{ value }}"}], + "DataProcessing": { + "InputFilter": "{{ input_filter }}", + "JoinSource": "{{ join_source }}", + "OutputFilter": "{{ output_filter }}", + }, } assert config == expected_config @@ -1238,6 +1244,9 @@ def test_transform_config_from_framework_estimator(ecr_prefix, sagemaker_session instance_count="{{ instance_count }}", instance_type="ml.p2.xlarge", data=transform_data, + input_filter="{{ input_filter }}", + output_filter="{{ output_filter }}", + join_source="{{ join_source }}", ) expected_config = { "Model": { @@ -1272,6 +1281,11 @@ def test_transform_config_from_framework_estimator(ecr_prefix, sagemaker_session "InstanceType": "ml.p2.xlarge", }, "Environment": {}, + "DataProcessing": { + "InputFilter": "{{ input_filter }}", + "JoinSource": "{{ join_source }}", + "OutputFilter": "{{ output_filter }}", + }, }, } diff --git a/tests/unit/test_amazon_estimator.py b/tests/unit/test_amazon_estimator.py index 274606fbc4..1c0a2fbd10 100644 --- a/tests/unit/test_amazon_estimator.py +++ b/tests/unit/test_amazon_estimator.py @@ -486,3 +486,12 @@ def test_is_latest_xgboost_version(): assert _is_latest_xgboost_version("0.90-1-cpu-py3") is False assert _is_latest_xgboost_version(XGBOOST_LATEST_VERSION) is True + + +def test_get_image_uri_warn(caplog): + warning_message = ( + "'get_image_uri' method will be deprecated in favor of 'ImageURIProvider' class " + "in SageMaker Python SDK v2." + ) + get_image_uri("us-west-2", "kmeans", "latest") + assert warning_message in caplog.text diff --git a/tests/unit/test_fw_utils.py b/tests/unit/test_fw_utils.py index 1c6388c38b..1e211193ca 100644 --- a/tests/unit/test_fw_utils.py +++ b/tests/unit/test_fw_utils.py @@ -337,13 +337,13 @@ def test_mxnet_eia_images(): "us-east-1", "mxnet-serving", "ml.c4.2xlarge", - "1.4.1", + "1.5.1", "py3", accelerator_type="ml.eia1.large", ) assert ( image_uri - == "{}.dkr.ecr.us-east-1.amazonaws.com/mxnet-inference-eia:1.4.1-cpu-py3".format( + == "{}.dkr.ecr.us-east-1.amazonaws.com/mxnet-inference-eia:1.5.1-cpu-py3".format( fw_utils.ASIMOV_PROD_ACCOUNT ) ) diff --git a/tests/unit/test_inputs.py b/tests/unit/test_inputs.py index cd68501396..a4ae8a0da7 100644 --- a/tests/unit/test_inputs.py +++ b/tests/unit/test_inputs.py @@ -18,7 +18,7 @@ from sagemaker.inputs import FileSystemInput -def test_s3_input_all_defaults(): +def test_s3_input_all_defaults(caplog): prefix = "pre" actual = s3_input(s3_data=prefix) expected = { @@ -32,6 +32,11 @@ def test_s3_input_all_defaults(): } assert actual.config == expected + warning_message = ( + "'s3_input' class will be renamed to 'TrainingInput' in SageMaker Python SDK v2." + ) + assert warning_message in caplog.text + def test_s3_input_all_arguments(): prefix = "pre" diff --git a/tests/unit/test_mxnet.py b/tests/unit/test_mxnet.py index 2736bc6736..e073462a3f 100644 --- a/tests/unit/test_mxnet.py +++ b/tests/unit/test_mxnet.py @@ -675,7 +675,8 @@ def test_attach_custom_image(sagemaker_session): assert estimator.train_image() == training_image -def test_estimator_script_mode_launch_parameter_server(sagemaker_session): +@patch("sagemaker.mxnet.estimator.parameter_v2_rename_warning") +def test_estimator_script_mode_launch_parameter_server(warning, sagemaker_session): mx = MXNet( entry_point=SCRIPT_PATH, role=ROLE, @@ -686,6 +687,7 @@ def test_estimator_script_mode_launch_parameter_server(sagemaker_session): framework_version="1.3.0", ) assert mx.hyperparameters().get(MXNet.LAUNCH_PS_ENV_NAME) == "true" + warning.assert_called_with("distributions", "distribution") def test_estimator_script_mode_dont_launch_parameter_server(sagemaker_session): diff --git a/tests/unit/test_s3.py b/tests/unit/test_s3.py index c073417116..12238e183b 100644 --- a/tests/unit/test_s3.py +++ b/tests/unit/test_s3.py @@ -40,7 +40,7 @@ def sagemaker_session(): return session_mock -def test_upload(sagemaker_session): +def test_upload(sagemaker_session, caplog): desired_s3_uri = os.path.join("s3://", BUCKET_NAME, CURRENT_JOB_NAME, SOURCE_NAME) S3Uploader.upload( local_path="/path/to/app.jar", desired_s3_uri=desired_s3_uri, session=sagemaker_session @@ -51,6 +51,10 @@ def test_upload(sagemaker_session): key_prefix=os.path.join(CURRENT_JOB_NAME, SOURCE_NAME), extra_args=None, ) + warning_message = ( + "Parameter 'session' will be renamed to 'sagemaker_session' " "in SageMaker Python SDK v2." + ) + assert warning_message in caplog.text def test_upload_with_kms_key(sagemaker_session): From c251fcc69b187776e7e3279696c6d55dbf9069e6 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 13:30:07 -0700 Subject: [PATCH 13/21] tf 2.2 using py37 --- tests/integ/test_tf_script_mode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index 075129f3a1..fe5749a47c 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -66,7 +66,7 @@ def test_mnist_with_checkpoint_config( sagemaker_session=sagemaker_session, script_mode=True, framework_version=tf_full_version, - py_version=py_version, + py_version="py37", metric_definitions=[{"Name": "train:global_steps", "Regex": r"global_step\/sec:\s(.*)"}], checkpoint_s3_uri=checkpoint_s3_uri, checkpoint_local_path=checkpoint_local_path, @@ -145,7 +145,7 @@ def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py train_instance_count=2, train_instance_type=instance_type, sagemaker_session=sagemaker_session, - py_version=py_version, + py_version="py37", script_mode=True, framework_version=tf_full_version, distributions=PARAMETER_SERVER_DISTRIBUTION, From 3255b0441389fce8dc18855b0b44b8b55c030d7d Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 14:14:30 -0700 Subject: [PATCH 14/21] test_data_capture_config use TFS latest version --- tests/integ/test_data_capture_config.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tests/integ/test_data_capture_config.py b/tests/integ/test_data_capture_config.py index afa8d23ebd..7b8704c495 100644 --- a/tests/integ/test_data_capture_config.py +++ b/tests/integ/test_data_capture_config.py @@ -40,8 +40,15 @@ CUSTOM_JSON_CONTENT_TYPES = ["application/jsontype1", "application/jsontype2"] +@pytest.fixture(scope="module") +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version + + def test_enabling_data_capture_on_endpoint_shows_correct_data_capture_status( - sagemaker_session, tf_full_version + sagemaker_session, tf_serving_version ): endpoint_name = unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( @@ -52,7 +59,7 @@ def test_enabling_data_capture_on_endpoint_shows_correct_data_capture_status( model = Model( model_data=model_data, role=ROLE, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) predictor = model.deploy( @@ -98,7 +105,7 @@ def test_enabling_data_capture_on_endpoint_shows_correct_data_capture_status( def test_disabling_data_capture_on_endpoint_shows_correct_data_capture_status( - sagemaker_session, tf_full_version + sagemaker_session, tf_serving_version ): endpoint_name = unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( @@ -109,7 +116,7 @@ def test_disabling_data_capture_on_endpoint_shows_correct_data_capture_status( model = Model( model_data=model_data, role=ROLE, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) destination_s3_uri = os.path.join( @@ -184,7 +191,7 @@ def test_disabling_data_capture_on_endpoint_shows_correct_data_capture_status( def test_updating_data_capture_on_endpoint_shows_correct_data_capture_status( - sagemaker_session, tf_full_version + sagemaker_session, tf_serving_version ): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( @@ -195,7 +202,7 @@ def test_updating_data_capture_on_endpoint_shows_correct_data_capture_status( model = Model( model_data=model_data, role=ROLE, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) destination_s3_uri = os.path.join( From 2a7f154aefa2c950db7fb00130ecf0f262037ebc Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 14:23:47 -0700 Subject: [PATCH 15/21] fix flake8 error --- tests/integ/test_data_capture_config.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/integ/test_data_capture_config.py b/tests/integ/test_data_capture_config.py index 7b8704c495..262175b86f 100644 --- a/tests/integ/test_data_capture_config.py +++ b/tests/integ/test_data_capture_config.py @@ -13,11 +13,13 @@ from __future__ import absolute_import import os +import pytest import sagemaker import tests.integ import tests.integ.timeout from sagemaker.model_monitor import DataCaptureConfig, NetworkConfig +from sagemaker.tensorflow import TensorFlow from sagemaker.tensorflow.serving import Model from sagemaker.utils import unique_name_from_base from tests.integ.retry import retries From 3b10a76abc45fbf10ae700221ab89158dc5a5378 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 15:20:09 -0700 Subject: [PATCH 16/21] update model monitoring test --- tests/integ/test_model_monitor.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/integ/test_model_monitor.py b/tests/integ/test_model_monitor.py index 338a676186..30b13aeb91 100644 --- a/tests/integ/test_model_monitor.py +++ b/tests/integ/test_model_monitor.py @@ -22,6 +22,7 @@ import tests.integ.timeout from sagemaker.s3 import S3Uploader +from sagemaker.tensorflow import TensorFlow from datetime import datetime, timedelta from tests.integ import DATA_DIR @@ -88,7 +89,14 @@ @pytest.fixture(scope="module") -def predictor(sagemaker_session, tf_full_version): +def tf_serving_version(tf_full_version): + if tf_full_version == TensorFlow.LATEST_VERSION: + return TensorFlow.LATEST_SERVING_VERSION + return tf_full_version + + +@pytest.fixture(scope="module") +def predictor(sagemaker_session, tf_serving_version): endpoint_name = unique_name_from_base("sagemaker-tensorflow-serving") model_data = sagemaker_session.upload_data( path=os.path.join(tests.integ.DATA_DIR, "tensorflow-serving-test-model.tar.gz"), @@ -100,7 +108,7 @@ def predictor(sagemaker_session, tf_full_version): model = Model( model_data=model_data, role=ROLE, - framework_version=tf_full_version, + framework_version=tf_serving_version, sagemaker_session=sagemaker_session, ) predictor = model.deploy( From 9c2bb6ca9fba10a87ee16c1aefb1e2577eef5ccc Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Thu, 21 May 2020 15:59:24 -0700 Subject: [PATCH 17/21] update python version for tuner integ test --- tests/integ/test_tuner.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/integ/test_tuner.py b/tests/integ/test_tuner.py index 705fbde56f..871d832322 100644 --- a/tests/integ/test_tuner.py +++ b/tests/integ/test_tuner.py @@ -51,6 +51,13 @@ DATA_PATH = os.path.join(DATA_DIR, "iris", "data") +PY37_SUPPORTED_FRAMEWORK_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] + + +@pytest.fixture(scope="module") +def py_version(tf_full_version): + return "py37" if tf_full_version in PY37_SUPPORTED_FRAMEWORK_VERSION else PYTHON_VERSION + @pytest.fixture(scope="module") def kmeans_train_set(sagemaker_session): @@ -590,7 +597,7 @@ def test_tuning_mxnet(sagemaker_session, mxnet_full_version, cpu_instance_type): @pytest.mark.canary_quick -def test_tuning_tf_script_mode(sagemaker_session, cpu_instance_type, tf_full_version): +def test_tuning_tf_script_mode(sagemaker_session, cpu_instance_type, tf_full_version, py_version): resource_path = os.path.join(DATA_DIR, "tensorflow_mnist") script_path = os.path.join(resource_path, "mnist.py") @@ -601,7 +608,7 @@ def test_tuning_tf_script_mode(sagemaker_session, cpu_instance_type, tf_full_ver train_instance_type=cpu_instance_type, script_mode=True, sagemaker_session=sagemaker_session, - py_version=PYTHON_VERSION, + py_version=py_version, framework_version=tf_full_version, ) From fe14848fa1c52aa0959ea0dd86b19e20101d7ae9 Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Fri, 22 May 2020 11:13:17 -0700 Subject: [PATCH 18/21] address comments --- src/sagemaker/tensorflow/estimator.py | 1 - tests/conftest.py | 11 +++++++++-- tests/integ/test_data_capture_config.py | 9 --------- tests/integ/test_model_monitor.py | 8 -------- tests/integ/test_tf_script_mode.py | 13 +++---------- tests/integ/test_tfs.py | 8 -------- tests/integ/test_transformer.py | 3 ++- tests/integ/test_tuner.py | 3 ++- 8 files changed, 16 insertions(+), 40 deletions(-) diff --git a/src/sagemaker/tensorflow/estimator.py b/src/sagemaker/tensorflow/estimator.py index fc3c52b200..e12633b349 100644 --- a/src/sagemaker/tensorflow/estimator.py +++ b/src/sagemaker/tensorflow/estimator.py @@ -201,7 +201,6 @@ class TensorFlow(Framework): __framework_name__ = "tensorflow" LATEST_VERSION = defaults.LATEST_VERSION - LATEST_SERVING_VERSION = defaults.LATEST_SERVING_VERSION _LATEST_1X_VERSION = "1.15.2" diff --git a/tests/conftest.py b/tests/conftest.py index d5cfc3a8a8..bf219d00a7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,7 +27,7 @@ from sagemaker.pytorch import PyTorch from sagemaker.rl import RLEstimator from sagemaker.sklearn.defaults import SKLEARN_VERSION -from sagemaker.tensorflow.estimator import TensorFlow +from sagemaker.tensorflow.defaults import _LATEST_1X_VERSION, LATEST_VERSION, LATEST_SERVING_VERSION DEFAULT_REGION = "us-west-2" CUSTOM_BUCKET_NAME_PREFIX = "sagemaker-custom-bucket" @@ -259,7 +259,7 @@ def sklearn_full_version(request): return request.config.getoption("--sklearn-full-version") -@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION]) +@pytest.fixture(scope="module", params=[_LATEST_1X_VERSION, LATEST_VERSION]) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") if tf_version is None: @@ -335,3 +335,10 @@ def pytest_generate_tests(metafunc): @pytest.fixture(scope="module") def xgboost_full_version(request): return request.config.getoption("--xgboost-full-version") + + +@pytest.fixture(scope="module") +def tf_serving_version(tf_full_version): + if tf_full_version == LATEST_VERSION: + return LATEST_SERVING_VERSION + return tf_full_version diff --git a/tests/integ/test_data_capture_config.py b/tests/integ/test_data_capture_config.py index 262175b86f..a75c71a076 100644 --- a/tests/integ/test_data_capture_config.py +++ b/tests/integ/test_data_capture_config.py @@ -13,13 +13,11 @@ from __future__ import absolute_import import os -import pytest import sagemaker import tests.integ import tests.integ.timeout from sagemaker.model_monitor import DataCaptureConfig, NetworkConfig -from sagemaker.tensorflow import TensorFlow from sagemaker.tensorflow.serving import Model from sagemaker.utils import unique_name_from_base from tests.integ.retry import retries @@ -42,13 +40,6 @@ CUSTOM_JSON_CONTENT_TYPES = ["application/jsontype1", "application/jsontype2"] -@pytest.fixture(scope="module") -def tf_serving_version(tf_full_version): - if tf_full_version == TensorFlow.LATEST_VERSION: - return TensorFlow.LATEST_SERVING_VERSION - return tf_full_version - - def test_enabling_data_capture_on_endpoint_shows_correct_data_capture_status( sagemaker_session, tf_serving_version ): diff --git a/tests/integ/test_model_monitor.py b/tests/integ/test_model_monitor.py index 30b13aeb91..499b3dc076 100644 --- a/tests/integ/test_model_monitor.py +++ b/tests/integ/test_model_monitor.py @@ -22,7 +22,6 @@ import tests.integ.timeout from sagemaker.s3 import S3Uploader -from sagemaker.tensorflow import TensorFlow from datetime import datetime, timedelta from tests.integ import DATA_DIR @@ -88,13 +87,6 @@ FIVE_MINUTE_CRON_EXPRESSION = "cron(0/5 * ? * * *)" -@pytest.fixture(scope="module") -def tf_serving_version(tf_full_version): - if tf_full_version == TensorFlow.LATEST_VERSION: - return TensorFlow.LATEST_SERVING_VERSION - return tf_full_version - - @pytest.fixture(scope="module") def predictor(sagemaker_session, tf_serving_version): endpoint_name = unique_name_from_base("sagemaker-tensorflow-serving") diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index fe5749a47c..fac815daeb 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -40,14 +40,7 @@ @pytest.fixture(scope="module") -def tf_serving_version(tf_full_version): - if tf_full_version == TensorFlow.LATEST_VERSION: - return TensorFlow.LATEST_SERVING_VERSION - return tf_full_version - - -@pytest.fixture(scope="module") -def py_version(tf_full_version): +def py_version(tf_full_version, tf_serving_version): return "py37" if tf_full_version == tf_serving_version else tests.integ.PYTHON_VERSION @@ -66,7 +59,7 @@ def test_mnist_with_checkpoint_config( sagemaker_session=sagemaker_session, script_mode=True, framework_version=tf_full_version, - py_version="py37", + py_version=py_version, metric_definitions=[{"Name": "train:global_steps", "Regex": r"global_step\/sec:\s(.*)"}], checkpoint_s3_uri=checkpoint_s3_uri, checkpoint_local_path=checkpoint_local_path, @@ -145,7 +138,7 @@ def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py train_instance_count=2, train_instance_type=instance_type, sagemaker_session=sagemaker_session, - py_version="py37", + py_version=py_version, script_mode=True, framework_version=tf_full_version, distributions=PARAMETER_SERVER_DISTRIBUTION, diff --git a/tests/integ/test_tfs.py b/tests/integ/test_tfs.py index 4ed13966e5..00fb6fdb75 100644 --- a/tests/integ/test_tfs.py +++ b/tests/integ/test_tfs.py @@ -23,17 +23,9 @@ import sagemaker.utils import tests.integ import tests.integ.timeout -from sagemaker.tensorflow import TensorFlow from sagemaker.tensorflow.serving import Model, Predictor -@pytest.fixture(scope="module") -def tf_serving_version(tf_full_version): - if tf_full_version == TensorFlow.LATEST_VERSION: - return TensorFlow.LATEST_SERVING_VERSION - return tf_full_version - - @pytest.fixture(scope="module") def tfs_predictor(sagemaker_session, tf_serving_version): endpoint_name = sagemaker.utils.unique_name_from_base("sagemaker-tensorflow-serving") diff --git a/tests/integ/test_transformer.py b/tests/integ/test_transformer.py index 1c167829fb..6f9b56bc09 100644 --- a/tests/integ/test_transformer.py +++ b/tests/integ/test_transformer.py @@ -25,6 +25,7 @@ from sagemaker.mxnet import MXNet from sagemaker.pytorch import PyTorchModel from sagemaker.tensorflow import TensorFlow +from sagemaker.tensorflow.defaults import LATEST_SERVING_VERSION from sagemaker.transformer import Transformer from sagemaker.estimator import Estimator from sagemaker.utils import unique_name_from_base @@ -351,7 +352,7 @@ def test_transform_tf_kms_network_isolation(sagemaker_session, cpu_instance_type role="SageMakerRole", train_instance_count=1, train_instance_type=cpu_instance_type, - framework_version=TensorFlow.LATEST_SERVING_VERSION, + framework_version=LATEST_SERVING_VERSION, script_mode=True, py_version=PYTHON_VERSION, sagemaker_session=sagemaker_session, diff --git a/tests/integ/test_tuner.py b/tests/integ/test_tuner.py index 871d832322..a2d7acadeb 100644 --- a/tests/integ/test_tuner.py +++ b/tests/integ/test_tuner.py @@ -37,6 +37,7 @@ from sagemaker.predictor import json_deserializer from sagemaker.pytorch import PyTorch from sagemaker.tensorflow import TensorFlow +from sagemaker.tensorflow.defaults import _LATEST_1X_VERSION, LATEST_VERSION from sagemaker.tuner import ( IntegerParameter, ContinuousParameter, @@ -51,7 +52,7 @@ DATA_PATH = os.path.join(DATA_DIR, "iris", "data") -PY37_SUPPORTED_FRAMEWORK_VERSION = [TensorFlow._LATEST_1X_VERSION, TensorFlow.LATEST_VERSION] +PY37_SUPPORTED_FRAMEWORK_VERSION = [_LATEST_1X_VERSION, LATEST_VERSION] @pytest.fixture(scope="module") From ff376d853dfb440ac1cecd2551cc0c2fbe94e2ad Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Fri, 22 May 2020 11:23:35 -0700 Subject: [PATCH 19/21] fix import error --- tests/conftest.py | 5 +++-- tests/integ/test_tuner.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index bf219d00a7..00874e8a1c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,7 +27,8 @@ from sagemaker.pytorch import PyTorch from sagemaker.rl import RLEstimator from sagemaker.sklearn.defaults import SKLEARN_VERSION -from sagemaker.tensorflow.defaults import _LATEST_1X_VERSION, LATEST_VERSION, LATEST_SERVING_VERSION +from sagemaker.tensorflow import TensorFlow +from sagemaker.tensorflow.defaults import LATEST_VERSION, LATEST_SERVING_VERSION DEFAULT_REGION = "us-west-2" CUSTOM_BUCKET_NAME_PREFIX = "sagemaker-custom-bucket" @@ -259,7 +260,7 @@ def sklearn_full_version(request): return request.config.getoption("--sklearn-full-version") -@pytest.fixture(scope="module", params=[_LATEST_1X_VERSION, LATEST_VERSION]) +@pytest.fixture(scope="module", params=[TensorFlow._LATEST_1X_VERSION, LATEST_VERSION]) def tf_full_version(request): tf_version = request.config.getoption("--tf-full-version") if tf_version is None: diff --git a/tests/integ/test_tuner.py b/tests/integ/test_tuner.py index a2d7acadeb..fc93b9b618 100644 --- a/tests/integ/test_tuner.py +++ b/tests/integ/test_tuner.py @@ -37,7 +37,7 @@ from sagemaker.predictor import json_deserializer from sagemaker.pytorch import PyTorch from sagemaker.tensorflow import TensorFlow -from sagemaker.tensorflow.defaults import _LATEST_1X_VERSION, LATEST_VERSION +from sagemaker.tensorflow.defaults import LATEST_VERSION from sagemaker.tuner import ( IntegerParameter, ContinuousParameter, @@ -52,7 +52,7 @@ DATA_PATH = os.path.join(DATA_DIR, "iris", "data") -PY37_SUPPORTED_FRAMEWORK_VERSION = [_LATEST_1X_VERSION, LATEST_VERSION] +PY37_SUPPORTED_FRAMEWORK_VERSION = [TensorFlow._LATEST_1X_VERSION, LATEST_VERSION] @pytest.fixture(scope="module") From 31110b40048cc0b71c77e1b7b7d2a8a295489f2b Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Fri, 22 May 2020 13:04:37 -0700 Subject: [PATCH 20/21] hardcode py_version for tensorflow-training 2.2 tests --- tests/integ/test_tf_script_mode.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index fac815daeb..34ea944dff 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -59,7 +59,7 @@ def test_mnist_with_checkpoint_config( sagemaker_session=sagemaker_session, script_mode=True, framework_version=tf_full_version, - py_version=py_version, + py_version="py37", metric_definitions=[{"Name": "train:global_steps", "Regex": r"global_step\/sec:\s(.*)"}], checkpoint_s3_uri=checkpoint_s3_uri, checkpoint_local_path=checkpoint_local_path, @@ -138,7 +138,7 @@ def test_mnist_distributed(sagemaker_session, instance_type, tf_full_version, py train_instance_count=2, train_instance_type=instance_type, sagemaker_session=sagemaker_session, - py_version=py_version, + py_version="py37", script_mode=True, framework_version=tf_full_version, distributions=PARAMETER_SERVER_DISTRIBUTION, From fa04c1aa98df543aeedd34506dbd1eb1f17f528f Mon Sep 17 00:00:00 2001 From: Chuyang Deng Date: Fri, 22 May 2020 13:45:26 -0700 Subject: [PATCH 21/21] import LATEST_SERVING_VERSION from TensorFlow.defaults --- tests/integ/test_tf_script_mode.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/integ/test_tf_script_mode.py b/tests/integ/test_tf_script_mode.py index 34ea944dff..de1ddac16a 100644 --- a/tests/integ/test_tf_script_mode.py +++ b/tests/integ/test_tf_script_mode.py @@ -19,6 +19,7 @@ import pytest from sagemaker.tensorflow import TensorFlow +from sagemaker.tensorflow.defaults import LATEST_SERVING_VERSION from sagemaker.utils import unique_name_from_base, sagemaker_timestamp import tests.integ @@ -166,7 +167,7 @@ def test_mnist_async(sagemaker_session, cpu_instance_type, tf_full_version, py_v sagemaker_session=sagemaker_session, script_mode=True, # testing py-sdk functionality, no need to run against all TF versions - framework_version=TensorFlow.LATEST_SERVING_VERSION, + framework_version=LATEST_SERVING_VERSION, tags=TAGS, ) inputs = estimator.sagemaker_session.upload_data(