Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow tensorflow protocol explanations #2188

Merged
merged 2 commits into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions executor/api/rest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,9 @@ func (r *SeldonRestApi) Initialise() {

case api.ProtocolTensorflow:
r.Router.NewRoute().Path("/v1/models/{"+ModelHttpPathVariable+"}/:predict").Methods("OPTIONS", "POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions))
r.Router.NewRoute().Path("/v1/models/{"+ModelHttpPathVariable+"}:predict").Methods("OPTIONS", "POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions))
axsaucedo marked this conversation as resolved.
Show resolved Hide resolved
r.Router.NewRoute().Path("/v1/models/:predict").Methods("OPTIONS", "POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) // Nonstandard path - Seldon extension
r.Router.NewRoute().Path("/v1/models:predict").Methods("OPTIONS", "POST").HandlerFunc(r.wrapMetrics(metric.PredictionHttpServiceName, r.predictions)) // Nonstandard path - Seldon extension
r.Router.NewRoute().Path("/v1/models/{"+ModelHttpPathVariable+"}").Methods("GET", "OPTIONS").HandlerFunc(r.wrapMetrics(metric.StatusHttpServiceName, r.status))
r.Router.NewRoute().Path("/v1/models/{"+ModelHttpPathVariable+"}/metadata").Methods("GET", "OPTIONS").HandlerFunc(r.wrapMetrics(metric.MetadataHttpServiceName, r.metadata))
}
Expand Down
147 changes: 146 additions & 1 deletion notebooks/explainer_examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,151 @@
"source": [
"!kubectl delete -f resources/imagenet_explainer_grpc.yaml"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Tensorflow CIFAR10 Model"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%writefile resources/cifar10_explainer.yaml\n",
"apiVersion: machinelearning.seldon.io/v1\n",
"kind: SeldonDeployment\n",
"metadata:\n",
" name: cifar10-classifier\n",
"spec:\n",
" protocol: tensorflow\n",
" annotations:\n",
" seldon.io/rest-timeout: \"100000\"\n",
" predictors:\n",
" - componentSpecs:\n",
" graph:\n",
" implementation: TENSORFLOW_SERVER\n",
" modelUri: gs://seldon-models/tfserving/cifar10/resnet32\n",
" name: cifar10-classifier\n",
" logger:\n",
" mode: all\n",
" explainer:\n",
" type: AnchorImages\n",
" modelUri: gs://seldon-models/tfserving/cifar10/explainer\n",
" name: default\n",
" replicas: 1"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl apply -f resources/cifar10_explainer.yaml"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=cifar10-classifier -o jsonpath='{.items[0].metadata.name}')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl rollout status deploy/cifar10-classifier-default-explainer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import tensorflow as tf\n",
"import matplotlib.pyplot as plt\n",
"import os\n",
"\n",
"url = 'https://storage.googleapis.com/seldon-models/alibi-detect/classifier/'\n",
"path_model = os.path.join(url, \"cifar10\", \"resnet32\", 'model.h5')\n",
"save_path = tf.keras.utils.get_file(\"resnet32\", path_model)\n",
"model = tf.keras.models.load_model(save_path)\n",
"\n",
"train, test = tf.keras.datasets.cifar10.load_data()\n",
"X_train, y_train = train\n",
"X_test, y_test = test\n",
"\n",
"X_train = X_train.astype('float32') / 255\n",
"X_test = X_test.astype('float32') / 255\n",
"print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)\n",
"class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer',\n",
" 'dog', 'frog', 'horse', 'ship', 'truck']"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from subprocess import run, Popen, PIPE\n",
"import json\n",
"import numpy as np\n",
"idx=12\n",
"test_example=X_test[idx:idx+1].tolist()\n",
"payload='{\"instances\":'+f\"{test_example}\"+' }'\n",
"cmd=f\"\"\"curl -d '{payload}' \\\n",
" http://localhost:8003/seldon/seldon/cifar10-classifier/v1/models/cifar10-classifier/:predict \\\n",
" -H \"Content-Type: application/json\"\n",
"\"\"\"\n",
"ret = Popen(cmd, shell=True,stdout=PIPE)\n",
"raw = ret.stdout.read().decode(\"utf-8\")\n",
"print(raw)\n",
"res=json.loads(raw)\n",
"arr=np.array(res[\"predictions\"])\n",
"X = X_test[idx].reshape(1, 32, 32, 3)\n",
"plt.imshow(X.reshape(32, 32, 3))\n",
"plt.axis('off')\n",
"plt.show()\n",
"print(\"class:\",class_names[y_test[idx][0]])\n",
"print(\"prediction:\",class_names[arr[0].argmax()])"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"test_example=X_test[idx:idx+1].tolist()\n",
"payload='{\"instances\":'+f\"{test_example}\"+' }'\n",
"cmd=f\"\"\"curl -d '{payload}' \\\n",
" http://localhost:8003/seldon/seldon/cifar10-classifier-explainer/default/v1/models/cifar10-classifier:explain \\\n",
" -H \"Content-Type: application/json\"\n",
"\"\"\"\n",
"ret = Popen(cmd, shell=True,stdout=PIPE)\n",
"raw = ret.stdout.read().decode(\"utf-8\")\n",
"explanation = json.loads(raw)\n",
"arr = np.array(explanation[\"anchor\"])\n",
"plt.imshow(arr)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand All @@ -626,7 +771,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.4"
"version": "3.6.8"
},
"varInspector": {
"cols": {
Expand Down
61 changes: 12 additions & 49 deletions notebooks/protocol_examples.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -304,10 +304,6 @@
" ports:\n",
" - containerPort: 8501\n",
" name: http\n",
" tolerations:\n",
" - key: model\n",
" operator: Exists\n",
" effect: NoSchedule\n",
" graph:\n",
" name: halfplustwo\n",
" type: MODEL\n",
Expand Down Expand Up @@ -440,36 +436,19 @@
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Waiting for deployment \"grpc-tfserving-model-0-halfplustwo\" rollout to finish: 0 of 1 updated replicas are available...\n",
"deployment \"grpc-tfserving-model-0-halfplustwo\" successfully rolled out\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl rollout status deploy/$(kubectl get deploy -l seldon-deployment-id=grpc-tfserving \\\n",
" -o jsonpath='{.items[0].metadata.name}')"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Available\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for i in range(60):\n",
" state=!kubectl get sdep grpc-tfserving -o jsonpath='{.status.state}'\n",
Expand All @@ -490,17 +469,9 @@
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'outputs': {'x': {'dtype': 'DT_FLOAT', 'tensorShape': {'dim': [{'size': '3'}]}, 'floatVal': [2.5, 3, 3.5]}}, 'modelSpec': {'name': 'halfplustwo', 'version': '123', 'signatureName': 'serving_default'}}\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"X=!cd ../executor/proto && grpcurl \\\n",
" -d '{\"model_spec\":{\"name\":\"halfplustwo\"},\"inputs\":{\"x\":{\"dtype\": 1, \"tensor_shape\": {\"dim\":[{\"size\": 3}]}, \"floatVal\" : [1.0, 2.0, 3.0]}}}' \\\n",
Expand All @@ -514,17 +485,9 @@
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"seldondeployment.machinelearning.seldon.io \"grpc-tfserving\" deleted\r\n"
]
}
],
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!kubectl delete -f resources/model_tfserving_grpc.yaml"
]
Expand Down
3 changes: 3 additions & 0 deletions notebooks/resources/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ fixed_v1_rep2.yaml
fixed_v1_rep4.yaml
fixed_v2_2predictors.yaml
fixed_v2_rep.yaml
cifar10_explainer.yaml
model_v2_grpc.yaml
model_v2_rest.yaml
Loading