mirror of
https://github.com/Azure/MachineLearningNotebooks.git
synced 2025-12-19 17:17:04 -05:00
354 lines
12 KiB
Plaintext
354 lines
12 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Copyright (c) Microsoft Corporation. All rights reserved.\n",
|
|
"\n",
|
|
"Licensed under the MIT License."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
""
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Deploying a web service to Azure Kubernetes Service (AKS)\n",
|
|
"This notebook shows the steps for deploying a service: registering a model, provisioning a cluster with ssl (one time action), and deploying a service to it. \n",
|
|
"We then test and delete the service, image and model."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core import Workspace\n",
|
|
"from azureml.core.compute import AksCompute, ComputeTarget\n",
|
|
"from azureml.core.webservice import Webservice, AksWebservice\n",
|
|
"from azureml.core.model import Model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import azureml.core\n",
|
|
"print(azureml.core.VERSION)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Get workspace\n",
|
|
"Load existing workspace from the config file info."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core.workspace import Workspace\n",
|
|
"\n",
|
|
"ws = Workspace.from_config()\n",
|
|
"print(ws.name, ws.resource_group, ws.location, ws.subscription_id, sep = '\\n')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Register the model\n",
|
|
"Register an existing trained model, add descirption and tags."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#Register the model\n",
|
|
"from azureml.core.model import Model\n",
|
|
"model = Model.register(model_path = \"sklearn_regression_model.pkl\", # this points to a local file\n",
|
|
" model_name = \"sklearn_model\", # this is the name the model is registered as\n",
|
|
" tags = {'area': \"diabetes\", 'type': \"regression\"},\n",
|
|
" description = \"Ridge regression model to predict diabetes\",\n",
|
|
" workspace = ws)\n",
|
|
"\n",
|
|
"print(model.name, model.description, model.version)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Create the Environment\n",
|
|
"Create an environment that the model will be deployed with"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core import Environment\n",
|
|
"from azureml.core.conda_dependencies import CondaDependencies \n",
|
|
"\n",
|
|
"conda_deps = CondaDependencies.create(conda_packages=['numpy', 'scikit-learn==0.19.1', 'scipy'], pip_packages=['azureml-defaults', 'inference-schema'])\n",
|
|
"myenv = Environment(name='myenv')\n",
|
|
"myenv.python.conda_dependencies = conda_deps"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"#### Use a custom Docker image\n",
|
|
"\n",
|
|
"You can also specify a custom Docker image to be used as base image if you don't want to use the default base image provided by Azure ML. Please make sure the custom Docker image has Ubuntu >= 16.04, Conda >= 4.5.\\* and Python(3.5.\\* or 3.6.\\*).\n",
|
|
"\n",
|
|
"Only supported with `python` runtime.\n",
|
|
"```python\n",
|
|
"# use an image available in public Container Registry without authentication\n",
|
|
"myenv.docker.base_image = \"mcr.microsoft.com/azureml/o16n-sample-user-base/ubuntu-miniconda\"\n",
|
|
"\n",
|
|
"# or, use an image available in a private Container Registry\n",
|
|
"myenv.docker.base_image = \"myregistry.azurecr.io/mycustomimage:1.0\"\n",
|
|
"myenv.docker.base_image_registry.address = \"myregistry.azurecr.io\"\n",
|
|
"myenv.docker.base_image_registry.username = \"username\"\n",
|
|
"myenv.docker.base_image_registry.password = \"password\"\n",
|
|
"```"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Write the Entry Script\n",
|
|
"Write the script that will be used to predict on your model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%writefile score_ssl.py\n",
|
|
"import os\n",
|
|
"import pickle\n",
|
|
"import json\n",
|
|
"import numpy\n",
|
|
"from sklearn.externals import joblib\n",
|
|
"from sklearn.linear_model import Ridge\n",
|
|
"from inference_schema.schema_decorators import input_schema, output_schema\n",
|
|
"from inference_schema.parameter_types.standard_py_parameter_type import StandardPythonParameterType\n",
|
|
"\n",
|
|
"def init():\n",
|
|
" global model\n",
|
|
" # AZUREML_MODEL_DIR is an environment variable created during deployment.\n",
|
|
" # It is the path to the model folder (./azureml-models/$MODEL_NAME/$VERSION)\n",
|
|
" # For multiple models, it points to the folder containing all deployed models (./azureml-models)\n",
|
|
" model_path = os.path.join(os.getenv('AZUREML_MODEL_DIR'), 'sklearn_regression_model.pkl')\n",
|
|
" # deserialize the model file back into a sklearn model\n",
|
|
" model = joblib.load(model_path)\n",
|
|
"\n",
|
|
"\n",
|
|
"standard_sample_input = {'a': 10, 'b': 9, 'c': 8, 'd': 7, 'e': 6, 'f': 5, 'g': 4, 'h': 3, 'i': 2, 'j': 1 }\n",
|
|
"standard_sample_output = {'outcome': 1}\n",
|
|
"\n",
|
|
"@input_schema('param', StandardPythonParameterType(standard_sample_input))\n",
|
|
"@output_schema(StandardPythonParameterType(standard_sample_output))\n",
|
|
"def run(param):\n",
|
|
" try:\n",
|
|
" raw_data = [param['a'], param['b'], param['c'], param['d'], param['e'], param['f'], param['g'], param['h'], param['i'], param['j']]\n",
|
|
" data = numpy.array([raw_data])\n",
|
|
" result = model.predict(data)\n",
|
|
" return { 'outcome' : result[0] }\n",
|
|
" except Exception as e:\n",
|
|
" error = str(e)\n",
|
|
" return error"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Create the InferenceConfig\n",
|
|
"Create the inference config that will be used when deploying the model"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"from azureml.core.model import InferenceConfig\n",
|
|
"\n",
|
|
"inf_config = InferenceConfig(entry_script='score_ssl.py', environment=myenv)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Provision the AKS Cluster with SSL\n",
|
|
"This is a one time setup. You can reuse this cluster for multiple deployments after it has been created. If you delete the cluster or the resource group that contains it, then you would have to recreate it.\n",
|
|
"\n",
|
|
"See code snippet below. Check the documentation [here](https://docs.microsoft.com/en-us/azure/machine-learning/service/how-to-secure-web-service) for more details"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Use the default configuration (can also provide parameters to customize)\n",
|
|
"\n",
|
|
"provisioning_config = AksCompute.provisioning_configuration()\n",
|
|
"# Leaf domain label generates a name using the formula\n",
|
|
"# \"<leaf-domain-label>######.<azure-region>.cloudapp.azure.net\"\n",
|
|
"# where \"######\" is a random series of characters\n",
|
|
"provisioning_config.enable_ssl(leaf_domain_label = \"contoso\", overwrite_existing_domain = True)\n",
|
|
"\n",
|
|
"aks_name = 'my-aks-ssl-1' \n",
|
|
"# Create the cluster\n",
|
|
"aks_target = ComputeTarget.create(workspace = ws, \n",
|
|
" name = aks_name, \n",
|
|
" provisioning_configuration = provisioning_config)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%time\n",
|
|
"aks_target.wait_for_completion(show_output = True)\n",
|
|
"print(aks_target.provisioning_state)\n",
|
|
"print(aks_target.provisioning_errors)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Deploy web service to AKS"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"tags": [
|
|
"sample-deploy-to-aks"
|
|
]
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%time\n",
|
|
"\n",
|
|
"aks_config = AksWebservice.deploy_configuration()\n",
|
|
"\n",
|
|
"aks_service_name ='aks-service-ssl-1'\n",
|
|
"\n",
|
|
"aks_service = Model.deploy(workspace=ws,\n",
|
|
" name=aks_service_name,\n",
|
|
" models=[model],\n",
|
|
" inference_config=inf_config,\n",
|
|
" deployment_config=aks_config,\n",
|
|
" deployment_target=aks_target,\n",
|
|
" overwrite=True)\n",
|
|
"\n",
|
|
"aks_service.wait_for_deployment(show_output = True)\n",
|
|
"print(aks_service.state)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Test the web service using run method\n",
|
|
"We test the web sevice by passing data.\n",
|
|
"Run() method retrieves API keys behind the scenes to make sure that call is authenticated."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%time\n",
|
|
"import json\n",
|
|
"\n",
|
|
"standard_sample_input = json.dumps({'param': {'a': 10, 'b': 9, 'c': 8, 'd': 7, 'e': 6, 'f': 5, 'g': 4, 'h': 3, 'i': 2, 'j': 1 }})\n",
|
|
"\n",
|
|
"aks_service.run(input_data=standard_sample_input)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Clean up\n",
|
|
"Delete the service, image and model."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%%time\n",
|
|
"aks_service.delete()\n",
|
|
"model.delete()"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"authors": [
|
|
{
|
|
"name": "vaidyas"
|
|
}
|
|
],
|
|
"kernelspec": {
|
|
"display_name": "Python 3.6",
|
|
"language": "python",
|
|
"name": "python36"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.6.6"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
} |