Deploy ML Model on Azure Machine Learning Studio

How to Deploy a Local ML Model as a Web Service on Azure Machine Learning Studio

Posted by

Azure Machine Learning Studio (MLS) is a service provided by Microsoft which lets you deploy your models as a web service and consume it as a REST endpoint. It is really useful when you are trying to integrate your web app/ API with Machine Learning models

UPDATE 08/24/21 : Fixed Error related to consuming endpoint (This error was bought up by quite a few people) If you encounter any issues, clone my repo with the link provided below.

Introduction

In this tutorial, I will show you how to deploy your model as a web service. First, we will create a simple KNN model on the iris-dataset and then deploy it. I will also show you how to consume the deployed model and mention some points to keep in mind while deploying the model.

You can find the repository for this article over here

https://github.com/rahulbanerjee26/Azure_Tutorials/tree/main/Azure_MLS


You will need a Microsoft Azure account for this tutorial

.Create your Azure free account today | Microsoft Azure

Setup Virtual Environment

pip install virtualenv /* Install virtual environment */
virtualenv venv /* Create a virtual environment */
venv/Scripts/activate /* Activate the virtual environment */

Create your Model

For this tutorial, we won’t be creating a fancy model, we will be creating a simple KNN model to use on the iris dataset provided by the sklearn library

Import Libraries

import pandas as pd
from sklearn.preprocessing import MinMaxScaler
from sklearn.datasets import load_iris
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
import joblib
import pickle

Load Dataset

data = load_iris()
df = pd.DataFrame(data.data , columns = data.feature_names)
print("Loaded Data Frame")
scaler = MinMaxScaler()
df = scaler.fit_transform(df)
X_train , X_test, y_train, y_test = train_test_split(df , data.target , test_size = 0.2)
print("Created Train/Test Split")
  • Since we are using a KNN, which uses Euclid Distances, we will need to scale the data before using it
  • Then we will split the data into a test/training set

Create Model

train_score , test_score = [] , []
for k in range(1,50):
model = KNeighborsClassifier(n_neighbors = k)
model.fit(X_train , y_train)
test_score.append(model.score(X_test , y_test))
train_score.append(model.score(X_train, y_train))
  • Chose an appropriate value for k based on the values in train and test scores

After you have selected a value for k, try predicting with your own input values

print ( model.predict(scaler.fit_transform([[1,1,1,1]]))[0])

Save the Model

# To dump
f = 'model/knn.pkl'
with open(f, 'wb') as file:
pickle.dump(model, file)

# To load
loaded_model = joblib.load(f)

Make sure your model works as expected by predicting the classification for custom input

loaded_model.predict(scaler.fit_transform( [[2,0,2,10]]))

Now we will move on to the deployment

Azure ML Studio

We will be using the azureml sdk for Python for deployment, you can check our this resource by Microsoft for reference

Azure Machine Learning SDK for Python – Azure Machine Learning Python

Install Required Libraries

pip install azureml , azureml-core

Import the Libraries

from azureml.core import Workspace
from azureml.core.webservice import AciWebservice
from azureml.core.webservice import Webservice
from azureml.core.model import InferenceConfig
from azureml.core.environment import Environment
from azureml.core import Workspace
from azureml.core.model import Model
from azureml.core.conda_dependencies import CondaDependencies

If you get an error ‘ azureml has no module .core’ or ‘Module azureml.core not found’, try installing the following library

pip install azureml.core

If you are using Python3.9+ use ` — ignore-requires-python` when installing the packages.


Create Workspace

We can either create the workspace manually on Azure or use Python to create it. If you create it manually, access the workspace and download the config.json file. Below is how you can create it in Python

ws = Workspace.create(
               name='myworkspace',            
               subscription_id='<azure-subscription-id>',           
               resource_group='myresourcegroup',                 
               create_resource_group=True,                 
               location='eastus2'                
               )
  • name: The name of your workspace
  • subscription_id: Your Azure Subscription ID
  • resource_group: The name of your resource Group
  • Set the create_resource_group to True if you want to create a new resource group. If you want to use an existing resource group, set it to False
  • Set the location

Once it is created, save the details of the workspace in a config.json file to use the workspace later.

ws.write_config()

Create a folder named ‘.azureml’ and save the json file inside it. Make sure you name the folder and json file correctly. Python will look for the config.json file inside this folder while loading up your workspace

You won’t need to create a workspace every time, in the future, you can use the following command to load the workspace

ws = Workspace.from_config()

Register the Model

We will use the pickle file we created earlier to register our model.

model = Model.register(workspace = ws,
              model_path ="model/knn.pkl",
              model_name = "knn",
              tags = {"version": "1"},
              description = "Iris classification",
              )
  • workspace: The workspace object we created
  • model_path: the path to the pickle file
  • model_name: Name of the model on Azure MLS
  • tags: Although not necessary, you can add tags to your model
  • description: A description of your model

Create an Environment

We will need to create an environment similar to our local virtual environment

# to install required packages
env = Environment('env')
cd = CondaDependencies.create(pip_packages=['pandas==1.1.5', 'azureml-defaults','joblib==0.17.0'], conda_packages = ['scikit-learn==0.23.2'])
env.python.conda_dependencies = cd
# Register environment to re-use later
env.register(workspace = ws)
print("Registered Environment")
  • You can pass the name as a parameter to the Environment Instance
  • Add dependencies as needed
  • Register the environment so it can be used later on
myenv = Environment.get(workspace=ws, name="env")

This get’s the environment you just created.

Confirm that all the required libraries have been installed by creating a .yml based on the created environment. Ensure all the libraries are mentioned inside the .yml file

myenv.save_to_directory('./environ', overwrite=True)

This will create a new folder called environ with a .yml and a .json file inside it


Config Objects

aciconfig = AciWebservice.deploy_configuration(
            cpu_cores=1,
            memory_gb=1,
            tags={"data":"iris classifier"},
            description='iRIS cLASSIFICATION knn MODEL',
            )

Create a container instance and set the number of cpu_cores and memory_gb based on your requirements.

inference_config = InferenceConfig(entry_script="score.py", environment=myenv)

Create and InferenceConfig instance to link your environment and entry script. We will be creating an entry script below. The entry_script parameter should be set to the path to entry scrip.


Entry Script

The entry script will two functions, an init function and a run function.

def init():
    global modelmodel_path = Model.get_model_path("knn")
    print("Model Path is  ", model_path)
    model = joblib.load(model_path)
  • Create a global variable called model
  • Load the model using the name of the model you registered earlier
  • Load the model from the path
def run(data):
   try:
     data = json.loads(data)
     result = model.predict(data['data'])
     return {'data' : result.tolist() , 'message' : "Successfully 
            classified Iris"}
   except Exception as e:
      error = str(e)
      return {'data' : error , 'message' : 'Failed to classify 
             iris'}

Save this file.


Deploy the Model

service = Model.deploy(workspace=ws,
                name='iris-model',
                models=[model],
                inference_config=inference_config,
                deployment_config=aciconfig, 
                overwrite = True)
service.wait_for_deployment(show_output=True)
url = service.scoring_uri
print(url)

Finally, we will deploy the model by combining our config objects, workspace and model together. Deployment usually takes a few minutes.

If your deployment is successful, the rest endpoint will be printed out. If it is unsuccessful, you can access the deployment logs

from azureml.core import Webservice
service = Webservice(ws,'iris-model-deployment')
print(service.get_logs())

Check the conclusion section for some things to keep in mind while deploying.

Consume the Endpoint

import requests
data = {
    'data': scaler.fit_transform([[0.9,0.1,0.1,0.9]]).tolist()
    }
headers = {'Content-Type':'application/json'}
r = requests.post(url, str.encode(json.dumps(data)), headers = headers)
print(r.status_code)
print(r.json())

We will use the requests library to make a request to the endpoint.

Conclusion

  • If you get an error related to Buffer Mismatch while deploying, ensure that your pkl file is created using a 64-bit Python
  • If you get any error related to ‘Module not found’, check the .yml file generated for your environment and ensure that all required libraries are present
  • If needed, specify the version of the library to be installed
  • Try running your score.py file locally to ensure there are no syntax errors. You can also invoke the init and the run function to make a prediction. To run it locally, create a workspace object from your config.json file and while accessing the model pass the workspace as a parameter
model_path = Model.get_model_path("knn" , workspace = ws)

Let me know if you face any errors and I will try to help you out based on my experience 🙂