Skip to content

Commit 96ff2a2

Browse files
Initial commit
1 parent 279f4e0 commit 96ff2a2

File tree

1 file changed

+395
-0
lines changed

1 file changed

+395
-0
lines changed
Lines changed: 395 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,395 @@
1+
---
2+
title: Deploy an encrypted image classification service
3+
titleSuffix: Azure Machine Learning
4+
description: Learn how to use Microsoft SEAL to deploy an encrypted prediction service for image classification
5+
author: luisquintanilla
6+
ms.author: luquinta
7+
ms.date: 05/14/2020
8+
services: machine-learning
9+
ms.service: machine-learning
10+
ms.subservice: core
11+
ms.topic: conceptual
12+
#intent: As a data scientist, I want to deploy a service that uses homomorphic encryption to make predictions on encrypted image data
13+
---
14+
15+
# Deploy an image classification model for encrypted inferencing in Azure Container Instance (ACI)
16+
17+
This tutorial is **a new addition to the two-part series**. In the [previous tutorial](img-classification-part1-training.ipynb), you trained machine learning models and then registered a model in your workspace on the cloud.
18+
19+
Now, you're ready to deploy the model as a encrypted inferencing web service in [Azure Container Instances](https://docs.microsoft.com/azure/container-instances/) (ACI). A web service is an image, in this case a Docker image, that encapsulates the scoring logic and the model itself.
20+
21+
In this part of the tutorial, you use Azure Machine Learning service (Preview) to:
22+
23+
> * Set up your testing environment
24+
> * Retrieve the model from your workspace
25+
> * Test the model locally
26+
> * Deploy the model to ACI
27+
> * Test the deployed model
28+
29+
ACI is a great solution for testing and understanding the workflow. For scalable production deployments, consider using Azure Kubernetes Service. For more information, see [how to deploy and where](https://docs.microsoft.com/azure/machine-learning/service/how-to-deploy-and-where).
30+
31+
32+
## Prerequisites
33+
34+
Complete the model training in the [Tutorial #1: Train an image classification model with Azure Machine Learning](train-models.ipynb) notebook.
35+
36+
37+
<!-- #endregion -->
38+
39+
```python
40+
# If you did NOT complete the tutorial, you can instead run this cell
41+
# This will register a model and download the data needed for this tutorial
42+
# These prerequisites are created in the training tutorial
43+
# Feel free to skip this cell if you completed the training tutorial
44+
45+
# register a model
46+
from azureml.core import Workspace
47+
ws = Workspace.from_config()
48+
49+
from azureml.core.model import Model
50+
51+
model_name = "sklearn_mnist"
52+
model = Model.register(model_path="sklearn_mnist_model.pkl",
53+
model_name=model_name,
54+
tags={"data": "mnist", "model": "classification"},
55+
description="Mnist handwriting recognition",
56+
workspace=ws)
57+
58+
59+
```
60+
61+
### Setup the Environment
62+
63+
Add `encrypted-inference` package as a conda dependency
64+
65+
```python
66+
from azureml.core.environment import Environment
67+
from azureml.core.conda_dependencies import CondaDependencies
68+
69+
# to install required packages
70+
env = Environment('tutorial-env')
71+
cd = CondaDependencies.create(pip_packages=['azureml-dataprep[pandas,fuse]>=1.1.14', 'azureml-defaults', 'azure-storage-blob', 'encrypted-inference==0.9'], conda_packages = ['scikit-learn==0.22.1'])
72+
73+
env.python.conda_dependencies = cd
74+
75+
# Register environment to re-use later
76+
env.register(workspace = ws)
77+
```
78+
79+
## Set up the environment
80+
81+
Start by setting up a testing environment.
82+
83+
### Import packages
84+
85+
Import the Python packages needed for this tutorial.
86+
87+
```python tags=["check version"]
88+
%matplotlib inline
89+
import numpy as np
90+
import matplotlib.pyplot as plt
91+
92+
import azureml.core
93+
94+
# display the core SDK version number
95+
print("Azure ML SDK Version: ", azureml.core.VERSION)
96+
```
97+
98+
#### Install Homomorphic Encryption based library for Secure Inferencing
99+
100+
Our library is based on [Microsoft SEAL](https://github.com/Microsoft/SEAL) and pubished to [PyPi.org](https://pypi.org/project/encrypted-inference) as an easy to use package
101+
102+
```python
103+
!pip install encrypted-inference==0.9
104+
```
105+
106+
## Deploy as web service
107+
108+
Deploy the model as a web service hosted in ACI.
109+
110+
To build the correct environment for ACI, provide the following:
111+
* A scoring script to show how to use the model
112+
* A configuration file to build the ACI
113+
* The model you trained before
114+
115+
### Create scoring script
116+
117+
Create the scoring script, called score.py, used by the web service call to show how to use the model.
118+
119+
You must include two required functions into the scoring script:
120+
* The `init()` function, which typically loads the model into a global object. This function is run only once when the Docker container is started.
121+
122+
* 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. The function fetches homomorphic encryption based public keys that are uploaded by the service caller.
123+
124+
125+
126+
```python
127+
%%writefile score.py
128+
import json
129+
import os
130+
import pickle
131+
import joblib
132+
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, PublicAccess
133+
from encrypted.inference.eiserver import EIServer
134+
135+
def init():
136+
global model
137+
# AZUREML_MODEL_DIR is an environment variable created during deployment.
138+
# It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
139+
# For multiple models, it points to the folder containing all deployed models (./azureml-models)
140+
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_mnist_model.pkl')
141+
model = joblib.load(model_path)
142+
143+
global server
144+
server = EIServer(model.coef_, model.intercept_, verbose=True)
145+
146+
def run(raw_data):
147+
148+
json_properties = json.loads(raw_data)
149+
150+
key_id = json_properties['key_id']
151+
conn_str = json_properties['conn_str']
152+
container = json_properties['container']
153+
data = json_properties['data']
154+
155+
# download the Galois keys from blob storage
156+
#TODO optimize by caching the keys locally
157+
blob_service_client = BlobServiceClient.from_connection_string(conn_str=conn_str)
158+
blob_client = blob_service_client.get_blob_client(container=container, blob=key_id)
159+
public_keys = blob_client.download_blob().readall()
160+
161+
result = {}
162+
# make prediction
163+
result = server.predict(data, public_keys)
164+
165+
# you can return any data type as long as it is JSON-serializable
166+
return result
167+
```
168+
169+
### Create configuration file
170+
171+
Create a deployment configuration file and specify the number of CPUs and gigabyte of RAM needed for your ACI container. While it depends on your model, the default of 1 core and 1 gigabyte of RAM is usually sufficient for many models. If you feel you need more later, you would have to recreate the image and redeploy the service.
172+
173+
```python tags=["configure web service", "aci"]
174+
from azureml.core.webservice import AciWebservice
175+
176+
aciconfig = AciWebservice.deploy_configuration(cpu_cores=1,
177+
memory_gb=1,
178+
tags={"data": "MNIST", "method" : "sklearn"},
179+
description='Encrypted Predict MNIST with sklearn + SEAL')
180+
```
181+
182+
### Deploy in ACI
183+
Estimated time to complete: **about 2-5 minutes**
184+
185+
Configure the image and deploy. The following code goes through these steps:
186+
187+
1. Create environment object containing dependencies needed by the model using the environment file (`myenv.yml`)
188+
1. Create inference configuration necessary to deploy the model as a web service using:
189+
* The scoring file (`score.py`)
190+
* envrionment object created in previous step
191+
1. Deploy the model to the ACI container.
192+
1. Get the web service HTTP endpoint.
193+
194+
```python tags=["configure image", "create image", "deploy web service", "aci"]
195+
%%time
196+
from azureml.core.webservice import Webservice
197+
from azureml.core.model import InferenceConfig
198+
from azureml.core.environment import Environment
199+
from azureml.core import Workspace
200+
from azureml.core.model import Model
201+
202+
ws = Workspace.from_config()
203+
model = Model(ws, 'sklearn_mnist')
204+
205+
myenv = Environment.get(workspace=ws, name="tutorial-env")
206+
inference_config = InferenceConfig(entry_script="score.py", environment=myenv)
207+
208+
service = Model.deploy(workspace=ws,
209+
name='sklearn-mnist-svc',
210+
models=[model],
211+
inference_config=inference_config,
212+
deployment_config=aciconfig)
213+
214+
service.wait_for_deployment(show_output=True)
215+
```
216+
217+
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.
218+
219+
```python tags=["get scoring uri"]
220+
print(service.scoring_uri)
221+
```
222+
223+
## Test the model
224+
225+
226+
227+
### Download test data
228+
Download the test data to the **./data/** directory
229+
230+
```python
231+
import os
232+
from azureml.core import Dataset
233+
from azureml.opendatasets import MNIST
234+
235+
data_folder = os.path.join(os.getcwd(), 'data')
236+
os.makedirs(data_folder, exist_ok=True)
237+
238+
mnist_file_dataset = MNIST.get_file_dataset()
239+
mnist_file_dataset.download(data_folder, overwrite=True)
240+
```
241+
242+
### Load test data
243+
244+
Load the test data from the **./data/** directory created during the training tutorial.
245+
246+
```python
247+
from utils import load_data
248+
import os
249+
import glob
250+
251+
data_folder = os.path.join(os.getcwd(), 'data')
252+
# note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the neural network converge faster
253+
X_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-images-idx3-ubyte.gz"), recursive=True)[0], False) / 255.0
254+
y_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-labels-idx1-ubyte.gz"), recursive=True)[0], True).reshape(-1)
255+
```
256+
257+
<!-- #region -->
258+
### Predict test data
259+
260+
Feed the test dataset to the model to get predictions.
261+
262+
263+
The following code goes through these steps:
264+
265+
1. Create our Homomorphic Encryption based client
266+
267+
1. Upload HE generated public keys
268+
269+
1. Encrypt the data
270+
271+
1. Send the data as JSON to the web service hosted in ACI.
272+
273+
1. Use the SDK's `run` API to invoke the service. You can also make raw calls using any HTTP tool such as curl.
274+
<!-- #endregion -->
275+
276+
#### Create our Homomorphic Encryption based client
277+
278+
Create a new EILinearRegressionClient and setup the public keys
279+
280+
```python
281+
from encrypted.inference.eiclient import EILinearRegressionClient
282+
283+
# Create a new Encrypted inference client and a new secret key.
284+
edp = EILinearRegressionClient(verbose=True)
285+
286+
public_keys_blob, public_keys_data = edp.get_public_keys()
287+
288+
```
289+
290+
#### Upload HE generated public keys
291+
292+
Upload the public keys to the workspace default blob store. This will allow us to share the keys with the inference server
293+
294+
```python
295+
import azureml.core
296+
from azureml.core import Workspace, Datastore
297+
import os
298+
299+
ws = Workspace.from_config()
300+
301+
datastore = ws.get_default_datastore()
302+
container_name=datastore.container_name
303+
304+
# Create a local file and write the keys to it
305+
public_keys = open(public_keys_blob, "wb")
306+
public_keys.write(public_keys_data)
307+
public_keys.close()
308+
309+
# Upload the file to blob store
310+
datastore.upload_files([public_keys_blob])
311+
312+
# Delete the local file
313+
os.remove(public_keys_blob)
314+
```
315+
316+
#### Encrypt the data
317+
318+
```python
319+
#choose any one sample from the test data
320+
sample_index = 1
321+
322+
#encrypt the data
323+
raw_data = edp.encrypt(X_test[sample_index])
324+
325+
```
326+
327+
#### Send the test data to the webservice hosted in ACI
328+
329+
Feed the test dataset to the model to get predictions. We will need to send the connection string to the blob storage where the public keys were uploaded
330+
331+
332+
```python
333+
import json
334+
from azureml.core import Webservice
335+
336+
service = Webservice(ws, 'sklearn-mnist-svc')
337+
338+
#pass the connection string for blob storage to give the server access to the uploaded public keys
339+
conn_str_template = 'DefaultEndpointsProtocol={};AccountName={};AccountKey={};EndpointSuffix=core.windows.net'
340+
conn_str = conn_str_template.format(datastore.protocol, datastore.account_name, datastore.account_key)
341+
342+
#build the json
343+
data = json.dumps({"data": raw_data, "key_id" : public_keys_blob, "conn_str" : conn_str, "container" : container_name })
344+
data = bytes(data, encoding='ASCII')
345+
346+
print ('Making an encrypted inference web service call ')
347+
eresult = service.run(input_data=data)
348+
349+
print ('Received encrypted inference results')
350+
```
351+
352+
#### Decrypt the data
353+
354+
Use the client to decrypt the results
355+
356+
```python
357+
import numpy as np
358+
359+
results = edp.decrypt(eresult)
360+
361+
print ('Decrypted the results ', results)
362+
363+
#Apply argmax to identify the prediction result
364+
prediction = np.argmax(results)
365+
366+
print ( ' Prediction : ', prediction)
367+
print ( ' Actual Label : ', y_test[sample_index])
368+
```
369+
370+
## Clean up resources
371+
372+
To keep the resource group and workspace for other tutorials and exploration, you can delete only the ACI deployment using this API call:
373+
374+
```python tags=["delete web service"]
375+
service.delete()
376+
```
377+
378+
<!-- #region -->
379+
380+
If you're not going to use what you've created here, delete the resources you just created with this quickstart so you don't incur any charges. In the Azure portal, select and delete your resource group. You can also keep the resource group, but delete a single workspace by displaying the workspace properties and selecting the Delete button.
381+
382+
## Next steps
383+
384+
In this Azure Machine Learning tutorial, you used Python to:
385+
386+
> * Set up your testing environment
387+
> * Retrieve the model from your workspace
388+
> * Test the model locally
389+
> * Deploy the model to ACI
390+
> * Test the deployed model
391+
392+
You can also try out the [regression tutorial](regression-part1-data-prep.ipynb).
393+
<!-- #endregion -->
394+
395+
![Impressions](https://PixelServer20190423114238.azurewebsites.net/api/impressions/MachineLearningNotebooks/tutorials/img-classification-part2-deploy.png)

0 commit comments

Comments
 (0)