From f630181c34a6920290765b04023b98d7f198718b Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Mon, 27 May 2019 15:36:28 +0100 Subject: [PATCH 1/3] Updated headlines for spacy and aws eks --- examples/models/aws_eks_deep_mnist/README.md | 3308 +++++++++++++++++ .../aws_eks_deep_mnist.ipynb | 30 +- .../aws_eks_deep_mnist_11_0.png | Bin 0 -> 3494 bytes .../aws_eks_deep_mnist_63_0.png | Bin 0 -> 3494 bytes examples/models/sklearn_spacy_text/README.md | 971 +++++ .../sklearn_spacy_text/requirements.txt | 1 + ...klearn_spacy_text_classifier_example.ipynb | 790 ++-- ...earn_spacy_text_classifier_example_4_1.png | Bin 0 -> 4562 bytes 8 files changed, 4849 insertions(+), 251 deletions(-) create mode 100644 examples/models/aws_eks_deep_mnist/README.md create mode 100644 examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png create mode 100644 examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png create mode 100644 examples/models/sklearn_spacy_text/README.md create mode 100644 examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example_files/sklearn_spacy_text_classifier_example_4_1.png diff --git a/examples/models/aws_eks_deep_mnist/README.md b/examples/models/aws_eks_deep_mnist/README.md new file mode 100644 index 0000000000..e4b568a24a --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/README.md @@ -0,0 +1,3308 @@ + +# Tensorflow MNIST Model +In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS). + +This tutorial will break down in the following sections: + +1) Train a tensorflow model to predict mnist locally + +2) Containerise the tensorflow model with our docker utility + +3) Send some data to the docker model to test it + +4) Install and configure AWS tools to interact with AWS + +5) Use the AWS tools to create and setup EKS cluster with Seldon + +6) Push and run docker image through the AWS Container Registry + +7) Test our Elastic Kubernetes deployment by sending some data + +#### Let's get started! 🚀🔥 + +## Dependencies: + +* Helm v2.13.1+ +* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM) +* kubectl v1.14+ +* EKS CLI v0.1.32 +* AWS Cli v1.16.163 +* Python 3.6+ +* Python DEV requirements + + +# 1) Train a tensorflow model to predict mnist locally +We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels + + +```python +from tensorflow.examples.tutorials.mnist import input_data +mnist = input_data.read_data_sets("MNIST_data/", one_hot = True) +import tensorflow as tf + +if __name__ == '__main__': + + x = tf.placeholder(tf.float32, [None,784], name="x") + + W = tf.Variable(tf.zeros([784,10])) + b = tf.Variable(tf.zeros([10])) + + y = tf.nn.softmax(tf.matmul(x,W) + b, name="y") + + y_ = tf.placeholder(tf.float32, [None, 10]) + + cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) + + train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) + + init = tf.initialize_all_variables() + + sess = tf.Session() + sess.run(init) + + for i in range(1000): + batch_xs, batch_ys = mnist.train.next_batch(100) + sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) + + correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) + accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + print(sess.run(accuracy, feed_dict = {x: mnist.test.images, y_:mnist.test.labels})) + + saver = tf.train.Saver() + + saver.save(sess, "model/deep_mnist_model") +``` + + Extracting MNIST_data/train-images-idx3-ubyte.gz + Extracting MNIST_data/train-labels-idx1-ubyte.gz + Extracting MNIST_data/t10k-images-idx3-ubyte.gz + Extracting MNIST_data/t10k-labels-idx1-ubyte.gz + 0.9194 + + +## 2) Containerise the tensorflow model with our docker utility + +First you need to make sure that you have added the .s2i/environment configuration file in this folder with the following content: + + +```python +!cat .s2i/environment +``` + + MODEL_NAME=DeepMnist + API_TYPE=REST + SERVICE_TYPE=MODEL + PERSISTENCE=0 + + +Now we can build a docker image named "deep-mnist" with the tag 0.1 + + +```python +!s2i build . seldonio/seldon-core-s2i-python36:0.5.1 deep-mnist:0.1 +``` + + ---> Installing application source... + ---> Installing dependencies ... + Looking in links: /whl + Requirement already satisfied: tensorflow>=1.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (1.13.1) + Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.9) + Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.2.2) + Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) + Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) + Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.7) + Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.12.0) + Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.1.0) + Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.19.0) + Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.33.1) + Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.1) + Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.16.2) + Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.7.0) + Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.0) + Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.9.0) + Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.0.1) + Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.15.0) + Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow>=1.12.0->-r requirements.txt (line 1)) (40.8.0) + Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.0.0) + Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (5.1.3) + Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + You are using pip version 19.0.3, however version 19.1.1 is available. + You should consider upgrading via the 'pip install --upgrade pip' command. + Build completed successfully + + +## 3) Send some data to the docker model to test it +We first run the docker image we just created as a container called "mnist_predictor" + + +```python +!docker run --name "mnist_predictor" -d --rm -p 5000:5000 deep-mnist:0.1 +``` + + 5157ab4f516bd0dea11b159780f31121e9fb41df6394e0d6d631e6e0d572463b + + +Send some random features that conform to the contract + + +```python +import matplotlib.pyplot as plt +# This is the variable that was initialised at the beginning of the file +i = [0] +x = mnist.test.images[i] +y = mnist.test.labels[i] +plt.imshow(x.reshape((28, 28)), cmap='gray') +plt.show() +print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) +``` + + +![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png) + + + Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] + + + +```python +from seldon_core.seldon_client import SeldonClient +import math +import numpy as np + +# We now test the REST endpoint expecting the same result +endpoint = "0.0.0.0:5000" +batch = x +payload_type = "ndarray" + +sc = SeldonClient(microservice_endpoint=endpoint) + +# We use the microservice, instead of the "predict" function +client_prediction = sc.microservice( + data=batch, + method="predict", + payload_type=payload_type, + names=["tfidf"]) + +for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): + print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") +``` + + LABEL 0: 0.0068 % + LABEL 1: 0.0000 % + LABEL 2: 0.0085 % + LABEL 3: 0.3409 % + LABEL 4: 0.0002 % + LABEL 5: 0.0020 % + LABEL 6: 0.0000 % + LABEL 7: 99.5371 % + LABEL 8: 0.0026 % + LABEL 9: 0.1019 % + + + +```python +!docker rm mnist_predictor --force +``` + + mnist_predictor + + +## 4) Install and configure AWS tools to interact with AWS + +First we install the awscli + + +```python +!pip install awscli --upgrade --user +``` + + Collecting awscli + Using cached https://files.pythonhosted.org/packages/f6/45/259a98719e7c7defc9be4cc00fbfb7ccf699fbd1f74455d8347d0ab0a1df/awscli-1.16.163-py2.py3-none-any.whl + Collecting colorama<=0.3.9,>=0.2.5 (from awscli) + Using cached https://files.pythonhosted.org/packages/db/c8/7dcf9dbcb22429512708fe3a547f8b6101c0d02137acbd892505aee57adf/colorama-0.3.9-py2.py3-none-any.whl + Collecting PyYAML<=3.13,>=3.10 (from awscli) + Collecting botocore==1.12.153 (from awscli) + Using cached https://files.pythonhosted.org/packages/ec/3b/029218966ce62ae9824a18730de862ac8fc5a0e8083d07d1379815e7cca1/botocore-1.12.153-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: docutils>=0.10 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.14) + Collecting rsa<=3.5.0,>=3.1.2 (from awscli) + Using cached https://files.pythonhosted.org/packages/e1/ae/baedc9cb175552e95f3395c43055a6a5e125ae4d48a1d7a924baca83e92e/rsa-3.4.2-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: s3transfer<0.3.0,>=0.2.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.2.0) + Requirement already satisfied, skipping upgrade: urllib3<1.25,>=1.20; python_version >= "3.4" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (1.24.2) + Requirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.1; python_version >= "2.7" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (2.8.0) + Requirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (0.9.4) + Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli) + Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: six>=1.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from python-dateutil<3.0.0,>=2.1; python_version >= "2.7"->botocore==1.12.153->awscli) (1.12.0) + Installing collected packages: colorama, PyYAML, botocore, pyasn1, rsa, awscli + Successfully installed PyYAML-3.13 awscli-1.16.163 botocore-1.12.153 colorama-0.3.9 pyasn1-0.4.5 rsa-3.4.2 + + +#### Configure aws so it can talk to your server +(if you are getting issues, make sure you have the permmissions to create clusters) + + +```bash +%%bash +# You must make sure that the access key and secret are changed +aws configure << END_OF_INPUTS +YOUR_ACCESS_KEY +YOUR_ACCESS_SECRET +us-west-2 +json +END_OF_INPUTS +``` + + AWS Access Key ID [****************SF4A]: AWS Secret Access Key [****************WLHu]: Default region name [eu-west-1]: Default output format [json]: + +#### Install EKCTL +*IMPORTANT*: These instructions are for linux +Please follow the official installation of ekctl at: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html + + +```python +!curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz +``` + + +```python +!chmod 755 ./eksctl +``` + + +```python +!./eksctl version +``` + + [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.32"} +  + +## 5) Use the AWS tools to create and setup EKS cluster with Seldon +In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly. + +If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard. + +It will take 10-15 minutes (so feel free to go grab a ☕). + +### IMPORTANT: If you get errors in this step... +It is most probably IAM role access requirements, which requires you to discuss with your administrator. + + +```bash +%%bash +./eksctl create cluster \ +--name demo-eks-cluster \ +--region us-west-2 \ +--nodes 2 +``` + + Process is interrupted. + + +### Configure local kubectl +We want to now configure our local Kubectl so we can actually reach the cluster we've just created + + +```python +!aws eks --region us-west-2 update-kubeconfig --name demo-eks-cluster +``` + + Updated context arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist in /home/alejandro/.kube/config + + +And we can check if the context has been added to kubectl config (contexts are basically the different k8s cluster connections) +You should be able to see the context as "...aws:eks:eu-west-1:27...". +If it's not activated you can activate that context with kubectlt config set-context + + +```python +!kubectl config get-contexts +``` + + CURRENT NAME CLUSTER AUTHINFO NAMESPACE + * arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist + docker-desktop docker-desktop docker-desktop + docker-for-desktop docker-desktop docker-desktop + gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 + + +## Install Seldon Core + +### Before we install seldon core, we need to install HELM +For that, we need to create a ClusterRoleBinding for us, a ServiceAccount, and then a RoleBinding + + +```python +!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default +``` + + clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created + + + +```python +!kubectl create serviceaccount tiller --namespace kube-system +``` + + serviceaccount/tiller created + + + +```python +!kubectl apply -f tiller-role-binding.yaml +``` + + clusterrolebinding.rbac.authorization.k8s.io/tiller-role-binding created + + +### Once that is set-up we can install Tiller + + +```python +!helm init --service-account tiller +``` + + $HELM_HOME has been configured at /home/alejandro/.helm. + + Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster. + + Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy. + To prevent this, run `helm init` with the --tiller-tls-verify flag. + For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation + Happy Helming! + + + +```python +# Wait until Tiller finishes +!kubectl rollout status deploy/tiller-deploy -n kube-system +``` + + deployment "tiller-deploy" successfully rolled out + + +### Now we can install SELDON. +We first start with the custom resource definitions (CRDs) + + +```python +!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --namespace seldon-system +``` + + NAME: seldon-core-operator + LAST DEPLOYED: Wed May 22 16:24:10 2019 + NAMESPACE: seldon-system + STATUS: DEPLOYED + + RESOURCES: + ==> v1/ClusterRole + NAME AGE + seldon-operator-manager-role 2s + + ==> v1/ClusterRoleBinding + NAME AGE + seldon-operator-manager-rolebinding 2s + + ==> v1/ConfigMap + NAME DATA AGE + seldon-spartakus-config 3 2s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + seldon-operator-controller-manager-0 0/1 ContainerCreating 0 2s + seldon-spartakus-volunteer-6954cffb89-qz4pq 0/1 ContainerCreating 0 1s + + ==> v1/Secret + NAME TYPE DATA AGE + seldon-operator-webhook-server-secret Opaque 0 2s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + seldon-operator-controller-manager-service ClusterIP 10.100.198.157 443/TCP 2s + + ==> v1/ServiceAccount + NAME SECRETS AGE + seldon-spartakus-volunteer 1 2s + + ==> v1/StatefulSet + NAME READY AGE + seldon-operator-controller-manager 0/1 2s + + ==> v1beta1/ClusterRole + NAME AGE + seldon-spartakus-volunteer 2s + + ==> v1beta1/ClusterRoleBinding + NAME AGE + seldon-spartakus-volunteer 2s + + ==> v1beta1/CustomResourceDefinition + NAME AGE + seldondeployments.machinelearning.seldon.io 2s + + ==> v1beta1/Deployment + NAME READY UP-TO-DATE AVAILABLE AGE + seldon-spartakus-volunteer 0/1 1 0 2s + + + NOTES: + NOTES: TODO + + + + +And confirm they are running by getting the pods: + + +```python +!kubectl rollout status statefulset.apps/seldon-operator-controller-manager -n seldon-system +``` + + partitioned roll out complete: 1 new pods have been updated... + + +### Now we set-up the ingress +This will allow you to reach the Seldon models from outside the kubernetes cluster. + +In EKS it automatically creates an Elastic Load Balancer, which you can configure from the EC2 Console + + +```python +!helm install stable/ambassador --name ambassador --set image.tag=0.40.2 +``` + + NAME: ambassador + LAST DEPLOYED: Wed May 22 16:25:38 2019 + NAMESPACE: default + STATUS: DEPLOYED + + RESOURCES: + ==> v1/Deployment + NAME READY UP-TO-DATE AVAILABLE AGE + ambassador 0/3 3 0 0s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + ambassador-6dbf99c886-frlfm 0/1 ContainerCreating 0 0s + ambassador-6dbf99c886-kj56r 0/1 ContainerCreating 0 0s + ambassador-6dbf99c886-v5mtv 0/1 ContainerCreating 0 0s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ambassador LoadBalancer 10.100.59.146 80:30911/TCP,443:31715/TCP 0s + ambassador-admins ClusterIP 10.100.152.178 8877/TCP 0s + + ==> v1/ServiceAccount + NAME SECRETS AGE + ambassador 1 0s + + ==> v1beta1/ClusterRole + NAME AGE + ambassador 0s + + ==> v1beta1/ClusterRoleBinding + NAME AGE + ambassador 0s + + + NOTES: + Congratuations! You've successfully installed Ambassador. + + For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io. + + To get the IP address of Ambassador, run the following commands: + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w --namespace default ambassador' + + On GKE/Azure: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + + On AWS: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + + echo http://$SERVICE_IP: + + + +And let's wait until it's fully deployed + + +```python +!kubectl rollout status deployment.apps/ambassador +``` + +## Push docker image +In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR). + +If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html + +### First we create a registry +You can run the following command, and then see the result at https://us-west-2.console.aws.amazon.com/ecr/repositories?# + + +```python +!aws ecr create-repository --repository-name seldon-repository --region us-west-2 +``` + + { + "repository": { + "repositoryArn": "arn:aws:ecr:us-west-2:271049282727:repository/seldon-repository", + "registryId": "271049282727", + "repositoryName": "seldon-repository", + "repositoryUri": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository", + "createdAt": 1558535798.0 + } + } + + +### Now prepare docker image +We need to first tag the docker image before we can push it + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +docker tag deep-mnist:0.1 "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" +``` + +### We now login to aws through docker so we can access the repository + + +```python +!`aws ecr get-login --no-include-email --region us-west-2` +``` + + WARNING! Using --password via the CLI is insecure. Use --password-stdin. + WARNING! Your password will be stored unencrypted in /home/alejandro/.docker/config.json. + Configure a credential helper to remove this warning. See + https://docs.docker.com/engine/reference/commandline/login/#credentials-store + + Login Succeeded + + +### And push the image +Make sure you add your AWS Account ID + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +docker push "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" +``` + + The push refers to repository [271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository] + f7d0d000c138: Preparing + 987f3f1afb00: Preparing + 00d16a381c47: Preparing + bb01f50d544a: Preparing + fcb82c6941b5: Preparing + 67290e35c458: Preparing + b813745f5bb3: Preparing + ffecb18e9f0b: Preparing + f50f856f49fa: Preparing + 80b43ad4adf9: Preparing + 14c77983a1cf: Preparing + a22a5ac18042: Preparing + 6257fa9f9597: Preparing + 578414b395b9: Preparing + abc3250a6c7f: Preparing + 13d5529fd232: Preparing + 67290e35c458: Waiting + b813745f5bb3: Waiting + ffecb18e9f0b: Waiting + f50f856f49fa: Waiting + 80b43ad4adf9: Waiting + 6257fa9f9597: Waiting + 14c77983a1cf: Waiting + a22a5ac18042: Waiting + 578414b395b9: Waiting + abc3250a6c7f: Waiting + 13d5529fd232: Waiting + 987f3f1afb00: Pushed + fcb82c6941b5: Pushed + bb01f50d544a: Pushed + f7d0d000c138: Pushed + ffecb18e9f0b: Pushed + b813745f5bb3: Pushed + f50f856f49fa: Pushed + 67290e35c458: Pushed + 14c77983a1cf: Pushed + 578414b395b9: Pushed + 80b43ad4adf9: Pushed + 13d5529fd232: Pushed + 6257fa9f9597: Pushed + abc3250a6c7f: Pushed + 00d16a381c47: Pushed + a22a5ac18042: Pushed + latest: digest: sha256:19aefaa9d87c1287eb46ec08f5d4f9a689744d9d0d0b75668b7d15e447819d74 size: 3691 + + +## Running the Model +We will now run the model. + +Let's first have a look at the file we'll be using to trigger the model: + + +```python +!cat deep_mnist.json +``` + + { + "apiVersion": "machinelearning.seldon.io/v1alpha2", + "kind": "SeldonDeployment", + "metadata": { + "labels": { + "app": "seldon" + }, + "name": "deep-mnist" + }, + "spec": { + "annotations": { + "project_name": "Tensorflow MNIST", + "deployment_version": "v1" + }, + "name": "deep-mnist", + "oauth_key": "oauth-key", + "oauth_secret": "oauth-secret", + "predictors": [ + { + "componentSpecs": [{ + "spec": { + "containers": [ + { + "image": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest", + "imagePullPolicy": "IfNotPresent", + "name": "classifier", + "resources": { + "requests": { + "memory": "1Mi" + } + } + } + ], + "terminationGracePeriodSeconds": 20 + } + }], + "graph": { + "children": [], + "name": "classifier", + "endpoint": { + "type" : "REST" + }, + "type": "MODEL" + }, + "name": "single-model", + "replicas": 1, + "annotations": { + "predictor_version" : "v1" + } + } + ] + } + } + + +Now let's trigger seldon to run the model. + +We basically have a yaml file, where we want to replace the value "REPLACE_FOR_IMAGE_AND_TAG" for the image you pushed + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +sed 's|REPLACE_FOR_IMAGE_AND_TAG|'"$AWS_ACCOUNT_ID"'.dkr.ecr.'"$AWS_REGION"'.amazonaws.com/seldon-repository|g' deep_mnist.json | kubectl apply -f - +``` + + error: unable to recognize "STDIN": Get https://461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com/api?timeout=32s: dial tcp: lookup 461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com on 1.1.1.1:53: no such host + + + + --------------------------------------------------------------------------- + + CalledProcessError Traceback (most recent call last) + + in + ----> 1 get_ipython().run_cell_magic('bash', '', 'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n') + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell) + 2350 with self.builtin_trap: + 2351 args = (magic_arg_s, cell) + -> 2352 result = fn(*args, **kwargs) + 2353 return result + 2354 + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in named_script_magic(line, cell) + 140 else: + 141 line = script + --> 142 return self.shebang(line, cell) + 143 + 144 # write a basic docstring: + + + in shebang(self, line, cell) + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magic.py in (f, *a, **k) + 185 # but it's overkill for just that one bit of state. + 186 def magic_deco(arg): + --> 187 call = lambda f, *a, **k: f(*a, **k) + 188 + 189 if callable(arg): + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in shebang(self, line, cell) + 243 sys.stderr.flush() + 244 if args.raise_error and p.returncode!=0: + --> 245 raise CalledProcessError(p.returncode, cell, output=out, stderr=err) + 246 + 247 def _run_script(self, p, cell, to_close): + + + CalledProcessError: Command 'b'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n'' returned non-zero exit status 1. + + +And let's check that it's been created. + +You should see an image called "deep-mnist-single-model...". + +We'll wait until STATUS changes from "ContainerCreating" to "Running" + + +```python +!kubectl get pods +``` + + NAME READY STATUS RESTARTS AGE + ambassador-5475779f98-7bhcw 1/1 Running 0 21m + ambassador-5475779f98-986g5 1/1 Running 0 21m + ambassador-5475779f98-zcd28 1/1 Running 0 21m + deep-mnist-single-model-42ed9d9-fdb557d6b-6xv2h 2/2 Running 0 18m + + +## Test the model +Now we can test the model, let's first find out what is the URL that we'll have to use: + + +```python +!kubectl get svc ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' +``` + + a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com + +We'll use a random example from our dataset + + +```python +import matplotlib.pyplot as plt +# This is the variable that was initialised at the beginning of the file +i = [0] +x = mnist.test.images[i] +y = mnist.test.labels[i] +plt.imshow(x.reshape((28, 28)), cmap='gray') +plt.show() +print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) +``` + + +![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png) + + + Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] + + +We can now add the URL above to send our request: + + +```python +from seldon_core.seldon_client import SeldonClient +import math +import numpy as np + +host = "a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com" +port = "80" # Make sure you use the port above +batch = x +payload_type = "ndarray" + +sc = SeldonClient( + gateway="ambassador", + ambassador_endpoint=host + ":" + port, + namespace="default", + oauth_key="oauth-key", + oauth_secret="oauth-secret") + +client_prediction = sc.predict( + data=batch, + deployment_name="deep-mnist", + names=["text"], + payload_type=payload_type) + +print(client_prediction) +``` + + Success:True message: + Request: + data { + names: "text" + ndarray { + values { + list_value { + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.3294117748737335 + } + values { + number_value: 0.7254902124404907 + } + values { + number_value: 0.6235294342041016 + } + values { + number_value: 0.5921568870544434 + } + values { + number_value: 0.2352941334247589 + } + values { + number_value: 0.1411764770746231 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.8705883026123047 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9450981020927429 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.6666666865348816 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.44705885648727417 + } + values { + number_value: 0.2823529541492462 + } + values { + number_value: 0.44705885648727417 + } + values { + number_value: 0.6392157077789307 + } + values { + number_value: 0.8901961445808411 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8823530077934265 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9803922176361084 + } + values { + number_value: 0.8980392813682556 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.5490196347236633 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.06666667014360428 + } + values { + number_value: 0.25882354378700256 + } + values { + number_value: 0.05490196496248245 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.23137256503105164 + } + values { + number_value: 0.08235294371843338 + } + values { + number_value: 0.9254902601242065 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.41568630933761597 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.32549020648002625 + } + values { + number_value: 0.9921569228172302 + } + values { + number_value: 0.8196079134941101 + } + values { + number_value: 0.07058823853731155 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.08627451211214066 + } + values { + number_value: 0.9137255549430847 + } + values { + number_value: 1.0 + } + values { + number_value: 0.32549020648002625 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5058823823928833 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9333333969116211 + } + values { + number_value: 0.1725490242242813 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.23137256503105164 + } + values { + number_value: 0.9764706492424011 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.24313727021217346 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5215686559677124 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.7333333492279053 + } + values { + number_value: 0.019607843831181526 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.03529411926865578 + } + values { + number_value: 0.803921639919281 + } + values { + number_value: 0.9725490808486938 + } + values { + number_value: 0.22745099663734436 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4941176772117615 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.7137255072593689 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.29411765933036804 + } + values { + number_value: 0.9843137860298157 + } + values { + number_value: 0.9411765336990356 + } + values { + number_value: 0.22352942824363708 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.07450980693101883 + } + values { + number_value: 0.8666667342185974 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.6509804129600525 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.011764707043766975 + } + values { + number_value: 0.7960785031318665 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8588235974311829 + } + values { + number_value: 0.13725490868091583 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.14901961386203766 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.3019607961177826 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.12156863510608673 + } + values { + number_value: 0.8784314393997192 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.45098042488098145 + } + values { + number_value: 0.003921568859368563 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5215686559677124 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.2392157018184662 + } + values { + number_value: 0.9490196704864502 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4745098352432251 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8588235974311829 + } + values { + number_value: 0.1568627506494522 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4745098352432251 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8117647767066956 + } + values { + number_value: 0.07058823853731155 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + } + } + } + } + + Response: + meta { + puid: "l6bv1r38mmb32l0hbinln2jjcl" + requestPath { + key: "classifier" + value: "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest" + } + } + data { + names: "class:0" + names: "class:1" + names: "class:2" + names: "class:3" + names: "class:4" + names: "class:5" + names: "class:6" + names: "class:7" + names: "class:8" + names: "class:9" + ndarray { + values { + list_value { + values { + number_value: 6.839015986770391e-05 + } + values { + number_value: 9.376968534979824e-09 + } + values { + number_value: 8.48581112222746e-05 + } + values { + number_value: 0.0034086888190358877 + } + values { + number_value: 2.3978568606253248e-06 + } + values { + number_value: 2.0100669644307345e-05 + } + values { + number_value: 3.0251623428512175e-08 + } + values { + number_value: 0.9953710436820984 + } + values { + number_value: 2.6070511012221687e-05 + } + values { + number_value: 0.0010185304563492537 + } + } + } + } + } + + + +### Let's visualise the probability for each label +It seems that it correctly predicted the number 7 + + +```python +for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): + print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") +``` + + LABEL 0: 0.0068 % + LABEL 1: 0.0000 % + LABEL 2: 0.0085 % + LABEL 3: 0.3409 % + LABEL 4: 0.0002 % + LABEL 5: 0.0020 % + LABEL 6: 0.0000 % + LABEL 7: 99.5371 % + LABEL 8: 0.0026 % + LABEL 9: 0.1019 % + + + +```python + +``` diff --git a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb index 0211ad5a73..f6199e5456 100644 --- a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb +++ b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb @@ -25,13 +25,15 @@ "\n", "#### Let's get started! 🚀🔥\n", "\n", - "# Dependencies:\n", + "## Dependencies:\n", "\n", - "* Docker\n", - "* Helm\n", - "* Kubectl\n", - "* EKS CLI\n", - "* AWS Cli\n" + "* Helm v2.13.1+\n", + "* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM)\n", + "* kubectl v1.14+\n", + "* EKS CLI v0.1.32\n", + "* AWS Cli v1.16.163\n", + "* Python 3.6+\n", + "* Python DEV requirements\n" ] }, { @@ -101,7 +103,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 2) Containerise the tensorflow model with our docker utility" + "## 2) Containerise the tensorflow model with our docker utility" ] }, { @@ -187,7 +189,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 3) Send some data to the docker model to test it\n", + "## 3) Send some data to the docker model to test it\n", "We first run the docker image we just created as a container called \"mnist_predictor\"" ] }, @@ -317,7 +319,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 4) Install and configure AWS tools to interact with AWS" + "## 4) Install and configure AWS tools to interact with AWS" ] }, { @@ -445,7 +447,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 5) Use the AWS tools to create and setup EKS cluster with Seldon\n", + "## 5) Use the AWS tools to create and setup EKS cluster with Seldon\n", "In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly.\n", "\n", "If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard.\n", @@ -538,7 +540,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Install Seldon Core" + "## Install Seldon Core" ] }, { @@ -858,7 +860,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Push docker image\n", + "## Push docker image\n", "In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR).\n", "\n", "If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html" @@ -1034,7 +1036,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Running the Model\n", + "## Running the Model\n", "We will now run the model.\n", "\n", "Let's first have a look at the file we'll be using to trigger the model:" @@ -1197,7 +1199,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Test the model\n", + "## Test the model\n", "Now we can test the model, let's first find out what is the URL that we'll have to use:" ] }, diff --git a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f5f9912d842ed32f92e4a20602c4760aea2a7666 GIT binary patch literal 3494 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 literal 0 HcmV?d00001 diff --git a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png new file mode 100644 index 0000000000000000000000000000000000000000..f5f9912d842ed32f92e4a20602c4760aea2a7666 GIT binary patch literal 3494 zcmbtXdstH07N>D0YaGX+njShn!n7O{DqoX^XwvA(F?&rJ_((@HL^Km0fq>PNWR`X` zYc#_OEkz|$z(+t2=rt9IZ&68WB2u#wQ4!?g%$KV@J2%{$kp1IW@!hwQ7>B@Y)vVwe(IKKmZ@syZ zhxz<{&arX9ghMAiv#_7u59nFc+`vp=C^R0a8$IXKw27W}-UdGVsd77kl1 zj4yqbwb^Fn!$aQA_Mgpfv5|Y7_4O1t2+0ll$Ckp8o$FupjUs7+hJI(oxwVQOhV6RD zyUEN(3&>`(TV~5POdMp+LFF#!HwIx^@2x*u`)9o|0-#iza)~PGCvHRWS1)Vm`y5A; z>l8fxEwzsdRT(t3^(G$PopY+e2@=|V-&$MdSvMhyprErinxFn| z$apreoIITfm|VWDzsSrh<`|WPd(72i!T36zos4l>WeUieS{7!6;is;mVDL_Ah*a-i zXouT|9vZ>KKu8tC0TcouJBeDN(Cp7M%lPH^AA556rw#xAgWXmav0$8a9&wZOE(k}9 zHoF&o@`P-8M7Tczt*tQ`ob|--8?_OTY(AY^cUx^Gv+dnG$D2kZbqZI)Hg%szD8H7C zY!FqKJ8u^*m=Ht0SnP*R-4T_LOZ0*X!p~mzv@m+I8C`#RvfFEjN8t=hLP<_aM^Mda z@`C8v?nmg8K`LQNN}^gp5viq)5M&4E_H=>Uoe0#EBqVCccvY7LwlQMoJEK&8c`6x$x ze9<`j6z-g7YIOubKdqw-MP1F#$#Jhlj?0z~STp(XmKM|E(ip(sFo6{pLyrlFSVb zzq;E;Ci9|d(`vl(*rU8GRFUw zg&#ksZ=`=`2ee5hd+~FcoGO!SB>75FT~<7uH7HoFoF${>s=UXnZhUcTT>aB- zY*;N=FOXZH3ED`b)>E(OEEcX!TSWBaSdb`vi{G;k;BRvhZ!L(;5+`C`R&BJt!>VJ@C z;mY(YUbtN9LQCqRM|o(&G8fN8#ULMcHkyJ z<8x^VA*a)-7TNwg7})+CdJFVzB03~rH6KX*`i12Q`UU#pSRMfB?btCvK%9N2#)InQ z%a#zG^g*d0#?CZAbA31wke_miBOhbt8i?mk?zGLYdU}9Ld|tt-{dK7yF9%%_^v9Ax#(jMk81CSCOvW$Yg&R(p_P(C zS5`1hS$fClyCh3t*wEz1ib|PeR2H^ExdaH$C2o=KMQc0N>i}VXU9faDkn_FBIIvwj zs-?6Kd8F6khf{kJ{c5Ps@12U|s~%Eoqnpngl8fde<=GDG0a61n_$h`R(g7EP?pcA0 znc;b}ix!&rEv&CPjFCt5mX3itHg<dzRRS^ zdZ{+v-MAzbBQO-RZvfdciX&_~ibupOok_xOyqPz<&QSS~*u0zac~D`6J%h_HsX*is z_cTV^M!LX`!XmF&m>Ru2S=K-P96o&+{1PoPyPVGrz=ZO{oRpKVdB!C>F%7M}5NX1) z;kM_cUI2!De{{METnKo;m4ndL%~7EtuLf(2;v36@X(Rk`4~+i7X~*MZi^9?_TpD}! zfI}*0E7ux`S zJYsheA19D&n57^U8%XL=kHjThL-KB}`QxzB>X1<#yH?9p_;=eYvCy~60Si0IF6q2L zt0mgqjlaSEji-t3lb2w@tpqaH{;<#vMzsT=i5@Voll0>t6{f82%n za++Qz)`&!CciBzIj6;*%fx>wms)I|iJ+&DhIFB_jd{@f$tcxkR3yW+F7-ifz|DSW( z-$?Lk{HtDCzKXW3k0vN|qtE8>e1-!q@=}s(c@~)B8n*jndgL>8X9<-jFHyT)p#ZA( z>PFJDtAEVbW;xwl$O~U{g>M=gK9A2~74*d-6~>zxjpJHK?ACw@0{bfEi8?|S)ZXlC z%gyQP!%r1AW-ewO_3`|PEYHV{#t9>*%-STlOn_C+Gv(@qnxVcL-R?lXQ=Lx8HS6q4 zm_o6X9BRrDLF{CYhT54xE@1kCR=F;4r4x{|K{PVe?Qg`*0nD@L-R!xt=|zCT4mlsn z+tG3!bb&(UENbH86Lh_KZl9aKNBH=?M{OBvOv+BKbW%nD`f77j)B5n7ildUMlSq9i z_@$qynLbg=4EM+E^0hWXz*2z5^w#XtpxaKiJN_LiNbdTQV1pKw)6<$rlugpoQ>A#_ z(C3u4iznZNBb1{2@n`0hONGADFJgPu?gKDyb#I@(Ch^8tlQYSvQmRxbfLj+eUoiiD%P^!`b^!v2UCcR z9)?x5WYP25B+ekU>ZS!{LRIRsmBomOeXU^6#yx+b{Jx+alAdzdWgywIpB5lJ!4*bL z)q;YhII<}v{m?Lrg%aIUw}FC-2IsUUW?S1}8+e{wb4KXA!q(m0d>6)*mU7r_Alb=% za{HMz(^%>tT6{4i3eDrqwo6hQ*99C1zTG;5zXq dO{YJxIs5A3twd`_!<`BOY}kaZUcdX$zW}Cb+G_v+ literal 0 HcmV?d00001 diff --git a/examples/models/sklearn_spacy_text/README.md b/examples/models/sklearn_spacy_text/README.md new file mode 100644 index 0000000000..a9c047b967 --- /dev/null +++ b/examples/models/sklearn_spacy_text/README.md @@ -0,0 +1,971 @@ + +# SKLearn Spacy Reddit Text Classification Example + +In this example we will be buiding a text classifier using the reddit content moderation dataset. + +For this, we will be using SpaCy for the word tokenization and lemmatization. + +The classification will be done with a Logistic Regression binary classifier. + +The steps in this tutorial include: + +1) Train and build your NLP model + +2) Build your containerized model + +3) Test your model as a docker container + +4) Run Seldon in your kubernetes cluster + +5) Deploy your model with Seldon + +6) Interact with your model through API + +7) Clean your environment + + +### Before you start +Make sure you install the following dependencies, as they are critical for this example to work: + +* Helm v2.13.1+ +* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM) +* kubectl v1.14+ +* Python 3.6+ +* Python DEV requirements (we'll install them below) + +Let's get started! 🚀🔥 + +## 1) Train and build your NLP model + + +```python +# Let's first install any dependencies +!pip install -r requirements.txt +``` + + +```python +import pandas as pd +from sklearn.model_selection import train_test_split +import numpy as np +from sklearn.feature_extraction.text import TfidfVectorizer +from sklearn.linear_model import LogisticRegression +from seldon_core.seldon_client import SeldonClient +import dill +import sys, os + +# This import may take a while as it will download the Spacy ENGLISH model +from ml_utils import CleanTextTransformer, SpacyTokenTransformer +``` + + +```python +df_cols = ["prev_idx", "parent_idx", "body", "removed"] + +TEXT_COLUMN = "body" +CLEAN_COLUMN = "clean_body" +TOKEN_COLUMN = "token_body" + +# Downloading the 50k reddit dataset of moderated comments +df = pd.read_csv("https://raw.githubusercontent.com/axsauze/reddit-classification-exploration/master/data/reddit_train.csv", + names=df_cols, skiprows=1, encoding="ISO-8859-1") + +df.head() +``` + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
prev_idxparent_idxbodyremoved
087568877Always be wary of news articles that cite unpu...0
173307432The problem I have with this is that the artic...0
21571115944This is indicative of a typical power law, and...0
316041625This doesn't make sense. Chess obviously trans...0
413327135201. I dispute that gene engineering is burdenso...0
+
+ + + + +```python +# Let's see how many examples we have of each class +df["removed"].value_counts().plot.bar() +``` + + + + + + + + + +![png](sklearn_spacy_text_classifier_example_files/sklearn_spacy_text_classifier_example_4_1.png) + + + +```python +x = df["body"].values +y = df["removed"].values +x_train, x_test, y_train, y_test = train_test_split( + x, y, + stratify=y, + random_state=42, + test_size=0.1, shuffle=True) +``` + + +```python +# Clean the text +clean_text_transformer = CleanTextTransformer() +x_train_clean = clean_text_transformer.transform(x_train) +``` + + +```python +# Tokenize the text and get the lemmas +spacy_tokenizer = SpacyTokenTransformer() +x_train_tokenized = spacy_tokenizer.transform(x_train_clean) +``` + + +```python +# Build tfidf vectorizer +tfidf_vectorizer = TfidfVectorizer( + max_features=10000, + preprocessor=lambda x: x, + tokenizer=lambda x: x, + token_pattern=None, + ngram_range=(1, 3)) + +tfidf_vectorizer.fit(x_train_tokenized) +``` + + + + + TfidfVectorizer(analyzer='word', binary=False, decode_error='strict', + dtype=, encoding='utf-8', input='content', + lowercase=True, max_df=1.0, max_features=10000, min_df=1, + ngram_range=(1, 3), norm='l2', + preprocessor= at 0x7fcda0a72950>, + smooth_idf=True, stop_words=None, strip_accents=None, + sublinear_tf=False, token_pattern=None, + tokenizer= at 0x7fcda0a72730>, use_idf=True, + vocabulary=None) + + + + +```python +# Transform our tokens to tfidf vectors +x_train_tfidf = tfidf_vectorizer.transform( + x_train_tokenized) +``` + + +```python +# Train logistic regression classifier +lr = LogisticRegression(C=0.1, solver='sag') +lr.fit(x_train_tfidf, y_train) +``` + + + + + LogisticRegression(C=0.1, class_weight=None, dual=False, fit_intercept=True, + intercept_scaling=1, max_iter=100, multi_class='warn', + n_jobs=None, penalty='l2', random_state=None, solver='sag', + tol=0.0001, verbose=0, warm_start=False) + + + + +```python +# These are the models we'll deploy +with open('tfidf_vectorizer.model', 'wb') as model_file: + dill.dump(tfidf_vectorizer, model_file) +with open('lr.model', 'wb') as model_file: + dill.dump(lr, model_file) +``` + +## 2) Build your containerized model + + +```python +# This is the class we will use to deploy +!cat RedditClassifier.py +``` + + import dill + + from ml_utils import CleanTextTransformer, SpacyTokenTransformer + + class RedditClassifier(object): + def __init__(self): + + self._clean_text_transformer = CleanTextTransformer() + self._spacy_tokenizer = SpacyTokenTransformer() + + with open('tfidf_vectorizer.model', 'rb') as model_file: + self._tfidf_vectorizer = dill.load(model_file) + + with open('lr.model', 'rb') as model_file: + self._lr_model = dill.load(model_file) + + def predict(self, X, feature_names): + clean_text = self._clean_text_transformer.transform(X) + spacy_tokens = self._spacy_tokenizer.transform(clean_text) + tfidf_features = self._tfidf_vectorizer.transform(spacy_tokens) + predictions = self._lr_model.predict_proba(tfidf_features) + return predictions + + + + +```python +# test that our model works +from RedditClassifier import RedditClassifier +# With one sample +sample = x_test[0:1] +print(sample) +print(RedditClassifier().predict(sample, ["feature_name"])) +``` + + ['This is the study that the article is based on:\r\n\r\nhttps://www.nature.com/articles/nature25778.epdf'] + [[0.82767095 0.17232905]] + + +### Create Docker Image with the S2i utility +Using the S2I command line interface we wrap our current model to seve it through the Seldon interface + + +```python +# To create a docker image we need to create the .s2i folder configuration as below: +!cat .s2i/environment +``` + + MODEL_NAME=RedditClassifier + API_TYPE=REST + SERVICE_TYPE=MODEL + PERSISTENCE=0 + + + +```python +# As well as a requirements.txt file with all the relevant dependencies +!cat requirements.txt +``` + + scipy>= 0.13.3 + scikit-learn>=0.18 + spacy==2.0.18 + dill==0.2.9 + seldon-core==0.2.7 + + + +```python +!s2i build . seldonio/seldon-core-s2i-python3:0.6 reddit-classifier:0.1 +``` + + ---> Installing application source... + ---> Installing dependencies ... + Looking in links: /whl + Collecting scipy>=0.13.3 (from -r requirements.txt (line 1)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/72/4c/5f81e7264b0a7a8bd570810f48cd346ba36faedbd2ba255c873ad556de76/scipy-1.3.0-cp36-cp36m-manylinux1_x86_64.whl (25.2MB) + Collecting scikit-learn>=0.18 (from -r requirements.txt (line 2)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/85/04/49633f490f726da6e454fddc8e938bbb5bfed2001681118d3814c219b723/scikit_learn-0.21.2-cp36-cp36m-manylinux1_x86_64.whl (6.7MB) + Collecting spacy==2.0.18 (from -r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/ae/6e/a89da6b5c83f8811e46e3a9270c1aed90e9b9ee6c60faf52b7239e5d3d69/spacy-2.0.18-cp36-cp36m-manylinux1_x86_64.whl (25.2MB) + Collecting dill==0.2.9 (from -r requirements.txt (line 4)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/fe/42/bfe2e0857bc284cbe6a011d93f2a9ad58a22cb894461b199ae72cfef0f29/dill-0.2.9.tar.gz (150kB) + Requirement already satisfied: seldon-core==0.2.7 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 5)) (0.2.7) + Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from scipy>=0.13.3->-r requirements.txt (line 1)) (1.16.3) + Collecting joblib>=0.11 (from scikit-learn>=0.18->-r requirements.txt (line 2)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/cd/c1/50a758e8247561e58cb87305b1e90b171b8c767b15b12a1734001f41d356/joblib-0.13.2-py2.py3-none-any.whl (278kB) + Collecting murmurhash<1.1.0,>=0.28.0 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/a6/e6/63f160a4fdf0e875d16b28f972083606d8d54f56cd30cb8929f9a1ee700e/murmurhash-1.0.2-cp36-cp36m-manylinux1_x86_64.whl + Collecting thinc<6.13.0,>=6.12.1 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/db/a7/46640a46fd707aeb204aa4257a70974b6a22a0204ba703164d803215776f/thinc-6.12.1-cp36-cp36m-manylinux1_x86_64.whl (1.9MB) + Collecting plac<1.0.0,>=0.9.6 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/9e/9b/62c60d2f5bc135d2aa1d8c8a86aaf84edb719a59c7f11a4316259e61a298/plac-0.9.6-py2.py3-none-any.whl + Collecting ujson>=1.35 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/16/c4/79f3409bc710559015464e5f49b9879430d8f87498ecdc335899732e5377/ujson-1.35.tar.gz (192kB) + Collecting regex==2018.01.10 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/76/f4/7146c3812f96fcaaf2d06ff6862582302626a59011ccb6f2833bb38d80f7/regex-2018.01.10.tar.gz (612kB) + Requirement already satisfied: requests<3.0.0,>=2.13.0 in /usr/local/lib/python3.6/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (2.21.0) + Collecting preshed<2.1.0,>=2.0.1 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/20/93/f222fb957764a283203525ef20e62008675fd0a14ffff8cc1b1490147c63/preshed-2.0.1-cp36-cp36m-manylinux1_x86_64.whl (83kB) + Collecting cymem<2.1.0,>=2.0.2 (from spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/3d/61/9b0520c28eb199a4b1ca667d96dd625bba003c14c75230195f9691975f85/cymem-2.0.2-cp36-cp36m-manylinux1_x86_64.whl + Requirement already satisfied: jaeger-client in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (4.0.0) + Requirement already satisfied: Flask-OpenTracing==0.2.0 in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (0.2.0) + Requirement already satisfied: grpcio in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.20.1) + Requirement already satisfied: tensorflow in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.1) + Requirement already satisfied: grpcio-opentracing in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.4) + Requirement already satisfied: flatbuffers in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.11) + Requirement already satisfied: pyyaml in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (5.1) + Requirement already satisfied: protobuf in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.7.1) + Requirement already satisfied: opentracing<2,>=1.2.2 in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.3.0) + Requirement already satisfied: flask-cors in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.0.7) + Requirement already satisfied: flask in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.2) + Requirement already satisfied: redis in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.2.1) + Collecting tqdm<5.0.0,>=4.10.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/45/af/685bf3ce889ea191f3b916557f5677cc95a5e87b2fa120d74b5dd6d049d0/tqdm-4.32.1-py2.py3-none-any.whl (49kB) + Collecting msgpack<0.6.0,>=0.5.6 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/22/4e/dcf124fd97e5f5611123d6ad9f40ffd6eb979d1efdc1049e28a795672fcd/msgpack-0.5.6-cp36-cp36m-manylinux1_x86_64.whl (315kB) + Requirement already satisfied: six<2.0.0,>=1.10.0 in /usr/local/lib/python3.6/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (1.12.0) + Collecting wrapt<1.11.0,>=1.10.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/a0/47/66897906448185fcb77fc3c2b1bc20ed0ecca81a0f2f88eda3fc5a34fc3d/wrapt-1.10.11.tar.gz + Collecting msgpack-numpy<0.4.4 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/ad/45/464be6da85b5ca893cfcbd5de3b31a6710f636ccb8521b17bd4110a08d94/msgpack_numpy-0.4.3.2-py2.py3-none-any.whl + Collecting cytoolz<0.10,>=0.9.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/36/f4/9728ba01ccb2f55df9a5af029b48ba0aaca1081bbd7823ea2ee223ba7a42/cytoolz-0.9.0.1.tar.gz (443kB) + Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2019.3.9) + Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (1.24.2) + Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2.8) + Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (3.0.4) + Requirement already satisfied: threadloop<2,>=1 in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.2) + Requirement already satisfied: tornado<5,>=4.3 in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (4.5.3) + Requirement already satisfied: thrift in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.11.0) + Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.0) + Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.9) + Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.33.1) + Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.7) + Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.7.1) + Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.0) + Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.7.1) + Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.1) + Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.2.2) + Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf->seldon-core==0.2.7->-r requirements.txt (line 5)) (41.0.1) + Requirement already satisfied: itsdangerous>=0.24 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.0) + Requirement already satisfied: click>=5.1 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (7.0) + Requirement already satisfied: Jinja2>=2.10 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.10.1) + Requirement already satisfied: Werkzeug>=0.14 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.15.2) + Collecting toolz>=0.8.0 (from cytoolz<0.10,>=0.9.0->thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + Downloading https://files.pythonhosted.org/packages/14/d0/a73c15bbeda3d2e7b381a36afb0d9cd770a9f4adc5d1532691013ba881db/toolz-0.9.0.tar.gz (45kB) + Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.9.0) + Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.0.0) + Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (3.1) + Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.6/site-packages (from Jinja2>=2.10->flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.1) + Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (5.2.0) + Building wheels for collected packages: dill, ujson, regex, wrapt, cytoolz, toolz + Building wheel for dill (setup.py): started + Building wheel for dill (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/5b/d7/0f/e58eae695403de585269f4e4a94e0cd6ca60ec0c202936fa4a + Building wheel for ujson (setup.py): started + Building wheel for ujson (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/28/77/e4/0311145b9c2e2f01470e744855131f9e34d6919687550f87d1 + Building wheel for regex (setup.py): started + Building wheel for regex (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/74/17/3f/c77bba99efd74ba1a19862c9dd97f4b6d735e2826721dc00ff + Building wheel for wrapt (setup.py): started + Building wheel for wrapt (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/48/5d/04/22361a593e70d23b1f7746d932802efe1f0e523376a74f321e + Building wheel for cytoolz (setup.py): started + Building wheel for cytoolz (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/88/f3/11/9817b001e59ab04889e8cffcbd9087e2e2155b9ebecfc8dd38 + Building wheel for toolz (setup.py): started + Building wheel for toolz (setup.py): finished with status 'done' + Stored in directory: /root/.cache/pip/wheels/f4/0c/f6/ce6b2d1aa459ee97cc3c0f82236302bd62d89c86c700219463 + Successfully built dill ujson regex wrapt cytoolz toolz + Installing collected packages: scipy, joblib, scikit-learn, murmurhash, tqdm, plac, msgpack, dill, wrapt, msgpack-numpy, cymem, preshed, toolz, cytoolz, thinc, ujson, regex, spacy + Successfully installed cymem-2.0.2 cytoolz-0.9.0.1 dill-0.2.9 joblib-0.13.2 msgpack-0.5.6 msgpack-numpy-0.4.3.2 murmurhash-1.0.2 plac-0.9.6 preshed-2.0.1 regex-2018.1.10 scikit-learn-0.21.2 scipy-1.3.0 spacy-2.0.18 thinc-6.12.1 toolz-0.9.0 tqdm-4.32.1 ujson-1.35 wrapt-1.10.11 + WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + WARNING: You are using pip version 19.1, however version 19.1.1 is available. + You should consider upgrading via the 'pip install --upgrade pip' command. + Build completed successfully + + +## 3) Test your model as a docker container + + +```python +# Remove previously deployed containers for this model +!docker rm -f reddit_predictor +``` + + Error: No such container: reddit_predictor + + + +```python +!docker run --name "reddit_predictor" -d --rm -p 5001:5000 reddit-classifier:0.1 +``` + + be29c6a00adec0f708dc5a1c83613e0656fddc06daba4ca02d93b5a7ece9b92b + + +### Make sure you wait for language model +SpaCy will download the English language model, so you have to make sure the container finishes downloading it before it can be used. You can view this by running the logs until you see "Linking successful". + + +```python +# Here we need to wait until we see "Linking successful", as it's downloading the Spacy English model +# You can hit stop when this happens +!docker logs -t -f reddit_predictor +``` + + 2019-05-27T13:50:12.739381600Z starting microservice + 2019-05-27T13:50:14.023399000Z 2019-05-27 13:50:14,023 - seldon_core.microservice:main:154 - INFO: Starting microservice.py:main + 2019-05-27T13:50:14.024836400Z 2019-05-27 13:50:14,024 - seldon_core.microservice:main:185 - INFO: Annotations: {} + 2019-05-27T13:50:14.686919400Z Collecting en_core_web_sm==2.0.0 from https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz#egg=en_core_web_sm==2.0.0 + 2019-05-27T13:50:15.402484400Z Downloading https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz (37.4MB) + 2019-05-27T13:50:47.771818100Z Building wheels for collected packages: en-core-web-sm + 2019-05-27T13:50:47.772287600Z Building wheel for en-core-web-sm (setup.py): started + 2019-05-27T13:50:49.845376700Z Building wheel for en-core-web-sm (setup.py): finished with status 'done' + 2019-05-27T13:50:49.845641500Z Stored in directory: /tmp/pip-ephem-wheel-cache-wszfsf1z/wheels/54/7c/d8/f86364af8fbba7258e14adae115f18dd2c91552406edc3fdaa + 2019-05-27T13:50:50.163985100Z Successfully built en-core-web-sm + 2019-05-27T13:50:50.164057000Z Installing collected packages: en-core-web-sm + 2019-05-27T13:50:50.242852700Z Successfully installed en-core-web-sm-2.0.0 + 2019-05-27T13:50:50.400850200Z WARNING: You are using pip version 19.1, however version 19.1.1 is available. + 2019-05-27T13:50:50.400901100Z You should consider upgrading via the 'pip install --upgrade pip' command. + 2019-05-27T13:50:51.728895100Z --- Logging error --- + 2019-05-27T13:50:51.728944900Z Traceback (most recent call last): + 2019-05-27T13:50:51.728954200Z File "/usr/local/lib/python3.6/logging/__init__.py", line 994, in emit + 2019-05-27T13:50:51.728958900Z msg = self.format(record) + 2019-05-27T13:50:51.728963000Z File "/usr/local/lib/python3.6/logging/__init__.py", line 840, in format + 2019-05-27T13:50:51.728966900Z return fmt.format(record) + 2019-05-27T13:50:51.728970500Z File "/usr/local/lib/python3.6/logging/__init__.py", line 577, in format + 2019-05-27T13:50:51.728974300Z record.message = record.getMessage() + 2019-05-27T13:50:51.728977900Z File "/usr/local/lib/python3.6/logging/__init__.py", line 338, in getMessage + 2019-05-27T13:50:51.728981600Z msg = msg % self.args + 2019-05-27T13:50:51.728985100Z TypeError: not all arguments converted during string formatting + 2019-05-27T13:50:51.728988800Z Call stack: + 2019-05-27T13:50:51.728992300Z File "/usr/local/bin/seldon-core-microservice", line 10, in + 2019-05-27T13:50:51.728996500Z sys.exit(main()) + 2019-05-27T13:50:51.729000000Z File "/usr/local/lib/python3.6/site-packages/seldon_core/microservice.py", line 189, in main + 2019-05-27T13:50:51.729004000Z logger.info("Importing ",args.interface_name) + 2019-05-27T13:50:51.729007800Z Message: 'Importing ' + 2019-05-27T13:50:51.729011400Z Arguments: ('RedditClassifier',) + 2019-05-27T13:50:51.729025900Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfTransformer from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk. + 2019-05-27T13:50:51.729030000Z UserWarning) + 2019-05-27T13:50:51.729033400Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfVectorizer from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk. + 2019-05-27T13:50:51.729036900Z UserWarning) + 2019-05-27T13:50:51.729040100Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator LogisticRegression from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk. + 2019-05-27T13:50:51.729044000Z UserWarning) + 2019-05-27T13:50:51.729047500Z 2019-05-27 13:50:51,727 - seldon_core.microservice:main:226 - INFO: REST microservice running on port 5000 + 2019-05-27T13:50:51.729051200Z 2019-05-27 13:50:51,728 - seldon_core.microservice:main:260 - INFO: Starting servers + 2019-05-27T13:50:51.730423900Z + 2019-05-27T13:50:51.730464700Z  Linking successful + 2019-05-27T13:50:51.730473700Z /usr/local/lib/python3.6/site-packages/en_core_web_sm --> + 2019-05-27T13:50:51.730477700Z /usr/local/lib/python3.6/site-packages/spacy/data/en_core_web_sm + 2019-05-27T13:50:51.730481100Z + 2019-05-27T13:50:51.730484300Z You can now load the model via spacy.load('en_core_web_sm') + 2019-05-27T13:50:51.730487600Z + 2019-05-27T13:50:51.743475000Z * Serving Flask app "seldon_core.wrapper" (lazy loading) + 2019-05-27T13:50:51.743530400Z * Environment: production + 2019-05-27T13:50:51.743538900Z WARNING: Do not use the development server in a production environment. + 2019-05-27T13:50:51.743542800Z Use a production WSGI server instead. + 2019-05-27T13:50:51.743546000Z * Debug mode: off + 2019-05-27T13:50:51.760002000Z 2019-05-27 13:50:51,759 - werkzeug:_log:122 - INFO: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit) + ^C + + + +```python +# We now test the REST endpoint expecting the same result +endpoint = "0.0.0.0:5001" +batch = sample +payload_type = "ndarray" + +sc = SeldonClient(microservice_endpoint=endpoint) +response = sc.microservice( + data=batch, + method="predict", + payload_type=payload_type, + names=["tfidf"]) + +print(response) +``` + + Success:True message: + Request: + data { + names: "tfidf" + ndarray { + values { + string_value: "This is the study that the article is based on:\r\n\r\nhttps://www.nature.com/articles/nature25778.epdf" + } + } + } + + Response: + meta { + } + data { + names: "t:0" + names: "t:1" + ndarray { + values { + list_value { + values { + number_value: 0.8276709475641506 + } + values { + number_value: 0.1723290524358494 + } + } + } + } + } + + + + +```python +# We now stop it to run it in docker +!docker stop reddit_predictor +``` + + reddit_predictor + + +## 4) Run Seldon in your kubernetes cluster +In order to run Seldon we need to make sure that Helm is initialised and Tiller is running. + +For this we can run the following initialisation and waiting commands. + + +```python +# If not running you can install it +# First initialise helm +!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default +!helm init +!kubectl rollout status deploy/tiller-deploy -n kube-system +``` + + clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created + $HELM_HOME has been configured at /home/alejandro/.helm. + Warning: Tiller is already installed in the cluster. + (Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.) + Happy Helming! + deployment "tiller-deploy" successfully rolled out + + +Now we can install run the Seldon Operator using the latest Helm charts + + +```python +!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts +``` + + NAME: seldon-core-operator + LAST DEPLOYED: Mon May 27 15:04:30 2019 + NAMESPACE: default + STATUS: DEPLOYED + + RESOURCES: + ==> v1/ClusterRole + NAME AGE + seldon-operator-manager-role 0s + + ==> v1/ClusterRoleBinding + NAME AGE + seldon-operator-manager-rolebinding 0s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + seldon-operator-controller-manager-0 0/1 ContainerCreating 0 0s + + ==> v1/Secret + NAME TYPE DATA AGE + seldon-operator-webhook-server-secret Opaque 0 0s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + seldon-operator-controller-manager-service ClusterIP 10.101.147.136 443/TCP 0s + + ==> v1/StatefulSet + NAME READY AGE + seldon-operator-controller-manager 0/1 0s + + ==> v1beta1/CustomResourceDefinition + NAME AGE + seldondeployments.machinelearning.seldon.io 0s + + + NOTES: + NOTES: TODO + + + + +And we can make sure that it is actually running with the following command + + +```python +!kubectl get pod | grep seldon +``` + + seldon-operator-controller-manager-0 1/1 Running 1 12s + + +In order for us to be able to reach the model, we will need to set up an ingress. For this we will use ambassador: + + +```python +!helm install stable/ambassador --name ambassador --set image.tag=0.40.2 +``` + + NAME: ambassador + LAST DEPLOYED: Mon May 27 15:04:50 2019 + NAMESPACE: default + STATUS: DEPLOYED + + RESOURCES: + ==> v1/Deployment + NAME READY UP-TO-DATE AVAILABLE AGE + ambassador 0/3 3 0 0s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + ambassador-7bfc87f865-jkxs8 0/1 ContainerCreating 0 0s + ambassador-7bfc87f865-nr7bn 0/1 ContainerCreating 0 0s + ambassador-7bfc87f865-q4lng 0/1 ContainerCreating 0 0s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ambassador LoadBalancer 10.101.89.32 localhost 80:30004/TCP,443:31350/TCP 0s + ambassador-admins ClusterIP 10.98.228.159 8877/TCP 0s + + ==> v1/ServiceAccount + NAME SECRETS AGE + ambassador 1 1s + + ==> v1beta1/ClusterRole + NAME AGE + ambassador 1s + + ==> v1beta1/ClusterRoleBinding + NAME AGE + ambassador 1s + + + NOTES: + Congratuations! You've successfully installed Ambassador. + + For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io. + + To get the IP address of Ambassador, run the following commands: + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w --namespace default ambassador' + + On GKE/Azure: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + + On AWS: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + + echo http://$SERVICE_IP: + + + +We can now see the ambassador service is running. In our case we can reach it through the external IP which is our localhost, but if you are using a cloud provider, make sure you have access to the ambassador endpoint. + + +```python +!kubectl get svc ambassador +``` + + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ambassador LoadBalancer 10.101.89.32 localhost 80:30004/TCP,443:31350/TCP 2m43s + + +## 5) Deploy your model with Seldon +We can now deploy our model by using the Seldon graph definition: + + +```python +# We'll use our seldon deployment file +!cat reddit_clf.json +``` + + { + "apiVersion": "machinelearning.seldon.io/v1alpha2", + "kind": "SeldonDeployment", + "metadata": { + "labels": { + "app": "seldon" + }, + "name": "reddit-classifier" + }, + "spec": { + "annotations": { + "project_name": "Reddit classifier", + "deployment_version": "v1" + }, + "name": "reddit-classifier", + "oauth_key": "oauth-key", + "oauth_secret": "oauth-secret", + "predictors": [ + { + "componentSpecs": [{ + "spec": { + "containers": [ + { + "image": "reddit-classifier:0.1", + "imagePullPolicy": "IfNotPresent", + "name": "classifier", + "resources": { + "requests": { + "memory": "1Mi" + } + } + } + ], + "terminationGracePeriodSeconds": 20 + } + }], + "graph": { + "children": [], + "name": "classifier", + "endpoint": { + "type" : "REST" + }, + "type": "MODEL" + }, + "name": "single-model", + "replicas": 1, + "annotations": { + "predictor_version" : "v1" + } + } + ] + } + } + + + +```python +!kubectl apply -f reddit_clf.json +``` + + seldondeployment.machinelearning.seldon.io/reddit-classifier created + + + +```python +!kubectl get pods +``` + + NAME READY STATUS RESTARTS AGE + ambassador-7bfc87f865-jkxs8 1/1 Running 0 5m2s + ambassador-7bfc87f865-nr7bn 1/1 Running 0 5m2s + ambassador-7bfc87f865-q4lng 1/1 Running 0 5m2s + reddit-classifier-single-model-9199e4b-bcc5cdcc-g8j2q 2/2 Running 1 77s + seldon-operator-controller-manager-0 1/1 Running 1 5m23s + + +## 6) Interact with your model through API +Now that our Seldon Deployment is live, we are able to interact with it through its API. + +There are two options in which we can interact with our new model. These are: + +a) Using CURL from the CLI (or another rest client like Postman) + +b) Using the Python SeldonClient + +#### a) Using CURL from the CLI + + +```bash +%%bash +curl -X POST -H 'Content-Type: application/json' \ + -d "{'data': {'names': ['text'], 'ndarray': ['Hello world this is a test']}}" \ + http://127.0.0.1/seldon/default/reddit-classifier/api/v0.1/predictions +``` + + { + "meta": { + "puid": "bvj1rjiq3vvnieo0oir4h7bf6f", + "tags": { + }, + "routing": { + }, + "requestPath": { + "classifier": "reddit-classifier:0.1" + }, + "metrics": [] + }, + "data": { + "names": ["t:0", "t:1"], + "ndarray": [[0.6815614604065544, 0.3184385395934456]] + } + } + + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed + 100 372 100 300 100 72 1522 365 --:--:-- --:--:-- --:--:-- 1897 + + +#### b) Using the Python SeldonClient + + +```python +from seldon_core.seldon_client import SeldonClient +import numpy as np + +host = "localhost" +port = "80" # Make sure you use the port above +batch = np.array(["Hello world this is a test"]) +payload_type = "ndarray" +deployment_name="reddit-classifier" +transport="rest" +namespace="default" + +sc = SeldonClient( + gateway="ambassador", + ambassador_endpoint=host + ":" + port, + namespace=namespace) + +client_prediction = sc.predict( + data=batch, + deployment_name=deployment_name, + names=["text"], + payload_type=payload_type, + transport="rest") + +print(client_prediction) +``` + + Success:True message: + Request: + data { + names: "text" + ndarray { + values { + string_value: "Hello world this is a test" + } + } + } + + Response: + meta { + puid: "uld2famhfrb97vd7regu0q7k32" + requestPath { + key: "classifier" + value: "reddit-classifier:0.1" + } + } + data { + names: "t:0" + names: "t:1" + ndarray { + values { + list_value { + values { + number_value: 0.6815614604065544 + } + values { + number_value: 0.3184385395934456 + } + } + } + } + } + + + +## 7) Clean your environment + + +```python +!kubectl delete -f reddit_clf.json +``` + + +```python +!helm del --purge ambassador +``` + + release "ambassador" deleted + + + +```python +!helm del --purge seldon-core-operator +``` + + release "seldon-core-operator" deleted + + + +```python + +``` diff --git a/examples/models/sklearn_spacy_text/requirements.txt b/examples/models/sklearn_spacy_text/requirements.txt index 021017680f..8d66c4531a 100644 --- a/examples/models/sklearn_spacy_text/requirements.txt +++ b/examples/models/sklearn_spacy_text/requirements.txt @@ -2,3 +2,4 @@ scipy>= 0.13.3 scikit-learn>=0.18 spacy==2.0.18 dill==0.2.9 +seldon-core==0.2.7 diff --git a/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example.ipynb b/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example.ipynb index 1d84c72425..73ef738c1a 100644 --- a/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example.ipynb +++ b/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example.ipynb @@ -4,98 +4,62 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Reddit classification\n", + "# SKLearn Spacy Reddit Text Classification Example\n", "\n", - "We are wrapping a logistic regression model that receives the text output from a tfidf model that stores 1000 features.\n", + "In this example we will be buiding a text classifier using the reddit content moderation dataset.\n", "\n", - "## Dependencies\n", + "For this, we will be using SpaCy for the word tokenization and lemmatization. \n", "\n", - "### Training\n", - "* Spacy\n", - "* Sklearn\n", - "* Seldon-core\n", + "The classification will be done with a Logistic Regression binary classifier.\n", "\n", - "### Seldon\n", - "* Sklearn\n", - "* Dill\n" + "The steps in this tutorial include:\n", + "\n", + "1) Train and build your NLP model\n", + "\n", + "2) Build your containerized model\n", + "\n", + "3) Test your model as a docker container\n", + "\n", + "4) Run Seldon in your kubernetes cluster\n", + "\n", + "5) Deploy your model with Seldon\n", + "\n", + "6) Interact with your model through API\n", + "\n", + "7) Clean your environment\n", + "\n", + "\n", + "### Before you start\n", + "Make sure you install the following dependencies, as they are critical for this example to work:\n", + "\n", + "* Helm v2.13.1+\n", + "* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM)\n", + "* kubectl v1.14+\n", + "* Python 3.6+\n", + "* Python DEV requirements (we'll install them below)\n", + "\n", + "Let's get started! 🚀🔥\n", + "\n", + "## 1) Train and build your NLP model" ] }, { "cell_type": "code", - "execution_count": 49, + "execution_count": null, "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Requirement already satisfied: scipy>=0.13.3 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from -r requirements.txt (line 1)) (1.2.1)\n", - "Requirement already satisfied: scikit-learn>=0.18 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from -r requirements.txt (line 2)) (0.20.3)\n", - "Collecting spacy==2.0.18 (from -r requirements.txt (line 3))\n", - " Using cached https://files.pythonhosted.org/packages/cd/70/65504a011d7b262e73cfe470c36ca245a1f8e45b3b6661081289ffd72009/spacy-2.0.18-cp37-cp37m-manylinux1_x86_64.whl\n", - "Requirement already satisfied: dill==0.2.9 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from -r requirements.txt (line 4)) (0.2.9)\n", - "Requirement already satisfied: numpy>=1.8.2 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from scikit-learn>=0.18->-r requirements.txt (line 2)) (1.16.3)\n", - "Requirement already satisfied: ujson>=1.35 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (1.35)\n", - "Requirement already satisfied: murmurhash<1.1.0,>=0.28.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (1.0.2)\n", - "Requirement already satisfied: cymem<2.1.0,>=2.0.2 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (2.0.2)\n", - "Requirement already satisfied: preshed<2.1.0,>=2.0.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (2.0.1)\n", - "Collecting regex==2018.01.10 (from spacy==2.0.18->-r requirements.txt (line 3))\n", - "Requirement already satisfied: plac<1.0.0,>=0.9.6 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (0.9.6)\n", - "Requirement already satisfied: thinc<6.13.0,>=6.12.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (6.12.1)\n", - "Requirement already satisfied: requests<3.0.0,>=2.13.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (2.21.0)\n", - "Collecting msgpack<0.6.0,>=0.5.6 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", - "Requirement already satisfied: msgpack-numpy<0.4.4 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (0.4.3.2)\n", - "Requirement already satisfied: cytoolz<0.10,>=0.9.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (0.9.0.1)\n", - "Requirement already satisfied: wrapt<1.11.0,>=1.10.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (1.10.11)\n", - "Requirement already satisfied: tqdm<5.0.0,>=4.10.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (4.31.1)\n", - "Requirement already satisfied: six<2.0.0,>=1.10.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (1.12.0)\n", - "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (3.0.4)\n", - "Requirement already satisfied: idna<2.9,>=2.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2.8)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2019.3.9)\n", - "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (1.24.2)\n", - "Requirement already satisfied: toolz>=0.8.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from cytoolz<0.10,>=0.9.0->thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (0.9.0)\n", - "Installing collected packages: regex, spacy, msgpack\n", - " Found existing installation: regex 2019.4.14\n", - " Uninstalling regex-2019.4.14:\n", - " Successfully uninstalled regex-2019.4.14\n", - " Found existing installation: spacy 2.0.16\n", - " Uninstalling spacy-2.0.16:\n", - " Successfully uninstalled spacy-2.0.16\n", - " Found existing installation: msgpack 0.6.1\n", - " Uninstalling msgpack-0.6.1:\n", - " Successfully uninstalled msgpack-0.6.1\n", - "Successfully installed msgpack-0.5.6 regex-2018.1.10 spacy-2.0.18\n" - ] - } - ], + "outputs": [], "source": [ "# Let's first install any dependencies\n", - "!pip install -r requirements.txt\n", - "!pip install seldon-core" + "!pip install -r requirements.txt" ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 21, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\u001b[93m Linking successful\u001b[0m\n", - " /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/en_core_web_sm\n", - " -->\n", - " /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/spacy/data/en_core_web_sm\n", - "\n", - " You can now load the model via spacy.load('en_core_web_sm')\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "import pandas as pd \n", "from sklearn.model_selection import train_test_split\n", @@ -112,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -198,7 +162,7 @@ "4 0 " ] }, - "execution_count": 2, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -219,16 +183,16 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 6, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" }, @@ -252,7 +216,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ @@ -267,7 +231,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ @@ -278,7 +242,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -289,7 +253,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -299,14 +263,14 @@ " dtype=, encoding='utf-8', input='content',\n", " lowercase=True, max_df=1.0, max_features=10000, min_df=1,\n", " ngram_range=(1, 3), norm='l2',\n", - " preprocessor= at 0x7fce08047378>,\n", + " preprocessor= at 0x7fcda0a72950>,\n", " smooth_idf=True, stop_words=None, strip_accents=None,\n", " sublinear_tf=False, token_pattern=None,\n", - " tokenizer= at 0x7fce080472f0>, use_idf=True,\n", + " tokenizer= at 0x7fcda0a72730>, use_idf=True,\n", " vocabulary=None)" ] }, - "execution_count": 10, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -325,7 +289,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -336,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 31, "metadata": {}, "outputs": [ { @@ -348,7 +312,7 @@ " tol=0.0001, verbose=0, warm_start=False)" ] }, - "execution_count": 13, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -361,7 +325,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 32, "metadata": {}, "outputs": [], "source": [ @@ -372,9 +336,16 @@ " dill.dump(lr, model_file)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2) Build your containerized model" + ] + }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 33, "metadata": {}, "outputs": [ { @@ -414,7 +385,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 34, "metadata": {}, "outputs": [ { @@ -422,7 +393,7 @@ "output_type": "stream", "text": [ "['This is the study that the article is based on:\\r\\n\\r\\nhttps://www.nature.com/articles/nature25778.epdf']\n", - "[[0.82767056 0.17232944]]\n" + "[[0.82767095 0.17232905]]\n" ] } ], @@ -439,13 +410,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Create Docker Image\n", + "### Create Docker Image with the S2i utility\n", "Using the S2I command line interface we wrap our current model to seve it through the Seldon interface" ] }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 35, "metadata": {}, "outputs": [ { @@ -466,7 +437,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 36, "metadata": {}, "outputs": [ { @@ -476,7 +447,8 @@ "scipy>= 0.13.3\r\n", "scikit-learn>=0.18\r\n", "spacy==2.0.18\r\n", - "dill==0.2.9\r\n" + "dill==0.2.9\r\n", + "seldon-core==0.2.7\r\n" ] } ], @@ -487,7 +459,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 37, "metadata": { "scrolled": true }, @@ -504,20 +476,27 @@ "Downloading https://files.pythonhosted.org/packages/72/4c/5f81e7264b0a7a8bd570810f48cd346ba36faedbd2ba255c873ad556de76/scipy-1.3.0-cp36-cp36m-manylinux1_x86_64.whl (25.2MB)\n", "Collecting scikit-learn>=0.18 (from -r requirements.txt (line 2))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/90/c7/401c231c445fb6fad135e92197da9c3e77983de169ff1887cc18af94498d/scikit_learn-0.21.1-cp36-cp36m-manylinux1_x86_64.whl (6.7MB)\n", + "Downloading https://files.pythonhosted.org/packages/85/04/49633f490f726da6e454fddc8e938bbb5bfed2001681118d3814c219b723/scikit_learn-0.21.2-cp36-cp36m-manylinux1_x86_64.whl (6.7MB)\n", "Collecting spacy==2.0.18 (from -r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/ae/6e/a89da6b5c83f8811e46e3a9270c1aed90e9b9ee6c60faf52b7239e5d3d69/spacy-2.0.18-cp36-cp36m-manylinux1_x86_64.whl (25.2MB)\n", "Collecting dill==0.2.9 (from -r requirements.txt (line 4))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/fe/42/bfe2e0857bc284cbe6a011d93f2a9ad58a22cb894461b199ae72cfef0f29/dill-0.2.9.tar.gz (150kB)\n", + "Requirement already satisfied: seldon-core==0.2.7 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 5)) (0.2.7)\n", "Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from scipy>=0.13.3->-r requirements.txt (line 1)) (1.16.3)\n", "Collecting joblib>=0.11 (from scikit-learn>=0.18->-r requirements.txt (line 2))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/cd/c1/50a758e8247561e58cb87305b1e90b171b8c767b15b12a1734001f41d356/joblib-0.13.2-py2.py3-none-any.whl (278kB)\n", - "Collecting preshed<2.1.0,>=2.0.1 (from spacy==2.0.18->-r requirements.txt (line 3))\n", + "Collecting murmurhash<1.1.0,>=0.28.0 (from spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/20/93/f222fb957764a283203525ef20e62008675fd0a14ffff8cc1b1490147c63/preshed-2.0.1-cp36-cp36m-manylinux1_x86_64.whl (83kB)\n", + "Downloading https://files.pythonhosted.org/packages/a6/e6/63f160a4fdf0e875d16b28f972083606d8d54f56cd30cb8929f9a1ee700e/murmurhash-1.0.2-cp36-cp36m-manylinux1_x86_64.whl\n", + "Collecting thinc<6.13.0,>=6.12.1 (from spacy==2.0.18->-r requirements.txt (line 3))\n", + " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", + "Downloading https://files.pythonhosted.org/packages/db/a7/46640a46fd707aeb204aa4257a70974b6a22a0204ba703164d803215776f/thinc-6.12.1-cp36-cp36m-manylinux1_x86_64.whl (1.9MB)\n", + "Collecting plac<1.0.0,>=0.9.6 (from spacy==2.0.18->-r requirements.txt (line 3))\n", + " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", + "Downloading https://files.pythonhosted.org/packages/9e/9b/62c60d2f5bc135d2aa1d8c8a86aaf84edb719a59c7f11a4316259e61a298/plac-0.9.6-py2.py3-none-any.whl\n", "Collecting ujson>=1.35 (from spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/16/c4/79f3409bc710559015464e5f49b9879430d8f87498ecdc335899732e5377/ujson-1.35.tar.gz (192kB)\n", @@ -525,41 +504,75 @@ " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/76/f4/7146c3812f96fcaaf2d06ff6862582302626a59011ccb6f2833bb38d80f7/regex-2018.01.10.tar.gz (612kB)\n", "Requirement already satisfied: requests<3.0.0,>=2.13.0 in /usr/local/lib/python3.6/site-packages (from spacy==2.0.18->-r requirements.txt (line 3)) (2.21.0)\n", - "Collecting plac<1.0.0,>=0.9.6 (from spacy==2.0.18->-r requirements.txt (line 3))\n", - " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/9e/9b/62c60d2f5bc135d2aa1d8c8a86aaf84edb719a59c7f11a4316259e61a298/plac-0.9.6-py2.py3-none-any.whl\n", - "Collecting thinc<6.13.0,>=6.12.1 (from spacy==2.0.18->-r requirements.txt (line 3))\n", - " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/db/a7/46640a46fd707aeb204aa4257a70974b6a22a0204ba703164d803215776f/thinc-6.12.1-cp36-cp36m-manylinux1_x86_64.whl (1.9MB)\n", + "Collecting preshed<2.1.0,>=2.0.1 (from spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Collecting murmurhash<1.1.0,>=0.28.0 (from spacy==2.0.18->-r requirements.txt (line 3))\n", - "Downloading https://files.pythonhosted.org/packages/a6/e6/63f160a4fdf0e875d16b28f972083606d8d54f56cd30cb8929f9a1ee700e/murmurhash-1.0.2-cp36-cp36m-manylinux1_x86_64.whl\n", + "Downloading https://files.pythonhosted.org/packages/20/93/f222fb957764a283203525ef20e62008675fd0a14ffff8cc1b1490147c63/preshed-2.0.1-cp36-cp36m-manylinux1_x86_64.whl (83kB)\n", "Collecting cymem<2.1.0,>=2.0.2 (from spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/3d/61/9b0520c28eb199a4b1ca667d96dd625bba003c14c75230195f9691975f85/cymem-2.0.2-cp36-cp36m-manylinux1_x86_64.whl\n", - "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (3.0.4)\n", - "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2019.3.9)\n", - "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (1.24.2)\n", - "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2.8)\n", - "Collecting wrapt<1.11.0,>=1.10.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", - " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/a0/47/66897906448185fcb77fc3c2b1bc20ed0ecca81a0f2f88eda3fc5a34fc3d/wrapt-1.10.11.tar.gz\n", + "Requirement already satisfied: jaeger-client in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (4.0.0)\n", + "Requirement already satisfied: Flask-OpenTracing==0.2.0 in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (0.2.0)\n", + "Requirement already satisfied: grpcio in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.20.1)\n", + "Requirement already satisfied: tensorflow in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.1)\n", + "Requirement already satisfied: grpcio-opentracing in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.4)\n", + "Requirement already satisfied: flatbuffers in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.11)\n", + "Requirement already satisfied: pyyaml in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (5.1)\n", + "Requirement already satisfied: protobuf in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.7.1)\n", + "Requirement already satisfied: opentracing<2,>=1.2.2 in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.3.0)\n", + "Requirement already satisfied: flask-cors in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.0.7)\n", + "Requirement already satisfied: flask in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.2)\n", + "Requirement already satisfied: redis in /usr/local/lib/python3.6/site-packages (from seldon-core==0.2.7->-r requirements.txt (line 5)) (3.2.1)\n", "Collecting tqdm<5.0.0,>=4.10.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/45/af/685bf3ce889ea191f3b916557f5677cc95a5e87b2fa120d74b5dd6d049d0/tqdm-4.32.1-py2.py3-none-any.whl (49kB)\n", - "Collecting msgpack-numpy<0.4.4 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", - " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/ad/45/464be6da85b5ca893cfcbd5de3b31a6710f636ccb8521b17bd4110a08d94/msgpack_numpy-0.4.3.2-py2.py3-none-any.whl\n", "Collecting msgpack<0.6.0,>=0.5.6 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/22/4e/dcf124fd97e5f5611123d6ad9f40ffd6eb979d1efdc1049e28a795672fcd/msgpack-0.5.6-cp36-cp36m-manylinux1_x86_64.whl (315kB)\n", "Requirement already satisfied: six<2.0.0,>=1.10.0 in /usr/local/lib/python3.6/site-packages (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3)) (1.12.0)\n", + "Collecting wrapt<1.11.0,>=1.10.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", + " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", + "Downloading https://files.pythonhosted.org/packages/a0/47/66897906448185fcb77fc3c2b1bc20ed0ecca81a0f2f88eda3fc5a34fc3d/wrapt-1.10.11.tar.gz\n", + "Collecting msgpack-numpy<0.4.4 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", + " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", + "Downloading https://files.pythonhosted.org/packages/ad/45/464be6da85b5ca893cfcbd5de3b31a6710f636ccb8521b17bd4110a08d94/msgpack_numpy-0.4.3.2-py2.py3-none-any.whl\n", "Collecting cytoolz<0.10,>=0.9.0 (from thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "Downloading https://files.pythonhosted.org/packages/36/f4/9728ba01ccb2f55df9a5af029b48ba0aaca1081bbd7823ea2ee223ba7a42/cytoolz-0.9.0.1.tar.gz (443kB)\n", + "Downloading https://files.pythonhosted.org/packages/36/f4/9728ba01ccb2f55df9a5af029b48ba0aaca1081bbd7823ea2ee223ba7a42/cytoolz-0.9.0.1.tar.gz (443kB)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2019.3.9)\n", + "Requirement already satisfied: urllib3<1.25,>=1.21.1 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (1.24.2)\n", + "Requirement already satisfied: idna<2.9,>=2.5 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (2.8)\n", + "Requirement already satisfied: chardet<3.1.0,>=3.0.2 in /usr/local/lib/python3.6/site-packages (from requests<3.0.0,>=2.13.0->spacy==2.0.18->-r requirements.txt (line 3)) (3.0.4)\n", + "Requirement already satisfied: threadloop<2,>=1 in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.2)\n", + "Requirement already satisfied: tornado<5,>=4.3 in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (4.5.3)\n", + "Requirement already satisfied: thrift in /usr/local/lib/python3.6/site-packages (from jaeger-client->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.11.0)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.0)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.9)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.33.1)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.0.7)\n", + "Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.7.1)\n", + "Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.0)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.7.1)\n", + "Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.13.1)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.2.2)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf->seldon-core==0.2.7->-r requirements.txt (line 5)) (41.0.1)\n", + "Requirement already satisfied: itsdangerous>=0.24 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.0)\n", + "Requirement already satisfied: click>=5.1 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (7.0)\n", + "Requirement already satisfied: Jinja2>=2.10 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.10.1)\n", + "Requirement already satisfied: Werkzeug>=0.14 in /usr/local/lib/python3.6/site-packages (from flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (0.15.2)\n", "Collecting toolz>=0.8.0 (from cytoolz<0.10,>=0.9.0->thinc<6.13.0,>=6.12.1->spacy==2.0.18->-r requirements.txt (line 3))\n", " WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "Downloading https://files.pythonhosted.org/packages/14/d0/a73c15bbeda3d2e7b381a36afb0d9cd770a9f4adc5d1532691013ba881db/toolz-0.9.0.tar.gz (45kB)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.9.0)\n", + "Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (2.0.0)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (3.1)\n", + "Requirement already satisfied: MarkupSafe>=0.23 in /usr/local/lib/python3.6/site-packages (from Jinja2>=2.10->flask->seldon-core==0.2.7->-r requirements.txt (line 5)) (1.1.1)\n", + "Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow->seldon-core==0.2.7->-r requirements.txt (line 5)) (5.2.0)\n", "Building wheels for collected packages: dill, ujson, regex, wrapt, cytoolz, toolz\n", "Building wheel for dill (setup.py): started\n", "Building wheel for dill (setup.py): finished with status 'done'\n", @@ -570,13 +583,7 @@ "Building wheel for regex (setup.py): started\n", "Building wheel for regex (setup.py): finished with status 'done'\n", "Stored in directory: /root/.cache/pip/wheels/74/17/3f/c77bba99efd74ba1a19862c9dd97f4b6d735e2826721dc00ff\n", - "Building wheel for wrapt (setup.py): started\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ + "Building wheel for wrapt (setup.py): started\n", "Building wheel for wrapt (setup.py): finished with status 'done'\n", "Stored in directory: /root/.cache/pip/wheels/48/5d/04/22361a593e70d23b1f7746d932802efe1f0e523376a74f321e\n", "Building wheel for cytoolz (setup.py): started\n", @@ -586,8 +593,8 @@ "Building wheel for toolz (setup.py): finished with status 'done'\n", "Stored in directory: /root/.cache/pip/wheels/f4/0c/f6/ce6b2d1aa459ee97cc3c0f82236302bd62d89c86c700219463\n", "Successfully built dill ujson regex wrapt cytoolz toolz\n", - "Installing collected packages: scipy, joblib, scikit-learn, cymem, preshed, ujson, regex, dill, plac, wrapt, tqdm, msgpack, msgpack-numpy, murmurhash, toolz, cytoolz, thinc, spacy\n", - "Successfully installed cymem-2.0.2 cytoolz-0.9.0.1 dill-0.2.9 joblib-0.13.2 msgpack-0.5.6 msgpack-numpy-0.4.3.2 murmurhash-1.0.2 plac-0.9.6 preshed-2.0.1 regex-2018.1.10 scikit-learn-0.21.1 scipy-1.3.0 spacy-2.0.18 thinc-6.12.1 toolz-0.9.0 tqdm-4.32.1 ujson-1.35 wrapt-1.10.11\n", + "Installing collected packages: scipy, joblib, scikit-learn, murmurhash, tqdm, plac, msgpack, dill, wrapt, msgpack-numpy, cymem, preshed, toolz, cytoolz, thinc, ujson, regex, spacy\n", + "Successfully installed cymem-2.0.2 cytoolz-0.9.0.1 dill-0.2.9 joblib-0.13.2 msgpack-0.5.6 msgpack-numpy-0.4.3.2 murmurhash-1.0.2 plac-0.9.6 preshed-2.0.1 regex-2018.1.10 scikit-learn-0.21.2 scipy-1.3.0 spacy-2.0.18 thinc-6.12.1 toolz-0.9.0 tqdm-4.32.1 ujson-1.35 wrapt-1.10.11\n", "WARNING: Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", "WARNING: You are using pip version 19.1, however version 19.1.1 is available.\n", "You should consider upgrading via the 'pip install --upgrade pip' command.\n", @@ -599,16 +606,23 @@ "!s2i build . seldonio/seldon-core-s2i-python3:0.6 reddit-classifier:0.1" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3) Test your model as a docker container" + ] + }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 38, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "reddit_predictor\r\n" + "Error: No such container: reddit_predictor\r\n" ] } ], @@ -619,14 +633,14 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 39, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "812a02932fb6d61eb90727f99df051a67720a14de59504bbd808f1159fcda65e\r\n" + "be29c6a00adec0f708dc5a1c83613e0656fddc06daba4ca02d93b5a7ece9b92b\r\n" ] } ], @@ -634,9 +648,17 @@ "!docker run --name \"reddit_predictor\" -d --rm -p 5001:5000 reddit-classifier:0.1" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Make sure you wait for language model\n", + "SpaCy will download the English language model, so you have to make sure the container finishes downloading it before it can be used. You can view this by running the logs until you see \"Linking successful\"." + ] + }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 40, "metadata": { "scrolled": true }, @@ -645,59 +667,59 @@ "name": "stdout", "output_type": "stream", "text": [ - "2019-05-21T05:18:10.089008100Z starting microservice\n", - "2019-05-21T05:18:11.567254000Z 2019-05-21 05:18:11,566 - seldon_core.microservice:main:154 - INFO: Starting microservice.py:main\n", - "2019-05-21T05:18:11.568744400Z 2019-05-21 05:18:11,568 - seldon_core.microservice:main:185 - INFO: Annotations: {}\n", - "2019-05-21T05:18:12.629109700Z Collecting en_core_web_sm==2.0.0 from https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz#egg=en_core_web_sm==2.0.0\n", - "2019-05-21T05:18:13.675815500Z Downloading https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz (37.4MB)\n", - "2019-05-21T05:18:22.124982300Z Building wheels for collected packages: en-core-web-sm\n", - "2019-05-21T05:18:22.125493500Z Building wheel for en-core-web-sm (setup.py): started\n", - "2019-05-21T05:18:24.199642200Z Building wheel for en-core-web-sm (setup.py): finished with status 'done'\n", - "2019-05-21T05:18:24.199964600Z Stored in directory: /tmp/pip-ephem-wheel-cache-d7p16zav/wheels/54/7c/d8/f86364af8fbba7258e14adae115f18dd2c91552406edc3fdaa\n", - "2019-05-21T05:18:24.513275700Z Successfully built en-core-web-sm\n", - "2019-05-21T05:18:24.513295200Z Installing collected packages: en-core-web-sm\n", - "2019-05-21T05:18:24.579380500Z Successfully installed en-core-web-sm-2.0.0\n", - "2019-05-21T05:18:24.893582100Z WARNING: You are using pip version 19.1, however version 19.1.1 is available.\n", - "2019-05-21T05:18:24.893610900Z You should consider upgrading via the 'pip install --upgrade pip' command.\n", - "2019-05-21T05:18:26.083684000Z --- Logging error ---\n", - "2019-05-21T05:18:26.083710200Z Traceback (most recent call last):\n", - "2019-05-21T05:18:26.083714300Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 994, in emit\n", - "2019-05-21T05:18:26.083718000Z msg = self.format(record)\n", - "2019-05-21T05:18:26.083721100Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 840, in format\n", - "2019-05-21T05:18:26.083724100Z return fmt.format(record)\n", - "2019-05-21T05:18:26.083726900Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 577, in format\n", - "2019-05-21T05:18:26.083729900Z record.message = record.getMessage()\n", - "2019-05-21T05:18:26.083732600Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 338, in getMessage\n", - "2019-05-21T05:18:26.083735600Z msg = msg % self.args\n", - "2019-05-21T05:18:26.083738400Z TypeError: not all arguments converted during string formatting\n", - "2019-05-21T05:18:26.083741300Z Call stack:\n", - "2019-05-21T05:18:26.083744100Z File \"/usr/local/bin/seldon-core-microservice\", line 10, in \n", - "2019-05-21T05:18:26.083747200Z sys.exit(main())\n", - "2019-05-21T05:18:26.083749900Z File \"/usr/local/lib/python3.6/site-packages/seldon_core/microservice.py\", line 189, in main\n", - "2019-05-21T05:18:26.083752800Z logger.info(\"Importing \",args.interface_name)\n", - "2019-05-21T05:18:26.083755600Z Message: 'Importing '\n", - "2019-05-21T05:18:26.083758300Z Arguments: ('RedditClassifier',)\n", - "2019-05-21T05:18:26.083774500Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfTransformer from version 0.20.3 when using version 0.21.1. This might lead to breaking code or invalid results. Use at your own risk.\n", - "2019-05-21T05:18:26.083778100Z UserWarning)\n", - "2019-05-21T05:18:26.083781000Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfVectorizer from version 0.20.3 when using version 0.21.1. This might lead to breaking code or invalid results. Use at your own risk.\n", - "2019-05-21T05:18:26.083784100Z UserWarning)\n", - "2019-05-21T05:18:26.083786800Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator LogisticRegression from version 0.20.3 when using version 0.21.1. This might lead to breaking code or invalid results. Use at your own risk.\n", - "2019-05-21T05:18:26.083789900Z UserWarning)\n", - "2019-05-21T05:18:26.083792600Z 2019-05-21 05:18:26,082 - seldon_core.microservice:main:226 - INFO: REST microservice running on port 5000\n", - "2019-05-21T05:18:26.083795500Z 2019-05-21 05:18:26,083 - seldon_core.microservice:main:260 - INFO: Starting servers\n", - "2019-05-21T05:18:26.084624400Z \n", - "2019-05-21T05:18:26.084636400Z \u001b[93m Linking successful\u001b[0m\n", - "2019-05-21T05:18:26.084639800Z /usr/local/lib/python3.6/site-packages/en_core_web_sm -->\n", - "2019-05-21T05:18:26.084642700Z /usr/local/lib/python3.6/site-packages/spacy/data/en_core_web_sm\n", - "2019-05-21T05:18:26.084645500Z \n", - "2019-05-21T05:18:26.084648200Z You can now load the model via spacy.load('en_core_web_sm')\n", - "2019-05-21T05:18:26.084651000Z \n", - "2019-05-21T05:18:26.100898500Z * Serving Flask app \"seldon_core.wrapper\" (lazy loading)\n", - "2019-05-21T05:18:26.100924900Z * Environment: production\n", - "2019-05-21T05:18:26.100930600Z WARNING: Do not use the development server in a production environment.\n", - "2019-05-21T05:18:26.100936000Z Use a production WSGI server instead.\n", - "2019-05-21T05:18:26.100941400Z * Debug mode: off\n", - "2019-05-21T05:18:26.111993300Z 2019-05-21 05:18:26,111 - werkzeug:_log:122 - INFO: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n", + "2019-05-27T13:50:12.739381600Z starting microservice\n", + "2019-05-27T13:50:14.023399000Z 2019-05-27 13:50:14,023 - seldon_core.microservice:main:154 - INFO: Starting microservice.py:main\n", + "2019-05-27T13:50:14.024836400Z 2019-05-27 13:50:14,024 - seldon_core.microservice:main:185 - INFO: Annotations: {}\n", + "2019-05-27T13:50:14.686919400Z Collecting en_core_web_sm==2.0.0 from https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz#egg=en_core_web_sm==2.0.0\n", + "2019-05-27T13:50:15.402484400Z Downloading https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-2.0.0/en_core_web_sm-2.0.0.tar.gz (37.4MB)\n", + "2019-05-27T13:50:47.771818100Z Building wheels for collected packages: en-core-web-sm\n", + "2019-05-27T13:50:47.772287600Z Building wheel for en-core-web-sm (setup.py): started\n", + "2019-05-27T13:50:49.845376700Z Building wheel for en-core-web-sm (setup.py): finished with status 'done'\n", + "2019-05-27T13:50:49.845641500Z Stored in directory: /tmp/pip-ephem-wheel-cache-wszfsf1z/wheels/54/7c/d8/f86364af8fbba7258e14adae115f18dd2c91552406edc3fdaa\n", + "2019-05-27T13:50:50.163985100Z Successfully built en-core-web-sm\n", + "2019-05-27T13:50:50.164057000Z Installing collected packages: en-core-web-sm\n", + "2019-05-27T13:50:50.242852700Z Successfully installed en-core-web-sm-2.0.0\n", + "2019-05-27T13:50:50.400850200Z WARNING: You are using pip version 19.1, however version 19.1.1 is available.\n", + "2019-05-27T13:50:50.400901100Z You should consider upgrading via the 'pip install --upgrade pip' command.\n", + "2019-05-27T13:50:51.728895100Z --- Logging error ---\n", + "2019-05-27T13:50:51.728944900Z Traceback (most recent call last):\n", + "2019-05-27T13:50:51.728954200Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 994, in emit\n", + "2019-05-27T13:50:51.728958900Z msg = self.format(record)\n", + "2019-05-27T13:50:51.728963000Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 840, in format\n", + "2019-05-27T13:50:51.728966900Z return fmt.format(record)\n", + "2019-05-27T13:50:51.728970500Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 577, in format\n", + "2019-05-27T13:50:51.728974300Z record.message = record.getMessage()\n", + "2019-05-27T13:50:51.728977900Z File \"/usr/local/lib/python3.6/logging/__init__.py\", line 338, in getMessage\n", + "2019-05-27T13:50:51.728981600Z msg = msg % self.args\n", + "2019-05-27T13:50:51.728985100Z TypeError: not all arguments converted during string formatting\n", + "2019-05-27T13:50:51.728988800Z Call stack:\n", + "2019-05-27T13:50:51.728992300Z File \"/usr/local/bin/seldon-core-microservice\", line 10, in \n", + "2019-05-27T13:50:51.728996500Z sys.exit(main())\n", + "2019-05-27T13:50:51.729000000Z File \"/usr/local/lib/python3.6/site-packages/seldon_core/microservice.py\", line 189, in main\n", + "2019-05-27T13:50:51.729004000Z logger.info(\"Importing \",args.interface_name)\n", + "2019-05-27T13:50:51.729007800Z Message: 'Importing '\n", + "2019-05-27T13:50:51.729011400Z Arguments: ('RedditClassifier',)\n", + "2019-05-27T13:50:51.729025900Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfTransformer from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk.\n", + "2019-05-27T13:50:51.729030000Z UserWarning)\n", + "2019-05-27T13:50:51.729033400Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator TfidfVectorizer from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk.\n", + "2019-05-27T13:50:51.729036900Z UserWarning)\n", + "2019-05-27T13:50:51.729040100Z /usr/local/lib/python3.6/site-packages/sklearn/base.py:306: UserWarning: Trying to unpickle estimator LogisticRegression from version 0.20.3 when using version 0.21.2. This might lead to breaking code or invalid results. Use at your own risk.\n", + "2019-05-27T13:50:51.729044000Z UserWarning)\n", + "2019-05-27T13:50:51.729047500Z 2019-05-27 13:50:51,727 - seldon_core.microservice:main:226 - INFO: REST microservice running on port 5000\n", + "2019-05-27T13:50:51.729051200Z 2019-05-27 13:50:51,728 - seldon_core.microservice:main:260 - INFO: Starting servers\n", + "2019-05-27T13:50:51.730423900Z \n", + "2019-05-27T13:50:51.730464700Z \u001b[93m Linking successful\u001b[0m\n", + "2019-05-27T13:50:51.730473700Z /usr/local/lib/python3.6/site-packages/en_core_web_sm -->\n", + "2019-05-27T13:50:51.730477700Z /usr/local/lib/python3.6/site-packages/spacy/data/en_core_web_sm\n", + "2019-05-27T13:50:51.730481100Z \n", + "2019-05-27T13:50:51.730484300Z You can now load the model via spacy.load('en_core_web_sm')\n", + "2019-05-27T13:50:51.730487600Z \n", + "2019-05-27T13:50:51.743475000Z * Serving Flask app \"seldon_core.wrapper\" (lazy loading)\n", + "2019-05-27T13:50:51.743530400Z * Environment: production\n", + "2019-05-27T13:50:51.743538900Z WARNING: Do not use the development server in a production environment.\n", + "2019-05-27T13:50:51.743542800Z Use a production WSGI server instead.\n", + "2019-05-27T13:50:51.743546000Z * Debug mode: off\n", + "2019-05-27T13:50:51.760002000Z 2019-05-27 13:50:51,759 - werkzeug:_log:122 - INFO: * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)\n", "^C\n" ] } @@ -710,7 +732,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 43, "metadata": { "scrolled": true }, @@ -740,10 +762,10 @@ " values {\n", " list_value {\n", " values {\n", - " number_value: 0.8276705633548711\n", + " number_value: 0.8276709475641506\n", " }\n", " values {\n", - " number_value: 0.17232943664512895\n", + " number_value: 0.1723290524358494\n", " }\n", " }\n", " }\n", @@ -755,7 +777,7 @@ ], "source": [ "# We now test the REST endpoint expecting the same result\n", - "endpoint = \"0.0.0.0:5000\"\n", + "endpoint = \"0.0.0.0:5001\"\n", "batch = sample\n", "payload_type = \"ndarray\"\n", "\n", @@ -771,7 +793,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 44, "metadata": {}, "outputs": [ { @@ -791,57 +813,238 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Run in kubernetes cluster" + "## 4) Run Seldon in your kubernetes cluster\n", + "In order to run Seldon we need to make sure that Helm is initialised and Tiller is running. \n", + "\n", + "For this we can run the following initialisation and waiting commands." ] }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 46, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "NAME READY STATUS RESTARTS AGE\r\n", - "seldon-core-redis-master-0 1/1 Running 0 59s\r\n", - "seldon-core-seldon-apiserver-d8fd4cd68-5mzzt 1/1 Running 0 59s\r\n", - "seldon-core-seldon-cluster-manager-67c64974b6-d8cfb 1/1 Running 0 59s\r\n" + "clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created\n", + "$HELM_HOME has been configured at /home/alejandro/.helm.\n", + "Warning: Tiller is already installed in the cluster.\n", + "(Use --client-only to suppress this message, or --upgrade to upgrade Tiller to the current version.)\n", + "Happy Helming!\n", + "deployment \"tiller-deploy\" successfully rolled out\n" ] } ], "source": [ - "# Make sure that seldon is running \n", - "!kubectl get pods " + "# If not running you can install it\n", + "# First initialise helm\n", + "!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default\n", + "!helm init\n", + "!kubectl rollout status deploy/tiller-deploy -n kube-system" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can install run the Seldon Operator using the latest Helm charts" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: seldon-core-operator\n", + "LAST DEPLOYED: Mon May 27 15:04:30 2019\n", + "NAMESPACE: default\n", + "STATUS: DEPLOYED\n", + "\n", + "RESOURCES:\n", + "==> v1/ClusterRole\n", + "NAME AGE\n", + "seldon-operator-manager-role 0s\n", + "\n", + "==> v1/ClusterRoleBinding\n", + "NAME AGE\n", + "seldon-operator-manager-rolebinding 0s\n", + "\n", + "==> v1/Pod(related)\n", + "NAME READY STATUS RESTARTS AGE\n", + "seldon-operator-controller-manager-0 0/1 ContainerCreating 0 0s\n", + "\n", + "==> v1/Secret\n", + "NAME TYPE DATA AGE\n", + "seldon-operator-webhook-server-secret Opaque 0 0s\n", + "\n", + "==> v1/Service\n", + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", + "seldon-operator-controller-manager-service ClusterIP 10.101.147.136 443/TCP 0s\n", + "\n", + "==> v1/StatefulSet\n", + "NAME READY AGE\n", + "seldon-operator-controller-manager 0/1 0s\n", + "\n", + "==> v1beta1/CustomResourceDefinition\n", + "NAME AGE\n", + "seldondeployments.machinelearning.seldon.io 0s\n", + "\n", + "\n", + "NOTES:\n", + "NOTES: TODO\n", + "\n", + "\n" + ] + } + ], + "source": [ + "!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts" + ] + }, + { + "cell_type": "markdown", "metadata": {}, - "outputs": [], "source": [ - "# If not running you can install it\n", - "# First initialise helm\n", - "!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default\n", - "!helm init\n", - "!kubectl rollout status deploy/tiller-deploy -n kube-system" + "And we can make sure that it is actually running with the following command " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 54, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "seldon-operator-controller-manager-0 1/1 Running 1 12s\r\n" + ] + } + ], "source": [ - "# Then install and run seldon\n", - "helm install seldon-core-crd --name seldon-core-crd --repo https://storage.googleapis.com/seldon-charts\n", - "helm install seldon-core --name seldon-core --repo https://storage.googleapis.com/seldon-charts " + "!kubectl get pod | grep seldon" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order for us to be able to reach the model, we will need to set up an ingress. For this we will use ambassador:" ] }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 55, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: ambassador\n", + "LAST DEPLOYED: Mon May 27 15:04:50 2019\n", + "NAMESPACE: default\n", + "STATUS: DEPLOYED\n", + "\n", + "RESOURCES:\n", + "==> v1/Deployment\n", + "NAME READY UP-TO-DATE AVAILABLE AGE\n", + "ambassador 0/3 3 0 0s\n", + "\n", + "==> v1/Pod(related)\n", + "NAME READY STATUS RESTARTS AGE\n", + "ambassador-7bfc87f865-jkxs8 0/1 ContainerCreating 0 0s\n", + "ambassador-7bfc87f865-nr7bn 0/1 ContainerCreating 0 0s\n", + "ambassador-7bfc87f865-q4lng 0/1 ContainerCreating 0 0s\n", + "\n", + "==> v1/Service\n", + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", + "ambassador LoadBalancer 10.101.89.32 localhost 80:30004/TCP,443:31350/TCP 0s\n", + "ambassador-admins ClusterIP 10.98.228.159 8877/TCP 0s\n", + "\n", + "==> v1/ServiceAccount\n", + "NAME SECRETS AGE\n", + "ambassador 1 1s\n", + "\n", + "==> v1beta1/ClusterRole\n", + "NAME AGE\n", + "ambassador 1s\n", + "\n", + "==> v1beta1/ClusterRoleBinding\n", + "NAME AGE\n", + "ambassador 1s\n", + "\n", + "\n", + "NOTES:\n", + "Congratuations! You've successfully installed Ambassador.\n", + "\n", + "For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io.\n", + "\n", + "To get the IP address of Ambassador, run the following commands:\n", + "NOTE: It may take a few minutes for the LoadBalancer IP to be available.\n", + " You can watch the status of by running 'kubectl get svc -w --namespace default ambassador'\n", + "\n", + " On GKE/Azure:\n", + " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "\n", + " On AWS:\n", + " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')\n", + "\n", + " echo http://$SERVICE_IP:\n", + "\n" + ] + } + ], + "source": [ + "!helm install stable/ambassador --name ambassador --set image.tag=0.40.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now see the ambassador service is running. In our case we can reach it through the external IP which is our localhost, but if you are using a cloud provider, make sure you have access to the ambassador endpoint." + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\r\n", + "ambassador LoadBalancer 10.101.89.32 localhost 80:30004/TCP,443:31350/TCP 2m43s\r\n" + ] + } + ], + "source": [ + "!kubectl get svc ambassador" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5) Deploy your model with Seldon\n", + "We can now deploy our model by using the Seldon graph definition:" + ] + }, + { + "cell_type": "code", + "execution_count": 60, "metadata": { "scrolled": true }, @@ -913,7 +1116,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 61, "metadata": {}, "outputs": [ { @@ -930,18 +1133,19 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 63, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "NAME READY STATUS RESTARTS AGE\r\n", - "reddit-classifier-single-model-9199e4b-5c49c85c7d-mjvrh 2/2 Running 0 62s\r\n", - "seldon-core-redis-master-0 1/1 Running 0 2m14s\r\n", - "seldon-core-seldon-apiserver-d8fd4cd68-5mzzt 1/1 Running 0 2m14s\r\n", - "seldon-core-seldon-cluster-manager-67c64974b6-d8cfb 1/1 Running 0 2m14s\r\n" + "NAME READY STATUS RESTARTS AGE\r\n", + "ambassador-7bfc87f865-jkxs8 1/1 Running 0 5m2s\r\n", + "ambassador-7bfc87f865-nr7bn 1/1 Running 0 5m2s\r\n", + "ambassador-7bfc87f865-q4lng 1/1 Running 0 5m2s\r\n", + "reddit-classifier-single-model-9199e4b-bcc5cdcc-g8j2q 2/2 Running 1 77s\r\n", + "seldon-operator-controller-manager-0 1/1 Running 1 5m23s\r\n" ] } ], @@ -949,47 +1153,99 @@ "!kubectl get pods " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6) Interact with your model through API\n", + "Now that our Seldon Deployment is live, we are able to interact with it through its API.\n", + "\n", + "There are two options in which we can interact with our new model. These are:\n", + "\n", + "a) Using CURL from the CLI (or another rest client like Postman)\n", + "\n", + "b) Using the Python SeldonClient\n", + "\n", + "#### a) Using CURL from the CLI" + ] + }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 66, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "31203\r\n" + "{\n", + " \"meta\": {\n", + " \"puid\": \"bvj1rjiq3vvnieo0oir4h7bf6f\",\n", + " \"tags\": {\n", + " },\n", + " \"routing\": {\n", + " },\n", + " \"requestPath\": {\n", + " \"classifier\": \"reddit-classifier:0.1\"\n", + " },\n", + " \"metrics\": []\n", + " },\n", + " \"data\": {\n", + " \"names\": [\"t:0\", \"t:1\"],\n", + " \"ndarray\": [[0.6815614604065544, 0.3184385395934456]]\n", + " }\n", + "}" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + " % Total % Received % Xferd Average Speed Time Time Time Current\n", + " Dload Upload Total Spent Left Speed\n", + "\r", + " 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0\r", + "100 372 100 300 100 72 1522 365 --:--:-- --:--:-- --:--:-- 1897\n" ] } ], "source": [ - "!echo `kubectl get svc -l app=seldon-apiserver-container-app -o jsonpath='{.items[0].spec.ports[0].nodePort}'`" + "%%bash\n", + "curl -X POST -H 'Content-Type: application/json' \\\n", + " -d \"{'data': {'names': ['text'], 'ndarray': ['Hello world this is a test']}}\" \\\n", + " http://127.0.0.1/seldon/default/reddit-classifier/api/v0.1/predictions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### b) Using the Python SeldonClient" ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 70, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "WORKS!!!!\n", "Success:True message:\n", "Request:\n", "data {\n", " names: \"text\"\n", " ndarray {\n", " values {\n", - " string_value: \"This is the study that the article is based on:\\r\\n\\r\\nhttps://www.nature.com/articles/nature25778.epdf\"\n", + " string_value: \"Hello world this is a test\"\n", " }\n", " }\n", "}\n", "\n", "Response:\n", "meta {\n", - " puid: \"9359cpdudo3b6i6cv82ktsl4pe\"\n", + " puid: \"uld2famhfrb97vd7regu0q7k32\"\n", " requestPath {\n", " key: \"classifier\"\n", " value: \"reddit-classifier:0.1\"\n", @@ -1002,10 +1258,10 @@ " values {\n", " list_value {\n", " values {\n", - " number_value: 0.8276705633548711\n", + " number_value: 0.6815614604065544\n", " }\n", " values {\n", - " number_value: 0.17232943664512895\n", + " number_value: 0.3184385395934456\n", " }\n", " }\n", " }\n", @@ -1016,20 +1272,80 @@ } ], "source": [ + "from seldon_core.seldon_client import SeldonClient\n", + "import numpy as np\n", + "\n", "host = \"localhost\"\n", - "port = \"31203\" # Make sure you use the port above\n", - "batch = sample\n", + "port = \"80\" # Make sure you use the port above\n", + "batch = np.array([\"Hello world this is a test\"])\n", "payload_type = \"ndarray\"\n", + "deployment_name=\"reddit-classifier\"\n", + "transport=\"rest\"\n", + "namespace=\"default\"\n", "\n", - "sc = SeldonClient(gateway=\"seldon\", seldon_rest_endpoint=host + \":\" + port,\n", - " oauth_key=\"oauth-key\", oauth_secret=\"oauth-secret\")\n", - "response = sc.predict(\n", + "sc = SeldonClient(\n", + " gateway=\"ambassador\", \n", + " ambassador_endpoint=host + \":\" + port,\n", + " namespace=namespace)\n", + "\n", + "client_prediction = sc.predict(\n", " data=batch, \n", - " deployment_name=\"mymodel\",\n", + " deployment_name=deployment_name,\n", " names=[\"text\"],\n", - " payload_type=payload_type)\n", + " payload_type=payload_type,\n", + " transport=\"rest\")\n", "\n", - "print(response)" + "print(client_prediction)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7) Clean your environment" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!kubectl delete -f reddit_clf.json" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "release \"ambassador\" deleted\r\n" + ] + } + ], + "source": [ + "!helm del --purge ambassador" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "release \"seldon-core-operator\" deleted\r\n" + ] + } + ], + "source": [ + "!helm del --purge seldon-core-operator" ] }, { diff --git a/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example_files/sklearn_spacy_text_classifier_example_4_1.png b/examples/models/sklearn_spacy_text/sklearn_spacy_text_classifier_example_files/sklearn_spacy_text_classifier_example_4_1.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ace5b9748a8d45c5a1c71aff16ee2935275f01 GIT binary patch literal 4562 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 EFDU Date: Mon, 27 May 2019 15:46:22 +0100 Subject: [PATCH 2/3] Updated headline --- examples/models/aws_eks_deep_mnist/README.md | 7128 +++++++++-------- .../aws_eks_deep_mnist.ipynb | 4 +- 2 files changed, 3825 insertions(+), 3307 deletions(-) diff --git a/examples/models/aws_eks_deep_mnist/README.md b/examples/models/aws_eks_deep_mnist/README.md index e4b568a24a..6cd31e9784 100644 --- a/examples/models/aws_eks_deep_mnist/README.md +++ b/examples/models/aws_eks_deep_mnist/README.md @@ -1,3308 +1,3826 @@ - -# Tensorflow MNIST Model -In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS). - -This tutorial will break down in the following sections: - -1) Train a tensorflow model to predict mnist locally - -2) Containerise the tensorflow model with our docker utility - -3) Send some data to the docker model to test it - -4) Install and configure AWS tools to interact with AWS - -5) Use the AWS tools to create and setup EKS cluster with Seldon - -6) Push and run docker image through the AWS Container Registry - -7) Test our Elastic Kubernetes deployment by sending some data - -#### Let's get started! 🚀🔥 - -## Dependencies: - -* Helm v2.13.1+ -* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM) -* kubectl v1.14+ -* EKS CLI v0.1.32 -* AWS Cli v1.16.163 -* Python 3.6+ -* Python DEV requirements - - -# 1) Train a tensorflow model to predict mnist locally -We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels - - -```python -from tensorflow.examples.tutorials.mnist import input_data -mnist = input_data.read_data_sets("MNIST_data/", one_hot = True) -import tensorflow as tf - -if __name__ == '__main__': - - x = tf.placeholder(tf.float32, [None,784], name="x") - - W = tf.Variable(tf.zeros([784,10])) - b = tf.Variable(tf.zeros([10])) - - y = tf.nn.softmax(tf.matmul(x,W) + b, name="y") - - y_ = tf.placeholder(tf.float32, [None, 10]) - - cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) - - train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) - - init = tf.initialize_all_variables() - - sess = tf.Session() - sess.run(init) - - for i in range(1000): - batch_xs, batch_ys = mnist.train.next_batch(100) - sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) - - correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) - accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) - print(sess.run(accuracy, feed_dict = {x: mnist.test.images, y_:mnist.test.labels})) - - saver = tf.train.Saver() - - saver.save(sess, "model/deep_mnist_model") -``` - - Extracting MNIST_data/train-images-idx3-ubyte.gz - Extracting MNIST_data/train-labels-idx1-ubyte.gz - Extracting MNIST_data/t10k-images-idx3-ubyte.gz - Extracting MNIST_data/t10k-labels-idx1-ubyte.gz - 0.9194 - - -## 2) Containerise the tensorflow model with our docker utility - -First you need to make sure that you have added the .s2i/environment configuration file in this folder with the following content: - - -```python -!cat .s2i/environment -``` - - MODEL_NAME=DeepMnist - API_TYPE=REST - SERVICE_TYPE=MODEL - PERSISTENCE=0 - - -Now we can build a docker image named "deep-mnist" with the tag 0.1 - - -```python -!s2i build . seldonio/seldon-core-s2i-python36:0.5.1 deep-mnist:0.1 -``` - - ---> Installing application source... - ---> Installing dependencies ... - Looking in links: /whl - Requirement already satisfied: tensorflow>=1.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (1.13.1) - Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.9) - Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.2.2) - Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) - Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) - Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.7) - Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.12.0) - Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.1.0) - Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.19.0) - Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.33.1) - Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.1) - Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.16.2) - Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.7.0) - Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.0) - Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.9.0) - Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.0.1) - Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.15.0) - Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow>=1.12.0->-r requirements.txt (line 1)) (40.8.0) - Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.0.0) - Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (5.1.3) - Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. - You are using pip version 19.0.3, however version 19.1.1 is available. - You should consider upgrading via the 'pip install --upgrade pip' command. - Build completed successfully - - -## 3) Send some data to the docker model to test it -We first run the docker image we just created as a container called "mnist_predictor" - - -```python -!docker run --name "mnist_predictor" -d --rm -p 5000:5000 deep-mnist:0.1 -``` - - 5157ab4f516bd0dea11b159780f31121e9fb41df6394e0d6d631e6e0d572463b - - -Send some random features that conform to the contract - - -```python -import matplotlib.pyplot as plt -# This is the variable that was initialised at the beginning of the file -i = [0] -x = mnist.test.images[i] -y = mnist.test.labels[i] -plt.imshow(x.reshape((28, 28)), cmap='gray') -plt.show() -print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) -``` - - -![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png) - - - Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] - - - -```python -from seldon_core.seldon_client import SeldonClient -import math -import numpy as np - -# We now test the REST endpoint expecting the same result -endpoint = "0.0.0.0:5000" -batch = x -payload_type = "ndarray" - -sc = SeldonClient(microservice_endpoint=endpoint) - -# We use the microservice, instead of the "predict" function -client_prediction = sc.microservice( - data=batch, - method="predict", - payload_type=payload_type, - names=["tfidf"]) - -for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): - print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") -``` - - LABEL 0: 0.0068 % - LABEL 1: 0.0000 % - LABEL 2: 0.0085 % - LABEL 3: 0.3409 % - LABEL 4: 0.0002 % - LABEL 5: 0.0020 % - LABEL 6: 0.0000 % - LABEL 7: 99.5371 % - LABEL 8: 0.0026 % - LABEL 9: 0.1019 % - - - -```python -!docker rm mnist_predictor --force -``` - - mnist_predictor - - -## 4) Install and configure AWS tools to interact with AWS - -First we install the awscli - - -```python -!pip install awscli --upgrade --user -``` - - Collecting awscli - Using cached https://files.pythonhosted.org/packages/f6/45/259a98719e7c7defc9be4cc00fbfb7ccf699fbd1f74455d8347d0ab0a1df/awscli-1.16.163-py2.py3-none-any.whl - Collecting colorama<=0.3.9,>=0.2.5 (from awscli) - Using cached https://files.pythonhosted.org/packages/db/c8/7dcf9dbcb22429512708fe3a547f8b6101c0d02137acbd892505aee57adf/colorama-0.3.9-py2.py3-none-any.whl - Collecting PyYAML<=3.13,>=3.10 (from awscli) - Collecting botocore==1.12.153 (from awscli) - Using cached https://files.pythonhosted.org/packages/ec/3b/029218966ce62ae9824a18730de862ac8fc5a0e8083d07d1379815e7cca1/botocore-1.12.153-py2.py3-none-any.whl - Requirement already satisfied, skipping upgrade: docutils>=0.10 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.14) - Collecting rsa<=3.5.0,>=3.1.2 (from awscli) - Using cached https://files.pythonhosted.org/packages/e1/ae/baedc9cb175552e95f3395c43055a6a5e125ae4d48a1d7a924baca83e92e/rsa-3.4.2-py2.py3-none-any.whl - Requirement already satisfied, skipping upgrade: s3transfer<0.3.0,>=0.2.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.2.0) - Requirement already satisfied, skipping upgrade: urllib3<1.25,>=1.20; python_version >= "3.4" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (1.24.2) - Requirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.1; python_version >= "2.7" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (2.8.0) - Requirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (0.9.4) - Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli) - Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl - Requirement already satisfied, skipping upgrade: six>=1.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from python-dateutil<3.0.0,>=2.1; python_version >= "2.7"->botocore==1.12.153->awscli) (1.12.0) - Installing collected packages: colorama, PyYAML, botocore, pyasn1, rsa, awscli - Successfully installed PyYAML-3.13 awscli-1.16.163 botocore-1.12.153 colorama-0.3.9 pyasn1-0.4.5 rsa-3.4.2 - - -#### Configure aws so it can talk to your server -(if you are getting issues, make sure you have the permmissions to create clusters) - - -```bash -%%bash -# You must make sure that the access key and secret are changed -aws configure << END_OF_INPUTS -YOUR_ACCESS_KEY -YOUR_ACCESS_SECRET -us-west-2 -json -END_OF_INPUTS -``` - - AWS Access Key ID [****************SF4A]: AWS Secret Access Key [****************WLHu]: Default region name [eu-west-1]: Default output format [json]: - -#### Install EKCTL -*IMPORTANT*: These instructions are for linux -Please follow the official installation of ekctl at: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html - - -```python -!curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -``` - - -```python -!chmod 755 ./eksctl -``` - - -```python -!./eksctl version -``` - - [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.32"} -  - -## 5) Use the AWS tools to create and setup EKS cluster with Seldon -In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly. - -If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard. - -It will take 10-15 minutes (so feel free to go grab a ☕). - -### IMPORTANT: If you get errors in this step... -It is most probably IAM role access requirements, which requires you to discuss with your administrator. - - -```bash -%%bash -./eksctl create cluster \ ---name demo-eks-cluster \ ---region us-west-2 \ ---nodes 2 -``` - - Process is interrupted. - - -### Configure local kubectl -We want to now configure our local Kubectl so we can actually reach the cluster we've just created - - -```python -!aws eks --region us-west-2 update-kubeconfig --name demo-eks-cluster -``` - - Updated context arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist in /home/alejandro/.kube/config - - -And we can check if the context has been added to kubectl config (contexts are basically the different k8s cluster connections) -You should be able to see the context as "...aws:eks:eu-west-1:27...". -If it's not activated you can activate that context with kubectlt config set-context - - -```python -!kubectl config get-contexts -``` - - CURRENT NAME CLUSTER AUTHINFO NAMESPACE - * arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist - docker-desktop docker-desktop docker-desktop - docker-for-desktop docker-desktop docker-desktop - gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 - - -## Install Seldon Core - -### Before we install seldon core, we need to install HELM -For that, we need to create a ClusterRoleBinding for us, a ServiceAccount, and then a RoleBinding - - -```python -!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default -``` - - clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created - - - -```python -!kubectl create serviceaccount tiller --namespace kube-system -``` - - serviceaccount/tiller created - - - -```python -!kubectl apply -f tiller-role-binding.yaml -``` - - clusterrolebinding.rbac.authorization.k8s.io/tiller-role-binding created - - -### Once that is set-up we can install Tiller - - -```python -!helm init --service-account tiller -``` - - $HELM_HOME has been configured at /home/alejandro/.helm. - - Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster. - - Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy. - To prevent this, run `helm init` with the --tiller-tls-verify flag. - For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation - Happy Helming! - - - -```python -# Wait until Tiller finishes -!kubectl rollout status deploy/tiller-deploy -n kube-system -``` - - deployment "tiller-deploy" successfully rolled out - - -### Now we can install SELDON. -We first start with the custom resource definitions (CRDs) - - -```python -!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --namespace seldon-system -``` - - NAME: seldon-core-operator - LAST DEPLOYED: Wed May 22 16:24:10 2019 - NAMESPACE: seldon-system - STATUS: DEPLOYED - - RESOURCES: - ==> v1/ClusterRole - NAME AGE - seldon-operator-manager-role 2s - - ==> v1/ClusterRoleBinding - NAME AGE - seldon-operator-manager-rolebinding 2s - - ==> v1/ConfigMap - NAME DATA AGE - seldon-spartakus-config 3 2s - - ==> v1/Pod(related) - NAME READY STATUS RESTARTS AGE - seldon-operator-controller-manager-0 0/1 ContainerCreating 0 2s - seldon-spartakus-volunteer-6954cffb89-qz4pq 0/1 ContainerCreating 0 1s - - ==> v1/Secret - NAME TYPE DATA AGE - seldon-operator-webhook-server-secret Opaque 0 2s - - ==> v1/Service - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - seldon-operator-controller-manager-service ClusterIP 10.100.198.157 443/TCP 2s - - ==> v1/ServiceAccount - NAME SECRETS AGE - seldon-spartakus-volunteer 1 2s - - ==> v1/StatefulSet - NAME READY AGE - seldon-operator-controller-manager 0/1 2s - - ==> v1beta1/ClusterRole - NAME AGE - seldon-spartakus-volunteer 2s - - ==> v1beta1/ClusterRoleBinding - NAME AGE - seldon-spartakus-volunteer 2s - - ==> v1beta1/CustomResourceDefinition - NAME AGE - seldondeployments.machinelearning.seldon.io 2s - - ==> v1beta1/Deployment - NAME READY UP-TO-DATE AVAILABLE AGE - seldon-spartakus-volunteer 0/1 1 0 2s - - - NOTES: - NOTES: TODO - - - - -And confirm they are running by getting the pods: - - -```python -!kubectl rollout status statefulset.apps/seldon-operator-controller-manager -n seldon-system -``` - - partitioned roll out complete: 1 new pods have been updated... - - -### Now we set-up the ingress -This will allow you to reach the Seldon models from outside the kubernetes cluster. - -In EKS it automatically creates an Elastic Load Balancer, which you can configure from the EC2 Console - - -```python -!helm install stable/ambassador --name ambassador --set image.tag=0.40.2 -``` - - NAME: ambassador - LAST DEPLOYED: Wed May 22 16:25:38 2019 - NAMESPACE: default - STATUS: DEPLOYED - - RESOURCES: - ==> v1/Deployment - NAME READY UP-TO-DATE AVAILABLE AGE - ambassador 0/3 3 0 0s - - ==> v1/Pod(related) - NAME READY STATUS RESTARTS AGE - ambassador-6dbf99c886-frlfm 0/1 ContainerCreating 0 0s - ambassador-6dbf99c886-kj56r 0/1 ContainerCreating 0 0s - ambassador-6dbf99c886-v5mtv 0/1 ContainerCreating 0 0s - - ==> v1/Service - NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE - ambassador LoadBalancer 10.100.59.146 80:30911/TCP,443:31715/TCP 0s - ambassador-admins ClusterIP 10.100.152.178 8877/TCP 0s - - ==> v1/ServiceAccount - NAME SECRETS AGE - ambassador 1 0s - - ==> v1beta1/ClusterRole - NAME AGE - ambassador 0s - - ==> v1beta1/ClusterRoleBinding - NAME AGE - ambassador 0s - - - NOTES: - Congratuations! You've successfully installed Ambassador. - - For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io. - - To get the IP address of Ambassador, run the following commands: - NOTE: It may take a few minutes for the LoadBalancer IP to be available. - You can watch the status of by running 'kubectl get svc -w --namespace default ambassador' - - On GKE/Azure: - export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}') - - On AWS: - export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') - - echo http://$SERVICE_IP: - - - -And let's wait until it's fully deployed - - -```python -!kubectl rollout status deployment.apps/ambassador -``` - -## Push docker image -In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR). - -If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html - -### First we create a registry -You can run the following command, and then see the result at https://us-west-2.console.aws.amazon.com/ecr/repositories?# - - -```python -!aws ecr create-repository --repository-name seldon-repository --region us-west-2 -``` - - { - "repository": { - "repositoryArn": "arn:aws:ecr:us-west-2:271049282727:repository/seldon-repository", - "registryId": "271049282727", - "repositoryName": "seldon-repository", - "repositoryUri": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository", - "createdAt": 1558535798.0 - } - } - - -### Now prepare docker image -We need to first tag the docker image before we can push it - - -```bash -%%bash -export AWS_ACCOUNT_ID="" -export AWS_REGION="us-west-2" -if [ -z "$AWS_ACCOUNT_ID" ]; then - echo "ERROR: Please provide a value for the AWS variables" - exit 1 -fi - -docker tag deep-mnist:0.1 "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" -``` - -### We now login to aws through docker so we can access the repository - - -```python -!`aws ecr get-login --no-include-email --region us-west-2` -``` - - WARNING! Using --password via the CLI is insecure. Use --password-stdin. - WARNING! Your password will be stored unencrypted in /home/alejandro/.docker/config.json. - Configure a credential helper to remove this warning. See - https://docs.docker.com/engine/reference/commandline/login/#credentials-store - - Login Succeeded - - -### And push the image -Make sure you add your AWS Account ID - - -```bash -%%bash -export AWS_ACCOUNT_ID="" -export AWS_REGION="us-west-2" -if [ -z "$AWS_ACCOUNT_ID" ]; then - echo "ERROR: Please provide a value for the AWS variables" - exit 1 -fi - -docker push "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" -``` - - The push refers to repository [271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository] - f7d0d000c138: Preparing - 987f3f1afb00: Preparing - 00d16a381c47: Preparing - bb01f50d544a: Preparing - fcb82c6941b5: Preparing - 67290e35c458: Preparing - b813745f5bb3: Preparing - ffecb18e9f0b: Preparing - f50f856f49fa: Preparing - 80b43ad4adf9: Preparing - 14c77983a1cf: Preparing - a22a5ac18042: Preparing - 6257fa9f9597: Preparing - 578414b395b9: Preparing - abc3250a6c7f: Preparing - 13d5529fd232: Preparing - 67290e35c458: Waiting - b813745f5bb3: Waiting - ffecb18e9f0b: Waiting - f50f856f49fa: Waiting - 80b43ad4adf9: Waiting - 6257fa9f9597: Waiting - 14c77983a1cf: Waiting - a22a5ac18042: Waiting - 578414b395b9: Waiting - abc3250a6c7f: Waiting - 13d5529fd232: Waiting - 987f3f1afb00: Pushed - fcb82c6941b5: Pushed - bb01f50d544a: Pushed - f7d0d000c138: Pushed - ffecb18e9f0b: Pushed - b813745f5bb3: Pushed - f50f856f49fa: Pushed - 67290e35c458: Pushed - 14c77983a1cf: Pushed - 578414b395b9: Pushed - 80b43ad4adf9: Pushed - 13d5529fd232: Pushed - 6257fa9f9597: Pushed - abc3250a6c7f: Pushed - 00d16a381c47: Pushed - a22a5ac18042: Pushed - latest: digest: sha256:19aefaa9d87c1287eb46ec08f5d4f9a689744d9d0d0b75668b7d15e447819d74 size: 3691 - - -## Running the Model -We will now run the model. - -Let's first have a look at the file we'll be using to trigger the model: - - -```python -!cat deep_mnist.json -``` - - { - "apiVersion": "machinelearning.seldon.io/v1alpha2", - "kind": "SeldonDeployment", - "metadata": { - "labels": { - "app": "seldon" - }, - "name": "deep-mnist" - }, - "spec": { - "annotations": { - "project_name": "Tensorflow MNIST", - "deployment_version": "v1" - }, - "name": "deep-mnist", - "oauth_key": "oauth-key", - "oauth_secret": "oauth-secret", - "predictors": [ - { - "componentSpecs": [{ - "spec": { - "containers": [ - { - "image": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest", - "imagePullPolicy": "IfNotPresent", - "name": "classifier", - "resources": { - "requests": { - "memory": "1Mi" - } - } - } - ], - "terminationGracePeriodSeconds": 20 - } - }], - "graph": { - "children": [], - "name": "classifier", - "endpoint": { - "type" : "REST" - }, - "type": "MODEL" - }, - "name": "single-model", - "replicas": 1, - "annotations": { - "predictor_version" : "v1" - } - } - ] - } - } - - -Now let's trigger seldon to run the model. - -We basically have a yaml file, where we want to replace the value "REPLACE_FOR_IMAGE_AND_TAG" for the image you pushed - - -```bash -%%bash -export AWS_ACCOUNT_ID="" -export AWS_REGION="us-west-2" -if [ -z "$AWS_ACCOUNT_ID" ]; then - echo "ERROR: Please provide a value for the AWS variables" - exit 1 -fi - -sed 's|REPLACE_FOR_IMAGE_AND_TAG|'"$AWS_ACCOUNT_ID"'.dkr.ecr.'"$AWS_REGION"'.amazonaws.com/seldon-repository|g' deep_mnist.json | kubectl apply -f - -``` - - error: unable to recognize "STDIN": Get https://461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com/api?timeout=32s: dial tcp: lookup 461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com on 1.1.1.1:53: no such host - - - - --------------------------------------------------------------------------- - - CalledProcessError Traceback (most recent call last) - - in - ----> 1 get_ipython().run_cell_magic('bash', '', 'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n') - - - ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell) - 2350 with self.builtin_trap: - 2351 args = (magic_arg_s, cell) - -> 2352 result = fn(*args, **kwargs) - 2353 return result - 2354 - - - ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in named_script_magic(line, cell) - 140 else: - 141 line = script - --> 142 return self.shebang(line, cell) - 143 - 144 # write a basic docstring: - - - in shebang(self, line, cell) - - - ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magic.py in (f, *a, **k) - 185 # but it's overkill for just that one bit of state. - 186 def magic_deco(arg): - --> 187 call = lambda f, *a, **k: f(*a, **k) - 188 - 189 if callable(arg): - - - ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in shebang(self, line, cell) - 243 sys.stderr.flush() - 244 if args.raise_error and p.returncode!=0: - --> 245 raise CalledProcessError(p.returncode, cell, output=out, stderr=err) - 246 - 247 def _run_script(self, p, cell, to_close): - - - CalledProcessError: Command 'b'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n'' returned non-zero exit status 1. - - -And let's check that it's been created. - -You should see an image called "deep-mnist-single-model...". - -We'll wait until STATUS changes from "ContainerCreating" to "Running" - - -```python -!kubectl get pods -``` - - NAME READY STATUS RESTARTS AGE - ambassador-5475779f98-7bhcw 1/1 Running 0 21m - ambassador-5475779f98-986g5 1/1 Running 0 21m - ambassador-5475779f98-zcd28 1/1 Running 0 21m - deep-mnist-single-model-42ed9d9-fdb557d6b-6xv2h 2/2 Running 0 18m - - -## Test the model -Now we can test the model, let's first find out what is the URL that we'll have to use: - - -```python -!kubectl get svc ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' -``` - - a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com - -We'll use a random example from our dataset - - -```python -import matplotlib.pyplot as plt -# This is the variable that was initialised at the beginning of the file -i = [0] -x = mnist.test.images[i] -y = mnist.test.labels[i] -plt.imshow(x.reshape((28, 28)), cmap='gray') -plt.show() -print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) -``` - - -![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png) - - - Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] - - -We can now add the URL above to send our request: - - -```python -from seldon_core.seldon_client import SeldonClient -import math -import numpy as np - -host = "a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com" -port = "80" # Make sure you use the port above -batch = x -payload_type = "ndarray" - -sc = SeldonClient( - gateway="ambassador", - ambassador_endpoint=host + ":" + port, - namespace="default", - oauth_key="oauth-key", - oauth_secret="oauth-secret") - -client_prediction = sc.predict( - data=batch, - deployment_name="deep-mnist", - names=["text"], - payload_type=payload_type) - -print(client_prediction) -``` - - Success:True message: - Request: - data { - names: "text" - ndarray { - values { - list_value { - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.3294117748737335 - } - values { - number_value: 0.7254902124404907 - } - values { - number_value: 0.6235294342041016 - } - values { - number_value: 0.5921568870544434 - } - values { - number_value: 0.2352941334247589 - } - values { - number_value: 0.1411764770746231 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.8705883026123047 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9450981020927429 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.7764706611633301 - } - values { - number_value: 0.6666666865348816 - } - values { - number_value: 0.2039215862751007 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.26274511218070984 - } - values { - number_value: 0.44705885648727417 - } - values { - number_value: 0.2823529541492462 - } - values { - number_value: 0.44705885648727417 - } - values { - number_value: 0.6392157077789307 - } - values { - number_value: 0.8901961445808411 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.8823530077934265 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9803922176361084 - } - values { - number_value: 0.8980392813682556 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.5490196347236633 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.06666667014360428 - } - values { - number_value: 0.25882354378700256 - } - values { - number_value: 0.05490196496248245 - } - values { - number_value: 0.26274511218070984 - } - values { - number_value: 0.26274511218070984 - } - values { - number_value: 0.26274511218070984 - } - values { - number_value: 0.23137256503105164 - } - values { - number_value: 0.08235294371843338 - } - values { - number_value: 0.9254902601242065 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.41568630933761597 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.32549020648002625 - } - values { - number_value: 0.9921569228172302 - } - values { - number_value: 0.8196079134941101 - } - values { - number_value: 0.07058823853731155 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.08627451211214066 - } - values { - number_value: 0.9137255549430847 - } - values { - number_value: 1.0 - } - values { - number_value: 0.32549020648002625 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.5058823823928833 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9333333969116211 - } - values { - number_value: 0.1725490242242813 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.23137256503105164 - } - values { - number_value: 0.9764706492424011 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.24313727021217346 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.5215686559677124 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.7333333492279053 - } - values { - number_value: 0.019607843831181526 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.03529411926865578 - } - values { - number_value: 0.803921639919281 - } - values { - number_value: 0.9725490808486938 - } - values { - number_value: 0.22745099663734436 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.4941176772117615 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.7137255072593689 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.29411765933036804 - } - values { - number_value: 0.9843137860298157 - } - values { - number_value: 0.9411765336990356 - } - values { - number_value: 0.22352942824363708 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.07450980693101883 - } - values { - number_value: 0.8666667342185974 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.6509804129600525 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.011764707043766975 - } - values { - number_value: 0.7960785031318665 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.8588235974311829 - } - values { - number_value: 0.13725490868091583 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.14901961386203766 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.3019607961177826 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.12156863510608673 - } - values { - number_value: 0.8784314393997192 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.45098042488098145 - } - values { - number_value: 0.003921568859368563 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.5215686559677124 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.2039215862751007 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.2392157018184662 - } - values { - number_value: 0.9490196704864502 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.2039215862751007 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.4745098352432251 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.8588235974311829 - } - values { - number_value: 0.1568627506494522 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.4745098352432251 - } - values { - number_value: 0.9960784912109375 - } - values { - number_value: 0.8117647767066956 - } - values { - number_value: 0.07058823853731155 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - values { - number_value: 0.0 - } - } - } - } +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# AWS Elastic Container Service (EKS) Deep MNIST Example\n", + "\n", + "In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS).\n", + "\n", + "This tutorial will break down in the following sections:\n", + "\n", + "1) Train a tensorflow model to predict mnist locally\n", + "\n", + "2) Containerise the tensorflow model with our docker utility\n", + "\n", + "3) Send some data to the docker model to test it\n", + "\n", + "4) Install and configure AWS tools to interact with AWS\n", + "\n", + "5) Use the AWS tools to create and setup EKS cluster with Seldon\n", + "\n", + "6) Push and run docker image through the AWS Container Registry\n", + "\n", + "7) Test our Elastic Kubernetes deployment by sending some data\n", + "\n", + "#### Let's get started! 🚀🔥\n", + "\n", + "## Dependencies:\n", + "\n", + "* Helm v2.13.1+\n", + "* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM)\n", + "* kubectl v1.14+\n", + "* EKS CLI v0.1.32\n", + "* AWS Cli v1.16.163\n", + "* Python 3.6+\n", + "* Python DEV requirements\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1) Train a tensorflow model to predict mnist locally\n", + "We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Extracting MNIST_data/train-images-idx3-ubyte.gz\n", + "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n", + "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n", + "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n", + "0.9194\n" + ] } - - Response: - meta { - puid: "l6bv1r38mmb32l0hbinln2jjcl" - requestPath { - key: "classifier" - value: "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest" - } + ], + "source": [ + "from tensorflow.examples.tutorials.mnist import input_data\n", + "mnist = input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", + "import tensorflow as tf\n", + "\n", + "if __name__ == '__main__':\n", + " \n", + " x = tf.placeholder(tf.float32, [None,784], name=\"x\")\n", + "\n", + " W = tf.Variable(tf.zeros([784,10]))\n", + " b = tf.Variable(tf.zeros([10]))\n", + "\n", + " y = tf.nn.softmax(tf.matmul(x,W) + b, name=\"y\")\n", + "\n", + " y_ = tf.placeholder(tf.float32, [None, 10])\n", + "\n", + " cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))\n", + "\n", + " train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)\n", + "\n", + " init = tf.initialize_all_variables()\n", + "\n", + " sess = tf.Session()\n", + " sess.run(init)\n", + "\n", + " for i in range(1000):\n", + " batch_xs, batch_ys = mnist.train.next_batch(100)\n", + " sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})\n", + "\n", + " correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))\n", + " accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n", + " print(sess.run(accuracy, feed_dict = {x: mnist.test.images, y_:mnist.test.labels}))\n", + "\n", + " saver = tf.train.Saver()\n", + "\n", + " saver.save(sess, \"model/deep_mnist_model\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2) Containerise the tensorflow model with our docker utility" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First you need to make sure that you have added the .s2i/environment configuration file in this folder with the following content:" + ] + }, + { + "cell_type": "code", + "execution_count": 118, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "MODEL_NAME=DeepMnist\r\n", + "API_TYPE=REST\r\n", + "SERVICE_TYPE=MODEL\r\n", + "PERSISTENCE=0\r\n" + ] } - data { - names: "class:0" - names: "class:1" - names: "class:2" - names: "class:3" - names: "class:4" - names: "class:5" - names: "class:6" - names: "class:7" - names: "class:8" - names: "class:9" - ndarray { - values { - list_value { - values { - number_value: 6.839015986770391e-05 - } - values { - number_value: 9.376968534979824e-09 - } - values { - number_value: 8.48581112222746e-05 - } - values { - number_value: 0.0034086888190358877 - } - values { - number_value: 2.3978568606253248e-06 - } - values { - number_value: 2.0100669644307345e-05 - } - values { - number_value: 3.0251623428512175e-08 - } - values { - number_value: 0.9953710436820984 - } - values { - number_value: 2.6070511012221687e-05 - } - values { - number_value: 0.0010185304563492537 - } - } - } - } + ], + "source": [ + "!cat .s2i/environment" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can build a docker image named \"deep-mnist\" with the tag 0.1" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "---> Installing application source...\n", + "---> Installing dependencies ...\n", + "Looking in links: /whl\n", + "Requirement already satisfied: tensorflow>=1.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (1.13.1)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.9)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.2.2)\n", + "Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.7)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.12.0)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.1.0)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.19.0)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.33.1)\n", + "Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.1)\n", + "Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.16.2)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.7.0)\n", + "Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.0)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.9.0)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.0.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.15.0)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow>=1.12.0->-r requirements.txt (line 1)) (40.8.0)\n", + "Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.0.0)\n", + "Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (5.1.3)\n", + "Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", + "You are using pip version 19.0.3, however version 19.1.1 is available.\n", + "You should consider upgrading via the 'pip install --upgrade pip' command.\n", + "Build completed successfully\n" + ] } - - - -### Let's visualise the probability for each label -It seems that it correctly predicted the number 7 - - -```python -for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): - print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") -``` - - LABEL 0: 0.0068 % - LABEL 1: 0.0000 % - LABEL 2: 0.0085 % - LABEL 3: 0.3409 % - LABEL 4: 0.0002 % - LABEL 5: 0.0020 % - LABEL 6: 0.0000 % - LABEL 7: 99.5371 % - LABEL 8: 0.0026 % - LABEL 9: 0.1019 % - - - -```python - -``` + ], + "source": [ + "!s2i build . seldonio/seldon-core-s2i-python36:0.5.1 deep-mnist:0.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3) Send some data to the docker model to test it\n", + "We first run the docker image we just created as a container called \"mnist_predictor\"" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5157ab4f516bd0dea11b159780f31121e9fb41df6394e0d6d631e6e0d572463b\r\n" + ] + } + ], + "source": [ + "!docker run --name \"mnist_predictor\" -d --rm -p 5000:5000 deep-mnist:0.1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Send some random features that conform to the contract" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]\n" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "# This is the variable that was initialised at the beginning of the file\n", + "i = [0]\n", + "x = mnist.test.images[i]\n", + "y = mnist.test.labels[i]\n", + "plt.imshow(x.reshape((28, 28)), cmap='gray')\n", + "plt.show()\n", + "print(\"Expected label: \", np.sum(range(0,10) * y), \". One hot encoding: \", y)" + ] + }, + { + "cell_type": "code", + "execution_count": 144, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LABEL 0:\t 0.0068 %\n", + "LABEL 1:\t 0.0000 %\n", + "LABEL 2:\t 0.0085 %\n", + "LABEL 3:\t 0.3409 %\n", + "LABEL 4:\t 0.0002 %\n", + "LABEL 5:\t 0.0020 %\n", + "LABEL 6:\t 0.0000 %\n", + "LABEL 7:\t 99.5371 %\n", + "LABEL 8:\t 0.0026 %\n", + "LABEL 9:\t 0.1019 %\n" + ] + } + ], + "source": [ + "from seldon_core.seldon_client import SeldonClient\n", + "import math\n", + "import numpy as np\n", + "\n", + "# We now test the REST endpoint expecting the same result\n", + "endpoint = \"0.0.0.0:5000\"\n", + "batch = x\n", + "payload_type = \"ndarray\"\n", + "\n", + "sc = SeldonClient(microservice_endpoint=endpoint)\n", + "\n", + "# We use the microservice, instead of the \"predict\" function\n", + "client_prediction = sc.microservice(\n", + " data=batch,\n", + " method=\"predict\",\n", + " payload_type=payload_type,\n", + " names=[\"tfidf\"])\n", + "\n", + "for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)):\n", + " print(f\"LABEL {label}:\\t {proba.number_value*100:6.4f} %\")" + ] + }, + { + "cell_type": "code", + "execution_count": 145, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "mnist_predictor\r\n" + ] + } + ], + "source": [ + "!docker rm mnist_predictor --force" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4) Install and configure AWS tools to interact with AWS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we install the awscli" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collecting awscli\n", + " Using cached https://files.pythonhosted.org/packages/f6/45/259a98719e7c7defc9be4cc00fbfb7ccf699fbd1f74455d8347d0ab0a1df/awscli-1.16.163-py2.py3-none-any.whl\n", + "Collecting colorama<=0.3.9,>=0.2.5 (from awscli)\n", + " Using cached https://files.pythonhosted.org/packages/db/c8/7dcf9dbcb22429512708fe3a547f8b6101c0d02137acbd892505aee57adf/colorama-0.3.9-py2.py3-none-any.whl\n", + "Collecting PyYAML<=3.13,>=3.10 (from awscli)\n", + "Collecting botocore==1.12.153 (from awscli)\n", + " Using cached https://files.pythonhosted.org/packages/ec/3b/029218966ce62ae9824a18730de862ac8fc5a0e8083d07d1379815e7cca1/botocore-1.12.153-py2.py3-none-any.whl\n", + "Requirement already satisfied, skipping upgrade: docutils>=0.10 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.14)\n", + "Collecting rsa<=3.5.0,>=3.1.2 (from awscli)\n", + " Using cached https://files.pythonhosted.org/packages/e1/ae/baedc9cb175552e95f3395c43055a6a5e125ae4d48a1d7a924baca83e92e/rsa-3.4.2-py2.py3-none-any.whl\n", + "Requirement already satisfied, skipping upgrade: s3transfer<0.3.0,>=0.2.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.2.0)\n", + "Requirement already satisfied, skipping upgrade: urllib3<1.25,>=1.20; python_version >= \"3.4\" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (1.24.2)\n", + "Requirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.1; python_version >= \"2.7\" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (2.8.0)\n", + "Requirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (0.9.4)\n", + "Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli)\n", + " Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl\n", + "Requirement already satisfied, skipping upgrade: six>=1.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from python-dateutil<3.0.0,>=2.1; python_version >= \"2.7\"->botocore==1.12.153->awscli) (1.12.0)\n", + "Installing collected packages: colorama, PyYAML, botocore, pyasn1, rsa, awscli\n", + "Successfully installed PyYAML-3.13 awscli-1.16.163 botocore-1.12.153 colorama-0.3.9 pyasn1-0.4.5 rsa-3.4.2\n" + ] + } + ], + "source": [ + "!pip install awscli --upgrade --user" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Configure aws so it can talk to your server \n", + "(if you are getting issues, make sure you have the permmissions to create clusters)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "AWS Access Key ID [****************SF4A]: AWS Secret Access Key [****************WLHu]: Default region name [eu-west-1]: Default output format [json]: " + ] + } + ], + "source": [ + "%%bash \n", + "# You must make sure that the access key and secret are changed\n", + "aws configure << END_OF_INPUTS\n", + "YOUR_ACCESS_KEY\n", + "YOUR_ACCESS_SECRET\n", + "us-west-2\n", + "json\n", + "END_OF_INPUTS" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Install EKCTL\n", + "*IMPORTANT*: These instructions are for linux\n", + "Please follow the official installation of ekctl at: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "!curl --silent --location \"https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz\" | tar xz " + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "!chmod 755 ./eksctl" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[36m[ℹ] version.Info{BuiltAt:\"\", GitCommit:\"\", GitTag:\"0.1.32\"}\r\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!./eksctl version" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5) Use the AWS tools to create and setup EKS cluster with Seldon\n", + "In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly.\n", + "\n", + "If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard.\n", + "\n", + "It will take 10-15 minutes (so feel free to go grab a ☕). \n", + "\n", + "### IMPORTANT: If you get errors in this step...\n", + "It is most probably IAM role access requirements, which requires you to discuss with your administrator." + ] + }, + { + "cell_type": "code", + "execution_count": 107, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Process is interrupted.\n" + ] + } + ], + "source": [ + "%%bash\n", + "./eksctl create cluster \\\n", + "--name demo-eks-cluster \\\n", + "--region us-west-2 \\\n", + "--nodes 2 " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Configure local kubectl \n", + "We want to now configure our local Kubectl so we can actually reach the cluster we've just created" + ] + }, + { + "cell_type": "code", + "execution_count": 108, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Updated context arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist in /home/alejandro/.kube/config\r\n" + ] + } + ], + "source": [ + "!aws eks --region us-west-2 update-kubeconfig --name demo-eks-cluster" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And we can check if the context has been added to kubectl config (contexts are basically the different k8s cluster connections)\n", + "You should be able to see the context as \"...aws:eks:eu-west-1:27...\". \n", + "If it's not activated you can activate that context with kubectlt config set-context " + ] + }, + { + "cell_type": "code", + "execution_count": 109, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CURRENT NAME CLUSTER AUTHINFO NAMESPACE\r\n", + "* arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist \r\n", + " docker-desktop docker-desktop docker-desktop \r\n", + " docker-for-desktop docker-desktop docker-desktop \r\n", + " gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 \r\n" + ] + } + ], + "source": [ + "!kubectl config get-contexts" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Install Seldon Core" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Before we install seldon core, we need to install HELM\n", + "For that, we need to create a ClusterRoleBinding for us, a ServiceAccount, and then a RoleBinding" + ] + }, + { + "cell_type": "code", + "execution_count": 114, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created\r\n" + ] + } + ], + "source": [ + "!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "serviceaccount/tiller created\r\n" + ] + } + ], + "source": [ + "!kubectl create serviceaccount tiller --namespace kube-system" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "clusterrolebinding.rbac.authorization.k8s.io/tiller-role-binding created\r\n" + ] + } + ], + "source": [ + "!kubectl apply -f tiller-role-binding.yaml" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Once that is set-up we can install Tiller" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "$HELM_HOME has been configured at /home/alejandro/.helm.\n", + "\n", + "Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.\n", + "\n", + "Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.\n", + "To prevent this, run `helm init` with the --tiller-tls-verify flag.\n", + "For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation\n", + "Happy Helming!\n" + ] + } + ], + "source": [ + "!helm init --service-account tiller" + ] + }, + { + "cell_type": "code", + "execution_count": 120, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "deployment \"tiller-deploy\" successfully rolled out\r\n" + ] + } + ], + "source": [ + "# Wait until Tiller finishes\n", + "!kubectl rollout status deploy/tiller-deploy -n kube-system" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now we can install SELDON. \n", + "We first start with the custom resource definitions (CRDs)" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: seldon-core-operator\n", + "LAST DEPLOYED: Wed May 22 16:24:10 2019\n", + "NAMESPACE: seldon-system\n", + "STATUS: DEPLOYED\n", + "\n", + "RESOURCES:\n", + "==> v1/ClusterRole\n", + "NAME AGE\n", + "seldon-operator-manager-role 2s\n", + "\n", + "==> v1/ClusterRoleBinding\n", + "NAME AGE\n", + "seldon-operator-manager-rolebinding 2s\n", + "\n", + "==> v1/ConfigMap\n", + "NAME DATA AGE\n", + "seldon-spartakus-config 3 2s\n", + "\n", + "==> v1/Pod(related)\n", + "NAME READY STATUS RESTARTS AGE\n", + "seldon-operator-controller-manager-0 0/1 ContainerCreating 0 2s\n", + "seldon-spartakus-volunteer-6954cffb89-qz4pq 0/1 ContainerCreating 0 1s\n", + "\n", + "==> v1/Secret\n", + "NAME TYPE DATA AGE\n", + "seldon-operator-webhook-server-secret Opaque 0 2s\n", + "\n", + "==> v1/Service\n", + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", + "seldon-operator-controller-manager-service ClusterIP 10.100.198.157 443/TCP 2s\n", + "\n", + "==> v1/ServiceAccount\n", + "NAME SECRETS AGE\n", + "seldon-spartakus-volunteer 1 2s\n", + "\n", + "==> v1/StatefulSet\n", + "NAME READY AGE\n", + "seldon-operator-controller-manager 0/1 2s\n", + "\n", + "==> v1beta1/ClusterRole\n", + "NAME AGE\n", + "seldon-spartakus-volunteer 2s\n", + "\n", + "==> v1beta1/ClusterRoleBinding\n", + "NAME AGE\n", + "seldon-spartakus-volunteer 2s\n", + "\n", + "==> v1beta1/CustomResourceDefinition\n", + "NAME AGE\n", + "seldondeployments.machinelearning.seldon.io 2s\n", + "\n", + "==> v1beta1/Deployment\n", + "NAME READY UP-TO-DATE AVAILABLE AGE\n", + "seldon-spartakus-volunteer 0/1 1 0 2s\n", + "\n", + "\n", + "NOTES:\n", + "NOTES: TODO\n", + "\n", + "\n" + ] + } + ], + "source": [ + "!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --namespace seldon-system" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And confirm they are running by getting the pods:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "partitioned roll out complete: 1 new pods have been updated...\r\n" + ] + } + ], + "source": [ + "!kubectl rollout status statefulset.apps/seldon-operator-controller-manager -n seldon-system" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now we set-up the ingress\n", + "This will allow you to reach the Seldon models from outside the kubernetes cluster. \n", + "\n", + "In EKS it automatically creates an Elastic Load Balancer, which you can configure from the EC2 Console" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME: ambassador\n", + "LAST DEPLOYED: Wed May 22 16:25:38 2019\n", + "NAMESPACE: default\n", + "STATUS: DEPLOYED\n", + "\n", + "RESOURCES:\n", + "==> v1/Deployment\n", + "NAME READY UP-TO-DATE AVAILABLE AGE\n", + "ambassador 0/3 3 0 0s\n", + "\n", + "==> v1/Pod(related)\n", + "NAME READY STATUS RESTARTS AGE\n", + "ambassador-6dbf99c886-frlfm 0/1 ContainerCreating 0 0s\n", + "ambassador-6dbf99c886-kj56r 0/1 ContainerCreating 0 0s\n", + "ambassador-6dbf99c886-v5mtv 0/1 ContainerCreating 0 0s\n", + "\n", + "==> v1/Service\n", + "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", + "ambassador LoadBalancer 10.100.59.146 80:30911/TCP,443:31715/TCP 0s\n", + "ambassador-admins ClusterIP 10.100.152.178 8877/TCP 0s\n", + "\n", + "==> v1/ServiceAccount\n", + "NAME SECRETS AGE\n", + "ambassador 1 0s\n", + "\n", + "==> v1beta1/ClusterRole\n", + "NAME AGE\n", + "ambassador 0s\n", + "\n", + "==> v1beta1/ClusterRoleBinding\n", + "NAME AGE\n", + "ambassador 0s\n", + "\n", + "\n", + "NOTES:\n", + "Congratuations! You've successfully installed Ambassador.\n", + "\n", + "For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io.\n", + "\n", + "To get the IP address of Ambassador, run the following commands:\n", + "NOTE: It may take a few minutes for the LoadBalancer IP to be available.\n", + " You can watch the status of by running 'kubectl get svc -w --namespace default ambassador'\n", + "\n", + " On GKE/Azure:\n", + " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", + "\n", + " On AWS:\n", + " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')\n", + "\n", + " echo http://$SERVICE_IP:\n", + "\n" + ] + } + ], + "source": [ + "!helm install stable/ambassador --name ambassador --set image.tag=0.40.2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And let's wait until it's fully deployed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!kubectl rollout status deployment.apps/ambassador" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Push docker image\n", + "In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR).\n", + "\n", + "If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### First we create a registry\n", + "You can run the following command, and then see the result at https://us-west-2.console.aws.amazon.com/ecr/repositories?#" + ] + }, + { + "cell_type": "code", + "execution_count": 110, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\r\n", + " \"repository\": {\r\n", + " \"repositoryArn\": \"arn:aws:ecr:us-west-2:271049282727:repository/seldon-repository\",\r\n", + " \"registryId\": \"271049282727\",\r\n", + " \"repositoryName\": \"seldon-repository\",\r\n", + " \"repositoryUri\": \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository\",\r\n", + " \"createdAt\": 1558535798.0\r\n", + " }\r\n", + "}\r\n" + ] + } + ], + "source": [ + "!aws ecr create-repository --repository-name seldon-repository --region us-west-2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Now prepare docker image\n", + "We need to first tag the docker image before we can push it" + ] + }, + { + "cell_type": "code", + "execution_count": 111, + "metadata": {}, + "outputs": [], + "source": [ + "%%bash\n", + "export AWS_ACCOUNT_ID=\"\"\n", + "export AWS_REGION=\"us-west-2\"\n", + "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", + " echo \"ERROR: Please provide a value for the AWS variables\"\n", + " exit 1\n", + "fi\n", + "\n", + "docker tag deep-mnist:0.1 \"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### We now login to aws through docker so we can access the repository" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING! Using --password via the CLI is insecure. Use --password-stdin.\n", + "WARNING! Your password will be stored unencrypted in /home/alejandro/.docker/config.json.\n", + "Configure a credential helper to remove this warning. See\n", + "https://docs.docker.com/engine/reference/commandline/login/#credentials-store\n", + "\n", + "Login Succeeded\n" + ] + } + ], + "source": [ + "!`aws ecr get-login --no-include-email --region us-west-2`" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### And push the image\n", + "Make sure you add your AWS Account ID" + ] + }, + { + "cell_type": "code", + "execution_count": 113, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The push refers to repository [271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository]\n", + "f7d0d000c138: Preparing\n", + "987f3f1afb00: Preparing\n", + "00d16a381c47: Preparing\n", + "bb01f50d544a: Preparing\n", + "fcb82c6941b5: Preparing\n", + "67290e35c458: Preparing\n", + "b813745f5bb3: Preparing\n", + "ffecb18e9f0b: Preparing\n", + "f50f856f49fa: Preparing\n", + "80b43ad4adf9: Preparing\n", + "14c77983a1cf: Preparing\n", + "a22a5ac18042: Preparing\n", + "6257fa9f9597: Preparing\n", + "578414b395b9: Preparing\n", + "abc3250a6c7f: Preparing\n", + "13d5529fd232: Preparing\n", + "67290e35c458: Waiting\n", + "b813745f5bb3: Waiting\n", + "ffecb18e9f0b: Waiting\n", + "f50f856f49fa: Waiting\n", + "80b43ad4adf9: Waiting\n", + "6257fa9f9597: Waiting\n", + "14c77983a1cf: Waiting\n", + "a22a5ac18042: Waiting\n", + "578414b395b9: Waiting\n", + "abc3250a6c7f: Waiting\n", + "13d5529fd232: Waiting\n", + "987f3f1afb00: Pushed\n", + "fcb82c6941b5: Pushed\n", + "bb01f50d544a: Pushed\n", + "f7d0d000c138: Pushed\n", + "ffecb18e9f0b: Pushed\n", + "b813745f5bb3: Pushed\n", + "f50f856f49fa: Pushed\n", + "67290e35c458: Pushed\n", + "14c77983a1cf: Pushed\n", + "578414b395b9: Pushed\n", + "80b43ad4adf9: Pushed\n", + "13d5529fd232: Pushed\n", + "6257fa9f9597: Pushed\n", + "abc3250a6c7f: Pushed\n", + "00d16a381c47: Pushed\n", + "a22a5ac18042: Pushed\n", + "latest: digest: sha256:19aefaa9d87c1287eb46ec08f5d4f9a689744d9d0d0b75668b7d15e447819d74 size: 3691\n" + ] + } + ], + "source": [ + "%%bash\n", + "export AWS_ACCOUNT_ID=\"\"\n", + "export AWS_REGION=\"us-west-2\"\n", + "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", + " echo \"ERROR: Please provide a value for the AWS variables\"\n", + " exit 1\n", + "fi\n", + "\n", + "docker push \"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Running the Model\n", + "We will now run the model.\n", + "\n", + "Let's first have a look at the file we'll be using to trigger the model:" + ] + }, + { + "cell_type": "code", + "execution_count": 127, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\r\n", + " \"apiVersion\": \"machinelearning.seldon.io/v1alpha2\",\r\n", + " \"kind\": \"SeldonDeployment\",\r\n", + " \"metadata\": {\r\n", + " \"labels\": {\r\n", + " \"app\": \"seldon\"\r\n", + " },\r\n", + " \"name\": \"deep-mnist\"\r\n", + " },\r\n", + " \"spec\": {\r\n", + " \"annotations\": {\r\n", + " \"project_name\": \"Tensorflow MNIST\",\r\n", + " \"deployment_version\": \"v1\"\r\n", + " },\r\n", + " \"name\": \"deep-mnist\",\r\n", + " \"oauth_key\": \"oauth-key\",\r\n", + " \"oauth_secret\": \"oauth-secret\",\r\n", + " \"predictors\": [\r\n", + " {\r\n", + " \"componentSpecs\": [{\r\n", + " \"spec\": {\r\n", + " \"containers\": [\r\n", + " {\r\n", + " \"image\": \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest\",\r\n", + " \"imagePullPolicy\": \"IfNotPresent\",\r\n", + " \"name\": \"classifier\",\r\n", + " \"resources\": {\r\n", + " \"requests\": {\r\n", + " \"memory\": \"1Mi\"\r\n", + " }\r\n", + " }\r\n", + " }\r\n", + " ],\r\n", + " \"terminationGracePeriodSeconds\": 20\r\n", + " }\r\n", + " }],\r\n", + " \"graph\": {\r\n", + " \"children\": [],\r\n", + " \"name\": \"classifier\",\r\n", + " \"endpoint\": {\r\n", + "\t\t\t\"type\" : \"REST\"\r\n", + "\t\t },\r\n", + " \"type\": \"MODEL\"\r\n", + " },\r\n", + " \"name\": \"single-model\",\r\n", + " \"replicas\": 1,\r\n", + "\t\t\"annotations\": {\r\n", + "\t\t \"predictor_version\" : \"v1\"\r\n", + "\t\t}\r\n", + " }\r\n", + " ]\r\n", + " }\r\n", + "}\r\n" + ] + } + ], + "source": [ + "!cat deep_mnist.json" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's trigger seldon to run the model.\n", + "\n", + "We basically have a yaml file, where we want to replace the value \"REPLACE_FOR_IMAGE_AND_TAG\" for the image you pushed" + ] + }, + { + "cell_type": "code", + "execution_count": 165, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "error: unable to recognize \"STDIN\": Get https://461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com/api?timeout=32s: dial tcp: lookup 461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com on 1.1.1.1:53: no such host\n" + ] + }, + { + "ename": "CalledProcessError", + "evalue": "Command 'b'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'' returned non-zero exit status 1.", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_cell_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'bash'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2350\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2351\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2352\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2353\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py\u001b[0m in \u001b[0;36mnamed_script_magic\u001b[0;34m(line, cell)\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 141\u001b[0m \u001b[0mline\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mscript\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 142\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshebang\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 143\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 144\u001b[0m \u001b[0;31m# write a basic docstring:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mshebang\u001b[0;34m(self, line, cell)\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py\u001b[0m in \u001b[0;36mshebang\u001b[0;34m(self, line, cell)\u001b[0m\n\u001b[1;32m 243\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflush\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 244\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_error\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturncode\u001b[0m\u001b[0;34m!=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 245\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturncode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstderr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 246\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_run_script\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mto_close\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mCalledProcessError\u001b[0m: Command 'b'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'' returned non-zero exit status 1." + ] + } + ], + "source": [ + "%%bash\n", + "export AWS_ACCOUNT_ID=\"\"\n", + "export AWS_REGION=\"us-west-2\"\n", + "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", + " echo \"ERROR: Please provide a value for the AWS variables\"\n", + " exit 1\n", + "fi\n", + "\n", + "sed 's|REPLACE_FOR_IMAGE_AND_TAG|'\"$AWS_ACCOUNT_ID\"'.dkr.ecr.'\"$AWS_REGION\"'.amazonaws.com/seldon-repository|g' deep_mnist.json | kubectl apply -f -" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And let's check that it's been created.\n", + "\n", + "You should see an image called \"deep-mnist-single-model...\".\n", + "\n", + "We'll wait until STATUS changes from \"ContainerCreating\" to \"Running\"" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "NAME READY STATUS RESTARTS AGE\r\n", + "ambassador-5475779f98-7bhcw 1/1 Running 0 21m\r\n", + "ambassador-5475779f98-986g5 1/1 Running 0 21m\r\n", + "ambassador-5475779f98-zcd28 1/1 Running 0 21m\r\n", + "deep-mnist-single-model-42ed9d9-fdb557d6b-6xv2h 2/2 Running 0 18m\r\n" + ] + } + ], + "source": [ + "!kubectl get pods" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Test the model\n", + "Now we can test the model, let's first find out what is the URL that we'll have to use:" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com" + ] + } + ], + "source": [ + "!kubectl get svc ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll use a random example from our dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]\n" + ] + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "# This is the variable that was initialised at the beginning of the file\n", + "i = [0]\n", + "x = mnist.test.images[i]\n", + "y = mnist.test.labels[i]\n", + "plt.imshow(x.reshape((28, 28)), cmap='gray')\n", + "plt.show()\n", + "print(\"Expected label: \", np.sum(range(0,10) * y), \". One hot encoding: \", y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can now add the URL above to send our request:" + ] + }, + { + "cell_type": "code", + "execution_count": 112, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Success:True message:\n", + "Request:\n", + "data {\n", + " names: \"text\"\n", + " ndarray {\n", + " values {\n", + " list_value {\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.3294117748737335\n", + " }\n", + " values {\n", + " number_value: 0.7254902124404907\n", + " }\n", + " values {\n", + " number_value: 0.6235294342041016\n", + " }\n", + " values {\n", + " number_value: 0.5921568870544434\n", + " }\n", + " values {\n", + " number_value: 0.2352941334247589\n", + " }\n", + " values {\n", + " number_value: 0.1411764770746231\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.8705883026123047\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9450981020927429\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.7764706611633301\n", + " }\n", + " values {\n", + " number_value: 0.6666666865348816\n", + " }\n", + " values {\n", + " number_value: 0.2039215862751007\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.26274511218070984\n", + " }\n", + " values {\n", + " number_value: 0.44705885648727417\n", + " }\n", + " values {\n", + " number_value: 0.2823529541492462\n", + " }\n", + " values {\n", + " number_value: 0.44705885648727417\n", + " }\n", + " values {\n", + " number_value: 0.6392157077789307\n", + " }\n", + " values {\n", + " number_value: 0.8901961445808411\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.8823530077934265\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9803922176361084\n", + " }\n", + " values {\n", + " number_value: 0.8980392813682556\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.5490196347236633\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.06666667014360428\n", + " }\n", + " values {\n", + " number_value: 0.25882354378700256\n", + " }\n", + " values {\n", + " number_value: 0.05490196496248245\n", + " }\n", + " values {\n", + " number_value: 0.26274511218070984\n", + " }\n", + " values {\n", + " number_value: 0.26274511218070984\n", + " }\n", + " values {\n", + " number_value: 0.26274511218070984\n", + " }\n", + " values {\n", + " number_value: 0.23137256503105164\n", + " }\n", + " values {\n", + " number_value: 0.08235294371843338\n", + " }\n", + " values {\n", + " number_value: 0.9254902601242065\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.41568630933761597\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.32549020648002625\n", + " }\n", + " values {\n", + " number_value: 0.9921569228172302\n", + " }\n", + " values {\n", + " number_value: 0.8196079134941101\n", + " }\n", + " values {\n", + " number_value: 0.07058823853731155\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.08627451211214066\n", + " }\n", + " values {\n", + " number_value: 0.9137255549430847\n", + " }\n", + " values {\n", + " number_value: 1.0\n", + " }\n", + " values {\n", + " number_value: 0.32549020648002625\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.5058823823928833\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9333333969116211\n", + " }\n", + " values {\n", + " number_value: 0.1725490242242813\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.23137256503105164\n", + " }\n", + " values {\n", + " number_value: 0.9764706492424011\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.24313727021217346\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.5215686559677124\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.7333333492279053\n", + " }\n", + " values {\n", + " number_value: 0.019607843831181526\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.03529411926865578\n", + " }\n", + " values {\n", + " number_value: 0.803921639919281\n", + " }\n", + " values {\n", + " number_value: 0.9725490808486938\n", + " }\n", + " values {\n", + " number_value: 0.22745099663734436\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.4941176772117615\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.7137255072593689\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.29411765933036804\n", + " }\n", + " values {\n", + " number_value: 0.9843137860298157\n", + " }\n", + " values {\n", + " number_value: 0.9411765336990356\n", + " }\n", + " values {\n", + " number_value: 0.22352942824363708\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.07450980693101883\n", + " }\n", + " values {\n", + " number_value: 0.8666667342185974\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.6509804129600525\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.011764707043766975\n", + " }\n", + " values {\n", + " number_value: 0.7960785031318665\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.8588235974311829\n", + " }\n", + " values {\n", + " number_value: 0.13725490868091583\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.14901961386203766\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.3019607961177826\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.12156863510608673\n", + " }\n", + " values {\n", + " number_value: 0.8784314393997192\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.45098042488098145\n", + " }\n", + " values {\n", + " number_value: 0.003921568859368563\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.5215686559677124\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.2039215862751007\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.2392157018184662\n", + " }\n", + " values {\n", + " number_value: 0.9490196704864502\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.2039215862751007\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.4745098352432251\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.8588235974311829\n", + " }\n", + " values {\n", + " number_value: 0.1568627506494522\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.4745098352432251\n", + " }\n", + " values {\n", + " number_value: 0.9960784912109375\n", + " }\n", + " values {\n", + " number_value: 0.8117647767066956\n", + " }\n", + " values {\n", + " number_value: 0.07058823853731155\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " values {\n", + " number_value: 0.0\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "Response:\n", + "meta {\n", + " puid: \"l6bv1r38mmb32l0hbinln2jjcl\"\n", + " requestPath {\n", + " key: \"classifier\"\n", + " value: \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest\"\n", + " }\n", + "}\n", + "data {\n", + " names: \"class:0\"\n", + " names: \"class:1\"\n", + " names: \"class:2\"\n", + " names: \"class:3\"\n", + " names: \"class:4\"\n", + " names: \"class:5\"\n", + " names: \"class:6\"\n", + " names: \"class:7\"\n", + " names: \"class:8\"\n", + " names: \"class:9\"\n", + " ndarray {\n", + " values {\n", + " list_value {\n", + " values {\n", + " number_value: 6.839015986770391e-05\n", + " }\n", + " values {\n", + " number_value: 9.376968534979824e-09\n", + " }\n", + " values {\n", + " number_value: 8.48581112222746e-05\n", + " }\n", + " values {\n", + " number_value: 0.0034086888190358877\n", + " }\n", + " values {\n", + " number_value: 2.3978568606253248e-06\n", + " }\n", + " values {\n", + " number_value: 2.0100669644307345e-05\n", + " }\n", + " values {\n", + " number_value: 3.0251623428512175e-08\n", + " }\n", + " values {\n", + " number_value: 0.9953710436820984\n", + " }\n", + " values {\n", + " number_value: 2.6070511012221687e-05\n", + " }\n", + " values {\n", + " number_value: 0.0010185304563492537\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n" + ] + } + ], + "source": [ + "from seldon_core.seldon_client import SeldonClient\n", + "import math\n", + "import numpy as np\n", + "\n", + "host = \"a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com\"\n", + "port = \"80\" # Make sure you use the port above\n", + "batch = x\n", + "payload_type = \"ndarray\"\n", + "\n", + "sc = SeldonClient(\n", + " gateway=\"ambassador\", \n", + " ambassador_endpoint=host + \":\" + port,\n", + " namespace=\"default\",\n", + " oauth_key=\"oauth-key\", \n", + " oauth_secret=\"oauth-secret\")\n", + "\n", + "client_prediction = sc.predict(\n", + " data=batch, \n", + " deployment_name=\"deep-mnist\",\n", + " names=[\"text\"],\n", + " payload_type=payload_type)\n", + "\n", + "print(client_prediction)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Let's visualise the probability for each label\n", + "It seems that it correctly predicted the number 7" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LABEL 0:\t 0.0068 %\n", + "LABEL 1:\t 0.0000 %\n", + "LABEL 2:\t 0.0085 %\n", + "LABEL 3:\t 0.3409 %\n", + "LABEL 4:\t 0.0002 %\n", + "LABEL 5:\t 0.0020 %\n", + "LABEL 6:\t 0.0000 %\n", + "LABEL 7:\t 99.5371 %\n", + "LABEL 8:\t 0.0026 %\n", + "LABEL 9:\t 0.1019 %\n" + ] + } + ], + "source": [ + "for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)):\n", + " print(f\"LABEL {label}:\\t {proba.number_value*100:6.4f} %\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.7.3" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb index f6199e5456..ba0eba4089 100644 --- a/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb +++ b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb @@ -4,7 +4,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Tensorflow MNIST Model\n", + "# AWS Elastic Kubernetes Service (EKS) Deep MNIST\n", "In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS).\n", "\n", "This tutorial will break down in the following sections:\n", @@ -40,7 +40,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# 1) Train a tensorflow model to predict mnist locally\n", + "## 1) Train a tensorflow model to predict mnist locally\n", "We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels" ] }, From 1c62ff0c67611b6a95add3e195f89941028a55c0 Mon Sep 17 00:00:00 2001 From: Alejandro Saucedo Date: Mon, 27 May 2019 15:46:45 +0100 Subject: [PATCH 3/3] Updated headline --- examples/models/aws_eks_deep_mnist/README.md | 7128 ++++++++---------- 1 file changed, 3305 insertions(+), 3823 deletions(-) diff --git a/examples/models/aws_eks_deep_mnist/README.md b/examples/models/aws_eks_deep_mnist/README.md index 6cd31e9784..7153c25239 100644 --- a/examples/models/aws_eks_deep_mnist/README.md +++ b/examples/models/aws_eks_deep_mnist/README.md @@ -1,3826 +1,3308 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# AWS Elastic Container Service (EKS) Deep MNIST Example\n", - "\n", - "In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS).\n", - "\n", - "This tutorial will break down in the following sections:\n", - "\n", - "1) Train a tensorflow model to predict mnist locally\n", - "\n", - "2) Containerise the tensorflow model with our docker utility\n", - "\n", - "3) Send some data to the docker model to test it\n", - "\n", - "4) Install and configure AWS tools to interact with AWS\n", - "\n", - "5) Use the AWS tools to create and setup EKS cluster with Seldon\n", - "\n", - "6) Push and run docker image through the AWS Container Registry\n", - "\n", - "7) Test our Elastic Kubernetes deployment by sending some data\n", - "\n", - "#### Let's get started! 🚀🔥\n", - "\n", - "## Dependencies:\n", - "\n", - "* Helm v2.13.1+\n", - "* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM)\n", - "* kubectl v1.14+\n", - "* EKS CLI v0.1.32\n", - "* AWS Cli v1.16.163\n", - "* Python 3.6+\n", - "* Python DEV requirements\n" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 1) Train a tensorflow model to predict mnist locally\n", - "We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels" - ] - }, - { - "cell_type": "code", - "execution_count": 45, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Extracting MNIST_data/train-images-idx3-ubyte.gz\n", - "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n", - "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n", - "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n", - "0.9194\n" - ] + +# AWS Elastic Kubernetes Service (EKS) Deep MNIST +In this example we will deploy a tensorflow MNIST model in Amazon Web Services' Elastic Kubernetes Service (EKS). + +This tutorial will break down in the following sections: + +1) Train a tensorflow model to predict mnist locally + +2) Containerise the tensorflow model with our docker utility + +3) Send some data to the docker model to test it + +4) Install and configure AWS tools to interact with AWS + +5) Use the AWS tools to create and setup EKS cluster with Seldon + +6) Push and run docker image through the AWS Container Registry + +7) Test our Elastic Kubernetes deployment by sending some data + +#### Let's get started! 🚀🔥 + +## Dependencies: + +* Helm v2.13.1+ +* A Kubernetes cluster running v1.13 or above (minkube / docker-for-windows work well if enough RAM) +* kubectl v1.14+ +* EKS CLI v0.1.32 +* AWS Cli v1.16.163 +* Python 3.6+ +* Python DEV requirements + + +## 1) Train a tensorflow model to predict mnist locally +We will load the mnist images, together with their labels, and then train a tensorflow model to predict the right labels + + +```python +from tensorflow.examples.tutorials.mnist import input_data +mnist = input_data.read_data_sets("MNIST_data/", one_hot = True) +import tensorflow as tf + +if __name__ == '__main__': + + x = tf.placeholder(tf.float32, [None,784], name="x") + + W = tf.Variable(tf.zeros([784,10])) + b = tf.Variable(tf.zeros([10])) + + y = tf.nn.softmax(tf.matmul(x,W) + b, name="y") + + y_ = tf.placeholder(tf.float32, [None, 10]) + + cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1])) + + train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) + + init = tf.initialize_all_variables() + + sess = tf.Session() + sess.run(init) + + for i in range(1000): + batch_xs, batch_ys = mnist.train.next_batch(100) + sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) + + correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) + accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) + print(sess.run(accuracy, feed_dict = {x: mnist.test.images, y_:mnist.test.labels})) + + saver = tf.train.Saver() + + saver.save(sess, "model/deep_mnist_model") +``` + + Extracting MNIST_data/train-images-idx3-ubyte.gz + Extracting MNIST_data/train-labels-idx1-ubyte.gz + Extracting MNIST_data/t10k-images-idx3-ubyte.gz + Extracting MNIST_data/t10k-labels-idx1-ubyte.gz + 0.9194 + + +## 2) Containerise the tensorflow model with our docker utility + +First you need to make sure that you have added the .s2i/environment configuration file in this folder with the following content: + + +```python +!cat .s2i/environment +``` + + MODEL_NAME=DeepMnist + API_TYPE=REST + SERVICE_TYPE=MODEL + PERSISTENCE=0 + + +Now we can build a docker image named "deep-mnist" with the tag 0.1 + + +```python +!s2i build . seldonio/seldon-core-s2i-python36:0.5.1 deep-mnist:0.1 +``` + + ---> Installing application source... + ---> Installing dependencies ... + Looking in links: /whl + Requirement already satisfied: tensorflow>=1.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (1.13.1) + Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.9) + Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.2.2) + Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) + Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1) + Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.7) + Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.12.0) + Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.1.0) + Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.19.0) + Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.33.1) + Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.1) + Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.16.2) + Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.7.0) + Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.0) + Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.9.0) + Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.0.1) + Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.15.0) + Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow>=1.12.0->-r requirements.txt (line 1)) (40.8.0) + Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.0.0) + Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (5.1.3) + Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme. + You are using pip version 19.0.3, however version 19.1.1 is available. + You should consider upgrading via the 'pip install --upgrade pip' command. + Build completed successfully + + +## 3) Send some data to the docker model to test it +We first run the docker image we just created as a container called "mnist_predictor" + + +```python +!docker run --name "mnist_predictor" -d --rm -p 5000:5000 deep-mnist:0.1 +``` + + 5157ab4f516bd0dea11b159780f31121e9fb41df6394e0d6d631e6e0d572463b + + +Send some random features that conform to the contract + + +```python +import matplotlib.pyplot as plt +# This is the variable that was initialised at the beginning of the file +i = [0] +x = mnist.test.images[i] +y = mnist.test.labels[i] +plt.imshow(x.reshape((28, 28)), cmap='gray') +plt.show() +print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) +``` + + +![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_11_0.png) + + + Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] + + + +```python +from seldon_core.seldon_client import SeldonClient +import math +import numpy as np + +# We now test the REST endpoint expecting the same result +endpoint = "0.0.0.0:5000" +batch = x +payload_type = "ndarray" + +sc = SeldonClient(microservice_endpoint=endpoint) + +# We use the microservice, instead of the "predict" function +client_prediction = sc.microservice( + data=batch, + method="predict", + payload_type=payload_type, + names=["tfidf"]) + +for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): + print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") +``` + + LABEL 0: 0.0068 % + LABEL 1: 0.0000 % + LABEL 2: 0.0085 % + LABEL 3: 0.3409 % + LABEL 4: 0.0002 % + LABEL 5: 0.0020 % + LABEL 6: 0.0000 % + LABEL 7: 99.5371 % + LABEL 8: 0.0026 % + LABEL 9: 0.1019 % + + + +```python +!docker rm mnist_predictor --force +``` + + mnist_predictor + + +## 4) Install and configure AWS tools to interact with AWS + +First we install the awscli + + +```python +!pip install awscli --upgrade --user +``` + + Collecting awscli + Using cached https://files.pythonhosted.org/packages/f6/45/259a98719e7c7defc9be4cc00fbfb7ccf699fbd1f74455d8347d0ab0a1df/awscli-1.16.163-py2.py3-none-any.whl + Collecting colorama<=0.3.9,>=0.2.5 (from awscli) + Using cached https://files.pythonhosted.org/packages/db/c8/7dcf9dbcb22429512708fe3a547f8b6101c0d02137acbd892505aee57adf/colorama-0.3.9-py2.py3-none-any.whl + Collecting PyYAML<=3.13,>=3.10 (from awscli) + Collecting botocore==1.12.153 (from awscli) + Using cached https://files.pythonhosted.org/packages/ec/3b/029218966ce62ae9824a18730de862ac8fc5a0e8083d07d1379815e7cca1/botocore-1.12.153-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: docutils>=0.10 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.14) + Collecting rsa<=3.5.0,>=3.1.2 (from awscli) + Using cached https://files.pythonhosted.org/packages/e1/ae/baedc9cb175552e95f3395c43055a6a5e125ae4d48a1d7a924baca83e92e/rsa-3.4.2-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: s3transfer<0.3.0,>=0.2.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.2.0) + Requirement already satisfied, skipping upgrade: urllib3<1.25,>=1.20; python_version >= "3.4" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (1.24.2) + Requirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.1; python_version >= "2.7" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (2.8.0) + Requirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (0.9.4) + Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli) + Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl + Requirement already satisfied, skipping upgrade: six>=1.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from python-dateutil<3.0.0,>=2.1; python_version >= "2.7"->botocore==1.12.153->awscli) (1.12.0) + Installing collected packages: colorama, PyYAML, botocore, pyasn1, rsa, awscli + Successfully installed PyYAML-3.13 awscli-1.16.163 botocore-1.12.153 colorama-0.3.9 pyasn1-0.4.5 rsa-3.4.2 + + +#### Configure aws so it can talk to your server +(if you are getting issues, make sure you have the permmissions to create clusters) + + +```bash +%%bash +# You must make sure that the access key and secret are changed +aws configure << END_OF_INPUTS +YOUR_ACCESS_KEY +YOUR_ACCESS_SECRET +us-west-2 +json +END_OF_INPUTS +``` + + AWS Access Key ID [****************SF4A]: AWS Secret Access Key [****************WLHu]: Default region name [eu-west-1]: Default output format [json]: + +#### Install EKCTL +*IMPORTANT*: These instructions are for linux +Please follow the official installation of ekctl at: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html + + +```python +!curl --silent --location "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" | tar xz +``` + + +```python +!chmod 755 ./eksctl +``` + + +```python +!./eksctl version +``` + + [ℹ] version.Info{BuiltAt:"", GitCommit:"", GitTag:"0.1.32"} +  + +## 5) Use the AWS tools to create and setup EKS cluster with Seldon +In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly. + +If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard. + +It will take 10-15 minutes (so feel free to go grab a ☕). + +### IMPORTANT: If you get errors in this step... +It is most probably IAM role access requirements, which requires you to discuss with your administrator. + + +```bash +%%bash +./eksctl create cluster \ +--name demo-eks-cluster \ +--region us-west-2 \ +--nodes 2 +``` + + Process is interrupted. + + +### Configure local kubectl +We want to now configure our local Kubectl so we can actually reach the cluster we've just created + + +```python +!aws eks --region us-west-2 update-kubeconfig --name demo-eks-cluster +``` + + Updated context arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist in /home/alejandro/.kube/config + + +And we can check if the context has been added to kubectl config (contexts are basically the different k8s cluster connections) +You should be able to see the context as "...aws:eks:eu-west-1:27...". +If it's not activated you can activate that context with kubectlt config set-context + + +```python +!kubectl config get-contexts +``` + + CURRENT NAME CLUSTER AUTHINFO NAMESPACE + * arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist + docker-desktop docker-desktop docker-desktop + docker-for-desktop docker-desktop docker-desktop + gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 + + +## Install Seldon Core + +### Before we install seldon core, we need to install HELM +For that, we need to create a ClusterRoleBinding for us, a ServiceAccount, and then a RoleBinding + + +```python +!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default +``` + + clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created + + + +```python +!kubectl create serviceaccount tiller --namespace kube-system +``` + + serviceaccount/tiller created + + + +```python +!kubectl apply -f tiller-role-binding.yaml +``` + + clusterrolebinding.rbac.authorization.k8s.io/tiller-role-binding created + + +### Once that is set-up we can install Tiller + + +```python +!helm init --service-account tiller +``` + + $HELM_HOME has been configured at /home/alejandro/.helm. + + Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster. + + Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy. + To prevent this, run `helm init` with the --tiller-tls-verify flag. + For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation + Happy Helming! + + + +```python +# Wait until Tiller finishes +!kubectl rollout status deploy/tiller-deploy -n kube-system +``` + + deployment "tiller-deploy" successfully rolled out + + +### Now we can install SELDON. +We first start with the custom resource definitions (CRDs) + + +```python +!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --namespace seldon-system +``` + + NAME: seldon-core-operator + LAST DEPLOYED: Wed May 22 16:24:10 2019 + NAMESPACE: seldon-system + STATUS: DEPLOYED + + RESOURCES: + ==> v1/ClusterRole + NAME AGE + seldon-operator-manager-role 2s + + ==> v1/ClusterRoleBinding + NAME AGE + seldon-operator-manager-rolebinding 2s + + ==> v1/ConfigMap + NAME DATA AGE + seldon-spartakus-config 3 2s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + seldon-operator-controller-manager-0 0/1 ContainerCreating 0 2s + seldon-spartakus-volunteer-6954cffb89-qz4pq 0/1 ContainerCreating 0 1s + + ==> v1/Secret + NAME TYPE DATA AGE + seldon-operator-webhook-server-secret Opaque 0 2s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + seldon-operator-controller-manager-service ClusterIP 10.100.198.157 443/TCP 2s + + ==> v1/ServiceAccount + NAME SECRETS AGE + seldon-spartakus-volunteer 1 2s + + ==> v1/StatefulSet + NAME READY AGE + seldon-operator-controller-manager 0/1 2s + + ==> v1beta1/ClusterRole + NAME AGE + seldon-spartakus-volunteer 2s + + ==> v1beta1/ClusterRoleBinding + NAME AGE + seldon-spartakus-volunteer 2s + + ==> v1beta1/CustomResourceDefinition + NAME AGE + seldondeployments.machinelearning.seldon.io 2s + + ==> v1beta1/Deployment + NAME READY UP-TO-DATE AVAILABLE AGE + seldon-spartakus-volunteer 0/1 1 0 2s + + + NOTES: + NOTES: TODO + + + + +And confirm they are running by getting the pods: + + +```python +!kubectl rollout status statefulset.apps/seldon-operator-controller-manager -n seldon-system +``` + + partitioned roll out complete: 1 new pods have been updated... + + +### Now we set-up the ingress +This will allow you to reach the Seldon models from outside the kubernetes cluster. + +In EKS it automatically creates an Elastic Load Balancer, which you can configure from the EC2 Console + + +```python +!helm install stable/ambassador --name ambassador --set image.tag=0.40.2 +``` + + NAME: ambassador + LAST DEPLOYED: Wed May 22 16:25:38 2019 + NAMESPACE: default + STATUS: DEPLOYED + + RESOURCES: + ==> v1/Deployment + NAME READY UP-TO-DATE AVAILABLE AGE + ambassador 0/3 3 0 0s + + ==> v1/Pod(related) + NAME READY STATUS RESTARTS AGE + ambassador-6dbf99c886-frlfm 0/1 ContainerCreating 0 0s + ambassador-6dbf99c886-kj56r 0/1 ContainerCreating 0 0s + ambassador-6dbf99c886-v5mtv 0/1 ContainerCreating 0 0s + + ==> v1/Service + NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE + ambassador LoadBalancer 10.100.59.146 80:30911/TCP,443:31715/TCP 0s + ambassador-admins ClusterIP 10.100.152.178 8877/TCP 0s + + ==> v1/ServiceAccount + NAME SECRETS AGE + ambassador 1 0s + + ==> v1beta1/ClusterRole + NAME AGE + ambassador 0s + + ==> v1beta1/ClusterRoleBinding + NAME AGE + ambassador 0s + + + NOTES: + Congratuations! You've successfully installed Ambassador. + + For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io. + + To get the IP address of Ambassador, run the following commands: + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get svc -w --namespace default ambassador' + + On GKE/Azure: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}') + + On AWS: + export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') + + echo http://$SERVICE_IP: + + + +And let's wait until it's fully deployed + + +```python +!kubectl rollout status deployment.apps/ambassador +``` + +## Push docker image +In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR). + +If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html + +### First we create a registry +You can run the following command, and then see the result at https://us-west-2.console.aws.amazon.com/ecr/repositories?# + + +```python +!aws ecr create-repository --repository-name seldon-repository --region us-west-2 +``` + + { + "repository": { + "repositoryArn": "arn:aws:ecr:us-west-2:271049282727:repository/seldon-repository", + "registryId": "271049282727", + "repositoryName": "seldon-repository", + "repositoryUri": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository", + "createdAt": 1558535798.0 + } + } + + +### Now prepare docker image +We need to first tag the docker image before we can push it + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +docker tag deep-mnist:0.1 "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" +``` + +### We now login to aws through docker so we can access the repository + + +```python +!`aws ecr get-login --no-include-email --region us-west-2` +``` + + WARNING! Using --password via the CLI is insecure. Use --password-stdin. + WARNING! Your password will be stored unencrypted in /home/alejandro/.docker/config.json. + Configure a credential helper to remove this warning. See + https://docs.docker.com/engine/reference/commandline/login/#credentials-store + + Login Succeeded + + +### And push the image +Make sure you add your AWS Account ID + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +docker push "$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository" +``` + + The push refers to repository [271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository] + f7d0d000c138: Preparing + 987f3f1afb00: Preparing + 00d16a381c47: Preparing + bb01f50d544a: Preparing + fcb82c6941b5: Preparing + 67290e35c458: Preparing + b813745f5bb3: Preparing + ffecb18e9f0b: Preparing + f50f856f49fa: Preparing + 80b43ad4adf9: Preparing + 14c77983a1cf: Preparing + a22a5ac18042: Preparing + 6257fa9f9597: Preparing + 578414b395b9: Preparing + abc3250a6c7f: Preparing + 13d5529fd232: Preparing + 67290e35c458: Waiting + b813745f5bb3: Waiting + ffecb18e9f0b: Waiting + f50f856f49fa: Waiting + 80b43ad4adf9: Waiting + 6257fa9f9597: Waiting + 14c77983a1cf: Waiting + a22a5ac18042: Waiting + 578414b395b9: Waiting + abc3250a6c7f: Waiting + 13d5529fd232: Waiting + 987f3f1afb00: Pushed + fcb82c6941b5: Pushed + bb01f50d544a: Pushed + f7d0d000c138: Pushed + ffecb18e9f0b: Pushed + b813745f5bb3: Pushed + f50f856f49fa: Pushed + 67290e35c458: Pushed + 14c77983a1cf: Pushed + 578414b395b9: Pushed + 80b43ad4adf9: Pushed + 13d5529fd232: Pushed + 6257fa9f9597: Pushed + abc3250a6c7f: Pushed + 00d16a381c47: Pushed + a22a5ac18042: Pushed + latest: digest: sha256:19aefaa9d87c1287eb46ec08f5d4f9a689744d9d0d0b75668b7d15e447819d74 size: 3691 + + +## Running the Model +We will now run the model. + +Let's first have a look at the file we'll be using to trigger the model: + + +```python +!cat deep_mnist.json +``` + + { + "apiVersion": "machinelearning.seldon.io/v1alpha2", + "kind": "SeldonDeployment", + "metadata": { + "labels": { + "app": "seldon" + }, + "name": "deep-mnist" + }, + "spec": { + "annotations": { + "project_name": "Tensorflow MNIST", + "deployment_version": "v1" + }, + "name": "deep-mnist", + "oauth_key": "oauth-key", + "oauth_secret": "oauth-secret", + "predictors": [ + { + "componentSpecs": [{ + "spec": { + "containers": [ + { + "image": "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest", + "imagePullPolicy": "IfNotPresent", + "name": "classifier", + "resources": { + "requests": { + "memory": "1Mi" + } + } + } + ], + "terminationGracePeriodSeconds": 20 + } + }], + "graph": { + "children": [], + "name": "classifier", + "endpoint": { + "type" : "REST" + }, + "type": "MODEL" + }, + "name": "single-model", + "replicas": 1, + "annotations": { + "predictor_version" : "v1" + } + } + ] + } + } + + +Now let's trigger seldon to run the model. + +We basically have a yaml file, where we want to replace the value "REPLACE_FOR_IMAGE_AND_TAG" for the image you pushed + + +```bash +%%bash +export AWS_ACCOUNT_ID="" +export AWS_REGION="us-west-2" +if [ -z "$AWS_ACCOUNT_ID" ]; then + echo "ERROR: Please provide a value for the AWS variables" + exit 1 +fi + +sed 's|REPLACE_FOR_IMAGE_AND_TAG|'"$AWS_ACCOUNT_ID"'.dkr.ecr.'"$AWS_REGION"'.amazonaws.com/seldon-repository|g' deep_mnist.json | kubectl apply -f - +``` + + error: unable to recognize "STDIN": Get https://461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com/api?timeout=32s: dial tcp: lookup 461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com on 1.1.1.1:53: no such host + + + + --------------------------------------------------------------------------- + + CalledProcessError Traceback (most recent call last) + + in + ----> 1 get_ipython().run_cell_magic('bash', '', 'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n') + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell) + 2350 with self.builtin_trap: + 2351 args = (magic_arg_s, cell) + -> 2352 result = fn(*args, **kwargs) + 2353 return result + 2354 + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in named_script_magic(line, cell) + 140 else: + 141 line = script + --> 142 return self.shebang(line, cell) + 143 + 144 # write a basic docstring: + + + in shebang(self, line, cell) + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magic.py in (f, *a, **k) + 185 # but it's overkill for just that one bit of state. + 186 def magic_deco(arg): + --> 187 call = lambda f, *a, **k: f(*a, **k) + 188 + 189 if callable(arg): + + + ~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py in shebang(self, line, cell) + 243 sys.stderr.flush() + 244 if args.raise_error and p.returncode!=0: + --> 245 raise CalledProcessError(p.returncode, cell, output=out, stderr=err) + 246 + 247 def _run_script(self, p, cell, to_close): + + + CalledProcessError: Command 'b'export AWS_ACCOUNT_ID="2710"\nexport AWS_REGION="us-west-2"\nif [ -z "$AWS_ACCOUNT_ID" ]; then\n echo "ERROR: Please provide a value for the AWS variables"\n exit 1\nfi\n\nsed \'s|REPLACE_FOR_IMAGE_AND_TAG|\'"$AWS_ACCOUNT_ID"\'.dkr.ecr.\'"$AWS_REGION"\'.amazonaws.com/seldon-repository|g\' deep_mnist.json | kubectl apply -f -\n'' returned non-zero exit status 1. + + +And let's check that it's been created. + +You should see an image called "deep-mnist-single-model...". + +We'll wait until STATUS changes from "ContainerCreating" to "Running" + + +```python +!kubectl get pods +``` + + NAME READY STATUS RESTARTS AGE + ambassador-5475779f98-7bhcw 1/1 Running 0 21m + ambassador-5475779f98-986g5 1/1 Running 0 21m + ambassador-5475779f98-zcd28 1/1 Running 0 21m + deep-mnist-single-model-42ed9d9-fdb557d6b-6xv2h 2/2 Running 0 18m + + +## Test the model +Now we can test the model, let's first find out what is the URL that we'll have to use: + + +```python +!kubectl get svc ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' +``` + + a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com + +We'll use a random example from our dataset + + +```python +import matplotlib.pyplot as plt +# This is the variable that was initialised at the beginning of the file +i = [0] +x = mnist.test.images[i] +y = mnist.test.labels[i] +plt.imshow(x.reshape((28, 28)), cmap='gray') +plt.show() +print("Expected label: ", np.sum(range(0,10) * y), ". One hot encoding: ", y) +``` + + +![png](aws_eks_deep_mnist_files/aws_eks_deep_mnist_63_0.png) + + + Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]] + + +We can now add the URL above to send our request: + + +```python +from seldon_core.seldon_client import SeldonClient +import math +import numpy as np + +host = "a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com" +port = "80" # Make sure you use the port above +batch = x +payload_type = "ndarray" + +sc = SeldonClient( + gateway="ambassador", + ambassador_endpoint=host + ":" + port, + namespace="default", + oauth_key="oauth-key", + oauth_secret="oauth-secret") + +client_prediction = sc.predict( + data=batch, + deployment_name="deep-mnist", + names=["text"], + payload_type=payload_type) + +print(client_prediction) +``` + + Success:True message: + Request: + data { + names: "text" + ndarray { + values { + list_value { + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.3294117748737335 + } + values { + number_value: 0.7254902124404907 + } + values { + number_value: 0.6235294342041016 + } + values { + number_value: 0.5921568870544434 + } + values { + number_value: 0.2352941334247589 + } + values { + number_value: 0.1411764770746231 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.8705883026123047 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9450981020927429 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.7764706611633301 + } + values { + number_value: 0.6666666865348816 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.44705885648727417 + } + values { + number_value: 0.2823529541492462 + } + values { + number_value: 0.44705885648727417 + } + values { + number_value: 0.6392157077789307 + } + values { + number_value: 0.8901961445808411 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8823530077934265 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9803922176361084 + } + values { + number_value: 0.8980392813682556 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.5490196347236633 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.06666667014360428 + } + values { + number_value: 0.25882354378700256 + } + values { + number_value: 0.05490196496248245 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.26274511218070984 + } + values { + number_value: 0.23137256503105164 + } + values { + number_value: 0.08235294371843338 + } + values { + number_value: 0.9254902601242065 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.41568630933761597 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.32549020648002625 + } + values { + number_value: 0.9921569228172302 + } + values { + number_value: 0.8196079134941101 + } + values { + number_value: 0.07058823853731155 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.08627451211214066 + } + values { + number_value: 0.9137255549430847 + } + values { + number_value: 1.0 + } + values { + number_value: 0.32549020648002625 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5058823823928833 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9333333969116211 + } + values { + number_value: 0.1725490242242813 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.23137256503105164 + } + values { + number_value: 0.9764706492424011 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.24313727021217346 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5215686559677124 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.7333333492279053 + } + values { + number_value: 0.019607843831181526 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.03529411926865578 + } + values { + number_value: 0.803921639919281 + } + values { + number_value: 0.9725490808486938 + } + values { + number_value: 0.22745099663734436 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4941176772117615 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.7137255072593689 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.29411765933036804 + } + values { + number_value: 0.9843137860298157 + } + values { + number_value: 0.9411765336990356 + } + values { + number_value: 0.22352942824363708 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.07450980693101883 + } + values { + number_value: 0.8666667342185974 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.6509804129600525 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.011764707043766975 + } + values { + number_value: 0.7960785031318665 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8588235974311829 + } + values { + number_value: 0.13725490868091583 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.14901961386203766 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.3019607961177826 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.12156863510608673 + } + values { + number_value: 0.8784314393997192 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.45098042488098145 + } + values { + number_value: 0.003921568859368563 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.5215686559677124 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.2392157018184662 + } + values { + number_value: 0.9490196704864502 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.2039215862751007 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4745098352432251 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8588235974311829 + } + values { + number_value: 0.1568627506494522 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.4745098352432251 + } + values { + number_value: 0.9960784912109375 + } + values { + number_value: 0.8117647767066956 + } + values { + number_value: 0.07058823853731155 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + values { + number_value: 0.0 + } + } + } + } } - ], - "source": [ - "from tensorflow.examples.tutorials.mnist import input_data\n", - "mnist = input_data.read_data_sets(\"MNIST_data/\", one_hot = True)\n", - "import tensorflow as tf\n", - "\n", - "if __name__ == '__main__':\n", - " \n", - " x = tf.placeholder(tf.float32, [None,784], name=\"x\")\n", - "\n", - " W = tf.Variable(tf.zeros([784,10]))\n", - " b = tf.Variable(tf.zeros([10]))\n", - "\n", - " y = tf.nn.softmax(tf.matmul(x,W) + b, name=\"y\")\n", - "\n", - " y_ = tf.placeholder(tf.float32, [None, 10])\n", - "\n", - " cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))\n", - "\n", - " train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)\n", - "\n", - " init = tf.initialize_all_variables()\n", - "\n", - " sess = tf.Session()\n", - " sess.run(init)\n", - "\n", - " for i in range(1000):\n", - " batch_xs, batch_ys = mnist.train.next_batch(100)\n", - " sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})\n", - "\n", - " correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))\n", - " accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n", - " print(sess.run(accuracy, feed_dict = {x: mnist.test.images, y_:mnist.test.labels}))\n", - "\n", - " saver = tf.train.Saver()\n", - "\n", - " saver.save(sess, \"model/deep_mnist_model\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 2) Containerise the tensorflow model with our docker utility" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First you need to make sure that you have added the .s2i/environment configuration file in this folder with the following content:" - ] - }, - { - "cell_type": "code", - "execution_count": 118, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "MODEL_NAME=DeepMnist\r\n", - "API_TYPE=REST\r\n", - "SERVICE_TYPE=MODEL\r\n", - "PERSISTENCE=0\r\n" - ] + + Response: + meta { + puid: "l6bv1r38mmb32l0hbinln2jjcl" + requestPath { + key: "classifier" + value: "271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest" + } } - ], - "source": [ - "!cat .s2i/environment" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now we can build a docker image named \"deep-mnist\" with the tag 0.1" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "---> Installing application source...\n", - "---> Installing dependencies ...\n", - "Looking in links: /whl\n", - "Requirement already satisfied: tensorflow>=1.12.0 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (1.13.1)\n", - "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.9)\n", - "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.2.2)\n", - "Requirement already satisfied: absl-py>=0.1.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1)\n", - "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.7.1)\n", - "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.0.7)\n", - "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.12.0)\n", - "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.1.0)\n", - "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.19.0)\n", - "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.33.1)\n", - "Requirement already satisfied: tensorboard<1.14.0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.1)\n", - "Requirement already satisfied: numpy>=1.13.3 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.16.2)\n", - "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.7.0)\n", - "Requirement already satisfied: tensorflow-estimator<1.14.0rc0,>=1.13.0 in /usr/local/lib/python3.6/site-packages (from tensorflow>=1.12.0->-r requirements.txt (line 1)) (1.13.0)\n", - "Requirement already satisfied: h5py in /usr/local/lib/python3.6/site-packages (from keras-applications>=1.0.6->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.9.0)\n", - "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (3.0.1)\n", - "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/site-packages (from tensorboard<1.14.0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (0.15.0)\n", - "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/site-packages (from protobuf>=3.6.1->tensorflow>=1.12.0->-r requirements.txt (line 1)) (40.8.0)\n", - "Requirement already satisfied: mock>=2.0.0 in /usr/local/lib/python3.6/site-packages (from tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (2.0.0)\n", - "Requirement already satisfied: pbr>=0.11 in /usr/local/lib/python3.6/site-packages (from mock>=2.0.0->tensorflow-estimator<1.14.0rc0,>=1.13.0->tensorflow>=1.12.0->-r requirements.txt (line 1)) (5.1.3)\n", - "Url '/whl' is ignored. It is either a non-existing path or lacks a specific scheme.\n", - "You are using pip version 19.0.3, however version 19.1.1 is available.\n", - "You should consider upgrading via the 'pip install --upgrade pip' command.\n", - "Build completed successfully\n" - ] + data { + names: "class:0" + names: "class:1" + names: "class:2" + names: "class:3" + names: "class:4" + names: "class:5" + names: "class:6" + names: "class:7" + names: "class:8" + names: "class:9" + ndarray { + values { + list_value { + values { + number_value: 6.839015986770391e-05 + } + values { + number_value: 9.376968534979824e-09 + } + values { + number_value: 8.48581112222746e-05 + } + values { + number_value: 0.0034086888190358877 + } + values { + number_value: 2.3978568606253248e-06 + } + values { + number_value: 2.0100669644307345e-05 + } + values { + number_value: 3.0251623428512175e-08 + } + values { + number_value: 0.9953710436820984 + } + values { + number_value: 2.6070511012221687e-05 + } + values { + number_value: 0.0010185304563492537 + } + } + } + } } - ], - "source": [ - "!s2i build . seldonio/seldon-core-s2i-python36:0.5.1 deep-mnist:0.1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 3) Send some data to the docker model to test it\n", - "We first run the docker image we just created as a container called \"mnist_predictor\"" - ] - }, - { - "cell_type": "code", - "execution_count": 119, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "5157ab4f516bd0dea11b159780f31121e9fb41df6394e0d6d631e6e0d572463b\r\n" - ] - } - ], - "source": [ - "!docker run --name \"mnist_predictor\" -d --rm -p 5000:5000 deep-mnist:0.1" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Send some random features that conform to the contract" - ] - }, - { - "cell_type": "code", - "execution_count": 120, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]\n" - ] - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "# This is the variable that was initialised at the beginning of the file\n", - "i = [0]\n", - "x = mnist.test.images[i]\n", - "y = mnist.test.labels[i]\n", - "plt.imshow(x.reshape((28, 28)), cmap='gray')\n", - "plt.show()\n", - "print(\"Expected label: \", np.sum(range(0,10) * y), \". One hot encoding: \", y)" - ] - }, - { - "cell_type": "code", - "execution_count": 144, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "LABEL 0:\t 0.0068 %\n", - "LABEL 1:\t 0.0000 %\n", - "LABEL 2:\t 0.0085 %\n", - "LABEL 3:\t 0.3409 %\n", - "LABEL 4:\t 0.0002 %\n", - "LABEL 5:\t 0.0020 %\n", - "LABEL 6:\t 0.0000 %\n", - "LABEL 7:\t 99.5371 %\n", - "LABEL 8:\t 0.0026 %\n", - "LABEL 9:\t 0.1019 %\n" - ] - } - ], - "source": [ - "from seldon_core.seldon_client import SeldonClient\n", - "import math\n", - "import numpy as np\n", - "\n", - "# We now test the REST endpoint expecting the same result\n", - "endpoint = \"0.0.0.0:5000\"\n", - "batch = x\n", - "payload_type = \"ndarray\"\n", - "\n", - "sc = SeldonClient(microservice_endpoint=endpoint)\n", - "\n", - "# We use the microservice, instead of the \"predict\" function\n", - "client_prediction = sc.microservice(\n", - " data=batch,\n", - " method=\"predict\",\n", - " payload_type=payload_type,\n", - " names=[\"tfidf\"])\n", - "\n", - "for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)):\n", - " print(f\"LABEL {label}:\\t {proba.number_value*100:6.4f} %\")" - ] - }, - { - "cell_type": "code", - "execution_count": 145, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "mnist_predictor\r\n" - ] - } - ], - "source": [ - "!docker rm mnist_predictor --force" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 4) Install and configure AWS tools to interact with AWS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "First we install the awscli" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Collecting awscli\n", - " Using cached https://files.pythonhosted.org/packages/f6/45/259a98719e7c7defc9be4cc00fbfb7ccf699fbd1f74455d8347d0ab0a1df/awscli-1.16.163-py2.py3-none-any.whl\n", - "Collecting colorama<=0.3.9,>=0.2.5 (from awscli)\n", - " Using cached https://files.pythonhosted.org/packages/db/c8/7dcf9dbcb22429512708fe3a547f8b6101c0d02137acbd892505aee57adf/colorama-0.3.9-py2.py3-none-any.whl\n", - "Collecting PyYAML<=3.13,>=3.10 (from awscli)\n", - "Collecting botocore==1.12.153 (from awscli)\n", - " Using cached https://files.pythonhosted.org/packages/ec/3b/029218966ce62ae9824a18730de862ac8fc5a0e8083d07d1379815e7cca1/botocore-1.12.153-py2.py3-none-any.whl\n", - "Requirement already satisfied, skipping upgrade: docutils>=0.10 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.14)\n", - "Collecting rsa<=3.5.0,>=3.1.2 (from awscli)\n", - " Using cached https://files.pythonhosted.org/packages/e1/ae/baedc9cb175552e95f3395c43055a6a5e125ae4d48a1d7a924baca83e92e/rsa-3.4.2-py2.py3-none-any.whl\n", - "Requirement already satisfied, skipping upgrade: s3transfer<0.3.0,>=0.2.0 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from awscli) (0.2.0)\n", - "Requirement already satisfied, skipping upgrade: urllib3<1.25,>=1.20; python_version >= \"3.4\" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (1.24.2)\n", - "Requirement already satisfied, skipping upgrade: python-dateutil<3.0.0,>=2.1; python_version >= \"2.7\" in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (2.8.0)\n", - "Requirement already satisfied, skipping upgrade: jmespath<1.0.0,>=0.7.1 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from botocore==1.12.153->awscli) (0.9.4)\n", - "Collecting pyasn1>=0.1.3 (from rsa<=3.5.0,>=3.1.2->awscli)\n", - " Using cached https://files.pythonhosted.org/packages/7b/7c/c9386b82a25115cccf1903441bba3cbadcfae7b678a20167347fa8ded34c/pyasn1-0.4.5-py2.py3-none-any.whl\n", - "Requirement already satisfied, skipping upgrade: six>=1.5 in /home/alejandro/miniconda3/envs/reddit-classification/lib/python3.7/site-packages (from python-dateutil<3.0.0,>=2.1; python_version >= \"2.7\"->botocore==1.12.153->awscli) (1.12.0)\n", - "Installing collected packages: colorama, PyYAML, botocore, pyasn1, rsa, awscli\n", - "Successfully installed PyYAML-3.13 awscli-1.16.163 botocore-1.12.153 colorama-0.3.9 pyasn1-0.4.5 rsa-3.4.2\n" - ] - } - ], - "source": [ - "!pip install awscli --upgrade --user" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Configure aws so it can talk to your server \n", - "(if you are getting issues, make sure you have the permmissions to create clusters)" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "AWS Access Key ID [****************SF4A]: AWS Secret Access Key [****************WLHu]: Default region name [eu-west-1]: Default output format [json]: " - ] - } - ], - "source": [ - "%%bash \n", - "# You must make sure that the access key and secret are changed\n", - "aws configure << END_OF_INPUTS\n", - "YOUR_ACCESS_KEY\n", - "YOUR_ACCESS_SECRET\n", - "us-west-2\n", - "json\n", - "END_OF_INPUTS" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Install EKCTL\n", - "*IMPORTANT*: These instructions are for linux\n", - "Please follow the official installation of ekctl at: https://docs.aws.amazon.com/eks/latest/userguide/getting-started-eksctl.html" - ] - }, - { - "cell_type": "code", - "execution_count": 23, - "metadata": {}, - "outputs": [], - "source": [ - "!curl --silent --location \"https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz\" | tar xz " - ] - }, - { - "cell_type": "code", - "execution_count": 25, - "metadata": {}, - "outputs": [], - "source": [ - "!chmod 755 ./eksctl" - ] - }, - { - "cell_type": "code", - "execution_count": 27, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "\u001b[36m[ℹ] version.Info{BuiltAt:\"\", GitCommit:\"\", GitTag:\"0.1.32\"}\r\n", - "\u001b[0m" - ] - } - ], - "source": [ - "!./eksctl version" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## 5) Use the AWS tools to create and setup EKS cluster with Seldon\n", - "In this example we will create a cluster with 2 nodes, with a minimum of 1 and a max of 3. You can tweak this accordingly.\n", - "\n", - "If you want to check the status of the deployment you can go to AWS CloudFormation or to the EKS dashboard.\n", - "\n", - "It will take 10-15 minutes (so feel free to go grab a ☕). \n", - "\n", - "### IMPORTANT: If you get errors in this step...\n", - "It is most probably IAM role access requirements, which requires you to discuss with your administrator." - ] - }, - { - "cell_type": "code", - "execution_count": 107, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Process is interrupted.\n" - ] - } - ], - "source": [ - "%%bash\n", - "./eksctl create cluster \\\n", - "--name demo-eks-cluster \\\n", - "--region us-west-2 \\\n", - "--nodes 2 " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Configure local kubectl \n", - "We want to now configure our local Kubectl so we can actually reach the cluster we've just created" - ] - }, - { - "cell_type": "code", - "execution_count": 108, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Updated context arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist in /home/alejandro/.kube/config\r\n" - ] - } - ], - "source": [ - "!aws eks --region us-west-2 update-kubeconfig --name demo-eks-cluster" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And we can check if the context has been added to kubectl config (contexts are basically the different k8s cluster connections)\n", - "You should be able to see the context as \"...aws:eks:eu-west-1:27...\". \n", - "If it's not activated you can activate that context with kubectlt config set-context " - ] - }, - { - "cell_type": "code", - "execution_count": 109, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "CURRENT NAME CLUSTER AUTHINFO NAMESPACE\r\n", - "* arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist arn:aws:eks:eu-west-1:271049282727:cluster/deepmnist \r\n", - " docker-desktop docker-desktop docker-desktop \r\n", - " docker-for-desktop docker-desktop docker-desktop \r\n", - " gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 gke_ml-engineer_us-central1-a_security-cluster-1 \r\n" - ] - } - ], - "source": [ - "!kubectl config get-contexts" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Install Seldon Core" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Before we install seldon core, we need to install HELM\n", - "For that, we need to create a ClusterRoleBinding for us, a ServiceAccount, and then a RoleBinding" - ] - }, - { - "cell_type": "code", - "execution_count": 114, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "clusterrolebinding.rbac.authorization.k8s.io/kube-system-cluster-admin created\r\n" - ] - } - ], - "source": [ - "!kubectl create clusterrolebinding kube-system-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:default" - ] - }, - { - "cell_type": "code", - "execution_count": 115, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "serviceaccount/tiller created\r\n" - ] - } - ], - "source": [ - "!kubectl create serviceaccount tiller --namespace kube-system" - ] - }, - { - "cell_type": "code", - "execution_count": 116, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "clusterrolebinding.rbac.authorization.k8s.io/tiller-role-binding created\r\n" - ] - } - ], - "source": [ - "!kubectl apply -f tiller-role-binding.yaml" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Once that is set-up we can install Tiller" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "$HELM_HOME has been configured at /home/alejandro/.helm.\n", - "\n", - "Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.\n", - "\n", - "Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.\n", - "To prevent this, run `helm init` with the --tiller-tls-verify flag.\n", - "For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation\n", - "Happy Helming!\n" - ] - } - ], - "source": [ - "!helm init --service-account tiller" - ] - }, - { - "cell_type": "code", - "execution_count": 120, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "deployment \"tiller-deploy\" successfully rolled out\r\n" - ] - } - ], - "source": [ - "# Wait until Tiller finishes\n", - "!kubectl rollout status deploy/tiller-deploy -n kube-system" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Now we can install SELDON. \n", - "We first start with the custom resource definitions (CRDs)" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NAME: seldon-core-operator\n", - "LAST DEPLOYED: Wed May 22 16:24:10 2019\n", - "NAMESPACE: seldon-system\n", - "STATUS: DEPLOYED\n", - "\n", - "RESOURCES:\n", - "==> v1/ClusterRole\n", - "NAME AGE\n", - "seldon-operator-manager-role 2s\n", - "\n", - "==> v1/ClusterRoleBinding\n", - "NAME AGE\n", - "seldon-operator-manager-rolebinding 2s\n", - "\n", - "==> v1/ConfigMap\n", - "NAME DATA AGE\n", - "seldon-spartakus-config 3 2s\n", - "\n", - "==> v1/Pod(related)\n", - "NAME READY STATUS RESTARTS AGE\n", - "seldon-operator-controller-manager-0 0/1 ContainerCreating 0 2s\n", - "seldon-spartakus-volunteer-6954cffb89-qz4pq 0/1 ContainerCreating 0 1s\n", - "\n", - "==> v1/Secret\n", - "NAME TYPE DATA AGE\n", - "seldon-operator-webhook-server-secret Opaque 0 2s\n", - "\n", - "==> v1/Service\n", - "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", - "seldon-operator-controller-manager-service ClusterIP 10.100.198.157 443/TCP 2s\n", - "\n", - "==> v1/ServiceAccount\n", - "NAME SECRETS AGE\n", - "seldon-spartakus-volunteer 1 2s\n", - "\n", - "==> v1/StatefulSet\n", - "NAME READY AGE\n", - "seldon-operator-controller-manager 0/1 2s\n", - "\n", - "==> v1beta1/ClusterRole\n", - "NAME AGE\n", - "seldon-spartakus-volunteer 2s\n", - "\n", - "==> v1beta1/ClusterRoleBinding\n", - "NAME AGE\n", - "seldon-spartakus-volunteer 2s\n", - "\n", - "==> v1beta1/CustomResourceDefinition\n", - "NAME AGE\n", - "seldondeployments.machinelearning.seldon.io 2s\n", - "\n", - "==> v1beta1/Deployment\n", - "NAME READY UP-TO-DATE AVAILABLE AGE\n", - "seldon-spartakus-volunteer 0/1 1 0 2s\n", - "\n", - "\n", - "NOTES:\n", - "NOTES: TODO\n", - "\n", - "\n" - ] - } - ], - "source": [ - "!helm install seldon-core-operator --name seldon-core-operator --repo https://storage.googleapis.com/seldon-charts --set usageMetrics.enabled=true --namespace seldon-system" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And confirm they are running by getting the pods:" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "partitioned roll out complete: 1 new pods have been updated...\r\n" - ] - } - ], - "source": [ - "!kubectl rollout status statefulset.apps/seldon-operator-controller-manager -n seldon-system" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Now we set-up the ingress\n", - "This will allow you to reach the Seldon models from outside the kubernetes cluster. \n", - "\n", - "In EKS it automatically creates an Elastic Load Balancer, which you can configure from the EC2 Console" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NAME: ambassador\n", - "LAST DEPLOYED: Wed May 22 16:25:38 2019\n", - "NAMESPACE: default\n", - "STATUS: DEPLOYED\n", - "\n", - "RESOURCES:\n", - "==> v1/Deployment\n", - "NAME READY UP-TO-DATE AVAILABLE AGE\n", - "ambassador 0/3 3 0 0s\n", - "\n", - "==> v1/Pod(related)\n", - "NAME READY STATUS RESTARTS AGE\n", - "ambassador-6dbf99c886-frlfm 0/1 ContainerCreating 0 0s\n", - "ambassador-6dbf99c886-kj56r 0/1 ContainerCreating 0 0s\n", - "ambassador-6dbf99c886-v5mtv 0/1 ContainerCreating 0 0s\n", - "\n", - "==> v1/Service\n", - "NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\n", - "ambassador LoadBalancer 10.100.59.146 80:30911/TCP,443:31715/TCP 0s\n", - "ambassador-admins ClusterIP 10.100.152.178 8877/TCP 0s\n", - "\n", - "==> v1/ServiceAccount\n", - "NAME SECRETS AGE\n", - "ambassador 1 0s\n", - "\n", - "==> v1beta1/ClusterRole\n", - "NAME AGE\n", - "ambassador 0s\n", - "\n", - "==> v1beta1/ClusterRoleBinding\n", - "NAME AGE\n", - "ambassador 0s\n", - "\n", - "\n", - "NOTES:\n", - "Congratuations! You've successfully installed Ambassador.\n", - "\n", - "For help, visit our Slack at https://d6e.co/slack or view the documentation online at https://www.getambassador.io.\n", - "\n", - "To get the IP address of Ambassador, run the following commands:\n", - "NOTE: It may take a few minutes for the LoadBalancer IP to be available.\n", - " You can watch the status of by running 'kubectl get svc -w --namespace default ambassador'\n", - "\n", - " On GKE/Azure:\n", - " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].ip}')\n", - "\n", - " On AWS:\n", - " export SERVICE_IP=$(kubectl get svc --namespace default ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')\n", - "\n", - " echo http://$SERVICE_IP:\n", - "\n" - ] - } - ], - "source": [ - "!helm install stable/ambassador --name ambassador --set image.tag=0.40.2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And let's wait until it's fully deployed" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!kubectl rollout status deployment.apps/ambassador" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Push docker image\n", - "In order for the EKS seldon deployment to access the image we just built, we need to push it to the Elastic Container Registry (ECR).\n", - "\n", - "If you have any issues please follow the official AWS documentation: https://docs.aws.amazon.com/AmazonECR/latest/userguide/docker-basics.html" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### First we create a registry\n", - "You can run the following command, and then see the result at https://us-west-2.console.aws.amazon.com/ecr/repositories?#" - ] - }, - { - "cell_type": "code", - "execution_count": 110, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\r\n", - " \"repository\": {\r\n", - " \"repositoryArn\": \"arn:aws:ecr:us-west-2:271049282727:repository/seldon-repository\",\r\n", - " \"registryId\": \"271049282727\",\r\n", - " \"repositoryName\": \"seldon-repository\",\r\n", - " \"repositoryUri\": \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository\",\r\n", - " \"createdAt\": 1558535798.0\r\n", - " }\r\n", - "}\r\n" - ] - } - ], - "source": [ - "!aws ecr create-repository --repository-name seldon-repository --region us-west-2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Now prepare docker image\n", - "We need to first tag the docker image before we can push it" - ] - }, - { - "cell_type": "code", - "execution_count": 111, - "metadata": {}, - "outputs": [], - "source": [ - "%%bash\n", - "export AWS_ACCOUNT_ID=\"\"\n", - "export AWS_REGION=\"us-west-2\"\n", - "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", - " echo \"ERROR: Please provide a value for the AWS variables\"\n", - " exit 1\n", - "fi\n", - "\n", - "docker tag deep-mnist:0.1 \"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### We now login to aws through docker so we can access the repository" - ] - }, - { - "cell_type": "code", - "execution_count": 112, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WARNING! Using --password via the CLI is insecure. Use --password-stdin.\n", - "WARNING! Your password will be stored unencrypted in /home/alejandro/.docker/config.json.\n", - "Configure a credential helper to remove this warning. See\n", - "https://docs.docker.com/engine/reference/commandline/login/#credentials-store\n", - "\n", - "Login Succeeded\n" - ] - } - ], - "source": [ - "!`aws ecr get-login --no-include-email --region us-west-2`" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### And push the image\n", - "Make sure you add your AWS Account ID" - ] - }, - { - "cell_type": "code", - "execution_count": 113, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The push refers to repository [271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository]\n", - "f7d0d000c138: Preparing\n", - "987f3f1afb00: Preparing\n", - "00d16a381c47: Preparing\n", - "bb01f50d544a: Preparing\n", - "fcb82c6941b5: Preparing\n", - "67290e35c458: Preparing\n", - "b813745f5bb3: Preparing\n", - "ffecb18e9f0b: Preparing\n", - "f50f856f49fa: Preparing\n", - "80b43ad4adf9: Preparing\n", - "14c77983a1cf: Preparing\n", - "a22a5ac18042: Preparing\n", - "6257fa9f9597: Preparing\n", - "578414b395b9: Preparing\n", - "abc3250a6c7f: Preparing\n", - "13d5529fd232: Preparing\n", - "67290e35c458: Waiting\n", - "b813745f5bb3: Waiting\n", - "ffecb18e9f0b: Waiting\n", - "f50f856f49fa: Waiting\n", - "80b43ad4adf9: Waiting\n", - "6257fa9f9597: Waiting\n", - "14c77983a1cf: Waiting\n", - "a22a5ac18042: Waiting\n", - "578414b395b9: Waiting\n", - "abc3250a6c7f: Waiting\n", - "13d5529fd232: Waiting\n", - "987f3f1afb00: Pushed\n", - "fcb82c6941b5: Pushed\n", - "bb01f50d544a: Pushed\n", - "f7d0d000c138: Pushed\n", - "ffecb18e9f0b: Pushed\n", - "b813745f5bb3: Pushed\n", - "f50f856f49fa: Pushed\n", - "67290e35c458: Pushed\n", - "14c77983a1cf: Pushed\n", - "578414b395b9: Pushed\n", - "80b43ad4adf9: Pushed\n", - "13d5529fd232: Pushed\n", - "6257fa9f9597: Pushed\n", - "abc3250a6c7f: Pushed\n", - "00d16a381c47: Pushed\n", - "a22a5ac18042: Pushed\n", - "latest: digest: sha256:19aefaa9d87c1287eb46ec08f5d4f9a689744d9d0d0b75668b7d15e447819d74 size: 3691\n" - ] - } - ], - "source": [ - "%%bash\n", - "export AWS_ACCOUNT_ID=\"\"\n", - "export AWS_REGION=\"us-west-2\"\n", - "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", - " echo \"ERROR: Please provide a value for the AWS variables\"\n", - " exit 1\n", - "fi\n", - "\n", - "docker push \"$AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/seldon-repository\"" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Running the Model\n", - "We will now run the model.\n", - "\n", - "Let's first have a look at the file we'll be using to trigger the model:" - ] - }, - { - "cell_type": "code", - "execution_count": 127, - "metadata": { - "scrolled": true - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{\r\n", - " \"apiVersion\": \"machinelearning.seldon.io/v1alpha2\",\r\n", - " \"kind\": \"SeldonDeployment\",\r\n", - " \"metadata\": {\r\n", - " \"labels\": {\r\n", - " \"app\": \"seldon\"\r\n", - " },\r\n", - " \"name\": \"deep-mnist\"\r\n", - " },\r\n", - " \"spec\": {\r\n", - " \"annotations\": {\r\n", - " \"project_name\": \"Tensorflow MNIST\",\r\n", - " \"deployment_version\": \"v1\"\r\n", - " },\r\n", - " \"name\": \"deep-mnist\",\r\n", - " \"oauth_key\": \"oauth-key\",\r\n", - " \"oauth_secret\": \"oauth-secret\",\r\n", - " \"predictors\": [\r\n", - " {\r\n", - " \"componentSpecs\": [{\r\n", - " \"spec\": {\r\n", - " \"containers\": [\r\n", - " {\r\n", - " \"image\": \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest\",\r\n", - " \"imagePullPolicy\": \"IfNotPresent\",\r\n", - " \"name\": \"classifier\",\r\n", - " \"resources\": {\r\n", - " \"requests\": {\r\n", - " \"memory\": \"1Mi\"\r\n", - " }\r\n", - " }\r\n", - " }\r\n", - " ],\r\n", - " \"terminationGracePeriodSeconds\": 20\r\n", - " }\r\n", - " }],\r\n", - " \"graph\": {\r\n", - " \"children\": [],\r\n", - " \"name\": \"classifier\",\r\n", - " \"endpoint\": {\r\n", - "\t\t\t\"type\" : \"REST\"\r\n", - "\t\t },\r\n", - " \"type\": \"MODEL\"\r\n", - " },\r\n", - " \"name\": \"single-model\",\r\n", - " \"replicas\": 1,\r\n", - "\t\t\"annotations\": {\r\n", - "\t\t \"predictor_version\" : \"v1\"\r\n", - "\t\t}\r\n", - " }\r\n", - " ]\r\n", - " }\r\n", - "}\r\n" - ] - } - ], - "source": [ - "!cat deep_mnist.json" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now let's trigger seldon to run the model.\n", - "\n", - "We basically have a yaml file, where we want to replace the value \"REPLACE_FOR_IMAGE_AND_TAG\" for the image you pushed" - ] - }, - { - "cell_type": "code", - "execution_count": 165, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "error: unable to recognize \"STDIN\": Get https://461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com/api?timeout=32s: dial tcp: lookup 461835FD3FF52848655C8F09FBF5EEAA.yl4.us-west-2.eks.amazonaws.com on 1.1.1.1:53: no such host\n" - ] - }, - { - "ename": "CalledProcessError", - "evalue": "Command 'b'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'' returned non-zero exit status 1.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mCalledProcessError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_cell_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'bash'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", - "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_cell_magic\u001b[0;34m(self, magic_name, line, cell)\u001b[0m\n\u001b[1;32m 2350\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2351\u001b[0m \u001b[0margs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mmagic_arg_s\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2352\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2353\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2354\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py\u001b[0m in \u001b[0;36mnamed_script_magic\u001b[0;34m(line, cell)\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 141\u001b[0m \u001b[0mline\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mscript\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 142\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshebang\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mline\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 143\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 144\u001b[0m \u001b[0;31m# write a basic docstring:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m\u001b[0m in \u001b[0;36mshebang\u001b[0;34m(self, line, cell)\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/miniconda3/envs/reddit-classification/lib/python3.7/site-packages/IPython/core/magics/script.py\u001b[0m in \u001b[0;36mshebang\u001b[0;34m(self, line, cell)\u001b[0m\n\u001b[1;32m 243\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mstderr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflush\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 244\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mraise_error\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturncode\u001b[0m\u001b[0;34m!=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 245\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mCalledProcessError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreturncode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moutput\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mout\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstderr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0merr\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 246\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_run_script\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcell\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mto_close\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mCalledProcessError\u001b[0m: Command 'b'export AWS_ACCOUNT_ID=\"2710\"\\nexport AWS_REGION=\"us-west-2\"\\nif [ -z \"$AWS_ACCOUNT_ID\" ]; then\\n echo \"ERROR: Please provide a value for the AWS variables\"\\n exit 1\\nfi\\n\\nsed \\'s|REPLACE_FOR_IMAGE_AND_TAG|\\'\"$AWS_ACCOUNT_ID\"\\'.dkr.ecr.\\'\"$AWS_REGION\"\\'.amazonaws.com/seldon-repository|g\\' deep_mnist.json | kubectl apply -f -\\n'' returned non-zero exit status 1." - ] - } - ], - "source": [ - "%%bash\n", - "export AWS_ACCOUNT_ID=\"\"\n", - "export AWS_REGION=\"us-west-2\"\n", - "if [ -z \"$AWS_ACCOUNT_ID\" ]; then\n", - " echo \"ERROR: Please provide a value for the AWS variables\"\n", - " exit 1\n", - "fi\n", - "\n", - "sed 's|REPLACE_FOR_IMAGE_AND_TAG|'\"$AWS_ACCOUNT_ID\"'.dkr.ecr.'\"$AWS_REGION\"'.amazonaws.com/seldon-repository|g' deep_mnist.json | kubectl apply -f -" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "And let's check that it's been created.\n", - "\n", - "You should see an image called \"deep-mnist-single-model...\".\n", - "\n", - "We'll wait until STATUS changes from \"ContainerCreating\" to \"Running\"" - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "NAME READY STATUS RESTARTS AGE\r\n", - "ambassador-5475779f98-7bhcw 1/1 Running 0 21m\r\n", - "ambassador-5475779f98-986g5 1/1 Running 0 21m\r\n", - "ambassador-5475779f98-zcd28 1/1 Running 0 21m\r\n", - "deep-mnist-single-model-42ed9d9-fdb557d6b-6xv2h 2/2 Running 0 18m\r\n" - ] - } - ], - "source": [ - "!kubectl get pods" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Test the model\n", - "Now we can test the model, let's first find out what is the URL that we'll have to use:" - ] - }, - { - "cell_type": "code", - "execution_count": 22, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com" - ] - } - ], - "source": [ - "!kubectl get svc ambassador -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' " - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We'll use a random example from our dataset" - ] - }, - { - "cell_type": "code", - "execution_count": 42, - "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAADQNJREFUeJzt3W+MVfWdx/HPZylNjPQBWLHEgnQb3bgaAzoaE3AzamxYbYKN1NQHGzbZMH2AZps0ZA1PypMmjemfrU9IpikpJtSWhFbRGBeDGylRGwejBYpQICzMgkAzJgUT0yDfPphDO8W5v3u5/84dv+9XQube8z1/vrnhM+ecOefcnyNCAPL5h7obAFAPwg8kRfiBpAg/kBThB5Ii/EBShB9IivADSRF+IKnP9HNjtrmdEOixiHAr83W057e9wvZB24dtP9nJugD0l9u9t9/2LEmHJD0gaVzSW5Iei4jfF5Zhzw/0WD/2/HdJOhwRRyPiz5J+IWllB+sD0EedhP96SSemvB+vpv0d2yO2x2yPdbAtAF3WyR/8pju0+MRhfUSMShqVOOwHBkkne/5xSQunvP+ipJOdtQOgXzoJ/1uSbrT9JduflfQNSdu70xaAXmv7sD8iLth+XNL/SJolaVNE7O9aZwB6qu1LfW1tjHN+oOf6cpMPgJmL8ANJEX4gKcIPJEX4gaQIP5AU4QeSIvxAUoQfSIrwA0kRfiApwg8kRfiBpAg/kBThB5Ii/EBShB9IivADSRF+ICnCDyRF+IGkCD+QFOEHkiL8QFKEH0iK8ANJEX4gKcIPJEX4gaTaHqJbkmwfk3RO0seSLkTEUDeaAtB7HYW/cm9E/LEL6wHQRxz2A0l1Gv6QtMP2Htsj3WgIQH90eti/LCJO2p4v6RXb70XErqkzVL8U+MUADBhHRHdWZG+QdD4ivl+YpzsbA9BQRLiV+do+7Ld9te3PXXot6SuS9rW7PgD91clh/3WSfm370np+HhEvd6UrAD3XtcP+ljbGYT/Qcz0/7AcwsxF+ICnCDyRF+IGkCD+QFOEHkurGU30prFq1qmFtzZo1xWVPnjxZrH/00UfF+pYtW4r1999/v2Ht8OHDxWWRF3t+ICnCDyRF+IGkCD+QFOEHkiL8QFKEH0iKR3pbdPTo0Ya1xYsX96+RaZw7d65hbf/+/X3sZLCMj483rD311FPFZcfGxrrdTt/wSC+AIsIPJEX4gaQIP5AU4QeSIvxAUoQfSIrn+VtUemb/tttuKy574MCBYv3mm28u1m+//fZifXh4uGHt7rvvLi574sSJYn3hwoXFeicuXLhQrJ89e7ZYX7BgQdvbPn78eLE+k6/zt4o9P5AU4QeSIvxAUoQfSIrwA0kRfiApwg8k1fR5ftubJH1V0pmIuLWaNk/SLyUtlnRM0qMR8UHTjc3g5/kH2dy5cxvWlixZUlx2z549xfqdd97ZVk+taDZewaFDh4r1ZvdPzJs3r2Ft7dq1xWU3btxYrA+ybj7P/zNJKy6b9qSknRFxo6Sd1XsAM0jT8EfELkkTl01eKWlz9XqzpIe73BeAHmv3nP+6iDglSdXP+d1rCUA/9PzeftsjkkZ6vR0AV6bdPf9p2wskqfp5ptGMETEaEUMRMdTmtgD0QLvh3y5pdfV6taTnu9MOgH5pGn7bz0p6Q9I/2R63/R+SvifpAdt/kPRA9R7ADML39mNgPfLII8X61q1bi/V9+/Y1rN17773FZScmLr/ANXPwvf0Aigg/kBThB5Ii/EBShB9IivADSXGpD7WZP7/8SMjevXs7Wn7VqlUNa9u2bSsuO5NxqQ9AEeEHkiL8QFKEH0iK8ANJEX4gKcIPJMUQ3ahNs6/Pvvbaa4v1Dz4of1v8wYMHr7inTNjzA0kRfiApwg8kRfiBpAg/kBThB5Ii/EBSPM+Pnlq2bFnD2quvvlpcdvbs2cX68PBwsb5r165i/dOK5/kBFBF+ICnCDyRF+IGkCD+QFOEHkiL8QFJNn+e3vUnSVyWdiYhbq2kbJK2RdLaabX1EvNSrJjFzPfjggw1rza7j79y5s1h/44032uoJk1rZ8/9M0opppv8oIpZU/wg+MMM0DX9E7JI00YdeAPRRJ+f8j9v+ne1Ntud2rSMAfdFu+DdK+rKkJZJOSfpBoxltj9gesz3W5rYA9EBb4Y+I0xHxcURclPQTSXcV5h2NiKGIGGq3SQDd11b4bS+Y8vZrkvZ1px0A/dLKpb5nJQ1L+rztcUnfkTRse4mkkHRM0jd72COAHuB5fnTkqquuKtZ3797dsHbLLbcUl73vvvuK9ddff71Yz4rn+QEUEX4gKcIPJEX4gaQIP5AU4QeSYohudGTdunXF+tKlSxvWXn755eKyXMrrLfb8QFKEH0iK8ANJEX4gKcIPJEX4gaQIP5AUj/Si6KGHHirWn3vuuWL9ww8/bFhbsWK6L4X+mzfffLNYx/R4pBdAEeEHkiL8QFKEH0iK8ANJEX4gKcIPJMXz/Mldc801xfrTTz9drM+aNatYf+mlxgM4cx2/Xuz5gaQIP5AU4QeSIvxAUoQfSIrwA0kRfiCpps/z214o6RlJX5B0UdJoRPzY9jxJv5S0WNIxSY9GxAdN1sXz/H3W7Dp8s2vtd9xxR7F+5MiRYr30zH6zZdGebj7Pf0HStyPiZkl3S1pr+58lPSlpZ0TcKGln9R7ADNE0/BFxKiLerl6fk3RA0vWSVkraXM22WdLDvWoSQPdd0Tm/7cWSlkr6raTrIuKUNPkLQtL8bjcHoHdavrff9hxJ2yR9KyL+ZLd0WiHbI5JG2msPQK+0tOe3PVuTwd8SEb+qJp+2vaCqL5B0ZrplI2I0IoYiYqgbDQPojqbh9+Qu/qeSDkTED6eUtktaXb1eLen57rcHoFdaudS3XNJvJO3V5KU+SVqvyfP+rZIWSTou6esRMdFkXVzq67ObbrqpWH/vvfc6Wv/KlSuL9RdeeKGj9ePKtXqpr+k5f0TsltRoZfdfSVMABgd3+AFJEX4gKcIPJEX4gaQIP5AU4QeS4qu7PwVuuOGGhrUdO3Z0tO5169YV6y+++GJH60d92PMDSRF+ICnCDyRF+IGkCD+QFOEHkiL8QFJc5/8UGBlp/C1pixYt6mjdr732WrHe7PsgMLjY8wNJEX4gKcIPJEX4gaQIP5AU4QeSIvxAUlznnwGWL19erD/xxBN96gSfJuz5gaQIP5AU4QeSIvxAUoQfSIrwA0kRfiCpptf5bS+U9IykL0i6KGk0In5se4OkNZLOVrOuj4iXetVoZvfcc0+xPmfOnLbXfeTIkWL9/Pnzba8bg62Vm3wuSPp2RLxt+3OS9th+par9KCK+37v2APRK0/BHxClJp6rX52wfkHR9rxsD0FtXdM5ve7GkpZJ+W0163PbvbG+yPbfBMiO2x2yPddQpgK5qOfy250jaJulbEfEnSRslfVnSEk0eGfxguuUiYjQihiJiqAv9AuiSlsJve7Ymg78lIn4lSRFxOiI+joiLkn4i6a7etQmg25qG37Yl/VTSgYj44ZTpC6bM9jVJ+7rfHoBeaeWv/csk/Zukvbbfqaatl/SY7SWSQtIxSd/sSYfoyLvvvlus33///cX6xMREN9vBAGnlr/27JXmaEtf0gRmMO/yApAg/kBThB5Ii/EBShB9IivADSbmfQyzbZjxnoMciYrpL85/Anh9IivADSRF+ICnCDyRF+IGkCD+QFOEHkur3EN1/lPR/U95/vpo2iAa1t0HtS6K3dnWztxtanbGvN/l8YuP22KB+t9+g9jaofUn01q66euOwH0iK8ANJ1R3+0Zq3XzKovQ1qXxK9tauW3mo95wdQn7r3/ABqUkv4ba+wfdD2YdtP1tFDI7aP2d5r+526hxirhkE7Y3vflGnzbL9i+w/Vz2mHSauptw22/7/67N6x/WBNvS20/b+2D9jeb/s/q+m1fnaFvmr53Pp+2G97lqRDkh6QNC7pLUmPRcTv+9pIA7aPSRqKiNqvCdv+F0nnJT0TEbdW056SNBER36t+cc6NiP8akN42SDpf98jN1YAyC6aOLC3pYUn/rho/u0Jfj6qGz62OPf9dkg5HxNGI+LOkX0haWUMfAy8idkm6fNSMlZI2V683a/I/T9816G0gRMSpiHi7en1O0qWRpWv97Ap91aKO8F8v6cSU9+MarCG/Q9IO23tsj9TdzDSuq4ZNvzR8+vya+7lc05Gb++mykaUH5rNrZ8Trbqsj/NN9xdAgXXJYFhG3S/pXSWurw1u0pqWRm/tlmpGlB0K7I153Wx3hH5e0cMr7L0o6WUMf04qIk9XPM5J+rcEbffj0pUFSq59nau7nrwZp5ObpRpbWAHx2gzTidR3hf0vSjba/ZPuzkr4haXsNfXyC7aurP8TI9tWSvqLBG314u6TV1evVkp6vsZe/MygjNzcaWVo1f3aDNuJ1LTf5VJcy/lvSLEmbIuK7fW9iGrb/UZN7e2nyicef19mb7WclDWvyqa/Tkr4j6TlJWyUtknRc0tcjou9/eGvQ27AmD13/OnLzpXPsPve2XNJvJO2VdLGavF6T59e1fXaFvh5TDZ8bd/gBSXGHH5AU4QeSIvxAUoQfSIrwA0kRfiApwg8kRfiBpP4CIJjqosJxHysAAAAASUVORK5CYII=\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Expected label: 7.0 . One hot encoding: [[0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]]\n" - ] - } - ], - "source": [ - "import matplotlib.pyplot as plt\n", - "# This is the variable that was initialised at the beginning of the file\n", - "i = [0]\n", - "x = mnist.test.images[i]\n", - "y = mnist.test.labels[i]\n", - "plt.imshow(x.reshape((28, 28)), cmap='gray')\n", - "plt.show()\n", - "print(\"Expected label: \", np.sum(range(0,10) * y), \". One hot encoding: \", y)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can now add the URL above to send our request:" - ] - }, - { - "cell_type": "code", - "execution_count": 112, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Success:True message:\n", - "Request:\n", - "data {\n", - " names: \"text\"\n", - " ndarray {\n", - " values {\n", - " list_value {\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.3294117748737335\n", - " }\n", - " values {\n", - " number_value: 0.7254902124404907\n", - " }\n", - " values {\n", - " number_value: 0.6235294342041016\n", - " }\n", - " values {\n", - " number_value: 0.5921568870544434\n", - " }\n", - " values {\n", - " number_value: 0.2352941334247589\n", - " }\n", - " values {\n", - " number_value: 0.1411764770746231\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.8705883026123047\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9450981020927429\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.7764706611633301\n", - " }\n", - " values {\n", - " number_value: 0.6666666865348816\n", - " }\n", - " values {\n", - " number_value: 0.2039215862751007\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.26274511218070984\n", - " }\n", - " values {\n", - " number_value: 0.44705885648727417\n", - " }\n", - " values {\n", - " number_value: 0.2823529541492462\n", - " }\n", - " values {\n", - " number_value: 0.44705885648727417\n", - " }\n", - " values {\n", - " number_value: 0.6392157077789307\n", - " }\n", - " values {\n", - " number_value: 0.8901961445808411\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.8823530077934265\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9803922176361084\n", - " }\n", - " values {\n", - " number_value: 0.8980392813682556\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.5490196347236633\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.06666667014360428\n", - " }\n", - " values {\n", - " number_value: 0.25882354378700256\n", - " }\n", - " values {\n", - " number_value: 0.05490196496248245\n", - " }\n", - " values {\n", - " number_value: 0.26274511218070984\n", - " }\n", - " values {\n", - " number_value: 0.26274511218070984\n", - " }\n", - " values {\n", - " number_value: 0.26274511218070984\n", - " }\n", - " values {\n", - " number_value: 0.23137256503105164\n", - " }\n", - " values {\n", - " number_value: 0.08235294371843338\n", - " }\n", - " values {\n", - " number_value: 0.9254902601242065\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.41568630933761597\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.32549020648002625\n", - " }\n", - " values {\n", - " number_value: 0.9921569228172302\n", - " }\n", - " values {\n", - " number_value: 0.8196079134941101\n", - " }\n", - " values {\n", - " number_value: 0.07058823853731155\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.08627451211214066\n", - " }\n", - " values {\n", - " number_value: 0.9137255549430847\n", - " }\n", - " values {\n", - " number_value: 1.0\n", - " }\n", - " values {\n", - " number_value: 0.32549020648002625\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.5058823823928833\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9333333969116211\n", - " }\n", - " values {\n", - " number_value: 0.1725490242242813\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.23137256503105164\n", - " }\n", - " values {\n", - " number_value: 0.9764706492424011\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.24313727021217346\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.5215686559677124\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.7333333492279053\n", - " }\n", - " values {\n", - " number_value: 0.019607843831181526\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.03529411926865578\n", - " }\n", - " values {\n", - " number_value: 0.803921639919281\n", - " }\n", - " values {\n", - " number_value: 0.9725490808486938\n", - " }\n", - " values {\n", - " number_value: 0.22745099663734436\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.4941176772117615\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.7137255072593689\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.29411765933036804\n", - " }\n", - " values {\n", - " number_value: 0.9843137860298157\n", - " }\n", - " values {\n", - " number_value: 0.9411765336990356\n", - " }\n", - " values {\n", - " number_value: 0.22352942824363708\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.07450980693101883\n", - " }\n", - " values {\n", - " number_value: 0.8666667342185974\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.6509804129600525\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.011764707043766975\n", - " }\n", - " values {\n", - " number_value: 0.7960785031318665\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.8588235974311829\n", - " }\n", - " values {\n", - " number_value: 0.13725490868091583\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.14901961386203766\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.3019607961177826\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.12156863510608673\n", - " }\n", - " values {\n", - " number_value: 0.8784314393997192\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.45098042488098145\n", - " }\n", - " values {\n", - " number_value: 0.003921568859368563\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.5215686559677124\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.2039215862751007\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.2392157018184662\n", - " }\n", - " values {\n", - " number_value: 0.9490196704864502\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.2039215862751007\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.4745098352432251\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.8588235974311829\n", - " }\n", - " values {\n", - " number_value: 0.1568627506494522\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.4745098352432251\n", - " }\n", - " values {\n", - " number_value: 0.9960784912109375\n", - " }\n", - " values {\n", - " number_value: 0.8117647767066956\n", - " }\n", - " values {\n", - " number_value: 0.07058823853731155\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " values {\n", - " number_value: 0.0\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n", - "Response:\n", - "meta {\n", - " puid: \"l6bv1r38mmb32l0hbinln2jjcl\"\n", - " requestPath {\n", - " key: \"classifier\"\n", - " value: \"271049282727.dkr.ecr.us-west-2.amazonaws.com/seldon-repository:latest\"\n", - " }\n", - "}\n", - "data {\n", - " names: \"class:0\"\n", - " names: \"class:1\"\n", - " names: \"class:2\"\n", - " names: \"class:3\"\n", - " names: \"class:4\"\n", - " names: \"class:5\"\n", - " names: \"class:6\"\n", - " names: \"class:7\"\n", - " names: \"class:8\"\n", - " names: \"class:9\"\n", - " ndarray {\n", - " values {\n", - " list_value {\n", - " values {\n", - " number_value: 6.839015986770391e-05\n", - " }\n", - " values {\n", - " number_value: 9.376968534979824e-09\n", - " }\n", - " values {\n", - " number_value: 8.48581112222746e-05\n", - " }\n", - " values {\n", - " number_value: 0.0034086888190358877\n", - " }\n", - " values {\n", - " number_value: 2.3978568606253248e-06\n", - " }\n", - " values {\n", - " number_value: 2.0100669644307345e-05\n", - " }\n", - " values {\n", - " number_value: 3.0251623428512175e-08\n", - " }\n", - " values {\n", - " number_value: 0.9953710436820984\n", - " }\n", - " values {\n", - " number_value: 2.6070511012221687e-05\n", - " }\n", - " values {\n", - " number_value: 0.0010185304563492537\n", - " }\n", - " }\n", - " }\n", - " }\n", - "}\n", - "\n" - ] - } - ], - "source": [ - "from seldon_core.seldon_client import SeldonClient\n", - "import math\n", - "import numpy as np\n", - "\n", - "host = \"a68bbac487ca611e988060247f81f4c1-707754258.us-west-2.elb.amazonaws.com\"\n", - "port = \"80\" # Make sure you use the port above\n", - "batch = x\n", - "payload_type = \"ndarray\"\n", - "\n", - "sc = SeldonClient(\n", - " gateway=\"ambassador\", \n", - " ambassador_endpoint=host + \":\" + port,\n", - " namespace=\"default\",\n", - " oauth_key=\"oauth-key\", \n", - " oauth_secret=\"oauth-secret\")\n", - "\n", - "client_prediction = sc.predict(\n", - " data=batch, \n", - " deployment_name=\"deep-mnist\",\n", - " names=[\"text\"],\n", - " payload_type=payload_type)\n", - "\n", - "print(client_prediction)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Let's visualise the probability for each label\n", - "It seems that it correctly predicted the number 7" - ] - }, - { - "cell_type": "code", - "execution_count": 117, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "LABEL 0:\t 0.0068 %\n", - "LABEL 1:\t 0.0000 %\n", - "LABEL 2:\t 0.0085 %\n", - "LABEL 3:\t 0.3409 %\n", - "LABEL 4:\t 0.0002 %\n", - "LABEL 5:\t 0.0020 %\n", - "LABEL 6:\t 0.0000 %\n", - "LABEL 7:\t 99.5371 %\n", - "LABEL 8:\t 0.0026 %\n", - "LABEL 9:\t 0.1019 %\n" - ] - } - ], - "source": [ - "for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)):\n", - " print(f\"LABEL {label}:\\t {proba.number_value*100:6.4f} %\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "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.7.3" - }, - "varInspector": { - "cols": { - "lenName": 16, - "lenType": 16, - "lenVar": 40 - }, - "kernels_config": { - "python": { - "delete_cmd_postfix": "", - "delete_cmd_prefix": "del ", - "library": "var_list.py", - "varRefreshCmd": "print(var_dic_list())" - }, - "r": { - "delete_cmd_postfix": ") ", - "delete_cmd_prefix": "rm(", - "library": "var_list.r", - "varRefreshCmd": "cat(var_dic_list()) " - } - }, - "types_to_exclude": [ - "module", - "function", - "builtin_function_or_method", - "instance", - "_Feature" - ], - "window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} + + + +### Let's visualise the probability for each label +It seems that it correctly predicted the number 7 + + +```python +for proba, label in zip(client_prediction.response.data.ndarray.values[0].list_value.ListFields()[0][1], range(0,10)): + print(f"LABEL {label}:\t {proba.number_value*100:6.4f} %") +``` + + LABEL 0: 0.0068 % + LABEL 1: 0.0000 % + LABEL 2: 0.0085 % + LABEL 3: 0.3409 % + LABEL 4: 0.0002 % + LABEL 5: 0.0020 % + LABEL 6: 0.0000 % + LABEL 7: 99.5371 % + LABEL 8: 0.0026 % + LABEL 9: 0.1019 % + + + +```python + +```