From bfd92b0bc98250107b72adcb6df1bbf2ac678e25 Mon Sep 17 00:00:00 2001 From: amlrelsa-ms Date: Wed, 10 Feb 2021 03:29:07 +0000 Subject: [PATCH] update samples from Release-64 as a part of 1.22.0 SDK stable release --- configuration.ipynb | 2 +- .../automated-machine-learning/automl_env.yml | 5 +- .../automl_env_linux.yml | 5 +- .../automl_env_mac.yml | 5 +- ...fication-bank-marketing-all-features.ipynb | 2 +- ...-ml-classification-credit-card-fraud.ipynb | 2 +- .../auto-ml-classification-text-dnn.ipynb | 2 +- .../auto-ml-continuous-retraining.ipynb | 2 +- .../experimental/automl_thin_client_env.yml | 1 - .../automl_thin_client_env_mac.yml | 1 - .../auto-ml-regression-model-proxy.ipynb | 2 +- .../auto-ml-forecasting-beer-remote.ipynb | 2 +- .../auto-ml-forecasting-bike-share.ipynb | 10 +- .../auto-ml-forecasting-energy-demand.ipynb | 2 +- .../auto-ml-forecasting-function.ipynb | 2 +- ...to-ml-forecasting-orange-juice-sales.ipynb | 7 +- ...assification-credit-card-fraud-local.ipynb | 2 +- ...regression-explanation-featurization.ipynb | 2 +- .../regression/auto-ml-regression.ipynb | 2 +- .../register-model-deploy-local.ipynb | 112 +++++- ...facial-expression-recognition-deploy.ipynb | 8 +- .../onnx/onnx-inference-mnist-deploy.ipynb | 39 +- .../intro-to-pipelines/README.md | 3 +- .../aml-pipelines-data-transfer.ipynb | 2 + ...-publish-and-run-using-rest-endpoint.ipynb | 34 +- .../aml-pipelines-with-commandstep-r.ipynb | 343 ++++++++++++++++++ ...b => aml-pipelines-with-commandstep.ipynb} | 147 ++++---- .../commandstep_r/Dockerfile | 11 + .../commandstep_r/accidents.R | 34 ++ .../commandstep_r/accidents.Rd | Bin 0 -> 166122 bytes .../commandstep_train/conda_dependencies.yml | 8 + .../commandstep_train/train.py | 120 ++++++ .../estimator_train/dummy_train.py | 30 -- .../publish_run_compare/compare.py | 3 + .../publish_run_extract/extract.py | 5 + .../publish_run_train/train.py | 5 + .../authentication-in-azureml.ipynb | 63 +++- .../logging-api/logging-api.ipynb | 2 +- how-to-use-azureml/training/README.md | 2 +- index.md | 3 +- setup-environment/configuration.ipynb | 2 +- ...ipeline-batch-scoring-classification.ipynb | 2 +- 42 files changed, 826 insertions(+), 210 deletions(-) create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep-r.ipynb rename how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/{aml-pipelines-how-to-use-estimatorstep.ipynb => aml-pipelines-with-commandstep.ipynb} (65%) create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/Dockerfile create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.R create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.Rd create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/conda_dependencies.yml create mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/train.py delete mode 100644 how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/estimator_train/dummy_train.py diff --git a/configuration.ipynb b/configuration.ipynb index 96cddc29..c85736f9 100644 --- a/configuration.ipynb +++ b/configuration.ipynb @@ -103,7 +103,7 @@ "source": [ "import azureml.core\n", "\n", - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/automl_env.yml b/how-to-use-azureml/automated-machine-learning/automl_env.yml index 0faed851..f10cb050 100644 --- a/how-to-use-azureml/automated-machine-learning/automl_env.yml +++ b/how-to-use-azureml/automated-machine-learning/automl_env.yml @@ -21,8 +21,9 @@ dependencies: - pip: # Required packages for AzureML execution, history, and data preparation. - - azureml-widgets~=1.21.0 + - azureml-widgets~=1.22.0 - pytorch-transformers==1.0.0 - spacy==2.1.8 - https://aka.ms/automl-resources/packages/en_core_web_sm-2.1.0.tar.gz - - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.21.0/validated_win32_requirements.txt [--no-deps] + - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.22.0/validated_win32_requirements.txt [--no-deps] + - PyJWT < 2.0.0 diff --git a/how-to-use-azureml/automated-machine-learning/automl_env_linux.yml b/how-to-use-azureml/automated-machine-learning/automl_env_linux.yml index 12d16e18..70bf2f27 100644 --- a/how-to-use-azureml/automated-machine-learning/automl_env_linux.yml +++ b/how-to-use-azureml/automated-machine-learning/automl_env_linux.yml @@ -21,9 +21,10 @@ dependencies: - pip: # Required packages for AzureML execution, history, and data preparation. - - azureml-widgets~=1.21.0 + - azureml-widgets~=1.22.0 - pytorch-transformers==1.0.0 - spacy==2.1.8 - https://aka.ms/automl-resources/packages/en_core_web_sm-2.1.0.tar.gz - - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.21.0/validated_linux_requirements.txt [--no-deps] + - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.22.0/validated_linux_requirements.txt [--no-deps] + - PyJWT < 2.0.0 diff --git a/how-to-use-azureml/automated-machine-learning/automl_env_mac.yml b/how-to-use-azureml/automated-machine-learning/automl_env_mac.yml index c73d6796..3966fa56 100644 --- a/how-to-use-azureml/automated-machine-learning/automl_env_mac.yml +++ b/how-to-use-azureml/automated-machine-learning/automl_env_mac.yml @@ -22,8 +22,9 @@ dependencies: - pip: # Required packages for AzureML execution, history, and data preparation. - - azureml-widgets~=1.21.0 + - azureml-widgets~=1.22.0 - pytorch-transformers==1.0.0 - spacy==2.1.8 - https://aka.ms/automl-resources/packages/en_core_web_sm-2.1.0.tar.gz - - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.21.0/validated_darwin_requirements.txt [--no-deps] + - -r https://automlcesdkdataresources.blob.core.windows.net/validated-requirements/1.22.0/validated_darwin_requirements.txt [--no-deps] + - PyJWT < 2.0.0 diff --git a/how-to-use-azureml/automated-machine-learning/classification-bank-marketing-all-features/auto-ml-classification-bank-marketing-all-features.ipynb b/how-to-use-azureml/automated-machine-learning/classification-bank-marketing-all-features/auto-ml-classification-bank-marketing-all-features.ipynb index 72512357..c40781af 100644 --- a/how-to-use-azureml/automated-machine-learning/classification-bank-marketing-all-features/auto-ml-classification-bank-marketing-all-features.ipynb +++ b/how-to-use-azureml/automated-machine-learning/classification-bank-marketing-all-features/auto-ml-classification-bank-marketing-all-features.ipynb @@ -105,7 +105,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/classification-credit-card-fraud/auto-ml-classification-credit-card-fraud.ipynb b/how-to-use-azureml/automated-machine-learning/classification-credit-card-fraud/auto-ml-classification-credit-card-fraud.ipynb index b784c217..d0a6cd14 100644 --- a/how-to-use-azureml/automated-machine-learning/classification-credit-card-fraud/auto-ml-classification-credit-card-fraud.ipynb +++ b/how-to-use-azureml/automated-machine-learning/classification-credit-card-fraud/auto-ml-classification-credit-card-fraud.ipynb @@ -93,7 +93,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/classification-text-dnn/auto-ml-classification-text-dnn.ipynb b/how-to-use-azureml/automated-machine-learning/classification-text-dnn/auto-ml-classification-text-dnn.ipynb index 4f466a42..5af772aa 100644 --- a/how-to-use-azureml/automated-machine-learning/classification-text-dnn/auto-ml-classification-text-dnn.ipynb +++ b/how-to-use-azureml/automated-machine-learning/classification-text-dnn/auto-ml-classification-text-dnn.ipynb @@ -96,7 +96,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/continuous-retraining/auto-ml-continuous-retraining.ipynb b/how-to-use-azureml/automated-machine-learning/continuous-retraining/auto-ml-continuous-retraining.ipynb index a967d785..c4010566 100644 --- a/how-to-use-azureml/automated-machine-learning/continuous-retraining/auto-ml-continuous-retraining.ipynb +++ b/how-to-use-azureml/automated-machine-learning/continuous-retraining/auto-ml-continuous-retraining.ipynb @@ -81,7 +81,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env.yml b/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env.yml index eb7913b9..69453c0a 100644 --- a/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env.yml +++ b/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env.yml @@ -18,4 +18,3 @@ dependencies: - azureml-sdk - azureml-widgets - azureml-explain-model - - PyJWT < 2.0.0 diff --git a/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env_mac.yml b/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env_mac.yml index 765bfd70..838c3d40 100644 --- a/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env_mac.yml +++ b/how-to-use-azureml/automated-machine-learning/experimental/automl_thin_client_env_mac.yml @@ -19,4 +19,3 @@ dependencies: - azureml-sdk - azureml-widgets - azureml-explain-model - - PyJWT < 2.0.0 diff --git a/how-to-use-azureml/automated-machine-learning/experimental/regression-model-proxy/auto-ml-regression-model-proxy.ipynb b/how-to-use-azureml/automated-machine-learning/experimental/regression-model-proxy/auto-ml-regression-model-proxy.ipynb index 353eccee..c4f248d8 100644 --- a/how-to-use-azureml/automated-machine-learning/experimental/regression-model-proxy/auto-ml-regression-model-proxy.ipynb +++ b/how-to-use-azureml/automated-machine-learning/experimental/regression-model-proxy/auto-ml-regression-model-proxy.ipynb @@ -93,7 +93,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/forecasting-beer-remote/auto-ml-forecasting-beer-remote.ipynb b/how-to-use-azureml/automated-machine-learning/forecasting-beer-remote/auto-ml-forecasting-beer-remote.ipynb index d51c7ca1..30a1fe7b 100644 --- a/how-to-use-azureml/automated-machine-learning/forecasting-beer-remote/auto-ml-forecasting-beer-remote.ipynb +++ b/how-to-use-azureml/automated-machine-learning/forecasting-beer-remote/auto-ml-forecasting-beer-remote.ipynb @@ -113,7 +113,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/forecasting-bike-share/auto-ml-forecasting-bike-share.ipynb b/how-to-use-azureml/automated-machine-learning/forecasting-bike-share/auto-ml-forecasting-bike-share.ipynb index c9ce6066..92341f58 100644 --- a/how-to-use-azureml/automated-machine-learning/forecasting-bike-share/auto-ml-forecasting-bike-share.ipynb +++ b/how-to-use-azureml/automated-machine-learning/forecasting-bike-share/auto-ml-forecasting-bike-share.ipynb @@ -87,7 +87,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, @@ -205,6 +205,10 @@ "outputs": [], "source": [ "dataset = Dataset.Tabular.from_delimited_files(path = [(datastore, 'dataset/bike-no.csv')]).with_timestamp_columns(fine_grain_timestamp=time_column_name) \n", + "\n", + "# Drop the columns 'casual' and 'registered' as these columns are a breakdown of the total and therefore a leak.\n", + "dataset = dataset.drop_columns(columns=['casual', 'registered'])\n", + "\n", "dataset.take(5).to_pandas_dataframe().reset_index(drop=True)" ] }, @@ -251,7 +255,6 @@ "|**forecast_horizon**|The forecast horizon is how many periods forward you would like to forecast. This integer horizon is in units of the timeseries frequency (e.g. daily, weekly).|\n", "|**country_or_region_for_holidays**|The country/region used to generate holiday features. These should be ISO 3166 two-letter country/region codes (i.e. 'US', 'GB').|\n", "|**target_lags**|The target_lags specifies how far back we will construct the lags of the target variable.|\n", - "|**drop_column_names**|Name(s) of columns to drop prior to modeling|\n", "|**freq**|Forecast frequency. This optional parameter represents the period with which the forecast is desired, for example, daily, weekly, yearly, etc. Use this parameter for the correction of time series containing irregular data points or for padding of short time series. The frequency needs to be a pandas offset alias. Please refer to [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#dateoffset-objects) for more information." ] }, @@ -315,8 +318,7 @@ " time_column_name=time_column_name,\n", " forecast_horizon=forecast_horizon,\n", " country_or_region_for_holidays='US', # set country_or_region will trigger holiday featurizer\n", - " target_lags='auto', # use heuristic based lag setting \n", - " drop_column_names=['casual', 'registered'] # these columns are a breakdown of the total and therefore a leak\n", + " target_lags='auto' # use heuristic based lag setting \n", ")\n", "\n", "automl_config = AutoMLConfig(task='forecasting', \n", diff --git a/how-to-use-azureml/automated-machine-learning/forecasting-energy-demand/auto-ml-forecasting-energy-demand.ipynb b/how-to-use-azureml/automated-machine-learning/forecasting-energy-demand/auto-ml-forecasting-energy-demand.ipynb index bbb209c4..6ff32c0d 100644 --- a/how-to-use-azureml/automated-machine-learning/forecasting-energy-demand/auto-ml-forecasting-energy-demand.ipynb +++ b/how-to-use-azureml/automated-machine-learning/forecasting-energy-demand/auto-ml-forecasting-energy-demand.ipynb @@ -97,7 +97,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/forecasting-forecast-function/auto-ml-forecasting-function.ipynb b/how-to-use-azureml/automated-machine-learning/forecasting-forecast-function/auto-ml-forecasting-function.ipynb index c0a59335..3c66f1ac 100644 --- a/how-to-use-azureml/automated-machine-learning/forecasting-forecast-function/auto-ml-forecasting-function.ipynb +++ b/how-to-use-azureml/automated-machine-learning/forecasting-forecast-function/auto-ml-forecasting-function.ipynb @@ -94,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/forecasting-orange-juice-sales/auto-ml-forecasting-orange-juice-sales.ipynb b/how-to-use-azureml/automated-machine-learning/forecasting-orange-juice-sales/auto-ml-forecasting-orange-juice-sales.ipynb index 2ad8df5f..5b05f82b 100644 --- a/how-to-use-azureml/automated-machine-learning/forecasting-orange-juice-sales/auto-ml-forecasting-orange-juice-sales.ipynb +++ b/how-to-use-azureml/automated-machine-learning/forecasting-orange-juice-sales/auto-ml-forecasting-orange-juice-sales.ipynb @@ -82,7 +82,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, @@ -169,6 +169,10 @@ "source": [ "time_column_name = 'WeekStarting'\n", "data = pd.read_csv(\"dominicks_OJ.csv\", parse_dates=[time_column_name])\n", + "\n", + "# Drop the columns 'logQuantity' as it is a leaky feature.\n", + "data.drop('logQuantity', axis=1, inplace=True)\n", + "\n", "data.head()" ] }, @@ -343,7 +347,6 @@ "outputs": [], "source": [ "featurization_config = FeaturizationConfig()\n", - "featurization_config.drop_columns = ['logQuantity'] # 'logQuantity' is a leaky feature, so we remove it.\n", "# Force the CPWVOL5 feature to be numeric type.\n", "featurization_config.add_column_purpose('CPWVOL5', 'Numeric')\n", "# Fill missing values in the target column, Quantity, with zeros.\n", diff --git a/how-to-use-azureml/automated-machine-learning/local-run-classification-credit-card-fraud/auto-ml-classification-credit-card-fraud-local.ipynb b/how-to-use-azureml/automated-machine-learning/local-run-classification-credit-card-fraud/auto-ml-classification-credit-card-fraud-local.ipynb index f799c9f5..9da57318 100644 --- a/how-to-use-azureml/automated-machine-learning/local-run-classification-credit-card-fraud/auto-ml-classification-credit-card-fraud-local.ipynb +++ b/how-to-use-azureml/automated-machine-learning/local-run-classification-credit-card-fraud/auto-ml-classification-credit-card-fraud-local.ipynb @@ -96,7 +96,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/regression-explanation-featurization/auto-ml-regression-explanation-featurization.ipynb b/how-to-use-azureml/automated-machine-learning/regression-explanation-featurization/auto-ml-regression-explanation-featurization.ipynb index ee08edbb..43687f44 100644 --- a/how-to-use-azureml/automated-machine-learning/regression-explanation-featurization/auto-ml-regression-explanation-featurization.ipynb +++ b/how-to-use-azureml/automated-machine-learning/regression-explanation-featurization/auto-ml-regression-explanation-featurization.ipynb @@ -96,7 +96,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/automated-machine-learning/regression/auto-ml-regression.ipynb b/how-to-use-azureml/automated-machine-learning/regression/auto-ml-regression.ipynb index 04b825d3..cdf74b2a 100644 --- a/how-to-use-azureml/automated-machine-learning/regression/auto-ml-regression.ipynb +++ b/how-to-use-azureml/automated-machine-learning/regression/auto-ml-regression.ipynb @@ -92,7 +92,7 @@ "metadata": {}, "outputs": [], "source": [ - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/how-to-use-azureml/deployment/deploy-to-local/register-model-deploy-local.ipynb b/how-to-use-azureml/deployment/deploy-to-local/register-model-deploy-local.ipynb index 0c216969..33e5eadc 100644 --- a/how-to-use-azureml/deployment/deploy-to-local/register-model-deploy-local.ipynb +++ b/how-to-use-azureml/deployment/deploy-to-local/register-model-deploy-local.ipynb @@ -77,7 +77,7 @@ "source": [ "## Create trained model\n", "\n", - "For this example, we will train a small model on scikit-learn's [diabetes dataset](https://scikit-learn.org/stable/datasets/index.html#diabetes-dataset). " + "For this example, we will train a small model on scikit-learn's [diabetes dataset](https://scikit-learn.org/stable/datasets/toy_dataset.html#diabetes-dataset). " ] }, { @@ -382,13 +382,111 @@ "source": [ "## Update Service\n", "\n", - "If you want to change your model(s), Conda dependencies, or deployment configuration, call `update()` to rebuild the Docker image.\n", - "\n", - "```python\n", - "local_service.update(models=[SomeOtherModelObject],\n", + "If you want to change your model(s), Conda dependencies or deployment configuration, call `update()` to rebuild the Docker image.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "local_service.update(models=[model],\n", " inference_config=inference_config,\n", - " deployment_config=local_config)\n", - "```" + " deployment_config=deployment_config)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Deploy model to AKS cluster based on the LocalWebservice's configuration." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# This is a one time setup for AKS Cluster. You can reuse this cluster for multiple deployments after it has been created. If you delete the cluster or the resource group that contains it, then you would have to recreate it.\n", + "from azureml.core.compute import AksCompute, ComputeTarget\n", + "from azureml.core.compute_target import ComputeTargetException\n", + "\n", + "# Choose a name for your AKS cluster\n", + "aks_name = 'my-aks-9' \n", + "\n", + "# Verify the cluster does not exist already\n", + "try:\n", + " aks_target = ComputeTarget(workspace=ws, name=aks_name)\n", + " print('Found existing cluster, use it.')\n", + "except ComputeTargetException:\n", + " # Use the default configuration (can also provide parameters to customize)\n", + " prov_config = AksCompute.provisioning_configuration()\n", + "\n", + " # Create the cluster\n", + " aks_target = ComputeTarget.create(workspace = ws, \n", + " name = aks_name, \n", + " provisioning_configuration = prov_config)\n", + "\n", + "if aks_target.get_status() != \"Succeeded\":\n", + " aks_target.wait_for_completion(show_output=True)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.webservice import AksWebservice\n", + "# Set the web service configuration (using default here)\n", + "aks_config = AksWebservice.deploy_configuration()\n", + "\n", + "# # Enable token auth and disable (key) auth on the webservice\n", + "# aks_config = AksWebservice.deploy_configuration(token_auth_enabled=True, auth_enabled=False)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%%time\n", + "aks_service_name ='aks-service-1'\n", + "\n", + "aks_service = local_service.deploy_to_cloud(name=aks_service_name,\n", + " deployment_config=aks_config,\n", + " deployment_target=aks_target)\n", + "\n", + "aks_service.wait_for_deployment(show_output = True)\n", + "print(aks_service.state)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Test aks service\n", + "\n", + "sample_input = json.dumps({\n", + " 'data': dataset_x[0:2].tolist()\n", + "})\n", + "\n", + "aks_service.run(sample_input)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Delete the service if not needed.\n", + "aks_service.delete()" ] }, { diff --git a/how-to-use-azureml/deployment/onnx/onnx-inference-facial-expression-recognition-deploy.ipynb b/how-to-use-azureml/deployment/onnx/onnx-inference-facial-expression-recognition-deploy.ipynb index 9f2963e1..6610d900 100644 --- a/how-to-use-azureml/deployment/onnx/onnx-inference-facial-expression-recognition-deploy.ipynb +++ b/how-to-use-azureml/deployment/onnx/onnx-inference-facial-expression-recognition-deploy.ipynb @@ -70,16 +70,16 @@ "\n", "import urllib.request\n", "\n", - "onnx_model_url = \"https://www.cntk.ai/OnnxModels/emotion_ferplus/opset_7/emotion_ferplus.tar.gz\"\n", + "onnx_model_url = \"https://github.com/onnx/models/blob/master/vision/body_analysis/emotion_ferplus/model/emotion-ferplus-7.tar.gz?raw=true\"\n", "\n", - "urllib.request.urlretrieve(onnx_model_url, filename=\"emotion_ferplus.tar.gz\")\n", + "urllib.request.urlretrieve(onnx_model_url, filename=\"emotion-ferplus-7.tar.gz\")\n", "\n", "# the ! magic command tells our jupyter notebook kernel to run the following line of \n", "# code from the command line instead of the notebook kernel\n", "\n", "# We use tar and xvcf to unzip the files we just retrieved from the ONNX model zoo\n", "\n", - "!tar xvzf emotion_ferplus.tar.gz" + "!tar xvzf emotion-ferplus-7.tar.gz" ] }, { @@ -570,7 +570,7 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize = (16, 6), frameon=False)\n", + "plt.figure(figsize = (16, 6))\n", "plt.subplot(1, 8, 1)\n", "\n", "plt.text(x = 0, y = -30, s = \"True Label: \", fontsize = 13, color = 'black')\n", diff --git a/how-to-use-azureml/deployment/onnx/onnx-inference-mnist-deploy.ipynb b/how-to-use-azureml/deployment/onnx/onnx-inference-mnist-deploy.ipynb index b9202470..33b8bcce 100644 --- a/how-to-use-azureml/deployment/onnx/onnx-inference-mnist-deploy.ipynb +++ b/how-to-use-azureml/deployment/onnx/onnx-inference-mnist-deploy.ipynb @@ -70,9 +70,9 @@ "\n", "import urllib.request\n", "\n", - "onnx_model_url = \"https://www.cntk.ai/OnnxModels/mnist/opset_7/mnist.tar.gz\"\n", + "onnx_model_url = \"https://github.com/onnx/models/blob/master/vision/classification/mnist/model/mnist-7.tar.gz?raw=true\"\n", "\n", - "urllib.request.urlretrieve(onnx_model_url, filename=\"mnist.tar.gz\")" + "urllib.request.urlretrieve(onnx_model_url, filename=\"mnist-7.tar.gz\")" ] }, { @@ -86,7 +86,7 @@ "\n", "# We use tar and xvcf to unzip the files we just retrieved from the ONNX model zoo\n", "\n", - "!tar xvzf mnist.tar.gz" + "!tar xvzf mnist-7.tar.gz" ] }, { @@ -521,7 +521,7 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize = (16, 6), frameon=False)\n", + "plt.figure(figsize = (16, 6))\n", "plt.subplot(1, 8, 1)\n", "\n", "plt.text(x = 0, y = -30, s = \"True Label: \", fontsize = 13, color = 'black')\n", @@ -684,18 +684,7 @@ "\n", "A convolution layer is a set of filters. Each filter is defined by a weight (**W**) matrix, and bias ($b$).\n", "\n", - "![](https://www.cntk.ai/jup/cntk103d_filterset_v2.png)\n", - "\n", - "These filters are scanned across the image performing the dot product between the weights and corresponding input value ($x$). The bias value is added to the output of the dot product and the resulting sum is optionally mapped through an activation function. This process is illustrated in the following animation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "Image(url=\"https://www.cntk.ai/jup/cntk103d_conv2d_final.gif\", width= 200)" + "These filters are scanned across the image performing the dot product between the weights and corresponding input value ($x$). The bias value is added to the output of the dot product and the resulting sum is optionally mapped through an activation function." ] }, { @@ -707,24 +696,6 @@ "The MNIST model from the ONNX Model Zoo uses maxpooling to update the weights in its convolutions, summarized by the graphic below. You can see the entire workflow of our pre-trained model in the following image, with our input images and our output probabilities of each of our 10 labels. If you're interested in exploring the logic behind creating a Deep Learning model further, please look at the [training tutorial for our ONNX MNIST Convolutional Neural Network](https://github.com/Microsoft/CNTK/blob/master/Tutorials/CNTK_103D_MNIST_ConvolutionalNeuralNetwork.ipynb). " ] }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Max-Pooling for Convolutional Neural Nets\n", - "\n", - "![](http://www.cntk.ai/jup/c103d_max_pooling.gif)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Pre-Trained Model Architecture\n", - "\n", - "![](http://www.cntk.ai/jup/conv103d_mnist-conv-mp.png)" - ] - }, { "cell_type": "code", "execution_count": null, diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/README.md b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/README.md index c0fae5ac..2aeb93b6 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/README.md +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/README.md @@ -9,7 +9,7 @@ These notebooks below are designed to go in sequence. 4. [aml-pipelines-data-transfer.ipynb](https://aka.ms/pl-data-trans): This notebook shows how you transfer data between supported datastores. 5. [aml-pipelines-use-databricks-as-compute-target.ipynb](https://aka.ms/pl-databricks): This notebooks shows how you can use Pipelines to send your compute payload to Azure Databricks. 6. [aml-pipelines-use-adla-as-compute-target.ipynb](https://aka.ms/pl-adla): This notebook shows how you can use Azure Data Lake Analytics (ADLA) as a compute target. -7. [aml-pipelines-how-to-use-estimatorstep.ipynb](https://aka.ms/pl-estimator): This notebook shows how to use the EstimatorStep. +7. [aml-pipelines-with-commandstep.ipynb](aml-pipelines-with-commandstep.ipynb): This notebook shows how to use the CommandStep. 8. [aml-pipelines-parameter-tuning-with-hyperdrive.ipynb](https://aka.ms/pl-hyperdrive): HyperDriveStep in Pipelines shows how you can do hyper parameter tuning using Pipelines. 9. [aml-pipelines-how-to-use-azurebatch-to-run-a-windows-executable.ipynb](https://aka.ms/pl-azbatch): AzureBatchStep can be used to run your custom code in AzureBatch cluster. 10. [aml-pipelines-setup-schedule-for-a-published-pipeline.ipynb](https://aka.ms/pl-schedule): Once you publish a Pipeline, you can schedule it to trigger based on an interval or on data change in a defined datastore. @@ -19,5 +19,6 @@ These notebooks below are designed to go in sequence. 14. [aml-pipelines-how-to-use-pipeline-drafts.ipynb](http://aka.ms/pl-pl-draft): This notebook shows how to use Pipeline Drafts. Pipeline Drafts are mutable pipelines which can be used to submit runs and create Published Pipelines. 15. [aml-pipelines-hot-to-use-modulestep.ipynb](https://aka.ms/pl-modulestep): This notebook shows how to define Module, ModuleVersion and how to use them in an AML Pipeline using ModuleStep. 16. [aml-pipelines-with-notebook-runner-step.ipynb](https://aka.ms/pl-nbrstep): This notebook shows how you can run another notebook as a step in Azure Machine Learning Pipeline. +17. [aml-pipelines-with-commandstep-r.ipynb](aml-pipelines-with-commandstep-r.ipynb): This notebook shows how to use CommandStep to run R scripts. ![Impressions](https://PixelServer20190423114238.azurewebsites.net/api/impressions/MachineLearningNotebooks/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/README.png) diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-data-transfer.ipynb b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-data-transfer.ipynb index 1956ea81..f35fb322 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-data-transfer.ipynb +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-data-transfer.ipynb @@ -22,6 +22,8 @@ "# Azure Machine Learning Pipeline with DataTransferStep\n", "This notebook is used to demonstrate the use of DataTransferStep in an Azure Machine Learning Pipeline.\n", "\n", + "> **Note:** In Azure Machine Learning, you can write output data directly to Azure Blob Storage, Azure Data Lake Storage Gen 1, Azure Data Lake Storage Gen 2, Azure FileShare without going through extra DataTransferStep. Learn how to use [OutputFileDatasetConfig](https://docs.microsoft.com/python/api/azureml-core/azureml.data.output_dataset_config.outputfiledatasetconfig?view=azure-ml-py) to achieve that with sample notebooks [here](https://aka.ms/pipeline-with-dataset).**\n", + "\n", "In certain cases, you will need to transfer data from one data location to another. For example, your data may be in Azure SQL Database and you may want to move it to Azure Data Lake storage. Or, your data is in an ADLS account and you want to make it available in the Blob storage. The built-in **DataTransferStep** class helps you transfer data in these situations.\n", "\n", "The below examples show how to move data between different storage types supported in Azure Machine Learning.\n", diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-publish-and-run-using-rest-endpoint.ipynb b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-publish-and-run-using-rest-endpoint.ipynb index d0c76568..0bb96e22 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-publish-and-run-using-rest-endpoint.ipynb +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-publish-and-run-using-rest-endpoint.ipynb @@ -41,14 +41,14 @@ "source": [ "import azureml.core\n", "from azureml.core import Workspace, Datastore, Experiment, Dataset\n", + "from azureml.data import OutputFileDatasetConfig\n", "from azureml.core.compute import AmlCompute\n", "from azureml.core.compute import ComputeTarget\n", "\n", "# Check core SDK version number\n", "print(\"SDK version:\", azureml.core.VERSION)\n", "\n", - "from azureml.data.data_reference import DataReference\n", - "from azureml.pipeline.core import Pipeline, PipelineData\n", + "from azureml.pipeline.core import Pipeline\n", "from azureml.pipeline.steps import PythonScriptStep\n", "from azureml.pipeline.core.graph import PipelineParameter\n", "\n", @@ -140,9 +140,9 @@ "metadata": {}, "outputs": [], "source": [ - "# Define intermediate data using PipelineData\n", - "processed_data1 = PipelineData(\"processed_data1\",datastore=def_blob_store)\n", - "print(\"PipelineData object created\")" + "# Define intermediate data using OutputFileDatasetConfig\n", + "processed_data1 = OutputFileDatasetConfig(name=\"processed_data1\")\n", + "print(\"Output dataset object created\")" ] }, { @@ -170,9 +170,7 @@ "\n", "trainStep = PythonScriptStep(\n", " script_name=\"train.py\", \n", - " arguments=[\"--input_data\", blob_input_data, \"--output_train\", processed_data1],\n", - " inputs=[blob_input_data],\n", - " outputs=[processed_data1],\n", + " arguments=[\"--input_data\", blob_input_data.as_mount(), \"--output_train\", processed_data1],\n", " compute_target=aml_compute, \n", " source_directory=source_directory\n", ")\n", @@ -195,16 +193,14 @@ "metadata": {}, "outputs": [], "source": [ - "# extractStep to use the intermediate data produced by step4\n", + "# extractStep to use the intermediate data produced by trainStep\n", "# This step also produces an output processed_data2\n", - "processed_data2 = PipelineData(\"processed_data2\", datastore=def_blob_store)\n", + "processed_data2 = OutputFileDatasetConfig(name=\"processed_data2\")\n", "source_directory = \"publish_run_extract\"\n", "\n", "extractStep = PythonScriptStep(\n", " script_name=\"extract.py\",\n", - " arguments=[\"--input_extract\", processed_data1, \"--output_extract\", processed_data2],\n", - " inputs=[processed_data1],\n", - " outputs=[processed_data2],\n", + " arguments=[\"--input_extract\", processed_data1.as_input(), \"--output_extract\", processed_data2],\n", " compute_target=aml_compute, \n", " source_directory=source_directory)\n", "print(\"extractStep created\")" @@ -256,15 +252,17 @@ "metadata": {}, "outputs": [], "source": [ - "# Now define step6 that takes two inputs (both intermediate data), and produce an output\n", - "processed_data3 = PipelineData(\"processed_data3\", datastore=def_blob_store)\n", + "# Now define compareStep that takes two inputs (both intermediate data), and produce an output\n", + "processed_data3 = OutputFileDatasetConfig(name=\"processed_data3\")\n", + "\n", + "# You can register the output as dataset after job completion\n", + "processed_data3 = processed_data3.register_on_complete(\"compare_result\")\n", + "\n", "source_directory = \"publish_run_compare\"\n", "\n", "compareStep = PythonScriptStep(\n", " script_name=\"compare.py\",\n", - " arguments=[\"--compare_data1\", processed_data1, \"--compare_data2\", processed_data2, \"--output_compare\", processed_data3, \"--pipeline_param\", pipeline_param],\n", - " inputs=[processed_data1, processed_data2],\n", - " outputs=[processed_data3], \n", + " arguments=[\"--compare_data1\", processed_data1.as_input(), \"--compare_data2\", processed_data2.as_input(), \"--output_compare\", processed_data3, \"--pipeline_param\", pipeline_param], \n", " compute_target=aml_compute, \n", " source_directory=source_directory)\n", "print(\"compareStep created\")" diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep-r.ipynb b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep-r.ipynb new file mode 100644 index 00000000..7ff66e59 --- /dev/null +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep-r.ipynb @@ -0,0 +1,343 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Copyright (c) Microsoft Corporation. All rights reserved.\n", + "\n", + "Licensed under the MIT License." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Impressions](https://PixelServer20190423114238.azurewebsites.net/api/impressions/MachineLearningNotebooks/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-estimatorstep.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# How to use CommandStep in Azure ML Pipelines\n", + "\n", + "This notebook shows how to use the CommandStep with Azure Machine Learning Pipelines for running R scripts in a pipeline.\n", + "\n", + "The example shows training a model in R to predict probability of fatality for vehicle crashes.\n", + "\n", + "\n", + "## Prerequisite:\n", + "* Understand the [architecture and terms](https://docs.microsoft.com/azure/machine-learning/service/concept-azure-machine-learning-architecture) introduced by Azure Machine Learning\n", + "* If you are using an Azure Machine Learning Notebook VM, you are all set. Otherwise, go through the [configuration notebook](https://aka.ms/pl-config) to:\n", + " * install the Azure ML SDK\n", + " * create a workspace and its configuration file (`config.json`)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's get started. First let's import some Python libraries." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import azureml.core\n", + "# check core SDK version number\n", + "print(\"Azure ML SDK Version: \", azureml.core.VERSION)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize workspace\n", + "Initialize a [Workspace](https://docs.microsoft.com/azure/machine-learning/service/concept-azure-machine-learning-architecture#workspace) object from the existing workspace you created in the Prerequisites step. `Workspace.from_config()` creates a workspace object from the details stored in `config.json`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Workspace\n", + "ws = Workspace.from_config()\n", + "print('Workspace name: ' + ws.name, \n", + " 'Azure region: ' + ws.location, \n", + " 'Subscription id: ' + ws.subscription_id, \n", + " 'Resource group: ' + ws.resource_group, sep = '\\n')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create or Attach existing AmlCompute\n", + "You will need to create a [compute target](https://docs.microsoft.com/azure/machine-learning/service/concept-azure-machine-learning-architecture#compute-target) for training your model. In this tutorial, you create `AmlCompute` as your training compute resource." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If we could not find the cluster with the given name, then we will create a new cluster here. We will create an `AmlCompute` cluster of `STANDARD_D2_V2` CPU VMs. This process is broken down into 3 steps:\n", + "1. create the configuration (this step is local and only takes a second)\n", + "2. create the cluster (this step will take about **20 seconds**)\n", + "3. provision the VMs to bring the cluster to the initial size (of 1 in this case). This step will take about **3-5 minutes** and is providing only sparse output in the process. Please make sure to wait until the call returns before moving to the next cell" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.compute import ComputeTarget, AmlCompute\n", + "from azureml.core.compute_target import ComputeTargetException\n", + "\n", + "# choose a name for your cluster\n", + "cluster_name = \"cpu-cluster\"\n", + "\n", + "try:\n", + " compute_target = ComputeTarget(workspace=ws, name=cluster_name)\n", + " print('Found existing compute target')\n", + "except ComputeTargetException:\n", + " print('Creating a new compute target...')\n", + " compute_config = AmlCompute.provisioning_configuration(vm_size='STANDARD_D2_V2', max_nodes=4)\n", + "\n", + " # create the cluster\n", + " compute_target = ComputeTarget.create(ws, cluster_name, compute_config)\n", + "\n", + " # can poll for a minimum number of nodes and for a specific timeout. \n", + " # if no min node count is provided it uses the scale settings for the cluster\n", + " compute_target.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)\n", + "\n", + "# use get_status() to get a detailed status for the current cluster. \n", + "print(compute_target.get_status().serialize())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now that you have created the compute target, let's see what the workspace's `compute_targets` property returns. You should now see one entry named 'cpu-cluster' of type `AmlCompute`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Create a CommandStep\n", + "CommandStep adds a step to run a command in a Pipeline. For the full set of configurable options see the CommandStep [reference docs](https://docs.microsoft.com/python/api/azureml-pipeline-steps/azureml.pipeline.steps.commandstep?view=azure-ml-py).\n", + "\n", + "- **name:** Name of the step\n", + "- **runconfig:** ScriptRunConfig object. You can configure a ScriptRunConfig object as you would for a standalone non-pipeline run and pass it in to this parameter. If using this option, you do not have to specify the `command`, `source_directory`, `compute_target` parameters of the CommandStep constructor as they are already defined in your ScriptRunConfig.\n", + "- **runconfig_pipeline_params:** Override runconfig properties at runtime using key-value pairs each with name of the runconfig property and PipelineParameter for that property\n", + "- **command:** The command to run or path of the executable/script relative to `source_directory`. It is required unless the `runconfig` parameter is specified. It can be specified with string arguments in a single string or with input/output/PipelineParameter in a list.\n", + "- **source_directory:** A folder containing the script and other resources used in the step.\n", + "- **compute_target:** Compute target to use \n", + "- **allow_reuse:** Whether the step should reuse previous results when run with the same settings/inputs. If this is false, a new run will always be generated for this step during pipeline execution.\n", + "- **version:** Optional version tag to denote a change in functionality for the step\n", + "\n", + "> The best practice is to use separate folders for scripts and its dependent files for each step and specify that folder as the `source_directory` for the step. This helps reduce the size of the snapshot created for the step (only the specific folder is snapshotted). Since changes in any files in the `source_directory` would trigger a re-upload of the snapshot, this helps keep the reuse of the step when there are no changes in the `source_directory` of the step." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure environment\n", + "\n", + "Configure the environment for the train step. In this example we will create an environment from the Dockerfile we have included.\n", + "\n", + "> Azure ML currently requires Python as an implicit dependency, so Python must installed in your image even if your training script does not have this dependency." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Environment\n", + "import os\n", + "\n", + "src_dir = 'commandstep_r'\n", + "\n", + "env = Environment.from_dockerfile(name='r_env', dockerfile=os.path.join(src_dir, 'Dockerfile'))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure input training dataset\n", + "\n", + "This tutorial uses data from the US National Highway Traffic Safety Administration. This dataset includes data from over 25,000 car crashes in the US, with variables you can use to predict the likelihood of a fatality. We have included an Rdata file that includes the accidents data for analysis.\n", + "\n", + "Here we use the workspace's default datastore to upload the training data file (**accidents.Rd**); in practice you can use any datastore you want." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "datastore = ws.get_default_datastore()\n", + "data_ref = datastore.upload_files(files=[os.path.join(src_dir, 'accidents.Rd')], target_path='accidentdata')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a FileDataset from the data, which will be used as an input to the train step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import Dataset\n", + "dataset = Dataset.File.from_files(datastore.path('accidentdata'))\n", + "dataset" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a ScriptRunConfig that configures the training run. Note that in the `command` we include the input dataset for the training data.\n", + "\n", + "> For detailed guidance on how to move data in pipelines for input and output data, see the documentation [Moving data into and between ML pipelines](https://docs.microsoft.com/azure/machine-learning/how-to-move-data-in-out-of-pipelines)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import ScriptRunConfig\n", + "\n", + "train_config = ScriptRunConfig(source_directory=src_dir,\n", + " command=['Rscript accidents.R --data_folder', dataset.as_mount(), '--output_folder outputs'],\n", + " compute_target=compute_target,\n", + " environment=env)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a CommandStep and pass in the ScriptRunConfig object to the `runconfig` parameter." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.pipeline.steps import CommandStep\n", + "\n", + "train = CommandStep(name='train', runconfig=train_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Build and Submit the Pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.pipeline.core import Pipeline\n", + "from azureml.core import Experiment\n", + "\n", + "pipeline = Pipeline(workspace=ws, steps=[train])\n", + "pipeline_run = Experiment(ws, 'r-commandstep-pipeline').submit(pipeline)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## View Run Details" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.widgets import RunDetails\n", + "RunDetails(pipeline_run).show()" + ] + } + ], + "metadata": { + "authors": [ + { + "name": "minxia" + } + ], + "category": "tutorial", + "compute": [ + "AML Compute" + ], + "datasets": [ + "Custom" + ], + "deployment": [ + "None" + ], + "exclude_from_index": false, + "framework": [ + "Azure ML" + ], + "friendly_name": "Azure Machine Learning Pipeline with CommandStep for R", + "kernelspec": { + "display_name": "Python 3.6", + "language": "python", + "name": "python36" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.7" + }, + "order_index": 7, + "star_tag": [ + "None" + ], + "tags": [ + "None" + ], + "task": "Demonstrates the use of CommandStep for running R scripts" + }, + "nbformat": 4, + "nbformat_minor": 2 +} \ No newline at end of file diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-estimatorstep.ipynb b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep.ipynb similarity index 65% rename from how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-estimatorstep.ipynb rename to how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep.ipynb index 6f2c8589..ce69d4a2 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-estimatorstep.ipynb +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep.ipynb @@ -20,15 +20,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# How to use EstimatorStep in AML Pipeline\n", + "# How to use CommandStep in Azure ML Pipelines\n", "\n", - "This notebook shows how to use the EstimatorStep with Azure Machine Learning Pipelines. Estimator is a convenient object in Azure Machine Learning that wraps run configuration information to help simplify the tasks of specifying how a script is executed.\n", + "This notebook shows how to use the CommandStep with Azure Machine Learning Pipelines for running commands in steps. The example shows running distributed TensorFlow training from within a pipeline.\n", "\n", "\n", "## Prerequisite:\n", "* Understand the [architecture and terms](https://docs.microsoft.com/azure/machine-learning/service/concept-azure-machine-learning-architecture) introduced by Azure Machine Learning\n", "* If you are using an Azure Machine Learning Notebook VM, you are all set. Otherwise, go through the [configuration notebook](https://aka.ms/pl-config) to:\n", - " * install the AML SDK\n", + " * install the Azure ML SDK\n", " * create a workspace and its configuration file (`config.json`)" ] }, @@ -100,75 +100,57 @@ "from azureml.core.compute_target import ComputeTargetException\n", "\n", "# choose a name for your cluster\n", - "cluster_name = \"amlcomp\"\n", + "cluster_name = \"gpu-cluster\"\n", "\n", "try:\n", - " cpu_cluster = ComputeTarget(workspace=ws, name=cluster_name)\n", + " gpu_cluster = ComputeTarget(workspace=ws, name=cluster_name)\n", " print('Found existing compute target')\n", "except ComputeTargetException:\n", " print('Creating a new compute target...')\n", " compute_config = AmlCompute.provisioning_configuration(vm_size='STANDARD_NC6', max_nodes=4)\n", "\n", " # create the cluster\n", - " cpu_cluster = ComputeTarget.create(ws, cluster_name, compute_config)\n", + " gpu_cluster = ComputeTarget.create(ws, cluster_name, compute_config)\n", "\n", " # can poll for a minimum number of nodes and for a specific timeout. \n", " # if no min node count is provided it uses the scale settings for the cluster\n", - " cpu_cluster.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)\n", + " gpu_cluster.wait_for_completion(show_output=True, min_node_count=None, timeout_in_minutes=20)\n", "\n", "# use get_status() to get a detailed status for the current cluster. \n", - "print(cpu_cluster.get_status().serialize())" + "print(gpu_cluster.get_status().serialize())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now that you have created the compute target, let's see what the workspace's `compute_targets` property returns. You should now see one entry named 'cpu-cluster' of type `AmlCompute`." + "Now that you have created the compute target, let's see what the workspace's `compute_targets` property returns. You should now see one entry named 'gpu-cluster' of type `AmlCompute`." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Use a simple script\n", - "We have already created a simple \"hello world\" script. This is the script that we will submit through the estimator pattern. It prints a hello-world message, and if Azure ML SDK is installed, it will also logs an array of values ([Fibonacci numbers](https://en.wikipedia.org/wiki/Fibonacci_number))." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Build an Estimator object\n", - "Estimator by default will attempt to use Docker-based execution. You can also enable Docker and let estimator pick the default CPU image supplied by Azure ML for execution. You can target an AmlCompute cluster (or any other supported compute target types). You can also customize the conda environment by adding conda and/or pip packages.\n", + "## Create a CommandStep\n", + "CommandStep adds a step to run a command in a Pipeline. For the full set of configurable options see the CommandStep [reference docs](https://docs.microsoft.com/python/api/azureml-pipeline-steps/azureml.pipeline.steps.commandstep?view=azure-ml-py).\n", "\n", - "> Note: The arguments to the entry script used in the Estimator object should be specified as *list* using\n", - " 'estimator_entry_script_arguments' parameter when instantiating EstimatorStep. Estimator object's parameter\n", - " 'script_params' accepts a dictionary. However 'estimator_entry_script_arguments' parameter expects arguments as\n", - " a list.\n", + "- **name:** Name of the step\n", + "- **runconfig:** ScriptRunConfig object. You can configure a ScriptRunConfig object as you would for a standalone non-pipeline run and pass it in to this parameter. If using this option, you do not have to specify the `command`, `source_directory`, `compute_target` parameters of the CommandStep constructor as they are already defined in your ScriptRunConfig.\n", + "- **runconfig_pipeline_params:** Override runconfig properties at runtime using key-value pairs each with name of the runconfig property and PipelineParameter for that property\n", + "- **command:** The command to run or path of the executable/script relative to `source_directory`. It is required unless the `runconfig` parameter is specified. It can be specified with string arguments in a single string or with input/output/PipelineParameter in a list.\n", + "- **source_directory:** A folder containing the script and other resources used in the step.\n", + "- **compute_target:** Compute target to use \n", + "- **allow_reuse:** Whether the step should reuse previous results when run with the same settings/inputs. If this is false, a new run will always be generated for this step during pipeline execution.\n", + "- **version:** Optional version tag to denote a change in functionality for the step\n", "\n", - "> Estimator object initialization involves specifying a list of data input and output.\n", - " In Pipelines, a step can take another step's output as input. So when creating an EstimatorStep.\n", - " \n", "> The best practice is to use separate folders for scripts and its dependent files for each step and specify that folder as the `source_directory` for the step. This helps reduce the size of the snapshot created for the step (only the specific folder is snapshotted). Since changes in any files in the `source_directory` would trigger a re-upload of the snapshot, this helps keep the reuse of the step when there are no changes in the `source_directory` of the step." ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [ - "datareference-remarks-sample" - ] - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "from azureml.core import Datastore\n", - "\n", - "def_blob_store = Datastore(ws, \"workspaceblobstore\")\n", - "\n", - "#upload input data to workspaceblobstore\n", - "def_blob_store.upload_files(files=['20news.pkl'], target_path='20newsgroups', overwrite=True)" + "First define the environment that you want to step to run in. This example users a curated TensorFlow environment, but in practice you can configure any environment you want." ] }, { @@ -177,46 +159,46 @@ "metadata": {}, "outputs": [], "source": [ - "from azureml.core import Dataset\n", - "from azureml.data import OutputFileDatasetConfig\n", + "from azureml.core import Environment\n", "\n", - "# create dataset to be used as the input to estimator step\n", - "input_data = Dataset.File.from_files(def_blob_store.path('20newsgroups/20news.pkl'))\n", - "\n", - "# OutputFileDatasetConfig by default write output to the default workspaceblobstore\n", - "output = OutputFileDatasetConfig()\n", - "\n", - "source_directory = 'estimator_train'" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from azureml.train.estimator import Estimator\n", - "\n", - "est = Estimator(source_directory=source_directory, \n", - " compute_target=cpu_cluster, \n", - " entry_script='dummy_train.py', \n", - " conda_packages=['scikit-learn'])" + "tf_env = Environment.get(ws, name='AzureML-TensorFlow-2.3-GPU')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Create an EstimatorStep\n", - "[EstimatorStep](https://docs.microsoft.com/en-us/python/api/azureml-pipeline-steps/azureml.pipeline.steps.estimator_step.estimatorstep?view=azure-ml-py) adds a step to run Estimator in a Pipeline.\n", + "This example will first create a ScriptRunConfig object that configures the training job. Since we are running a distributed job, specify the `distributed_job_config` parameter. If you are just running a single-node job, omit that parameter.\n", "\n", - "- **name:** Name of the step\n", - "- **estimator:** Estimator object\n", - "- **estimator_entry_script_arguments:** A list of command-line arguments\n", - "- **runconfig_pipeline_params:** Override runconfig properties at runtime using key-value pairs each with name of the runconfig property and PipelineParameter for that property\n", - "- **compute_target:** Compute target to use \n", - "- **allow_reuse:** Whether the step should reuse previous results when run with the same settings/inputs. If this is false, a new run will always be generated for this step during pipeline execution.\n", - "- **version:** Optional version tag to denote a change in functionality for the step" + "> If you have an input dataset you want to use in this step, you can specify that as part of the command. For example, if you have a FileDataset object called `dataset` and a `--data-dir` script argument, you can do the following: `command=['python train.py --epochs 30 --data-dir', dataset.as_mount()]`.\n", + "\n", + "> For detailed guidance on how to move data in pipelines for input and output data, see the documentation [Moving data into and between ML pipelines](https://docs.microsoft.com/azure/machine-learning/how-to-move-data-in-out-of-pipelines)." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core import ScriptRunConfig\n", + "from azureml.core.runconfig import MpiConfiguration\n", + "\n", + "src_dir = 'commandstep_train'\n", + "distr_config = MpiConfiguration(node_count=2) # you can also specify the process_count_per_node parameter for multi-process-per-node training\n", + "\n", + "src = ScriptRunConfig(source_directory=src_dir,\n", + " command=['python train.py --epochs 30'],\n", + " compute_target=gpu_cluster,\n", + " environment=tf_env,\n", + " distributed_job_config=distr_config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now create a CommandStep and pass in the ScriptRunConfig object to the `runconfig` parameter." ] }, { @@ -229,20 +211,16 @@ }, "outputs": [], "source": [ - "from azureml.pipeline.steps import EstimatorStep\n", + "from azureml.pipeline.steps import CommandStep\n", "\n", - "est_step = EstimatorStep(name=\"Estimator_Train\", \n", - " estimator=est, \n", - " estimator_entry_script_arguments=[\"--datadir\", input_data.as_mount(), \"--output\", output],\n", - " runconfig_pipeline_params=None, \n", - " compute_target=cpu_cluster)" + "train = CommandStep(name='train-mnist', runconfig=src)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "## Build and Submit the Experiment" + "## Build and Submit the Pipeline" ] }, { @@ -253,8 +231,9 @@ "source": [ "from azureml.pipeline.core import Pipeline\n", "from azureml.core import Experiment\n", - "pipeline = Pipeline(workspace=ws, steps=[est_step])\n", - "pipeline_run = Experiment(ws, 'Estimator_sample').submit(pipeline)" + "\n", + "pipeline = Pipeline(workspace=ws, steps=[train])\n", + "pipeline_run = Experiment(ws, 'train-commandstep-pipeline').submit(pipeline)" ] }, { @@ -295,7 +274,7 @@ "framework": [ "Azure ML" ], - "friendly_name": "Azure Machine Learning Pipeline with EstimatorStep", + "friendly_name": "Azure Machine Learning Pipeline with CommandStep", "kernelspec": { "display_name": "Python 3.6", "language": "python", @@ -311,7 +290,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.7.7" }, "order_index": 7, "star_tag": [ @@ -320,7 +299,7 @@ "tags": [ "None" ], - "task": "Demonstrates the use of EstimatorStep" + "task": "Demonstrates the use of CommandStep" }, "nbformat": 4, "nbformat_minor": 2 diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/Dockerfile b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/Dockerfile new file mode 100644 index 00000000..e0c6ab95 --- /dev/null +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/Dockerfile @@ -0,0 +1,11 @@ +FROM rocker/tidyverse:4.0.0-ubuntu18.04 + +# Install python +RUN apt-get update -qq && \ + apt-get install -y python3 + +# Create link for python +RUN ln -f /usr/bin/python3 /usr/bin/python + +# Install additional R packages +RUN R -e "install.packages(c('optparse'), repos = 'https://cloud.r-project.org/')" \ No newline at end of file diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.R b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.R new file mode 100644 index 00000000..dac8e4cf --- /dev/null +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.R @@ -0,0 +1,34 @@ +#' Copyright(c) Microsoft Corporation. +#' Licensed under the MIT license. + +library(optparse) + +options <- list( + make_option(c("-d", "--data_folder")), + make_option(c("--output_folder")) + +) + +opt_parser <- OptionParser(option_list = options) +opt <- parse_args(opt_parser) + +paste(opt$data_folder) + +accidents <- readRDS(file.path(opt$data_folder, "accidents.Rd")) +summary(accidents) + +mod <- glm(dead ~ dvcat + seatbelt + frontal + sex + ageOFocc + yearVeh + airbag + occRole, family=binomial, data=accidents) +summary(mod) +predictions <- factor(ifelse(predict(mod)>0.1, "dead","alive")) +accuracy <- mean(predictions == accidents$dead) + +# make directory for output dir +output_dir = opt$output_folder +if (!dir.exists(output_dir)){ + dir.create(output_dir) +} + +# save model +model_path = file.path(output_dir, "model.rds") +saveRDS(mod, file = model_path) +message("Model saved") \ No newline at end of file diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.Rd b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_r/accidents.Rd new file mode 100644 index 0000000000000000000000000000000000000000..50a79575096abee45e9b5dbfceb17fe47d187cbb GIT binary patch literal 166122 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 `$;b4n#iFrLR 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 WSB|1`LLUcRkNdw<3@bb1U;RIzSIvX~ literal 0 HcmV?d00001 diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/conda_dependencies.yml b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/conda_dependencies.yml new file mode 100644 index 00000000..66ca1b85 --- /dev/null +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/conda_dependencies.yml @@ -0,0 +1,8 @@ +channels: + - conda-forge +dependencies: + - python=3.7 + - pip: + - azureml-defaults + - tensorflow-gpu==2.3.0 + - horovod==0.19.5 diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/train.py b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/train.py new file mode 100644 index 00000000..ddc4b4f3 --- /dev/null +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/commandstep_train/train.py @@ -0,0 +1,120 @@ +# Copyright 2019 Uber Technologies, Inc. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is 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. +# +# Script adapted from: https://github.com/horovod/horovod/blob/master/examples/tensorflow2_keras_mnist.py +# ============================================================================== + +import tensorflow as tf +import horovod.tensorflow.keras as hvd + +import os +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("--learning-rate", "-lr", type=float, default=0.001) +parser.add_argument("--epochs", type=int, default=24) +parser.add_argument("--steps-per-epoch", type=int, default=500) +args = parser.parse_args() + +# Horovod: initialize Horovod. +hvd.init() + +# Horovod: pin GPU to be used to process local rank (one GPU per process) +gpus = tf.config.experimental.list_physical_devices("GPU") +for gpu in gpus: + tf.config.experimental.set_memory_growth(gpu, True) +if gpus: + tf.config.experimental.set_visible_devices(gpus[hvd.local_rank()], "GPU") + +(mnist_images, mnist_labels), _ = tf.keras.datasets.mnist.load_data( + path="mnist-%d.npz" % hvd.rank() +) + +dataset = tf.data.Dataset.from_tensor_slices( + ( + tf.cast(mnist_images[..., tf.newaxis] / 255.0, tf.float32), + tf.cast(mnist_labels, tf.int64), + ) +) +dataset = dataset.repeat().shuffle(10000).batch(128) + +mnist_model = tf.keras.Sequential( + [ + tf.keras.layers.Conv2D(32, [3, 3], activation="relu"), + tf.keras.layers.Conv2D(64, [3, 3], activation="relu"), + tf.keras.layers.MaxPooling2D(pool_size=(2, 2)), + tf.keras.layers.Dropout(0.25), + tf.keras.layers.Flatten(), + tf.keras.layers.Dense(128, activation="relu"), + tf.keras.layers.Dropout(0.5), + tf.keras.layers.Dense(10, activation="softmax"), + ] +) + +# Horovod: adjust learning rate based on number of GPUs. +scaled_lr = args.learning_rate * hvd.size() +opt = tf.optimizers.Adam(scaled_lr) + +# Horovod: add Horovod DistributedOptimizer. +opt = hvd.DistributedOptimizer(opt) + +# Horovod: Specify `experimental_run_tf_function=False` to ensure TensorFlow +# uses hvd.DistributedOptimizer() to compute gradients. +mnist_model.compile( + loss=tf.losses.SparseCategoricalCrossentropy(), + optimizer=opt, + metrics=["accuracy"], + experimental_run_tf_function=False, +) + +callbacks = [ + # Horovod: broadcast initial variable states from rank 0 to all other processes. + # This is necessary to ensure consistent initialization of all workers when + # training is started with random weights or restored from a checkpoint. + hvd.callbacks.BroadcastGlobalVariablesCallback(0), + # Horovod: average metrics among workers at the end of every epoch. + # + # Note: This callback must be in the list before the ReduceLROnPlateau, + # TensorBoard or other metrics-based callbacks. + hvd.callbacks.MetricAverageCallback(), + # Horovod: using `lr = 1.0 * hvd.size()` from the very beginning leads to worse final + # accuracy. Scale the learning rate `lr = 1.0` ---> `lr = 1.0 * hvd.size()` during + # the first three epochs. See https://arxiv.org/abs/1706.02677 for details. + hvd.callbacks.LearningRateWarmupCallback( + warmup_epochs=3, initial_lr=scaled_lr, verbose=1 + ), +] + +# Horovod: save checkpoints only on worker 0 to prevent other workers from corrupting them. +if hvd.rank() == 0: + output_dir = "./outputs" + os.makedirs(output_dir, exist_ok=True) + callbacks.append( + tf.keras.callbacks.ModelCheckpoint( + os.path.join(output_dir, "checkpoint-{epoch}.h5") + ) + ) + +# Horovod: write logs on worker 0. +verbose = 1 if hvd.rank() == 0 else 0 + +# Train the model. +# Horovod: adjust number of steps based on number of GPUs. +mnist_model.fit( + dataset, + steps_per_epoch=args.steps_per_epoch // hvd.size(), + callbacks=callbacks, + epochs=args.epochs, + verbose=verbose, +) diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/estimator_train/dummy_train.py b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/estimator_train/dummy_train.py deleted file mode 100644 index 0ad3b5ff..00000000 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/estimator_train/dummy_train.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -import argparse -import os - -print("*********************************************************") -print("Hello Azure ML!") - -parser = argparse.ArgumentParser() -parser.add_argument('--datadir', type=str, help="data directory") -parser.add_argument('--output', type=str, help="output") -args = parser.parse_args() - -print("Argument 1: %s" % args.datadir) -print("Argument 2: %s" % args.output) - -if not (args.output is None): - os.makedirs(args.output, exist_ok=True) - print("%s created" % args.output) - -try: - from azureml.core import Run - run = Run.get_context() - print("Log Fibonacci numbers.") - run.log_list('Fibonacci numbers', [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]) - run.complete() -except: - print("Warning: you need to install Azure ML SDK in order to log metrics.") - -print("*********************************************************") diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_compare/compare.py b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_compare/compare.py index 1784bc7b..977ca498 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_compare/compare.py +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_compare/compare.py @@ -22,3 +22,6 @@ print("Argument 4: %s" % args.pipeline_param) if not (args.output_compare is None): os.makedirs(args.output_compare, exist_ok=True) print("%s created" % args.output_compare) + +with open(os.path.join(args.output_compare, 'compare.txt'), 'w') as fw: + fw.write('here is the compare result') diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_extract/extract.py b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_extract/extract.py index 0134a090..e3cc1e79 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_extract/extract.py +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_extract/extract.py @@ -19,3 +19,8 @@ print("Argument 2: %s" % args.output_extract) if not (args.output_extract is None): os.makedirs(args.output_extract, exist_ok=True) print("%s created" % args.output_extract) + +with open(os.path.join(args.input_extract, '20news.pkl'), 'rb') as f: + content = f.read() + with open(os.path.join(args.output_extract, '20news.pkl'), 'wb') as fw: + fw.write(content) diff --git a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_train/train.py b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_train/train.py index 961f5ebf..4f88f0de 100644 --- a/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_train/train.py +++ b/how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/publish_run_train/train.py @@ -20,3 +20,8 @@ print("Argument 2: %s" % args.output_train) if not (args.output_train is None): os.makedirs(args.output_train, exist_ok=True) print("%s created" % args.output_train) + +with open(os.path.join(args.input_data, '20news.pkl'), 'rb') as f: + content = f.read() + with open(os.path.join(args.output_train, '20news.pkl'), 'wb') as fw: + fw.write(content) diff --git a/how-to-use-azureml/manage-azureml-service/authentication-in-azureml/authentication-in-azureml.ipynb b/how-to-use-azureml/manage-azureml-service/authentication-in-azureml/authentication-in-azureml.ipynb index 8e2d1ca0..9354a50b 100644 --- a/how-to-use-azureml/manage-azureml-service/authentication-in-azureml/authentication-in-azureml.ipynb +++ b/how-to-use-azureml/manage-azureml-service/authentication-in-azureml/authentication-in-azureml.ipynb @@ -28,6 +28,7 @@ " 2. Azure CLI Authentication\n", " 3. Managed Service Identity (MSI) Authentication\n", " 4. Service Principal Authentication\n", + " 5. Token Authentication\n", " \n", "The interactive authentication is suitable for local experimentation on your own computer. Azure CLI authentication is suitable if you are already using Azure CLI for managing Azure resources, and want to sign in only once. The MSI and Service Principal authentication are suitable for automated workflows, for example as part of Azure Devops build." ] @@ -319,6 +320,66 @@ "See [Register an application with the Microsoft identity platform](https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) quickstart for more details about application registrations. " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Token Authentication\n", + "\n", + "When token generation and its refresh needs to be outside on AML SDK, we recommend using Token Authentication. It can be used for getting token for AML or ARM audience. Thus giving more granular control over token generated.\n", + "\n", + "This authentication class requires users to provide method `get_token_for_audience` which will be called to retrieve the token based on the audience passed.\n", + "\n", + "Audience that is passed to `get_token_for_audience` can be ARM or AML. Exact value that will be passed as audience will depend on cloud and type for audience." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from azureml.core.authentication import TokenAuthentication, Audience\n", + "\n", + "# This is a sample method to retrieve token and will be passed to TokenAuthentication\n", + "def get_token_for_audience(audience):\n", + " from adal import AuthenticationContext\n", + " client_id = \"my-client-id\"\n", + " client_secret = \"my-client-secret\"\n", + " tenant_id = \"my-tenant-id\"\n", + " auth_context = AuthenticationContext(\"https://login.microsoftonline.com/{}\".format(tenant_id))\n", + " resp = auth_context.acquire_token_with_client_credentials(audience,client_id,client_secret)\n", + " token = resp[\"accessToken\"]\n", + " return token\n", + "\n", + "\n", + "token_auth = TokenAuthentication(get_token_for_audience=get_token_for_audience)\n", + "\n", + "ws = Workspace(\n", + " subscription_id=\"my-subscription-id\",\n", + " resource_group=\"my-ml-rg\",\n", + " workspace_name=\"my-ml-workspace\",\n", + " auth=token_auth\n", + " )\n", + "\n", + "print(\"Found workspace {} at location {}\".format(ws.name, ws.location))\n", + "\n", + "token_aml_audience = token_auth.get_token(Audience.aml)\n", + "token_arm_audience = token_auth.get_token(Audience.arm)\n", + "\n", + "# Value of audience pass to `get_token_for_audience` can be retrieved as follows:\n", + "# aud_aml_val = token_auth.get_aml_resource_id() # For AML\n", + "# aud_arm_val = token_auth._cloud_type.endpoints.active_directory_resource_id # For ARM\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Token authentication object can be used to retrieve token for either AML or ARM audience,\n", + "which can be used by other clients to authenticate to AML or ARM" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -350,7 +411,7 @@ }, "outputs": [], "source": [ - "import os, uuid\n", + "import uuid\n", "\n", "local_secret = os.environ.get(\"LOCAL_SECRET\", default = str(uuid.uuid4())) # Use random UUID as a substitute for real secret.\n", "keyvault = ws.get_default_keyvault()\n", diff --git a/how-to-use-azureml/track-and-monitor-experiments/logging-api/logging-api.ipynb b/how-to-use-azureml/track-and-monitor-experiments/logging-api/logging-api.ipynb index e0908fc6..d1acc681 100644 --- a/how-to-use-azureml/track-and-monitor-experiments/logging-api/logging-api.ipynb +++ b/how-to-use-azureml/track-and-monitor-experiments/logging-api/logging-api.ipynb @@ -100,7 +100,7 @@ "\n", "# Check core SDK version number\n", "\n", - "print(\"This notebook was created using SDK version 1.21.0, you are currently running version\", azureml.core.VERSION)" + "print(\"This notebook was created using SDK version 1.22.0, you are currently running version\", azureml.core.VERSION)" ] }, { diff --git a/how-to-use-azureml/training/README.md b/how-to-use-azureml/training/README.md index 39d2d6b7..cae8439d 100644 --- a/how-to-use-azureml/training/README.md +++ b/how-to-use-azureml/training/README.md @@ -7,6 +7,6 @@ Follow these sample notebooks to learn: 3. [Train on remote VM](train-on-remote-vm): train a model using a remote Azure VM as compute target. 4. [Train on ML Compute](train-on-amlcompute): train a model using an ML Compute cluster as compute target. 5. [Train in an HDI Spark cluster](train-in-spark): train a Spark ML model using an HDInsight Spark cluster as compute target. -6. [Train and hyperparameter tune on Iris Dataset with Scikit-learn](train-hyperparameter-tune-deploy-with-sklearn): train a model using the Scikit-learn estimator and tune hyperparameters with Hyperdrive. + ![Impressions](https://PixelServer20190423114238.azurewebsites.net/api/impressions/MachineLearningNotebooks/how-to-use-azureml/training/README.png) diff --git a/index.md b/index.md index 5082517f..dedd23e0 100644 --- a/index.md +++ b/index.md @@ -30,7 +30,6 @@ Machine Learning notebook samples and encourage efficient retrieval of topics an | :star:[Azure Machine Learning Pipeline with DataTranferStep](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-data-transfer.ipynb) | Demonstrates the use of DataTranferStep | Custom | ADF | None | Azure ML | None | | [Getting Started with Azure Machine Learning Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-getting-started.ipynb) | Getting Started notebook for ANML Pipelines | Custom | AML Compute | None | Azure ML | None | | [Azure Machine Learning Pipeline with AzureBatchStep](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-azurebatch-to-run-a-windows-executable.ipynb) | Demonstrates the use of AzureBatchStep | Custom | Azure Batch | None | Azure ML | None | -| [Azure Machine Learning Pipeline with EstimatorStep](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-estimatorstep.ipynb) | Demonstrates the use of EstimatorStep | Custom | AML Compute | None | Azure ML | None | | :star:[How to use ModuleStep with AML Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-modulestep.ipynb) | Demonstrates the use of ModuleStep | Custom | AML Compute | None | Azure ML | None | | :star:[How to use Pipeline Drafts to create a Published Pipeline](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-how-to-use-pipeline-drafts.ipynb) | Demonstrates the use of Pipeline Drafts | Custom | AML Compute | None | Azure ML | None | | :star:[Azure Machine Learning Pipeline with HyperDriveStep](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-parameter-tuning-with-hyperdrive.ipynb) | Demonstrates the use of HyperDriveStep | Custom | AML Compute | None | Azure ML | None | @@ -43,6 +42,8 @@ Machine Learning notebook samples and encourage efficient retrieval of topics an | :star:[How to use DatabricksStep with AML Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-use-databricks-as-compute-target.ipynb) | Demonstrates the use of DatabricksStep | Custom | Azure Databricks | None | Azure ML, Azure Databricks | None | | :star:[How to use KustoStep with AML Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-use-kusto-as-compute-target.ipynb) | Demonstrates the use of KustoStep | Custom | Kusto | None | Azure ML, Kusto | None | | :star:[How to use AutoMLStep with AML Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-automated-machine-learning-step.ipynb) | Demonstrates the use of AutoMLStep | Custom | AML Compute | None | Automated Machine Learning | None | +| [Azure Machine Learning Pipeline with CommandStep for R](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep-r.ipynb) | Demonstrates the use of CommandStep for running R scripts | Custom | AML Compute | None | Azure ML | None | +| [Azure Machine Learning Pipeline with CommandStep](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-commandstep.ipynb) | Demonstrates the use of CommandStep | Custom | AML Compute | None | Azure ML | None | | :star:[Azure Machine Learning Pipelines with Data Dependency](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-data-dependency-steps.ipynb) | Demonstrates how to construct a Pipeline with data dependency between steps | Custom | AML Compute | None | Azure ML | None | | [How to use run a notebook as a step in AML Pipelines](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/machine-learning-pipelines/intro-to-pipelines/aml-pipelines-with-notebook-runner-step.ipynb) | Demonstrates the use of NotebookRunnerStep | Custom | AML Compute | None | Azure ML | None | | [Use MLflow with Azure Machine Learning to Train and Deploy Keras Image Classifier](https://github.com/Azure/MachineLearningNotebooks/blob/master//how-to-use-azureml/ml-frameworks/using-mlflow/train-and-deploy-keras-auto-logging/train-and-deploy-keras-auto-logging.ipynb) | Use MLflow with Azure Machine Learning to Train and Deploy Keras Image Classifier, leveraging MLflow auto logging | MNIST | Local, AML Compute | Azure Container Instance | Keras | mlflow, keras | diff --git a/setup-environment/configuration.ipynb b/setup-environment/configuration.ipynb index 75293b19..443283f7 100644 --- a/setup-environment/configuration.ipynb +++ b/setup-environment/configuration.ipynb @@ -102,7 +102,7 @@ "source": [ "import azureml.core\n", "\n", - "print(\"This notebook was created using version 1.21.0 of the Azure ML SDK\")\n", + "print(\"This notebook was created using version 1.22.0 of the Azure ML SDK\")\n", "print(\"You are currently using version\", azureml.core.VERSION, \"of the Azure ML SDK\")" ] }, diff --git a/tutorials/machine-learning-pipelines-advanced/tutorial-pipeline-batch-scoring-classification.ipynb b/tutorials/machine-learning-pipelines-advanced/tutorial-pipeline-batch-scoring-classification.ipynb index bd07da97..14effa63 100644 --- a/tutorials/machine-learning-pipelines-advanced/tutorial-pipeline-batch-scoring-classification.ipynb +++ b/tutorials/machine-learning-pipelines-advanced/tutorial-pipeline-batch-scoring-classification.ipynb @@ -581,7 +581,7 @@ "source": [ "from azureml.pipeline.core.run import PipelineRun\n", "\n", - "published_pipeline_run = PipelineRun(ws.experiments[\"batch_scoring\"], run_id)" + "published_pipeline_run = PipelineRun(ws.experiments[\"Tutorial-Batch-Scoring\"], run_id)" ] }, {