How to build an end-to-end Azure Machine Learning workflow
Are you a data scientist who’d like to know more about using Azure Machine Learning? Are you aware of all the individual possibilities that are available in Azure Machine Learning, but don’t know how to link everything?
Azure Machine Learning is a solution that helps you create data science solutions covering the whole Machine Learning lifecycle. It is fast, scalable, responsible, secure, and fully integrable.
In this article, I explore the end-to-end workflow that you can follow to put a Machine Learning model into production, from data preparation to building, training, deploying, and monitoring a model.
Workspace
The first step is to create an Azure Machine Learning workspace resource in the Azure Portal.
Then, you complete the details of the Subscription, Resource Group, Workspace Name, and Region that you want to use. You can leave other features as their defaults and a name will be automatically assigned to Storage Account, Key Vault, Application Insights, and Container Registry. These four resources are always automatically created when you build a new Azure Machine Learning resource.
Once created, you can navigate to the workspace resource and, in the middle of the screen, you can see a button (“Launch studio”) to navigate to the Azure Machine Learning Studio, the environment where you can operate.
Now that the workspace is created, I am going to show how to build an end-to-end solution with programming in Python, which we can do by going directly to the Notebooks pane to create it from a blank notebook. During the entire process, we will be importing several libraries, but the one to highlight is azureml, as it contains every functionality that I will show how to set up.
To indicate to Azure Machine Learning the workspace we are using, we are going to use the library Workspace from azureml.core, specifically, the function .from_config(). This function looks in the root where the notebook is located for a file named config.json to read the workspace denotation. To obtain this file, we can go back to the Azure resource and, in the upper bar, directly download this configuration file and, later, upload it to the notebook folder.
Subsequently, we apply the following piece of code to store the configuration in the variable ws:
import azureml.corefrom azureml.core import Workspacews = Workspace.from_config()
Script
The second step is to create a script that is going to contain the Machine Learning modeling. We are going to create the script right at the code, with two requirements:
- Keep all the script definition in the same cell.
- Use the first line of the cell to indicate the location of the new script and the script name.
%%writefile $folder_name/script.py
Next, we import the libraries that we are going to use for modeling. The execution of the script will result in a run, so we start the code creating the variable run to start its context and we close the code with the closure of the run.
run = Run.get_context()…run.complete()
The next part of the script reads the arguments sent to the execution. Later, we will see how to send these arguments as an input to the script, but now, we are going to see how to retrieve them. We need the Argument Parser to extract those arguments. We pass the input arguments to the parser indicating their name, their data type, how they will be named inside the script, and their default value in case no argument is provided. In our example, we have two arguments: The first one is a number and the second one is a dataset.
parser = argparse.ArgumentParser()parser.add_argument(‘ — argument’, type=float, dest=’a’,default=1)parser.add_argument(‘ — input-dataset’, type=str, dest=’datasetid’)args = parser.parse_args()a = args.adf = run.input_datasets[‘my_dataset’].to_pandas_dataframe()
After getting the arguments, we can jump to the data cleaning and feature engineering phase (in the example, I have skipped this step) and then to the modeling. We can enrich the run adding logs, which can be as simple as a text piece or an image. We log the input argument as shown:
run.log(‘Argument’, a)
The last step is to save and register the model that we have just created.
Full script code:
%%writefile $folder_name/script.pyfrom azureml.core import Run, Dataset, Modelimport pandas as pdimport numpy as npimport joblibfrom sklearn.model_selection import train_test_splitfrom sklearn.tree import DecisionTreeClassifierrun = Run.get_context()
# Argumentsparser = argparse.ArgumentParser()parser.add_argument(‘ — argument’, type=float, dest=’a’,default=1)parser.add_argument(‘ — input-dataset’, type=str, dest=’datasetid’)args = parser.parse_args()a = args.adf = run.input_datasets[‘my_dataset’].to_pandas_dataframe()
# ModelX, y = df[[‘ColumnA’,’ColumnB’,’ColumnC’]].values, df[‘Label’].valuesX_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=0)model = DecisionTreeClassifier().fit(X_train, y_train)
# Logsrun.log(‘Argument’, a)
# Save & register the modeljoblib.dump(value=model, filename=’model.pkl’)run.upload_file(name = ‘scripts/model.pkl’, path_or_stream = ‘./model.pkl’)run.register_model(model_path=’scripts/model.pkl’, model_name=’model’)run.complete()
Compute
Once we have defined the code to execute, we need a set of resources for executing the script, which is where the compute appears. The compute libraries come also from azureml:
from azureml.core.compute import ComputeTarget, AmlCompute
We are going to cover two scenarios regarding the compute:
- Use an already created compute: This is the easiest way to define the compute — you simply provide the workspace variable created at the beginning and the name of the compute that you want to use.
training_cluster = ComputeTarget(workspace=ws, name=”compute”)
- Create a new compute from scratch: For the compute provisioning, we must specify the type of virtual machine that we want to use and its number of nodes. As part of creating it, we add the workspace variable and the name of the new compute.
If you need to check compute alternatives, follow this link to understand the one that best suits your scenario: What are compute targets — Azure Machine Learning | Microsoft Docs
compute_config = AmlCompute.provisioning_configuration(vm_size=’STANDARD_DS11_V2', min_nodes=0, max_nodes=4)training_cluster = ComputeTarget.create(ws,’compute’, compute_config)training_cluster.wait_for_completion(show_output=True)
Environment
We have been using a few libraries during the script. Is there a way to consolidate them into a single site? The answer is yes, we can define the used libraries and packages in the environment. We must import two libraries first.
from azureml.core import Environmentfrom azureml.core.conda_dependencies import CondaDependencies
Once more, we have more than one possible scenario:
- Create a new environment: Here we define the name of the new environment, add the packages to be used, and afterward register it at the workspace.
environment = Environment(“environment”)packages = CondaDependencies.create(pip_packages=[‘scikit-learn’,’azureml-defaults’,’azureml-interpret’])environment.python.conda_dependencies = packagesenvironment.register(workspace=ws)
- Use an existing environment stored in Azure Machine Learning: To retrieve the environment using this option, we need only the workspace variable and the environment name.
environment = Environment.get(ws,”environment”)
- Use an existing environment stored in a YAML file: In this situation, we create a new environment in Azure Machine Learning based on a YAML file stored in the root.
environment = Environment.from_conda_specification(name=”environment”, file_path=’conda.yml’)
A YAML file has its own structure where the environment name and the libraries and packages are designated.
name: environmentdependencies: - numpy - pandas - scikit-learn - pip: - azureml-defaults
Datastore
We have been talking a lot about scripts and programming, but how are we going to create a Machine Learning model without data? In this section I show how we can collect it.
Inside Azure, the main entity for storing data is the Datastore, and there are two types: Azure Blob Storage and Azure File Share; we use one or the other depending on the type of data we have. In general, Blob is the option to use for Tabular data and File Share is the option to use for file-based data such as images.
We can quickly designate the default datastore to use in the workspace and upload files there to analyze. Once uploaded, we follow the next two steps:
- Extract the datasets from the Datastore.
- Register the datasets to keep them in the Azure Machine Learning dataset environment.
from azureml.core import Dataset
ds = ws.get_default_datastore()ds.upload_files(files=[‘data1.csv’, ‘data2.csv’], target_path=’files/’)
# Datasetdataset = Dataset.Tabular.from_delimited_files(path=(ds, ‘files/*.csv’))df_mycode = dataset.to_pandas_dataframe()dataset = dataset.register(workspace=ws, name=’dataset’, create_new_version=True)
Experimentation
At last, we have reached the point where we execute the Machine Learning script. First, it’s necessary to define the experiment configuration: the script to run, the input arguments, the environment, and the compute to use. Second, we create the experiment in the workspace and submit it to run.
from azureml.core import Experiment, ScriptRunConfigfrom azureml.widgets import RunDetails
script_config = ScriptRunConfig(source_directory=folder_name, script=’script.py’, arguments = [‘ — argument’, 2, ‘ — input-dataset’, dataset.as_named_input(‘my_dataset’)], environment=environment, compute_target=’compute’)
experiment = Experiment(workspace=ws, name=”experiment”)
run = experiment.submit(config=script_config)RunDetails(run).show()run.wait_for_completion()
After execution, we can navigate to the Experiments pane to check how the run appears there.
Deployment
We now have a working model, so let’s show it to the world and deploy it! For the deployment, it is crucial to have a scoring script where we define the steps that the model has to follow when we run it. This script is based on two functions: init() and run(). init() retrieves the model and run() executes it.
%%writefile $folder_name/score.pyimport jsonimport joblibimport numpy as npfrom azureml.core.model import Model
def init(): global model model_path = Model.get_model_path(‘model’) model = joblib.load(model_path)
def run(raw_data): data = np.array(json.loads(raw_data)[‘data’]) predictions = model.predict(data) classnames = [‘ClassA’, ‘ClassB’] predicted_classes = [] for prediction in predictions: predicted_classes.append(classnames[prediction]) return json.dumps(predicted_classes)
The next step is to stipulate the inference configuration: the runtime we are going to use, the scoring script to be used, the YAML file with the environment configuration, and the features of the container. This container can be one of two types: ACI (Azure Container Instances) or AKS (Azure Kubernetes Service). The deployment step uses the inference and deployment configuration, the workspace, the name of the new endpoint to be created, and the model to use.
from azureml.core.webservice import AciWebservicefrom azureml.core.model import InferenceConfigfrom azureml.core.model import Model
model = ws.models[‘model’]
inference_config = InferenceConfig(runtime= “python”, entry_script=’score.py’, conda_file=’conda.yml’)deployment_config = AciWebservice.deploy_configuration(cpu_cores = 1, memory_gb = 1)
service = Model.deploy(ws, ‘endpoint’, [model], inference_config, deployment_config)service.wait_for_deployment(True)
What happens after deployment?
If you want to use your deployed model for new predictions, you can reach it using the functions defined at the scoring script or with the REST API. For the first scenario, you just need to create the endpoint object and pass the input data to the run() function.
import jsonimport requestsfrom azureml.core import Webservice
x_new = [[2,180,74]]service = Webservice(workspace=ws, name=”endpoint”)input_json = json.dumps({“data”: x_new})predictions = service.run(input_data = input_json)predicted_classes = json.loads(predictions)
For the second scenario, you can do a POST request providing the endpoint, the input data, and some headers.
endpoint = service.scoring_uriinput_json = json.dumps({“data”: x_new})headers = { ‘Content-Type’:’application/json’ }predictions = requests.post(endpoint, input_json, headers = headers)predicted_classes = json.loads(predictions.json())
What we have learned
If you reached this point, you have likely already answered the questions I posed at the start of the article. Here’s a summary:
- Are you a data scientist who’d like to know more about using Azure Machine Learning? If so, you have now explored the roadmap to follow to integrate your Machine Learning solutions. This journey has included Python examples for Notebooks to provide a starting point. You are also now empowered to explore the other alternatives for building Machine Learning models, such as Designer or Automated ML.
- Are you aware of all the individual possibilities that are available in Azure Machine Learning, but don’t know how to link everything? I have shown step-by-step the main functionalities available in Azure Machine Learning Studio and put some order to them. They include workspace generation, Machine Learning script creation, compute and environment definition, data management in datastores, consolidation in an experiment, solution deployment, and model usage.
I hope this article helps get you started with Azure Machine Learning! Please leave any comments you might have in the feedback area below.
Eva Jurado Cortés is on LinkedIn.