sdk/python/jobs/automl-standalone-jobs/automl-forecasting-task-energy-demand/automl-forecasting-task-energy-demand-advanced.ipynb (456 lines of code) (raw):

{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# AutoML: Train \"the best\" Time-Series Forecasting model for the Energy Demand Dataset.\n", "\n", "**Requirements** - In order to benefit from this tutorial, you will need:\n", "- A basic understanding of Machine Learning\n", "- An Azure account with an active subscription. [Create an account for free](https://azure.microsoft.com/free/?WT.mc_id=A261C142F)\n", "- An Azure ML workspace. [Check this notebook for creating a workspace](../../../resources/workspace/workspace.ipynb) \n", "- A python environment\n", "- Installed Azure Machine Learning Python SDK v2 - [install instructions](../../../README.md) - check the getting started section\n", "\n", "**Learning Objectives** - By the end of this tutorial, you should be able to:\n", "- Connect to your AML workspace from the Python SDK\n", "- Create an `AutoML time-series forecasting Job` with the 'forecasting()' factory-fuction.\n", "- Train the model using [serverless compute (preview)](https://learn.microsoft.com/azure/machine-learning/how-to-use-serverless-compute?view=azureml-api-2&tabs=python) by submitting/running the AutoML forecasting training job\n", "- Obtaing the model and score predictions with it\n", "\n", "**Motivations** - This notebook explains how to setup and run an AutoML forecasting job. This is one of the nine ML-tasks supported by AutoML. Other ML-tasks are 'regression', 'classification', 'image classification', 'image object detection', 'nlp text classification', etc.\n", "\n", "In this example we use the associated New York City energy demand dataset to showcase how you can use AutoML for a simple forecasting problem and explore the results. The goal is predict the energy demand for the next 48 hours based on historic time-series data.\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 1. Connect to Azure Machine Learning Workspace\n", "\n", "The [workspace](https://docs.microsoft.com/en-us/azure/machine-learning/concept-workspace) is the top-level resource for Azure Machine Learning, providing a centralized place to work with all the artifacts you create when you use Azure Machine Learning. In this section we will connect to the workspace in which the job will be run.\n", "\n", "## 1.1. Import the required libraries" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gather": { "logged": 1634852261599 } }, "outputs": [], "source": [ "# Import required libraries\n", "from azure.identity import DefaultAzureCredential\n", "from azure.ai.ml import MLClient\n", "\n", "from azure.ai.ml.constants import AssetTypes, InputOutputModes\n", "from azure.ai.ml import automl\n", "from azure.ai.ml import Input" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 1.2. Configure workspace details and get a handle to the workspace\n", "\n", "To connect to a workspace, we need identifier parameters - a subscription, resource group and workspace name. We will use these details in the `MLClient` from `azure.ai.ml` to get a handle to the required Azure Machine Learning workspace. We use the default [default azure authentication](https://docs.microsoft.com/en-us/python/api/azure-identity/azure.identity.defaultazurecredential?view=azure-python) for this tutorial. Check the [configuration notebook](../../configuration.ipynb) for more details on how to configure credentials and connect to a workspace." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gather": { "logged": 1634852261884 }, "jupyter": { "outputs_hidden": false, "source_hidden": false }, "nteract": { "transient": { "deleting": false } } }, "outputs": [], "source": [ "credential = DefaultAzureCredential()\n", "ml_client = None\n", "try:\n", " ml_client = MLClient.from_config(credential)\n", "except Exception as ex:\n", " print(ex)\n", " # Enter details of your AML workspace\n", " subscription_id = \"<SUBSCRIPTION_ID>\"\n", " resource_group = \"<RESOURCE_GROUP>\"\n", " workspace = \"<AML_WORKSPACE_NAME>\"\n", " ml_client = MLClient(credential, subscription_id, resource_group, workspace)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Show Azure ML Workspace information" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "workspace = ml_client.workspaces.get(name=ml_client.workspace_name)\n", "\n", "output = {}\n", "output[\"Workspace\"] = ml_client.workspace_name\n", "output[\"Subscription ID\"] = ml_client.subscription_id\n", "output[\"Resource Group\"] = workspace.resource_group\n", "output[\"Location\"] = workspace.location\n", "output" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 2. Data\n", "\n", "We will use energy consumption [data from New York City](http://mis.nyiso.com/public/P-58Blist.htm) for model training. \n", "The data is stored in a tabular format and includes energy demand and basic weather data at an hourly frequency. \n", "\n", "With Azure Machine Learning MLTables you can keep a single copy of data in your storage, easily access data during model training, share data and collaborate with other users. \n", "Below, we will upload the data by creating an MLTable to be used for training.\n", "\n", "Please make use of the MLTable files present within the data folder at the same location (in the repo) as this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Training MLTable defined locally, with local data to be uploaded\n", "my_training_data_input = Input(\n", " type=AssetTypes.MLTABLE, path=\"./data/training-mltable-folder\"\n", ")\n", "\n", "# Training MLTable defined locally, with local data to be uploaded\n", "my_validation_data_input = Input(\n", " type=AssetTypes.MLTABLE, path=\"./data/validation-mltable-folder\"\n", ")\n", "\n", "# WITH REMOTE PATH\n", "# my_training_data_input = Input(type=AssetTypes.MLTABLE, path=\"azureml://datastores/workspaceblobstore/paths/my-forecasting-mltable\")" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "nteract": { "transient": { "deleting": false } } }, "source": [ "To create data input from TabularDataset created using V1 sdk, set the `type` to `AssetTypes.MLTABLE`, `mode` to `InputOutputModes.DIRECT` and `path` to the following format `azureml:<tabulardataset_name>` or `azureml:<tabulardataset_name:<version>`(in case we want to use specific version of the registered dataset).\n", "To run the following cell, remove `\"\"\"` at start and end." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "jupyter": { "outputs_hidden": false, "source_hidden": false }, "nteract": { "transient": { "deleting": false } } }, "outputs": [], "source": [ "\"\"\"\n", "# Training MLTable with v1 TabularDataset\n", "my_training_data_input = Input(\n", " type=AssetTypes.MLTABLE, path=\"azureml:nyc_energy_train:1\", mode=InputOutputModes.DIRECT\n", ")\n", "\"\"\"" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "For documentation on creating your own MLTable assets for jobs beyond this notebook:\n", "- https://learn.microsoft.com/en-us/azure/machine-learning/reference-yaml-mltable details how to write MLTable YAMLs (required for each MLTable asset).\n", "- https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-data-assets?tabs=Python-SDK covers how to work with them in the v2 CLI/SDK." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# 3. Configure and run the AutoML Forecasting training job\n", "In this section we will configure and run the AutoML job, for training the model.\n", "\n", "## 3.1 Configure the job through the forecasting() factory function\n", "\n", "### forecasting() function parameters:\n", "\n", "The `forecasting()` factory function allows user to configure AutoML for the forecasting task for the most common scenarios with the following properties.\n", "\n", "- `target_column_name` - The name of the column to target for predictions. It must always be specified. This parameter is applicable to 'training_data', 'validation_data' and 'test_data'.\n", "- `primary_metric` - The metric that AutoML will optimize for model selection.\n", "- `training_data` - The data to be used for training. It should contain both training feature columns and a target column. Optionally, this data can be split for segregating a validation or test dataset. \n", "You can use a registered MLTable in the workspace using the format '<mltable_name>:<version>' OR you can use a local file or folder as a MLTable. For e.g Input(mltable='my_mltable:1') OR Input(mltable=MLTable(local_path=\"./data\"))\n", "The parameter 'training_data' must always be provided.\n", "- `compute` - The compute on which the AutoML job will run. In this example we are using serverless compute. You can alternatively use a compute cluster in the workspace. \n", "- `name` - The name of the Job/Run. This is an optional property. If not specified, a random name will be generated.\n", "- `experiment_name` - The name of the Experiment. An Experiment is like a folder with multiple runs in Azure ML Workspace that should be related to the same logical machine learning experiment.\n", "\n", "### set_limits() parameters:\n", "This is an optional configuration method to configure limits parameters such as timeouts. \n", " \n", "- timeout_minutes - Maximum amount of time in minutes that the whole AutoML job can take before the job terminates. This timeout includes setup, featurization and training runs but does not include the ensembling and model explainability runs at the end of the process since those actions need to happen once all the trials (children jobs) are done. If not specified, the default job's total timeout is 6 days (8,640 minutes). To specify a timeout less than or equal to 1 hour (60 minutes), make sure your dataset's size is not greater than 10,000,000 (rows times column) or an error results.\n", "\n", "- trial_timeout_minutes - Maximum time in minutes that each trial (child job) can run for before it terminates. If not specified, a value of 1 month or 43200 minutes is used.\n", " \n", "- max_trials - The maximum number of trials/runs each with a different combination of algorithm and hyperparameters to try during an AutoML job. If not specified, the default is 1000 trials. If using 'enable_early_termination' the number of trials used can be smaller.\n", " \n", "- max_concurrent_trials - Represents the maximum number of trials (children jobs) that would be executed in parallel. It's a good practice to match this number with the number of nodes your cluster.\n", " \n", "- enable_early_termination - Whether to enable early termination if the score is not improving in the short term. \n", " " ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Specialized Forecasting Parameters\n", "To define forecasting parameters for your experiment training, you can leverage the .set_forecast_settings() method. \n", "The table below details the forecasting parameters we will be passing into our experiment.\n", "\n", "|Property|Description|\n", "|-|-|\n", "|**time_column_name**|The name of your time column.|\n", "|**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", "|**frequency**|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." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Advanced Forecasting Training <a id=\"advanced_training\"></a>\n", "### Using lags and rolling window features\n", "This training is also using the **target lags**, that is the previous values of the target variables, meaning the prediction uses a horizon. We therefore must still specify the `forecast_horizon` that the model will learn to forecast. The `target_lags` keyword specifies how far back we will construct the lags of the target variable, and the `target_rolling_window_size` specifies the size of the rolling window over which we will generate the `max`, `min` and `sum` features.\n", "\n", "This notebook uses the .set_training(blocked_training_algorithms=...) parameter to exclude some models that take a longer time to train on this dataset. You can choose to remove models from the blocked_training_algorithms list but you may need to increase the trial_timeout_minutes parameter value to get results." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [ "parameters" ] }, "outputs": [], "source": [ "# general job parameters\n", "max_trials = 5\n", "exp_name = \"dpv2-forecasting-experiment\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gather": { "logged": 1634852262026 }, "jupyter": { "outputs_hidden": false, "source_hidden": false }, "name": "forecasting-configuration", "nteract": { "transient": { "deleting": false } } }, "outputs": [], "source": [ "# Create the AutoML forecasting job with the related factory-function.\n", "\n", "forecasting_job = automl.forecasting(\n", " # name=\"dpv2-forecasting-job-02\",\n", " experiment_name=exp_name,\n", " training_data=my_training_data_input,\n", " # validation_data = my_validation_data_input,\n", " target_column_name=\"demand\",\n", " primary_metric=\"NormalizedRootMeanSquaredError\",\n", " n_cross_validations=\"auto\",\n", " enable_model_explainability=True,\n", " tags={\"my_custom_tag\": \"My custom value\"},\n", ")\n", "\n", "# Limits are all optional\n", "forecasting_job.set_limits(\n", " timeout_minutes=600,\n", " trial_timeout_minutes=20,\n", " max_trials=max_trials,\n", " # max_concurrent_trials = 4,\n", " # max_cores_per_trial: -1,\n", " enable_early_termination=True,\n", ")\n", "\n", "# Specialized properties for Time Series Forecasting training\n", "forecasting_job.set_forecast_settings(\n", " time_column_name=\"timeStamp\",\n", " forecast_horizon=48,\n", " frequency=\"H\",\n", " target_lags=[12],\n", " target_rolling_window_size=4,\n", " # ADDITIONAL FORECASTING TRAINING PARAMS ---\n", " # time_series_id_column_names=[\"tid1\", \"tid2\", \"tid2\"],\n", " # short_series_handling_config=ShortSeriesHandlingConfiguration.DROP,\n", " # use_stl=\"season\",\n", " # seasonality=3,\n", ")\n", "\n", "# Training properties are optional\n", "forecasting_job.set_training(blocked_training_algorithms=[\"ExtremeRandomTrees\"])\n", "\n", "# Featurization properties are optional\n", "# forecasting_job.set_featurization(# drop_columns=[\"not_needed_column\"], # Optional\n", "# # enable_dnn_featurization=True # Enable if there are text columns\n", "# )" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## Run the Command\n", "Using the `MLClient` created earlier, we will now run this Command in the workspace." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "gather": { "logged": 1634852267930 }, "jupyter": { "outputs_hidden": false, "source_hidden": false }, "nteract": { "transient": { "deleting": false } } }, "outputs": [], "source": [ "# Submit the AutoML job\n", "returned_job = ml_client.jobs.create_or_update(\n", " forecasting_job\n", ") # submit the job to the backend\n", "\n", "print(f\"Created job: {returned_job}\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "ml_client.jobs.stream(returned_job.name)" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Next Steps\n", "You can see further examples of other AutoML tasks such as Image-Classification, Image-Object-Detection, NLP-Text-Classification, Time-Series-Forcasting, etc." ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [] } ], "metadata": { "kernel_info": { "name": "python310-sdkv2" }, "kernelspec": { "display_name": "Python 3.10 - SDK V2", "language": "python", "name": "python310-sdkv2" }, "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.10.9" }, "microsoft": { "host": { "AzureML": { "notebookHasBeenCompleted": true } }, "ms_spell_check": { "ms_spell_check_language": "en" } }, "nteract": { "version": "nteract-front-end@1.0.0" } }, "nbformat": 4, "nbformat_minor": 4 }