#!/usr/bin/env python # coding: utf-8 # ## Index # # 1. [Load workspace](#Load-workspace) # 2. [Retrieve the model](#Retrieve-the-model) # 3. [Deploy as web service](#Deploy-as-web-service) # - [Create scoring script](#Create-scoring-script) # - [Create environment file](#Create-environment-file) # - [Create configuration file](#Create-configuration-file) # - [Deploy in ACI](#Deploy-in-ACI) # - [Test deployed service](#Test-deployed-service) # 4. [Clean up a web service](#Clean-up-a-web-service) # # First of all, we should change the Azure Storage version to **0.30.0** so as to use the module `BlockBlobService` to create the web service and deploy the model. # # **_Note_**: Restart the kernel after updating the package. # In[1]: # should restart the kernel each time update the package # update azure storage (change version) in order to use BlockBlobService get_ipython().system('pip install azure-storage==0.30.0') # In[1]: import os import numpy as np import pandas as pd import azureml from azureml.core import Workspace, Run from azureml.core.model import Model # check core SDK version number print("Azure ML SDK Version: ", azureml.core.VERSION) # ## Load workspace # In[2]: # load workspace configuration from the config.json file in the current folder. ws = Workspace.from_config() print(ws.name, ws.location, ws.resource_group, ws.location, sep = '\t') # ## Retrieve the model # # We have registered the model in our workspace. Now, we should retrieve it. # # _**Note**_ : Once we download the model on local, we don't have to run the cell below anymore. # In[3]: model = Model(ws, 'nyc_taxi_model') # If the model has already been downloaded, we don't have to do this step. model.download(target_dir = '.') # verify the downloaded model file os.stat('./nyc_taxi_model.pkl') # ## Deploy as web service # # Once we've tested the model and are satisfied with the results, we can deploy the model as a web service. # ### Create scoring script # # Create the scoring script, called `score.py`, used by the web service call to show how to use the model. # # We must include two required functions into the scoring script: # # - The `init()` function, which typically loads the model into a global object. This function is run only once when the Docker container is started. # # - The `run(input_data)` function uses the model to predict a value based on the input data. Inputs and outputs to the run typically use JSON for serialization and de-serialization, but other formats are supported. # In[4]: get_ipython().run_cell_magic('writefile', 'score.py', "\nimport os\nimport json\nimport pickle\nimport numpy as np\n\nfrom sklearn.externals import joblib\nfrom sklearn.linear_model import LinearRegression\n\nfrom azureml.core.model import Model\n\ndef init():\n global model\n # retreive the path to the model file using the model name\n model_path = Model.get_model_path('nyc_taxi_model')\n model = joblib.load(model_path)\n\ndef run(raw_data):\n data = np.array(json.loads(raw_data)['data'])\n # make prediction\n y_hat = model.predict(data)\n return json.dumps(y_hat.tolist())\n") # ### Create environment file # # Next, create an environment file, called myenv.yml, that specifies all of the script's package dependencies. This file is used to ensure that all of those dependencies are installed in the Docker image. # In[5]: from azureml.core.conda_dependencies import CondaDependencies myenv = CondaDependencies() myenv.add_conda_package("scikit-learn") myenv.add_conda_package("numpy") myenv.add_conda_package("pandas") myenv.add_pip_package("pynacl==1.2.1") with open("myenv.yml","w") as f: f.write(myenv.serialize_to_string()) # Review the content of the `myenv.yml` file. # In[6]: with open("myenv.yml","r") as f: print(f.read()) # ### Create configuration file # # Create a deployment configuration file and specify the number of CPUs and gigabyte of RAM needed for our ACI container. While it depends on the model, the default of 1 core and 1 gigabyte of RAM is usually sufficient for many models. # In[8]: from azureml.core.webservice import AciWebservice aciconfig = AciWebservice.deploy_configuration(cpu_cores=1, memory_gb=1, tags={"data": "nyc-taxi-trip", "method" : "sklearn"}, description='NYC taxi trip duration prediction') # ### Deploy in ACI # # Configure the image and deploy. Normally, it will take 7-8 minutes to deploy the model. # In[10]: get_ipython().run_cell_magic('time', '', 'from azureml.core.webservice import Webservice\nfrom azureml.core.image import ContainerImage\n\n# configure the image\nimage_config = ContainerImage.image_configuration(execution_script="score.py", \n runtime="python", \n conda_file="myenv.yml")\n\nservice = Webservice.deploy_from_model(workspace=ws,\n name=\'nyc-taxi-dsvm\',\n deployment_config=aciconfig,\n models=[model],\n image_config=image_config)\n\nservice.wait_for_deployment(show_output=True)\n') # Get the scoring web service's HTTP endpoint, which accepts REST client calls. # # This endpoint can be shared with anyone who wants to test the web service or integrate it into an application. # In[11]: print(service.scoring_uri) # ### Test deployed service # # First of all, load the test sub-dataset. # In[13]: from sklearn import preprocessing pd_dataframe = pd.read_pickle("./data/sub_data_after_prep.pkl") y_test = np.array(pd_dataframe["trip_duration"]).astype(float) y_test = np.log(y_test) X_test = np.array(pd_dataframe.drop(["trip_duration"],axis = 1)) # normalize input scaler = preprocessing.StandardScaler().fit(X_test) X_test = scaler.transform(X_test) # Secondly, test the deployed model web service with test sub-dataset. # # With the first method, we can test a group of data. However, with the second method(HTTP request), we can only test one raw each time. # In[14]: import json from sklearn.metrics import mean_squared_error # find 30 random samples from test set n = 30 sample_indices = np.random.permutation(X_test.shape[0])[0:n] test_samples = json.dumps({"data": X_test[sample_indices].tolist()}) test_samples = bytes(test_samples, encoding = 'utf8') # predict using the deployed model y_pred = json.loads(service.run(input_data = test_samples)) mse = mean_squared_error(y_test[sample_indices], y_pred) print("Mean Squared Error for Linear Regression: {}".format(mse)) # We can also send raw HTTP request to test the web service. # In[15]: import requests import json from sklearn.metrics import mean_squared_error # send a random row from the test set to score random_index = np.random.randint(0, len(X_test)-1) input_data = "{\"data\": [" + str(list(X_test[random_index])) + "]}" headers = {'Content-Type':'application/json'} y_pred = requests.post(service.scoring_uri, input_data, headers = headers) print("POST to url", service.scoring_uri) #print("input data:", input_data) print("label:", y_test[random_index]) print("prediction:", y_pred.text) # ## Clean up a web service # In[16]: service.delete() # In[ ]: