From fda4e8c0ba876f946afda239be17cbd1748a3017 Mon Sep 17 00:00:00 2001 From: Dmitriy M Date: Fri, 13 May 2022 13:21:42 +0200 Subject: [PATCH] feat: Add notebook for large tensorflow model See: https://github.com/waylayio/plug-registry/pull/765 --- byoml/large_model/Tensorflow AlexNet.ipynb | 725 +++++++++++++++++++++ 1 file changed, 725 insertions(+) create mode 100644 byoml/large_model/Tensorflow AlexNet.ipynb diff --git a/byoml/large_model/Tensorflow AlexNet.ipynb b/byoml/large_model/Tensorflow AlexNet.ipynb new file mode 100644 index 0000000..73f1974 --- /dev/null +++ b/byoml/large_model/Tensorflow AlexNet.ipynb @@ -0,0 +1,725 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "39d123de", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "# conda environments:\r\n", + "#\r\n", + "base /Users/dmitriy/opt/anaconda3\r\n", + "byoml-test /Users/dmitriy/opt/anaconda3/envs/byoml-test\r\n", + "byoml_tensorflow * /Users/dmitriy/opt/anaconda3/envs/byoml_tensorflow\r\n", + "tsa37 /Users/dmitriy/opt/anaconda3/envs/tsa37\r\n", + "wr /Users/dmitriy/opt/anaconda3/envs/wr\r\n", + "\r\n" + ] + } + ], + "source": [ + "! conda env list" + ] + }, + { + "cell_type": "markdown", + "id": "be0a546f", + "metadata": {}, + "source": [ + "## Requirements\n", + "python==3.7.10
\n", + "tensorflow==2.1.0
\n", + "numpy==1.20.3
\n", + "seaborn==0.11.1
\n", + "matplotlib==3.4.2
\n", + "tenacity==7.0.0
\n", + "waylay-beta==0.2.0
" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "5d4f16dc", + "metadata": {}, + "outputs": [], + "source": [ + "# Imports\n", + "import tensorflow as tf\n", + "import numpy as np\n", + "import seaborn as sns\n", + "\n", + "%matplotlib inline\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "8ded5ef7", + "metadata": {}, + "outputs": [], + "source": [ + "MODEL_NAME='tf-reproduce'" + ] + }, + { + "cell_type": "markdown", + "id": "fd5462ac", + "metadata": {}, + "source": [ + "## TensorFlow example for AlexNet implementation and uploading model to Waylay BYOML\n", + "The CIFAR-10 dataset contains 60,000 colour images, each with dimensions 32x32px. The content of the images within the dataset is sampled from 10 classes. Ref.\n", + "https://towardsdatascience.com/implementing-alexnet-cnn-architecture-using-tensorflow-2-0-and-keras-2113e090ad98" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "56b4ab95", + "metadata": {}, + "outputs": [], + "source": [ + "(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.cifar10.load_data()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "8e6d9671", + "metadata": {}, + "outputs": [], + "source": [ + "CLASS_NAMES= ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "14ac8c37", + "metadata": {}, + "outputs": [], + "source": [ + "validation_images, validation_labels = train_images[:5000], train_labels[:5000]\n", + "train_images, train_labels = train_images[5000:], train_labels[5000:]" + ] + }, + { + "cell_type": "markdown", + "id": "3d4ecd80", + "metadata": {}, + "source": [ + "Training Dataset: This is the group of our dataset used to train the neural network directly. Training data refers to the dataset partition exposed to the neural network during training.\n", + "\n", + "Validation Dataset: This group of the dataset is utilized during training to assess the performance of the network at various iterations.\n", + "\n", + "Test Dataset: This partition of the dataset evaluates the performance of our network after the completion of the training phase." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "6fb5ba3d", + "metadata": {}, + "outputs": [], + "source": [ + "train_ds = tf.data.Dataset.from_tensor_slices((train_images, train_labels))\n", + "test_ds = tf.data.Dataset.from_tensor_slices((test_images, test_labels))\n", + "validation_ds = tf.data.Dataset.from_tensor_slices((validation_images, validation_labels))" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "d96dfc37", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.figure(figsize=(20,20))\n", + "for i, (image, label) in enumerate(train_ds.take(5)):\n", + " ax = plt.subplot(5,5,i+1)\n", + " plt.imshow(image)\n", + " plt.title(CLASS_NAMES[label.numpy()[0]])\n", + " plt.axis('off')" + ] + }, + { + "cell_type": "markdown", + "id": "4c49c313", + "metadata": {}, + "source": [ + "Dataset Preprocessing to AlexNet input format
\n", + "The primary preprocessing transformations that will be imposed on the data presented to the network are:\n", + "\n", + "
  • Normalizing and standardizing the images.
  • \n", + "
  • Resizing of the images from 32x32 to 227x227. The AlexNet network input expects a 227x227 image.
  • \n", + "We’ll create a function called process_images.\n", + "\n", + "This function will perform all preprocessing work that we require for the data. This function is called further down the machine learning workflow." + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "id": "712a4124", + "metadata": {}, + "outputs": [], + "source": [ + "def process_images(image, label):\n", + " # Normalize images to have a mean of 0 and standard deviation of 1\n", + " image = tf.image.per_image_standardization(image)\n", + " # Resize images from 32x32 to 277x277\n", + " image = tf.image.resize(image, (227,227))\n", + " return image, label\n" + ] + }, + { + "cell_type": "markdown", + "id": "b00dc1b1", + "metadata": {}, + "source": [ + "For our basic input/data pipeline, we will conduct three primary operations:\n", + "\n", + "
  • Preprocessing the data within the dataset
  • \n", + "
  • Shuffle the dataset
  • \n", + "
  • Batch data within the dataset
  • " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "id": "f759ff52", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training data size: 45000\n", + "Test data size: 10000\n", + "Validation data size: 5000\n" + ] + } + ], + "source": [ + "train_ds_size = tf.data.experimental.cardinality(train_ds).numpy()\n", + "test_ds_size = tf.data.experimental.cardinality(test_ds).numpy()\n", + "validation_ds_size = tf.data.experimental.cardinality(validation_ds).numpy()\n", + "print(\"Training data size:\", train_ds_size)\n", + "print(\"Test data size:\", test_ds_size)\n", + "print(\"Validation data size:\", validation_ds_size)" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "id": "4a67f590", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WARNING:tensorflow:From /Users/dmitriy/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/ops/image_ops_impl.py:1556: div (from tensorflow.python.ops.math_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Deprecated in favor of operator or tf.math.divide.\n" + ] + } + ], + "source": [ + "train_ds = (train_ds\n", + " .map(process_images)\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))\n", + "test_ds = (test_ds\n", + " .map(process_images)\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))\n", + "validation_ds = (validation_ds\n", + " .map(process_images)\n", + " .shuffle(buffer_size=train_ds_size)\n", + " .batch(batch_size=32, drop_remainder=True))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c87b7fca", + "metadata": {}, + "outputs": [], + "source": [ + "root_logdir = os.path.join(os.curdir, \"logs\\\\fit\\\\\")\n", + "def get_run_logdir():\n", + " run_id = time.strftime(\"run_%Y_%m_%d-%H_%M_%S\")\n", + " return os.path.join(root_logdir, run_id)\n", + "run_logdir = get_run_logdir()\n", + "tensorboard_cb = keras.callbacks.TensorBoard(run_logdir)" + ] + }, + { + "cell_type": "markdown", + "id": "29ea2567", + "metadata": {}, + "source": [ + "Now we can create a model, Keras implementation of the AlexNet CNN architecture.:" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "id": "14c53e1b", + "metadata": {}, + "outputs": [], + "source": [ + "lr = 0.001\n", + "model = tf.keras.models.Sequential([\n", + " #AlexNet\n", + " tf.keras.layers.Conv2D(filters=96, kernel_size=(11,11), strides=(4,4), activation='relu', input_shape=(227,227,3)),\n", + " tf.keras.layers.BatchNormalization(),\n", + " tf.keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n", + " tf.keras.layers.Conv2D(filters=256, kernel_size=(5,5), strides=(1,1), activation='relu', padding=\"same\"),\n", + " tf.keras.layers.BatchNormalization(),\n", + " tf.keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n", + " tf.keras.layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n", + " tf.keras.layers.BatchNormalization(),\n", + " tf.keras.layers.Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n", + " tf.keras.layers.BatchNormalization(),\n", + " tf.keras.layers.Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), activation='relu', padding=\"same\"),\n", + " tf.keras.layers.BatchNormalization(),\n", + " tf.keras.layers.MaxPool2D(pool_size=(3,3), strides=(2,2)),\n", + " tf.keras.layers.Flatten(),\n", + " tf.keras.layers.Dense(4096, activation='relu'),\n", + " tf.keras.layers.Dropout(0.5),\n", + " tf.keras.layers.Dense(4096, activation='relu'),\n", + " tf.keras.layers.Dropout(0.5),\n", + " tf.keras.layers.Dense(10, activation='softmax')\n", + "])" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "id": "3ce88a72", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Model: \"sequential_1\"\n", + "_________________________________________________________________\n", + "Layer (type) Output Shape Param # \n", + "=================================================================\n", + "conv2d_5 (Conv2D) (None, 55, 55, 96) 34944 \n", + "_________________________________________________________________\n", + "batch_normalization_5 (Batch (None, 55, 55, 96) 384 \n", + "_________________________________________________________________\n", + "max_pooling2d_3 (MaxPooling2 (None, 27, 27, 96) 0 \n", + "_________________________________________________________________\n", + "conv2d_6 (Conv2D) (None, 27, 27, 256) 614656 \n", + "_________________________________________________________________\n", + "batch_normalization_6 (Batch (None, 27, 27, 256) 1024 \n", + "_________________________________________________________________\n", + "max_pooling2d_4 (MaxPooling2 (None, 13, 13, 256) 0 \n", + "_________________________________________________________________\n", + "conv2d_7 (Conv2D) (None, 13, 13, 384) 885120 \n", + "_________________________________________________________________\n", + "batch_normalization_7 (Batch (None, 13, 13, 384) 1536 \n", + "_________________________________________________________________\n", + "conv2d_8 (Conv2D) (None, 13, 13, 384) 1327488 \n", + "_________________________________________________________________\n", + "batch_normalization_8 (Batch (None, 13, 13, 384) 1536 \n", + "_________________________________________________________________\n", + "conv2d_9 (Conv2D) (None, 13, 13, 256) 884992 \n", + "_________________________________________________________________\n", + "batch_normalization_9 (Batch (None, 13, 13, 256) 1024 \n", + "_________________________________________________________________\n", + "max_pooling2d_5 (MaxPooling2 (None, 6, 6, 256) 0 \n", + "_________________________________________________________________\n", + "flatten_1 (Flatten) (None, 9216) 0 \n", + "_________________________________________________________________\n", + "dense_3 (Dense) (None, 4096) 37752832 \n", + "_________________________________________________________________\n", + "dropout_2 (Dropout) (None, 4096) 0 \n", + "_________________________________________________________________\n", + "dense_4 (Dense) (None, 4096) 16781312 \n", + "_________________________________________________________________\n", + "dropout_3 (Dropout) (None, 4096) 0 \n", + "_________________________________________________________________\n", + "dense_5 (Dense) (None, 10) 40970 \n", + "=================================================================\n", + "Total params: 58,327,818\n", + "Trainable params: 58,325,066\n", + "Non-trainable params: 2,752\n", + "_________________________________________________________________\n" + ] + } + ], + "source": [ + "model.compile(loss='sparse_categorical_crossentropy', optimizer=tf.optimizers.SGD(lr=0.001), metrics=['accuracy'])\n", + "model.summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "id": "7973a699", + "metadata": { + "collapsed": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Train for 1406 steps, validate for 156 steps\n", + "Epoch 1/50\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-05-12 13:32:00.091524: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 10684 of 45000\n", + "2022-05-12 13:32:10.090806: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 20247 of 45000\n", + "2022-05-12 13:32:20.090387: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 29110 of 45000\n", + "2022-05-12 13:32:30.092005: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 37742 of 45000\n", + "2022-05-12 13:32:40.090670: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 43796 of 45000\n", + "2022-05-12 13:32:43.630317: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:199] Shuffle buffer filled.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1406/1406 [==============================] - 3562s 3s/step - loss: 2.1195 - accuracy: 0.3256 - val_loss: 1.4242 - val_accuracy: 0.5040\n", + "Epoch 2/50\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-05-12 14:31:21.647185: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 9630 of 45000\n", + "2022-05-12 14:31:31.649898: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 18490 of 45000\n", + "2022-05-12 14:31:41.649423: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 28251 of 45000\n", + "2022-05-12 14:31:51.645659: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 34483 of 45000\n", + "2022-05-12 14:32:01.645893: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 39567 of 45000\n", + "2022-05-12 14:32:11.645535: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 43642 of 45000\n", + "2022-05-12 14:32:13.020739: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:199] Shuffle buffer filled.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r", + " 1/1406 [..............................] - ETA: 26:32:37" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/xj/92nr7n311w10tgkscfj0csww0000gn/T/ipykernel_16152/616853289.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m50\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mvalidation_data\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_ds\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0mvalidation_freq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m1\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 5\u001b[0m \u001b[0;31m#callbacks=[tensorboard_cb]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)\u001b[0m\n\u001b[1;32m 817\u001b[0m \u001b[0mmax_queue_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmax_queue_size\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 818\u001b[0m \u001b[0mworkers\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mworkers\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 819\u001b[0;31m use_multiprocessing=use_multiprocessing)\n\u001b[0m\u001b[1;32m 820\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 821\u001b[0m def evaluate(self,\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py\u001b[0m in \u001b[0;36mfit\u001b[0;34m(self, model, x, y, batch_size, epochs, verbose, callbacks, validation_split, validation_data, shuffle, class_weight, sample_weight, initial_epoch, steps_per_epoch, validation_steps, validation_freq, max_queue_size, workers, use_multiprocessing, **kwargs)\u001b[0m\n\u001b[1;32m 340\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mModeKeys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTRAIN\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 341\u001b[0m \u001b[0mtraining_context\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mtraining_context\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 342\u001b[0;31m total_epochs=epochs)\n\u001b[0m\u001b[1;32m 343\u001b[0m \u001b[0mcbks\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmake_logs\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmodel\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mepoch_logs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtraining_result\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mModeKeys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mTRAIN\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 344\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2.py\u001b[0m in \u001b[0;36mrun_one_epoch\u001b[0;34m(model, iterator, execution_function, dataset_size, batch_size, strategy, steps_per_epoch, num_samples, mode, training_context, total_epochs)\u001b[0m\n\u001b[1;32m 126\u001b[0m step=step, mode=mode, size=current_batch_size) as batch_logs:\n\u001b[1;32m 127\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 128\u001b[0;31m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mexecution_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0miterator\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 129\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mStopIteration\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0merrors\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mOutOfRangeError\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 130\u001b[0m \u001b[0;31m# TODO(kaftan): File bug about tf function and errors.OutOfRangeError?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/training_v2_utils.py\u001b[0m in \u001b[0;36mexecution_function\u001b[0;34m(input_fn)\u001b[0m\n\u001b[1;32m 96\u001b[0m \u001b[0;31m# `numpy` translates Tensors to values in Eager mode.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 97\u001b[0m return nest.map_structure(_non_none_constant_value,\n\u001b[0;32m---> 98\u001b[0;31m distributed_function(input_fn))\n\u001b[0m\u001b[1;32m 99\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 100\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mexecution_function\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 566\u001b[0m \u001b[0mxla_context\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mExit\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 567\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[0;32m--> 568\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call\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[0mkwds\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 569\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 570\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mtracing_count\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_tracing_count\u001b[0m\u001b[0;34m(\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~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/def_function.py\u001b[0m in \u001b[0;36m_call\u001b[0;34m(self, *args, **kwds)\u001b[0m\n\u001b[1;32m 597\u001b[0m \u001b[0;31m# In this case we have created variables on the first call, so we run the\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 598\u001b[0m \u001b[0;31m# defunned version which is guaranteed to never create variables.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 599\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateless_fn\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[0mkwds\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# pylint: disable=not-callable\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 600\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_stateful_fn\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 601\u001b[0m \u001b[0;31m# Release the lock early so that multiple threads can perform the call\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 2361\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_lock\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2362\u001b[0m \u001b[0mgraph_function\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_maybe_define_function\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\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[0;32m-> 2363\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mgraph_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_filtered_call\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# pylint: disable=protected-access\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2364\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2365\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m_filtered_call\u001b[0;34m(self, args, kwargs)\u001b[0m\n\u001b[1;32m 1609\u001b[0m if isinstance(t, (ops.Tensor,\n\u001b[1;32m 1610\u001b[0m resource_variable_ops.BaseResourceVariable))),\n\u001b[0;32m-> 1611\u001b[0;31m self.captured_inputs)\n\u001b[0m\u001b[1;32m 1612\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1613\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_call_flat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcaptured_inputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcancellation_manager\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mNone\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~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args, captured_inputs, cancellation_manager)\u001b[0m\n\u001b[1;32m 1690\u001b[0m \u001b[0;31m# No tape is watching; skip to running the function.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1691\u001b[0m return self._build_call_outputs(self._inference_function.call(\n\u001b[0;32m-> 1692\u001b[0;31m ctx, args, cancellation_manager=cancellation_manager))\n\u001b[0m\u001b[1;32m 1693\u001b[0m forward_backward = self._select_forward_and_backward_functions(\n\u001b[1;32m 1694\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args, cancellation_manager)\u001b[0m\n\u001b[1;32m 543\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 544\u001b[0m \u001b[0mattrs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"executor_type\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mexecutor_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"config_proto\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfig\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--> 545\u001b[0;31m ctx=ctx)\n\u001b[0m\u001b[1;32m 546\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 547\u001b[0m outputs = execute.execute_with_cancellation(\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tensorflow_core/python/eager/execute.py\u001b[0m in \u001b[0;36mquick_execute\u001b[0;34m(op_name, num_outputs, inputs, attrs, ctx, name)\u001b[0m\n\u001b[1;32m 59\u001b[0m tensors = pywrap_tensorflow.TFE_Py_Execute(ctx._handle, device_name,\n\u001b[1;32m 60\u001b[0m \u001b[0mop_name\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0minputs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mattrs\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 61\u001b[0;31m num_outputs)\n\u001b[0m\u001b[1;32m 62\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mcore\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_NotOkStatusException\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 63\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mname\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "model.fit(train_ds,\n", + " epochs=50,\n", + " validation_data=validation_ds,\n", + " validation_freq=1,\n", + " #callbacks=[tensorboard_cb]\n", + " )" + ] + }, + { + "cell_type": "markdown", + "id": "ac42f32b", + "metadata": {}, + "source": [ + "Let's test the model on our test set" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "id": "54d743de", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2022-05-13 11:37:33.852348: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:150] Filling up shuffle buffer (this may take a while): 9208 of 45000\n", + "2022-05-13 11:37:34.845290: I tensorflow/core/kernels/data/shuffle_dataset_op.cc:199] Shuffle buffer filled.\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "312/312 [==============================] - 175s 562ms/step - loss: 1.4475 - accuracy: 0.4807\n", + "Test loss: 1.4474820712437997, test accuracy: 0.4806690812110901\n" + ] + } + ], + "source": [ + "test_loss, test_acc = model.evaluate(test_ds)\n", + "print(f\"Test loss: {test_loss}, test accuracy: {test_acc}\")" + ] + }, + { + "cell_type": "markdown", + "id": "8e2cc922", + "metadata": {}, + "source": [ + "# Save the model and upload\n", + "We will save the model in SavedModel format and then upload it to Waylay." + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "id": "ddf0e2ff", + "metadata": {}, + "outputs": [], + "source": [ + "from waylay import WaylayClient, RestResponseError\n", + "import tempfile\n", + "\n", + "waylay = WaylayClient.from_profile()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "31970827", + "metadata": {}, + "outputs": [], + "source": [ + "# clean up existing model\n", + "import time\n", + "try:\n", + " waylay.byoml.model.remove(MODEL_NAME)\n", + " display(f'Removed: {MODEL_NAME}')\n", + " time.sleep(5)\n", + "except RestResponseError as e:\n", + " display(f'Ignored: {e}')" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "fba3a275", + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=72.903\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 4.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=66.408\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 4.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=72.889\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 4.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=76.735\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 8.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=46.989\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 16.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=53.147\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 32.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n", + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=POST;status_code=409;dur=58.634\n", + "INFO:waylay.byoml.model._create:Retrying byoml.model._create in 32.0 seconds as it raised ByomlActionError(409: 'A kfserving entity with this name and version already exists'; POST 'https://byoml-staging.waylay.io/models').\n" + ] + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/var/folders/xj/92nr7n311w10tgkscfj0csww0000gn/T/ipykernel_16152/3500222438.py\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mtrained_model\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmodel_dir\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0mframework\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'tensorflow'\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 8\u001b[0;31m \u001b[0mdescription\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'tensorflow reproduction of Yokogawa issue'\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 9\u001b[0m )\n\u001b[1;32m 10\u001b[0m \u001b[0;31m# result\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/waylay/service/_decorators.py\u001b[0m in \u001b[0;36mwrapped\u001b[0;34m(slf, *args, **kwargs)\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mheader_value\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mslf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mheaders\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpop\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mheader_key\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 20\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 21\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0maction_method\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mslf\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 22\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mheader_value\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/waylay/service/byoml/model.py\u001b[0m in \u001b[0;36mupload\u001b[0;34m(self, model_name, trained_model, framework, framework_version, metadata, description, requirements_file, requirements, lib, work_dir, **kwargs)\u001b[0m\n\u001b[1;32m 419\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 420\u001b[0m ) as arguments:\n\u001b[0;32m--> 421\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_create\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0marguments\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m# pylint: disable=no-member\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 422\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 423\u001b[0m \u001b[0;34m@\u001b[0m\u001b[0msuppress_header_decorator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Content-Type'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/waylay/service/_decorators.py\u001b[0m in \u001b[0;36mwrapped\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 136\u001b[0m \u001b[0;34m'response_constructor'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdefault_response_constructor\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 137\u001b[0m ) or identity_transform\n\u001b[0;32m--> 138\u001b[0;31m \u001b[0mresponse\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0maction_method\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 139\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mraw\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 140\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresponse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/waylay/service/byoml/_decorators.py\u001b[0m in \u001b[0;36mwrapped\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 115\u001b[0m \u001b[0mbefore_sleep\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mbefore_sleep\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 116\u001b[0m \u001b[0mwait\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mwait_exponential\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m**\u001b[0m\u001b[0mWAIT_EXPONENTIAL\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--> 117\u001b[0;31m \u001b[0mreraise\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 118\u001b[0m ):\n\u001b[1;32m 119\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mattempt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tenacity/__init__.py\u001b[0m in \u001b[0;36m__iter__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 385\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdo\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mDoSleep\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 386\u001b[0m \u001b[0mretry_state\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mprepare_for_next_attempt\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--> 387\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mdo\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 388\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 389\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m~/opt/anaconda3/envs/byoml_tensorflow/lib/python3.7/site-packages/tenacity/nap.py\u001b[0m in \u001b[0;36msleep\u001b[0;34m(seconds)\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0mThis\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mdefault\u001b[0m \u001b[0mstrategy\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mmay\u001b[0m \u001b[0mbe\u001b[0m \u001b[0mmocked\u001b[0m \u001b[0mout\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0munit\u001b[0m \u001b[0mtesting\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \"\"\"\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mseconds\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 32\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "with tempfile.TemporaryDirectory() as model_dir:\n", + "# tf.saved_model.save(model, model_dir)\n", + " result = waylay.byoml.model.upload(\n", + " model_name=MODEL_NAME, \n", + " trained_model=model_dir, \n", + " framework='tensorflow', \n", + " description='tensorflow reproduction of Yokogawa issue'\n", + " )\n", + "# result" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "18ed83f5", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "INFO:tensorflow:Assets written to: testSize/assets\n" + ] + } + ], + "source": [ + "tf.saved_model.save(model, 'testSize')" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "id": "7b9ef1f3", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "INFO:waylay.service.byoml.model.server-timing:monitor/byoml./models/;environment=staging;tenant=6ccc8843-d78d-49e8-84c4-3734a4af9929;domain=staging.waylay.io;method=GET;status_code=200;dur=56.618\n" + ] + }, + { + "data": { + "text/plain": [ + "{'createdBy': 'users/ac1ff662-ad5b-433b-832d-59a21dc00c04',\n", + " 'createdOn': '2022-05-13T08:21:29.308000+00:00',\n", + " 'description': 'tensorflow reproduction of Yokogawa issue',\n", + " 'failure_reason': {'events': [],\n", + " 'log': ['BuildkitError: Failed to build and push: read EHOSTUNREACH: read EHOSTUNREACH']},\n", + " 'framework': 'tensorflow',\n", + " 'framework_version': '2.4',\n", + " 'metadata': {'description': 'tensorflow reproduction of Yokogawa issue'},\n", + " 'name': 'tf-reproduce',\n", + " 'ready': False,\n", + " 'runtime': {'framework': 'tensorflow',\n", + " 'framework_version': '2.4',\n", + " 'name': 'byoml-tensorflow-2.4',\n", + " 'python_version': '3.6'},\n", + " 'semantic_version': '0.0.1',\n", + " 'serving_name': 'kf-f6ee903c3642a3fa01a0efa53e9836e8821a997f.openfaas-fn-6ccc8843-d78d-49e8-84c4-3734a4af9929',\n", + " 'status': 'failed',\n", + " 'supported_endpoints': [],\n", + " 'updatedBy': 'users/ac1ff662-ad5b-433b-832d-59a21dc00c04',\n", + " 'updatedOn': '2022-05-13T08:37:51.789000+00:00',\n", + " 'version': '1'}" + ] + }, + "execution_count": 63, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "waylay.byoml.model.get(MODEL_NAME, params={'debug': True})" + ] + }, + { + "cell_type": "code", + "execution_count": 46, + "id": "a6298c31", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'message': 'Model tf-reproduce: all versions deleted',\n", + " 'name': 'tf-reproduce',\n", + " 'versions': ['0.0.1']}" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "waylay.byoml.model.remove(MODEL_NAME)" + ] + }, + { + "cell_type": "code", + "execution_count": 51, + "id": "0d315fbb", + "metadata": {}, + "outputs": [], + "source": [ + "import logging\n", + "logging.basicConfig(level='DEBUG')" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}