如何部署加密推理 Web 服务(预览版)
了解如何在 Azure 容器实例 (ACI) 中将映像分类模型部署为加密推理 Web 服务。 Web 服务是包含模型和评分逻辑的 Docker 容器映像。
在本指南中,将使用 Azure 机器学习服务执行以下操作:
- 配置环境
- 部署加密推理 Web 服务
- 准备测试数据
- 作出加密预测
- 清理资源
ACI 是用于测试和了解模型部署工作流的绝佳解决方案。 对于可缩放的生产部署,请考虑使用 Azure Kubernetes 服务。 有关详细信息,请参阅部署方式及位置。
本示例中使用的加密方法是同态加密。 使用同态加密,无需访问机密(解密)密钥即可对加密数据进行计算。 计算的结果已加密,只能由密钥的所有者公开。
先决条件
本指南默认你已在 Azure 机器学习中注册映像分类模型。 如果尚未注册,请使用预训练模型注册该模型或通过完成通过 Azure 机器学习教程训练映像分类模型来创建自己的模型。
配置本地环境
在 Jupyter 笔记本中
导入此示例所需的 Python 包。
%matplotlib inline import numpy as np import matplotlib.pyplot as plt import azureml.core # display the core SDK version number print("Azure ML SDK Version: ", azureml.core.VERSION)
安装同态加密库以进行安全推理。
注意
encrypted-inference
包目前处于预览阶段。encrypted-inference
是一个库,其中包含基于 Microsoft SEAL 的加密推理的绑定。!pip install encrypted-inference==0.9
配置推理环境
创建推理环境并将 encrypted-inference
包添加为 conda 依赖项。
from azureml.core.environment import Environment
from azureml.core.conda_dependencies import CondaDependencies
# to install required packages
env = Environment('tutorial-env')
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'])
env.python.conda_dependencies = cd
# Register environment to re-use later
env.register(workspace = ws)
部署加密推理 Web 服务
将该模型部署为在 ACI 中托管的 Web 服务。
要为 ACI 构建正确的环境,请提供以下信息:
- 显示如何使用模型的评分脚本
- 要生成 ACI 的配置文件
- 一个已训练模型
创建评分脚本
创建推理 Web 服务使用的评分脚本 score.py
。
必须在评分脚本中包含两个必需的函数:
init()
函数,它通常将模型加载到全局对象中。 此函数只能在 Docker 容器启动时运行一次。run(input_data)
函数,它使用模型来基于输入数据预测值。 运行的输入和输出通常使用 JSON 进行序列化和反序列化,但支持其他格式。 该函数将获取服务调用方上传的基于同态加密的公钥。
%%writefile score.py
import json
import os
import pickle
import joblib
from azure.storage.blob import BlobServiceClient, BlobClient, ContainerClient, PublicAccess
from encrypted.inference.eiserver import EIServer
def init():
global model
# AZUREML_MODEL_DIR is an environment variable created during deployment.
# It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)
# For multiple models, it points to the folder containing all deployed models (./azureml-models)
model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_mnist_model.pkl')
model = joblib.load(model_path)
global server
server = EIServer(model.coef_, model.intercept_, verbose=True)
def run(raw_data):
json_properties = json.loads(raw_data)
key_id = json_properties['key_id']
conn_str = json_properties['conn_str']
container = json_properties['container']
data = json_properties['data']
# download the public keys from blob storage
blob_service_client = BlobServiceClient.from_connection_string(conn_str=conn_str)
blob_client = blob_service_client.get_blob_client(container=container, blob=key_id)
public_keys = blob_client.download_blob().readall()
result = {}
# make prediction
result = server.predict(data, public_keys)
# you can return any data type as long as it is JSON-serializable
return result
创建配置文件
创建部署配置文件并指定 ACI 容器所需的 CPU 数量和 RAM 大小(单位为 GB)。 虽然这取决于具体模型,但对于许多模型而言,默认的 1 核和 1 GB 的 RAM 通常已足够。 如果你认为以后需要更多核心或 RAM,请重新创建映像并重新部署服务。
from azureml.core.webservice import AciWebservice
aciconfig = AciWebservice.deploy_configuration(cpu_cores=1,
memory_gb=1,
tags={"data": "MNIST", "method" : "sklearn"},
description='Encrypted Predict MNIST with sklearn + SEAL')
部署到 Azure 容器实例
估计完成时间:约 2-5 分钟
配置映像和部署。 下面的代码将完成这些步骤:
- 使用环境文件 (
myenv.yml
) 创建包含模型所需依赖项的环境对象 - 使用以下项创建将模型部署为 Web 服务所需的推理配置:
- 评分文件 (
score.py
) - 在上一步中创建的环境对象
- 评分文件 (
- 将模型部署到 ACI 容器。
- 获取 Web 服务 HTTP 终结点。
%%time
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
ws = Workspace.from_config()
model = Model(ws, 'sklearn_mnist')
myenv = Environment.get(workspace=ws, name="tutorial-env")
inference_config = InferenceConfig(entry_script="score.py", environment=myenv)
service = Model.deploy(workspace=ws,
name='sklearn-encrypted-mnist-svc',
models=[model],
inference_config=inference_config,
deployment_config=aciconfig)
service.wait_for_deployment(show_output=True)
获取评分 Web 服务的 HTTP 终结点,该终结点接受 REST 客户端调用。 可以与想要测试 Web 服务或要将其集成到应用程序中的任何人共享此终结点。
print(service.scoring_uri)
准备测试数据
下载测试数据。 在本例中,它会保存到名为“data”的目录中。
import os from azureml.core import Dataset from azureml.opendatasets import MNIST data_folder = os.path.join(os.getcwd(), 'data') os.makedirs(data_folder, exist_ok=True) mnist_file_dataset = MNIST.get_file_dataset() mnist_file_dataset.download(data_folder, overwrite=True)
从“data”目录加载测试数据。
from utils import load_data import os import glob data_folder = os.path.join(os.getcwd(), 'data') # note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the neural network converge faster X_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-images-idx3-ubyte.gz"), recursive=True)[0], False) / 255.0 y_test = load_data(glob.glob(os.path.join(data_folder,"**/t10k-labels-idx1-ubyte.gz"), recursive=True)[0], True).reshape(-1)
作出加密预测
将测试数据集提供给模型以获得预测。
作出加密预测:
创建一个新的
EILinearRegressionClient
(基于同态加密的客户端)和公钥。from encrypted.inference.eiclient import EILinearRegressionClient # Create a new Encrypted inference client and a new secret key. edp = EILinearRegressionClient(verbose=True) public_keys_blob, public_keys_data = edp.get_public_keys()
将同态加密生成的公钥上传到工作区的默认 Blob 存储。 这将允许你与推理服务器共享密钥。
import azureml.core from azureml.core import Workspace, Datastore import os ws = Workspace.from_config() datastore = ws.get_default_datastore() container_name=datastore.container_name # Create a local file and write the keys to it public_keys = open(public_keys_blob, "wb") public_keys.write(public_keys_data) public_keys.close() # Upload the file to blob store datastore.upload_files([public_keys_blob]) # Delete the local file os.remove(public_keys_blob)
加密测试数据
#choose any one sample from the test data sample_index = 1 #encrypt the data raw_data = edp.encrypt(X_test[sample_index])
使用 SDK 的
run
API 调用服务,并向模型提供测试数据集以获取预测。 我们需要将连接字符串发送到已上传公钥的 Blob 存储。import json from azureml.core import Webservice service = Webservice(ws, 'sklearn-encrypted-mnist-svc') #pass the connection string for blob storage to give the server access to the uploaded public keys conn_str_template = 'DefaultEndpointsProtocol={};AccountName={};AccountKey={};EndpointSuffix=core.chinacloudapi.cn' conn_str = conn_str_template.format(datastore.protocol, datastore.account_name, datastore.account_key) #build the json data = json.dumps({"data": raw_data, "key_id" : public_keys_blob, "conn_str" : conn_str, "container" : container_name }) data = bytes(data, encoding='ASCII') print ('Making an encrypted inference web service call ') eresult = service.run(input_data=data) print ('Received encrypted inference results')
使用客户端解密结果。
import numpy as np results = edp.decrypt(eresult) print ('Decrypted the results ', results) #Apply argmax to identify the prediction result prediction = np.argmax(results) print ( ' Prediction : ', prediction) print ( ' Actual Label : ', y_test[sample_index])
清理资源
删除在本示例中创建的 Web 服务:
service.delete()
如果不再打算使用你已创建的 Azure 资源,请将其删除。 这可避免对仍在运行中但未使用的资源付费。 有关详细信息,请参阅有关如何清理资源的指南。