diff --git a/doc/source/examples/aws_eks_deep_mnist.nblink b/doc/source/examples/aws_eks_deep_mnist.nblink new file mode 100644 index 0000000000..5aa7a755d9 --- /dev/null +++ b/doc/source/examples/aws_eks_deep_mnist.nblink @@ -0,0 +1,3 @@ +{ + "path": "../../../examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb" +} diff --git a/examples/models/aws_eks_deep_mnist/.s2i/environment b/examples/models/aws_eks_deep_mnist/.s2i/environment new file mode 100644 index 0000000000..d5a1d6d66a --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/.s2i/environment @@ -0,0 +1,4 @@ +MODEL_NAME=DeepMnist +API_TYPE=REST +SERVICE_TYPE=MODEL +PERSISTENCE=0 diff --git a/examples/models/aws_eks_deep_mnist/DeepMnist.py b/examples/models/aws_eks_deep_mnist/DeepMnist.py new file mode 100644 index 0000000000..0e45b33d86 --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/DeepMnist.py @@ -0,0 +1,19 @@ +import tensorflow as tf +import numpy as np + +class DeepMnist(object): + def __init__(self): + self.class_names = ["class:{}".format(str(i)) for i in range(10)] + self.sess = tf.Session() + saver = tf.train.import_meta_graph("model/deep_mnist_model.meta") + saver.restore(self.sess,tf.train.latest_checkpoint("./model/")) + + graph = tf.get_default_graph() + self.x = graph.get_tensor_by_name("x:0") + self.y = graph.get_tensor_by_name("y:0") + + def predict(self,X,feature_names): + predictions = self.sess.run(self.y,feed_dict={self.x:X}) + return predictions.astype(np.float64) + + 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 new file mode 100644 index 0000000000..0211ad5a73 --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/aws_eks_deep_mnist.ipynb @@ -0,0 +1,3823 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Tensorflow MNIST Model\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", + "* Docker\n", + "* Helm\n", + "* Kubectl\n", + "* EKS CLI\n", + "* AWS Cli\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" + ] + } + ], + "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" + ] + } + ], + "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" + ] + } + ], + "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/create_model.py b/examples/models/aws_eks_deep_mnist/create_model.py new file mode 100644 index 0000000000..2ea52b6aa5 --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/create_model.py @@ -0,0 +1,36 @@ +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") diff --git a/examples/models/aws_eks_deep_mnist/deep_mnist.json b/examples/models/aws_eks_deep_mnist/deep_mnist.json new file mode 100644 index 0000000000..6442bfd244 --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/deep_mnist.json @@ -0,0 +1,53 @@ +{ + "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": "REPLACE_FOR_IMAGE_AND_TAG", + "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" + } + } + ] + } +} diff --git a/examples/models/aws_eks_deep_mnist/requirements.txt b/examples/models/aws_eks_deep_mnist/requirements.txt new file mode 100644 index 0000000000..6f9706765e --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/requirements.txt @@ -0,0 +1 @@ +tensorflow>=1.12.0 diff --git a/examples/models/aws_eks_deep_mnist/tiller-role-binding.yaml b/examples/models/aws_eks_deep_mnist/tiller-role-binding.yaml new file mode 100644 index 0000000000..4c330d3585 --- /dev/null +++ b/examples/models/aws_eks_deep_mnist/tiller-role-binding.yaml @@ -0,0 +1,12 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tiller-role-binding +roleRef: + kind: ClusterRole + name: cluster-admin + apiGroup: rbac.authorization.k8s.io +subjects: +- kind: ServiceAccount + name: tiller + namespace: kube-system