Skip to content

Commit b1a6afb

Browse files
authored
Merge pull request #115475 from luisquintanilla/AB1716392-v2
Responsible ML | HE How-To Updated
2 parents c7e6dba + 454826d commit b1a6afb

File tree

2 files changed

+328
-0
lines changed

2 files changed

+328
-0
lines changed
Lines changed: 325 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,325 @@
1+
---
2+
title: Deploy an encrypted inferencing 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/18/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 data
13+
---
14+
15+
# How to deploy an encrypted inferencing web service
16+
17+
Learn how to deploy an image classification model as an encrypted inferencing web service in [Azure Container Instances](https://docs.microsoft.com/azure/container-instances/) (ACI). The web service is a Docker container image that contains the model and scoring logic.
18+
19+
In this guide, you use Azure Machine Learning service to:
20+
21+
> [!div class="checklist"]
22+
> * Configure your environments
23+
> * Deploy encrypted inferencing web service
24+
> * Prepare test data
25+
> * Make encrypted predictions
26+
> * Clean up resources
27+
28+
ACI is a great solution for testing and understanding the model deployment 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).
29+
30+
The encryption method used in this sample is [homomorphic encryption](https://github.com/Microsoft/SEAL#homomorphic-encryption). Homomorphic encryption allows for computations to be done on encrypted data without requiring access to a secret (decryption) key. The results of the computations are encrypted and can be revealed only by the owner of the secret key.
31+
32+
## Prerequisites
33+
34+
This guide assumes that you have an image classification model registered in Azure Machine Learning. If not, register the model using a [pretrained model](https://github.com/Azure/MachineLearningNotebooks/raw/master/tutorials/image-classification-mnist-data/sklearn_mnist_model.pkl) or create your own by completing the [train an image classification model with Azure Machine Learning tutorial](tutorial-train-models-with-aml.md).
35+
36+
## Configure local environment
37+
38+
In a Jupyter notebook
39+
40+
1. Import the Python packages needed for this sample.
41+
42+
```python
43+
%matplotlib inline
44+
import numpy as np
45+
import matplotlib.pyplot as plt
46+
47+
import azureml.core
48+
49+
# display the core SDK version number
50+
print("Azure ML SDK Version: ", azureml.core.VERSION)
51+
```
52+
53+
2. Install homomorphic encryption library for secure inferencing.
54+
55+
> [!NOTE]
56+
> The `encrypted-inference` package is currently in preview.
57+
58+
[`encrypted-inference`](https://pypi.org/project/encrypted-inference) is a library that contains bindings for encrypted inferencing based on [Microsoft SEAL](https://github.com/Microsoft/SEAL).
59+
60+
```python
61+
!pip install encrypted-inference==0.9
62+
```
63+
64+
## Configure the inferencing environment
65+
66+
Create an environment for inferencing and add `encrypted-inference` package as a conda dependency.
67+
68+
```python
69+
from azureml.core.environment import Environment
70+
from azureml.core.conda_dependencies import CondaDependencies
71+
72+
# to install required packages
73+
env = Environment('tutorial-env')
74+
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'])
75+
76+
env.python.conda_dependencies = cd
77+
78+
# Register environment to re-use later
79+
env.register(workspace = ws)
80+
```
81+
82+
## Deploy encrypted inferencing web service
83+
84+
Deploy the model as a web service hosted in ACI.
85+
86+
To build the correct environment for ACI, provide the following:
87+
88+
* A scoring script to show how to use the model
89+
* A configuration file to build the ACI
90+
* A trained model
91+
92+
### Create scoring script
93+
94+
Create the scoring script `score.py` used by the web service for inferencing.
95+
96+
You must include two required functions into the scoring script:
97+
98+
* The `init()` function, which typically loads the model into a global object. This function is run only once when the Docker container is started.
99+
* 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.
100+
101+
```python
102+
%%writefile score.py
103+
import json
104+
import os
105+
import pickle
106+
import joblib
107+
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, PublicAccess
108+
from encrypted.inference.eiserver import EIServer
109+
110+
def init():
111+
global model
112+
# AZUREML_MODEL_DIR is an environment variable created during deployment.
113+
# It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
114+
# For multiple models, it points to the folder containing all deployed models (./azureml-models)
115+
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_mnist_model.pkl')
116+
model = joblib.load(model_path)
117+
118+
global server
119+
server = EIServer(model.coef_, model.intercept_, verbose=True)
120+
121+
def run(raw_data):
122+
123+
json_properties = json.loads(raw_data)
124+
125+
key_id = json_properties['key_id']
126+
conn_str = json_properties['conn_str']
127+
container = json_properties['container']
128+
data = json_properties['data']
129+
130+
# download the public keys from blob storage
131+
blob_service_client = BlobServiceClient.from_connection_string(conn_str=conn_str)
132+
blob_client = blob_service_client.get_blob_client(container=container, blob=key_id)
133+
public_keys = blob_client.download_blob().readall()
134+
135+
result = {}
136+
# make prediction
137+
result = server.predict(data, public_keys)
138+
139+
# you can return any data type as long as it is JSON-serializable
140+
return result
141+
```
142+
143+
### Create configuration file
144+
145+
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.
146+
147+
```python
148+
from azureml.core.webservice import AciWebservice
149+
150+
aciconfig = AciWebservice.deploy_configuration(cpu_cores=1,
151+
memory_gb=1,
152+
tags={"data": "MNIST", "method" : "sklearn"},
153+
description='Encrypted Predict MNIST with sklearn + SEAL')
154+
```
155+
156+
### Deploy to Azure Container Instances
157+
158+
Estimated time to complete: **about 2-5 minutes**
159+
160+
Configure the image and deploy. The following code goes through these steps:
161+
162+
1. Create environment object containing dependencies needed by the model using the environment file (`myenv.yml`)
163+
1. Create inference configuration necessary to deploy the model as a web service using:
164+
* The scoring file (`score.py`)
165+
* Environment object created in the previous step
166+
1. Deploy the model to the ACI container.
167+
1. Get the web service HTTP endpoint.
168+
169+
```python
170+
%%time
171+
from azureml.core.webservice import Webservice
172+
from azureml.core.model import InferenceConfig
173+
from azureml.core.environment import Environment
174+
from azureml.core import Workspace
175+
from azureml.core.model import Model
176+
177+
ws = Workspace.from_config()
178+
model = Model(ws, 'sklearn_mnist')
179+
180+
myenv = Environment.get(workspace=ws, name="tutorial-env")
181+
inference_config = InferenceConfig(entry_script="score.py", environment=myenv)
182+
183+
service = Model.deploy(workspace=ws,
184+
name='sklearn-encrypted-mnist-svc',
185+
models=[model],
186+
inference_config=inference_config,
187+
deployment_config=aciconfig)
188+
189+
service.wait_for_deployment(show_output=True)
190+
```
191+
192+
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.
193+
194+
```python
195+
print(service.scoring_uri)
196+
```
197+
198+
## Prepare test data
199+
200+
1. Download the test data. In this case, it's saved into a directory called *data*.
201+
202+
```python
203+
import os
204+
from azureml.core import Dataset
205+
from azureml.opendatasets import MNIST
206+
207+
data_folder = os.path.join(os.getcwd(), 'data')
208+
os.makedirs(data_folder, exist_ok=True)
209+
210+
mnist_file_dataset = MNIST.get_file_dataset()
211+
mnist_file_dataset.download(data_folder, overwrite=True)
212+
```
213+
214+
1. Load the test data from the *data* directory.
215+
216+
```python
217+
from utils import load_data
218+
import os
219+
import glob
220+
221+
data_folder = os.path.join(os.getcwd(), 'data')
222+
# note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the neural network converge faster
223+
X_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-images-idx3-ubyte.gz"), recursive=True)[0], False) / 255.0
224+
y_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-labels-idx1-ubyte.gz"), recursive=True)[0], True).reshape(-1)
225+
```
226+
227+
## Make encrypted predictions
228+
229+
Use the test dataset with the model to get predictions.
230+
231+
To make encrypted predictions:
232+
233+
1. Create a new `EILinearRegressionClient`, a homomorphic encryption based client, and public keys.
234+
235+
```python
236+
from encrypted.inference.eiclient import EILinearRegressionClient
237+
238+
# Create a new Encrypted inference client and a new secret key.
239+
edp = EILinearRegressionClient(verbose=True)
240+
241+
public_keys_blob, public_keys_data = edp.get_public_keys()
242+
```
243+
244+
1. Upload homomorphic encryption generated public keys to the workspace default blob store. This will allow you to share the keys with the inference server.
245+
246+
```python
247+
import azureml.core
248+
from azureml.core import Workspace, Datastore
249+
import os
250+
251+
ws = Workspace.from_config()
252+
253+
datastore = ws.get_default_datastore()
254+
container_name=datastore.container_name
255+
256+
# Create a local file and write the keys to it
257+
public_keys = open(public_keys_blob, "wb")
258+
public_keys.write(public_keys_data)
259+
public_keys.close()
260+
261+
# Upload the file to blob store
262+
datastore.upload_files([public_keys_blob])
263+
264+
# Delete the local file
265+
os.remove(public_keys_blob)
266+
```
267+
268+
1. Encrypt the test data
269+
270+
```python
271+
#choose any one sample from the test data
272+
sample_index = 1
273+
274+
#encrypt the data
275+
raw_data = edp.encrypt(X_test[sample_index])
276+
277+
```
278+
279+
1. Use the SDK's `run` API to invoke the service and provide 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.
280+
281+
```python
282+
import json
283+
from azureml.core import Webservice
284+
285+
service = Webservice(ws, 'sklearn-encrypted-mnist-svc')
286+
287+
#pass the connection string for blob storage to give the server access to the uploaded public keys
288+
conn_str_template = 'DefaultEndpointsProtocol={};AccountName={};AccountKey={};EndpointSuffix=core.windows.net'
289+
conn_str = conn_str_template.format(datastore.protocol, datastore.account_name, datastore.account_key)
290+
291+
#build the json
292+
data = json.dumps({"data": raw_data, "key_id" : public_keys_blob, "conn_str" : conn_str, "container" : container_name })
293+
data = bytes(data, encoding='ASCII')
294+
295+
print ('Making an encrypted inference web service call ')
296+
eresult = service.run(input_data=data)
297+
298+
print ('Received encrypted inference results')
299+
```
300+
301+
1. Use the client to decrypt the results.
302+
303+
```python
304+
import numpy as np
305+
306+
results = edp.decrypt(eresult)
307+
308+
print ('Decrypted the results ', results)
309+
310+
#Apply argmax to identify the prediction result
311+
prediction = np.argmax(results)
312+
313+
print ( ' Prediction : ', prediction)
314+
print ( ' Actual Label : ', y_test[sample_index])
315+
```
316+
317+
## Clean up resources
318+
319+
Delete the web service created in this sample:
320+
321+
```python
322+
service.delete()
323+
```
324+
325+
If you no longer plan to use the Azure resources you’ve created, delete them. This prevents you from being charged for unutilized resources that are still running. See this guide on how to [clean up resources](how-to-manage-workspace.md#clean-up-resources) to learn more.

articles/machine-learning/toc.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@
376376
href: how-to-monitor-data-drift.md
377377
- name: Monitor with Application Insights
378378
href: how-to-enable-app-insights.md
379+
- name: Deploy encrypted inferencing service
380+
displayName: homomorhic,encryption,deployment
381+
href: how-to-homomorphic-encryption-seal.md
379382

380383
- name: Build & use ML pipelines
381384
displayName: pipelines

0 commit comments

Comments
 (0)