Skip to content

Commit

Permalink
Add text explainer notebook (kubeflow#355)
Browse files Browse the repository at this point in the history
* Add text explainer notebook example

* Fix formatting
  • Loading branch information
yuzisun authored and k8s-ci-robot committed Sep 24, 2019
1 parent fcf1a13 commit 4c647d9
Show file tree
Hide file tree
Showing 2 changed files with 255 additions and 0 deletions.
3 changes: 3 additions & 0 deletions docs/samples/explanation/alibi/moviesentiment/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,6 @@ make train

You can then store the `model.joblib` in a bucket accessible from your Kubernetes cluster.

## Run on Notebook

You can also run this example on [notebook](./kfserving_text_explainer.ipynb)
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Sample for KFService Explainer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The notebook shows how to use KFServing SDK to create KFService with explainer, predictor."
]
},
{
"cell_type": "code",
"execution_count": 59,
"metadata": {},
"outputs": [],
"source": [
"from kubernetes import client\n",
"\n",
"from kfserving import KFServingClient\n",
"from kfserving import constants\n",
"from kfserving import V1alpha2EndpointSpec\n",
"from kfserving import V1alpha2PredictorSpec\n",
"from kfserving import V1alpha2ExplainerSpec\n",
"from kfserving import V1alpha2AlibiExplainerSpec\n",
"from kfserving import V1alpha2SKLearnSpec\n",
"from kfserving import V1alpha2KFServiceSpec\n",
"from kfserving import V1alpha2KFService\n",
"from kubernetes.client import V1ResourceRequirements\n",
"from kubernetes import client, config\n",
"import kubernetes.client\n",
"import os\n",
"import requests \n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Define KFService with Explainer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Add predictor and explainer on the endpoint spec"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"api_version = constants.KFSERVING_GROUP + '/' + constants.KFSERVING_VERSION\n",
"default_endpoint_spec = V1alpha2EndpointSpec(\n",
" predictor=V1alpha2PredictorSpec(\n",
" min_replicas=1,\n",
" sklearn=V1alpha2SKLearnSpec(\n",
" storage_uri='gs://seldon-models/sklearn/moviesentiment',\n",
" resources=V1ResourceRequirements(\n",
" requests={'cpu': '100m', 'memory': '1Gi'},\n",
" limits={'cpu': '100m', 'memory': '1Gi'}))),\n",
" explainer=V1alpha2ExplainerSpec(\n",
" min_replicas=1, \n",
" alibi=V1alpha2AlibiExplainerSpec(\n",
" type='AnchorText',\n",
" resources=V1ResourceRequirements(\n",
" requests={'cpu': '100m', 'memory': '2Gi'},\n",
" limits={'cpu': '100m', 'memory': '2Gi'}))))\n",
" \n",
"kfsvc = V1alpha2KFService(api_version=api_version,\n",
" kind=constants.KFSERVING_KIND,\n",
" metadata=client.V1ObjectMeta(\n",
" name='moviesentiment', namespace='kubeflow'),\n",
" spec=V1alpha2KFServiceSpec(default=default_endpoint_spec))\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Create KFService"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Call KFServingClient to create KFService."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"KFServing = KFServingClient()\n",
"KFServing.create(kfsvc)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Check the KFService"
]
},
{
"cell_type": "code",
"execution_count": 60,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"NAME READY DEFAULT_TRAFFIC CANARY_TRAFFIC URL \n",
"moviesentiment True 100 http://moviesentiment-predict.kubeflow.example.com\n"
]
}
],
"source": [
"KFServing.get('moviesentiment', namespace='kubeflow', watch=True, timeout_seconds=120)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Predict the sentiment for the sentence"
]
},
{
"cell_type": "code",
"execution_count": 61,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"34.67.11.82\n"
]
}
],
"source": [
"api_instance = kubernetes.client.CoreV1Api(kubernetes.client.ApiClient())\n",
"service = api_instance.read_namespaced_service(\"istio-ingressgateway\", \"istio-system\", exact='true')\n",
"cluster_ip = service.status.load_balancer.ingress[0].ip\n",
"print(cluster_ip)"
]
},
{
"cell_type": "code",
"execution_count": 62,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"b'{\"predictions\": [0]}'\n",
"b'{\"predictions\": [1]}'\n"
]
}
],
"source": [
"url = \"http://\" + cluster_ip + \"/v1/models/moviesentiment:predict\"\n",
"headers = {'Host': 'moviesentiment-predict.kubeflow.example.com'}\n",
"response = requests.post(url, '{\"instances\":[\"This is a bad book .\"]}', headers=headers)\n",
"print(response.content)\n",
"response = requests.post(url, '{\"instances\":[\"This is a good book .\"]}', headers=headers)\n",
"print(response.content)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Explain the Prediction"
]
},
{
"cell_type": "code",
"execution_count": 58,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"b'{\"names\": [\"bad\"], \"precision\": 1.0, \"coverage\": 0.5007, \"raw\": {\"feature\": [3], \"mean\": [1.0], \"precision\": [1.0], \"coverage\": [0.5007], \"examples\": [{\"covered\": [[\"This is a bad book UNK\"], [\"UNK is UNK bad book UNK\"], [\"UNK is UNK bad book .\"], [\"This UNK UNK bad book UNK\"], [\"This is UNK bad UNK .\"], [\"UNK UNK UNK bad book .\"], [\"UNK is a bad UNK UNK\"], [\"UNK UNK a bad UNK .\"], [\"UNK UNK a bad book UNK\"], [\"UNK is UNK bad book .\"]], \"covered_true\": [[\"UNK is UNK bad UNK UNK\"], [\"UNK is UNK bad UNK UNK\"], [\"UNK is UNK bad book UNK\"], [\"This UNK UNK bad book UNK\"], [\"UNK UNK a bad book .\"], [\"This is UNK bad UNK UNK\"], [\"UNK UNK UNK bad UNK UNK\"], [\"This is UNK bad UNK .\"], [\"This is UNK bad UNK .\"], [\"This UNK a bad UNK .\"]], \"covered_false\": [], \"uncovered_true\": [], \"uncovered_false\": []}], \"all_precision\": 0, \"num_preds\": 1000101, \"names\": [\"bad\"], \"positions\": [10], \"instance\": \"This is a bad book .\", \"prediction\": 0}}'\n",
"b'{\"names\": [\"good\"], \"precision\": 1.0, \"coverage\": 0.5007, \"raw\": {\"feature\": [3], \"mean\": [1.0], \"precision\": [1.0], \"coverage\": [0.5007], \"examples\": [{\"covered\": [[\"This is a good book .\"], [\"This is a good book UNK\"], [\"UNK is UNK good book UNK\"], [\"This UNK UNK good UNK UNK\"], [\"UNK UNK a good book UNK\"], [\"This UNK a good UNK UNK\"], [\"UNK is a good book UNK\"], [\"UNK is a good UNK UNK\"], [\"This is UNK good book .\"], [\"UNK UNK UNK good UNK UNK\"]], \"covered_true\": [[\"UNK UNK UNK good book UNK\"], [\"UNK is a good book .\"], [\"UNK is a good book UNK\"], [\"UNK is UNK good book .\"], [\"UNK UNK UNK good book .\"], [\"UNK is a good book .\"], [\"UNK is UNK good UNK UNK\"], [\"UNK UNK UNK good UNK .\"], [\"This UNK a good UNK UNK\"], [\"This is a good UNK .\"]], \"covered_false\": [], \"uncovered_true\": [], \"uncovered_false\": []}], \"all_precision\": 0, \"num_preds\": 1000001, \"names\": [\"good\"], \"positions\": [10], \"instance\": \"This is a good book .\", \"prediction\": 1}}'\n"
]
}
],
"source": [
"url = \"http://\" + cluster_ip + \"/v1/models/moviesentiment:explain\"\n",
"headers = {'Host': 'moviesentiment-explain.kubeflow.example.com'}\n",
"response = requests.post(url, '{\"instances\":[\"This is a bad book .\"]}', headers=headers)\n",
"print(response.content)\n",
"response = requests.post(url, '{\"instances\":[\"This is a good book .\"]}', headers=headers)\n",
"print(response.content)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Delete the KFService"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"KFServing.delete('moviesentiment', namespace='kubeflow')\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"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.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit 4c647d9

Please sign in to comment.