diff --git a/docs/nb/DenseNetV1.ipynb b/docs/nb/DenseNetV1.ipynb new file mode 100644 index 0000000..e6e8ed1 --- /dev/null +++ b/docs/nb/DenseNetV1.ipynb @@ -0,0 +1,872 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "DenseNetV1.ipynb", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [ + "U74NGbY4508Z", + "08Eytj_3oYDI", + "2dnGV0FHocqH", + "Dvhr1SS2ojnf", + "apSpY04_op7G" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + } + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "U74NGbY4508Z", + "colab_type": "text" + }, + "source": [ + "# Import Tensorflow" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "rzmyPhhhvIRu", + "colab_type": "code", + "outputId": "7cace1eb-5944-4e27-f08b-4a6f50e8d4e4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 377 + } + }, + "source": [ + "!pip install tensorflow==2.0.0b1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Requirement already satisfied: tensorflow==2.0.0b1 in /usr/local/lib/python3.6/dist-packages (2.0.0b1)\n", + "Requirement already satisfied: tb-nightly<1.14.0a20190604,>=1.14.0a20190603 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.14.0a20190603)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.8.0)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (3.7.1)\n", + "Requirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.16.4)\n", + "Requirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.1.7)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.2.2)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.33.4)\n", + "Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.7.1)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.0.8)\n", + "Requirement already satisfied: tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.14.0.dev2019060501)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.15.0)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.12.0)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.11.2)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (3.1.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (0.15.5)\n", + "Requirement already satisfied: setuptools>=41.0.0 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (41.0.1)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow==2.0.0b1) (2.8.0)\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "08Eytj_3oYDI", + "colab_type": "text" + }, + "source": [ + "# SPIT Imports" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FIMdpjQ-f-nx", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "import numpy as np\n", + "import os\n", + "\n", + "from importlib import reload\n", + "from pkg_resources import resource_filename\n", + "from google.colab import drive\n", + "import imageio" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "EkgCyHlig-fl", + "colab_type": "code", + "outputId": "3a501b2e-f5ea-4028-c5fd-b1a09f14feae", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "import tensorflow\n", + "tensorflow.__version__" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'2.0.0-beta1'" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 41 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "LqfsN-WdhAcm", + "colab_type": "code", + "outputId": "2c0f2550-a886-4dfd-a93b-f2b7f47e0369", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "drive.mount('/content/drive/')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Drive already mounted at /content/drive/; to attempt to forcibly remount, call drive.mount(\"/content/drive/\", force_remount=True).\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "znIJK2HDhBsO", + "colab_type": "code", + "outputId": "40b47ba8-97ef-41b1-ec6b-4d447f238981", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!git clone https://github.com/pypeit/spit.git" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "fatal: destination path 'spit' already exists and is not an empty directory.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "N1kzH-dghJlh", + "colab_type": "code", + "outputId": "d171d3a9-f43c-42a2-8144-d9627b544ed2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "%cd spit" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/content/spit/spit\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "UCXppiJ_hLtu", + "colab_type": "code", + "outputId": "5da3b8a0-950f-4aea-e085-d5bfc8afdb20", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "!git checkout x_fussing" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Already on 'x_fussing'\n", + "Your branch is up to date with 'origin/x_fussing'.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "gFBV0bnthNV8", + "colab_type": "code", + "outputId": "add311d4-bec0-46de-9784-0f0cad9a3a66", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!git pull" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Already up to date.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "sI3uoAU0hOwc", + "colab_type": "code", + "outputId": "4dc311ca-5249-4ebe-d3d0-77becd2fc3d4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!python setup.py develop" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "python3: can't open file 'setup.py': [Errno 2] No such file or directory\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "p1o27AbvhP7c", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "from importlib import reload\n", + "\n", + "from spit import image_loader\n", + "from spit import labels\n", + "from spit import preprocess\n", + "from spit import classifier\n", + "from spit import utils" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2dnGV0FHocqH", + "colab_type": "text" + }, + "source": [ + "# Build DenseNet" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6UK-KubhvJ4E", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import tensorflow as tf\n", + "from tensorflow import keras" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "veTuJQk36S0Z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(4*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + "# x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + "# x = Relu(x)\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=1))\n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + "# x = conv_layer(x, filter=self.filters, kernel=[1,1], layer_name=scope+'_conv1')\n", + "# x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + "# x = Average_pooling(x, pool_size=[2,2], stride=2)\n", + " return\n", + " " + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HozlILKAvVCE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "#### DENSE NET ARCHITECTURE #####\n", + "#\n", + "# CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX\n", + "#\n", + "# BLOCK:\n", + "# BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output\n", + "#\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .5\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "mwc1bmdCfmDT", + "colab_type": "code", + "colab": {} + }, + "source": [ + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Dvhr1SS2ojnf", + "colab_type": "text" + }, + "source": [ + "# Fake Data" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1UOxTk6beV3M", + "colab_type": "code", + "colab": {} + }, + "source": [ + "x_train = np.random.random((100, 210, 650, 1))\n", + "train_labels = np.random.randint(5, size=(100, 1))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "3YbIjCS-fhEQ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "y_train = keras.utils.to_categorical(train_labels, num_classes=5)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zquoTIHjfild", + "colab_type": "code", + "outputId": "dfc5cff3-0d06-4cd2-e41d-84eafb485e80", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 429 + } + }, + "source": [ + " model.fit(\n", + " x_train, \n", + " y_train, \n", + " epochs=5, \n", + " batch_size=6 \n", + " )" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 100 samples\n", + "Epoch 1/5\n", + " 12/100 [==>...........................] - ETA: 2:54 - loss: 2.8118 - accuracy: 0.2500" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0my_train\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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 641\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 642\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--> 643\u001b[0;31m use_multiprocessing=use_multiprocessing)\n\u001b[0m\u001b[1;32m 644\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 645\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.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, **kwargs)\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mvalidation_steps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_steps\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 663\u001b[0m \u001b[0mvalidation_freq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_freq\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 664\u001b[0;31m steps_name='steps_per_epoch')\n\u001b[0m\u001b[1;32m 665\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 666\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.py\u001b[0m in \u001b[0;36mmodel_iteration\u001b[0;34m(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)\u001b[0m\n\u001b[1;32m 381\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 382\u001b[0m \u001b[0;31m# Get outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 383\u001b[0;31m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mins_batch\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 384\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\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 385\u001b[0m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 3508\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath_ops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3509\u001b[0m \u001b[0mconverted_inputs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3510\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mconverted_inputs\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 3511\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3512\u001b[0m \u001b[0;31m# EagerTensor.numpy() will often make a copy to ensure memory safety.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 570\u001b[0m raise TypeError(\"Keyword arguments {} unknown. Expected {}.\".format(\n\u001b[1;32m 571\u001b[0m list(kwargs.keys()), list(self._arg_keywords)))\n\u001b[0;32m--> 572\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call_flat\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[0m\u001b[1;32m 573\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_filtered_call\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[0mkwargs\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[0;31m# Only need to override the gradient in graph mode and when we have outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 670\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 671\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_inference_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mctx\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[0m\u001b[1;32m 672\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 673\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_register_gradient\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args)\u001b[0m\n\u001b[1;32m 443\u001b[0m attrs=(\"executor_type\", executor_type,\n\u001b[1;32m 444\u001b[0m \"config_proto\", config),\n\u001b[0;32m--> 445\u001b[0;31m ctx=ctx)\n\u001b[0m\u001b[1;32m 446\u001b[0m \u001b[0;31m# Replace empty list with None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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: " + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "apSpY04_op7G", + "colab_type": "text" + }, + "source": [ + "# Kast Training" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Z_qa1ZZphR7b", + "colab_type": "code", + "colab": {} + }, + "source": [ + " os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + " os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"\n", + "\n", + " # might need to add subset\n", + " def _train(epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, test_model=None, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')):\n", + " \"\"\"\n", + "\n", + " Trains the classifier with given images, labels, and training parameters.\n", + "\n", + " Parameters:\n", + "\n", + " :param epochs:\n", + " Number of epochs of the training. \n", + " Must be an integer value.\n", + "\n", + " :param batch_size:\n", + " Size of the training batches formed in the process. \n", + " Must be an integer value.\n", + "\n", + " :param save_path:\n", + " Path to where the best model will be saved.\n", + "\n", + " :param train_images:\n", + " Set of images for model to train on.\n", + " Assume this is a numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param train_labels:\n", + " Set of test labels corresponding to test images.\n", + " Assume this is a rank 1 array with (batch_size, ) as its dimensions.\n", + "\n", + " :param validation_data:\n", + " Data to be used for the validation set. \n", + " Assume this is a tuple with (images, labels) with same dimensions as train_images, train_labels.\n", + " If None is specified, validation_data will be None.\n", + "\n", + " :param steps_per_epoch:\n", + " Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch.\n", + " Assume this is an integer value. If None is specified, this will be None. \n", + "\n", + " :param validation_freq:\n", + " Specifies how many training epochs to run before a new validation run is performed.\n", + " Assume this is an integer value or a collection containing the epochs at which to run validation (ie [1,2,10]).\n", + "\n", + " :param test_model:\n", + " An alternative choice for model to train on. Assume None.\n", + "\n", + " :param spit_path & param save_path:\n", + " Path to the spit images and where the model will be saved respectively.\n", + " ***Environmental variables must be set by caller or the path must be passed manually.***\n", + "\n", + " Returns:\n", + " :returns history:\n", + " Tensorflow History object containing loss and accuracy data over the training.\n", + "\n", + " \"\"\"\n", + " # choose the model\n", + " if test_model is None:\n", + " model = test_model\n", + " else:\n", + " model = test_model\n", + "\n", + " # if None is passed, then use the kast images\n", + " if train_images is None or train_labels is None:\n", + " # load training set\n", + " train = np.load(os.path.join(spit_path, 'Kast', 'kast_train.npz'))\n", + " train_images = train['images']\n", + " train_labels = train['labels']\n", + "\n", + " # load validation set\n", + " validate = np.load(os.path.join(spit_path, 'Kast', 'kast_validate.npz'))\n", + " v_images = validate['images']\n", + " v_labels = validate['labels']\n", + "\n", + " validation_data = (v_images, v_labels)\n", + "\n", + " # change to categorical and make subsets\n", + " if validation_data is not None:\n", + " valid_images, valid_labels = validation_data\n", + " if subset_percent is not None:\n", + " valid_images, valid_labels = split_array(valid_images, valid_labels, subset_percent)\n", + " valid_labels = keras.utils.to_categorical(valid_labels, num_classes=len(label_dict))\n", + " validation_data = (valid_images, valid_labels)\n", + "\n", + " if train_images is not None and train_labels is not None:\n", + " if subset_percent is not None:\n", + " train_images, train_labels = split_array(train_images, train_labels, subset_percent)\n", + " train_labels = keras.utils.to_categorical(train_labels, num_classes=len(label_dict))\n", + "\n", + " # checkpoint to track best model\n", + " checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_acc', save_best_only=True, mode='max')\n", + "\n", + " # train the model\n", + " history = model.fit(\n", + " train_images, \n", + " train_labels, \n", + " epochs=epochs, \n", + " batch_size=batch_size,\n", + " validation_data=validation_data,\n", + " steps_per_epoch=steps_per_epoch,\n", + " validation_freq=validation_freq,\n", + " callbacks=[checkpoint]\n", + " )\n", + " # loss and accuracy data\n", + " keys = history.history\n", + " # save to disc differently based on whether validation set was used\n", + "# if len(history.history.keys()) == 2: # can we abstract this away?\n", + "# np.savez_compressed('history.npz', loss=keys['loss'], acc=keys['acc']) #can these keys be abstracted away?\n", + "# else:\n", + "# np.savez_compressed('history.npz', loss=keys['loss'], acc=keys['acc'], val_loss=keys['val_loss'], val_acc=keys['val_acc'])\n", + "\n", + " return history\n", + "\n", + " import math\n", + "\n", + " def split_array(images, labels, subset_percent):\n", + " \"\"\"\n", + " Splits dataset based on a percentage value.\n", + "\n", + " Parameters:\n", + " :param images:\n", + " Images from a dataset to be trained on.\n", + " 4-D Numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param labels:\n", + " Labels from a dataset to be trained on.\n", + " Rank 1 Numpy array with (batch_size,) as its dimensions.\n", + "\n", + " :param subset_percent:\n", + " Float value determining percentage of subset to remain.\n", + "\n", + " Returns:\n", + " :returns split_images:\n", + " Numpy array containing a fraction of the initial images parameter (batch_size*subset_percent)\n", + "\n", + " :returns split_labels:\n", + " Numpy array containing a fraction of the initial labels parameter (batch_size*subset_percent)\n", + " \"\"\"\n", + " split_images = []\n", + " split_labels = []\n", + " \n", + " # get all unique labels\n", + " uni_lbls = np.unique(labels)\n", + " \n", + " # find all instances of labels and subset based on that\n", + " for uni_lbl in uni_lbls:\n", + " idx = np.where(labels==uni_lbl)[0]\n", + " # 0 : len(idx)*subset_percent\n", + " lower = 0\n", + " upper = int(math.floor(len(idx)*subset_percent))\n", + " split_images.extend(images[idx[lower:upper]])\n", + " split_labels.extend(labels[idx[lower:upper]])\n", + " return np.asarray(split_images), np.asarray(split_labels)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "dq7R3gYehrjC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "label_dict = labels.kast_label_dict()\n", + "preproc_dict = preprocess.original_preproc_dict()\n", + "classify_dict = labels.kast_classify_dict(label_dict)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Hea_JEG7hsRn", + "colab_type": "code", + "outputId": "7bda9721-5735-432b-a6de-19de541a78d4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 575 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent = .05, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 775 samples, validate on 190 samples\n", + "Epoch 1/5\n", + "774/775 [============================>.] - ETA: 1s - loss: 1.1711 - accuracy: 0.5323 " + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0724 20:52:36.457918 140551106664320 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 1498s 2s/sample - loss: 1.1718 - accuracy: 0.5316 - val_loss: 12.1867 - val_accuracy: 0.2000\n", + "Epoch 2/5\n", + "774/775 [============================>.] - ETA: 1s - loss: 0.7773 - accuracy: 0.7003 " + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0724 21:17:27.445801 140551106664320 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 1491s 2s/sample - loss: 0.7765 - accuracy: 0.7006 - val_loss: 0.8673 - val_accuracy: 0.6842\n", + "Epoch 3/5\n", + "774/775 [============================>.] - ETA: 1s - loss: 0.7296 - accuracy: 0.7674 " + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0724 21:42:17.369124 140551106664320 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 1490s 2s/sample - loss: 0.7322 - accuracy: 0.7665 - val_loss: 1.6048 - val_accuracy: 0.5263\n", + "Epoch 4/5\n", + "774/775 [============================>.] - ETA: 1s - loss: 0.6023 - accuracy: 0.7804 " + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0724 22:07:09.766519 140551106664320 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 1492s 2s/sample - loss: 0.6113 - accuracy: 0.7794 - val_loss: 1.0964 - val_accuracy: 0.6947\n", + "Epoch 5/5\n", + "774/775 [============================>.] - ETA: 1s - loss: 0.5828 - accuracy: 0.7855 " + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0724 22:31:57.023474 140551106664320 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 1487s 2s/sample - loss: 0.5828 - accuracy: 0.7858 - val_loss: 3.1274 - val_accuracy: 0.5368\n" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyError", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\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[0mhistory\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_train\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msubset_percent\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m.05\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtest_model\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mmodel\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\u001b[0m in \u001b[0;36m_train\u001b[0;34m(epochs, batch_size, subset_percent, train_images, train_labels, validation_data, steps_per_epoch, validation_freq, test_model, spit_path, save_path)\u001b[0m\n\u001b[1;32m 107\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msavez_compressed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'history.npz'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0macc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'acc'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;31m#can these keys be abstracted away?\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\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--> 109\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msavez_compressed\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'history.npz'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mloss\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0macc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'acc'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mval_loss\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'val_loss'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mval_acc\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mkeys\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'val_acc'\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[0m\u001b[1;32m 110\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mhistory\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyError\u001b[0m: 'acc'" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6lrQn4dJiIJJ", + "colab_type": "code", + "outputId": "98119973-d0c6-48a1-bbb0-5693f3793081", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 164 + } + }, + "source": [ + "utils.display_training_trends(history, key1='acc', key2='val_acc')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "error", + "ename": "NameError", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\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[0mutils\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisplay_training_trends\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mhistory\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey1\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'acc'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mkey2\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'val_acc'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mNameError\u001b[0m: name 'history' is not defined" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "j2gL32rpHo_h", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/docs/nb/DenseNetV1_1_.ipynb b/docs/nb/DenseNetV1_1_.ipynb new file mode 100644 index 0000000..b8614b8 --- /dev/null +++ b/docs/nb/DenseNetV1_1_.ipynb @@ -0,0 +1,1466 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "DenseNetV1.1_.ipynb", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [ + "U74NGbY4508Z", + "08Eytj_3oYDI", + "2dnGV0FHocqH", + "Dvhr1SS2ojnf", + "apSpY04_op7G" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "U74NGbY4508Z", + "colab_type": "text" + }, + "source": [ + "# Import Tensorflow" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "rzmyPhhhvIRu", + "colab_type": "code", + "outputId": "40f8c221-fa09-43a9-8209-ffa55400f58e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 357 + } + }, + "source": [ + "!pip install tensorflow==2.0.0b1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Requirement already satisfied: tensorflow==2.0.0b1 in /usr/local/lib/python3.6/dist-packages (2.0.0b1)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.0.8)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.2.2)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (3.7.1)\n", + "Requirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.1.7)\n", + "Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.7.1)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.8.0)\n", + "Requirement already satisfied: tb-nightly<1.14.0a20190604,>=1.14.0a20190603 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.14.0a20190603)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.15.0)\n", + "Requirement already satisfied: tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.14.0.dev2019060501)\n", + "Requirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.16.4)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.33.4)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.12.0)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.11.2)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow==2.0.0b1) (2.8.0)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.6.1->tensorflow==2.0.0b1) (41.0.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (0.15.5)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (3.1.1)\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "08Eytj_3oYDI", + "colab_type": "text" + }, + "source": [ + "# Imports" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FIMdpjQ-f-nx", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "import numpy as np\n", + "import os\n", + "\n", + "from importlib import reload\n", + "from pkg_resources import resource_filename\n", + "from google.colab import drive\n", + "import imageio" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "EkgCyHlig-fl", + "colab_type": "code", + "outputId": "f55817a9-927f-4a8e-a631-efe432f1cd36", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "import tensorflow\n", + "tensorflow.__version__" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'2.0.0-beta1'" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 4 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "LqfsN-WdhAcm", + "colab_type": "code", + "outputId": "442c63b1-a61c-452d-e406-4f3bc9204cdb", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 122 + } + }, + "source": [ + "drive.mount('/content/drive/')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdocs.test%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.photos.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fpeopleapi.readonly&response_type=code\n", + "\n", + "Enter your authorization code:\n", + "··········\n", + "Mounted at /content/drive/\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "znIJK2HDhBsO", + "colab_type": "code", + "outputId": "ba8c2b9e-8011-4d54-b303-63c4b43992c7", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136 + } + }, + "source": [ + "!git clone https://github.com/pypeit/spit.git" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Cloning into 'spit'...\n", + "remote: Enumerating objects: 161, done.\u001b[K\n", + "remote: Counting objects: 100% (161/161), done.\u001b[K\n", + "remote: Compressing objects: 100% (121/121), done.\u001b[K\n", + "remote: Total 845 (delta 108), reused 65 (delta 40), pack-reused 684\u001b[K\n", + "Receiving objects: 100% (845/845), 930.91 KiB | 821.00 KiB/s, done.\n", + "Resolving deltas: 100% (483/483), done.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "N1kzH-dghJlh", + "colab_type": "code", + "outputId": "5509ef09-bc4f-4607-a02f-a0d2f9d22fb5", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "%cd spit" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/content/spit\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "UCXppiJ_hLtu", + "colab_type": "code", + "outputId": "31496ee6-291c-4806-fc88-a56237c3bf96", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "!git checkout new_models" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Branch 'new_models' set up to track remote branch 'new_models' from 'origin'.\n", + "Switched to a new branch 'new_models'\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "gFBV0bnthNV8", + "colab_type": "code", + "outputId": "7a0187fe-570d-4a05-c835-e0b11e401476", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!git pull" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Already up to date.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "sI3uoAU0hOwc", + "colab_type": "code", + "outputId": "b0aeb278-9a77-4b87-ba6e-b2778f453513", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 323 + } + }, + "source": [ + "!python setup.py develop" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "running develop\n", + "running egg_info\n", + "creating spit.egg-info\n", + "writing spit.egg-info/PKG-INFO\n", + "writing dependency_links to spit.egg-info/dependency_links.txt\n", + "writing top-level names to spit.egg-info/top_level.txt\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "running build_ext\n", + "Creating /usr/local/lib/python3.6/dist-packages/spit.egg-link (link to .)\n", + "Adding spit 0.1.dev0 to easy-install.pth file\n", + "Installing spit_train script to /usr/local/bin\n", + "Installing spit_png script to /usr/local/bin\n", + "Installing spit_classify_image script to /usr/local/bin\n", + "\n", + "Installed /content/spit\n", + "Processing dependencies for spit==0.1.dev0\n", + "Finished processing dependencies for spit==0.1.dev0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "p1o27AbvhP7c", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "from importlib import reload\n", + "\n", + "from spit import image_loader\n", + "from spit import labels\n", + "from spit import preprocess\n", + "from spit import classifier as c\n", + "from spit import utils" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2dnGV0FHocqH", + "colab_type": "text" + }, + "source": [ + "# Build DenseNet" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6UK-KubhvJ4E", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import tensorflow as tf\n", + "from tensorflow import keras" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Vg-eHZ3gfURL", + "colab_type": "code", + "outputId": "f1e2bd43-4237-41ec-9953-64211a94448b", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "print(tf.test.is_gpu_available())\n", + "device_name = tf.test.gpu_device_name()\n", + "if device_name != '/device:GPU:0':\n", + " raise SystemError('GPU device not found')\n", + "print('Found GPU at: {}'.format(device_name))" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "True\n", + "Found GPU at: /device:GPU:0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "veTuJQk36S0Z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# need to add compression to either block, transition, or both to get it to be BC\n", + "\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(filters, kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return\n", + " " + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HozlILKAvVCE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "#### DENSE NET ARCHITECTURE #####\n", + "#\n", + "# CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX\n", + "#\n", + "# BLOCK:\n", + "# BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output\n", + "#\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "theta = .5\n", + "growth_rate = 4\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "mwc1bmdCfmDT", + "colab_type": "code", + "colab": {} + }, + "source": [ + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Dvhr1SS2ojnf", + "colab_type": "text" + }, + "source": [ + "# Fake Data" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1UOxTk6beV3M", + "colab_type": "code", + "colab": {} + }, + "source": [ + "x_train = np.random.random((100, 210, 650, 1))\n", + "train_labels = np.random.randint(5, size=(100, 1))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "3YbIjCS-fhEQ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "y_train = keras.utils.to_categorical(train_labels, num_classes=5)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zquoTIHjfild", + "colab_type": "code", + "outputId": "dfc5cff3-0d06-4cd2-e41d-84eafb485e80", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 429 + } + }, + "source": [ + " model.fit(\n", + " x_train, \n", + " y_train, \n", + " epochs=5, \n", + " batch_size=6 \n", + " )" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 100 samples\n", + "Epoch 1/5\n", + " 12/100 [==>...........................] - ETA: 2:54 - loss: 2.8118 - accuracy: 0.2500" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0my_train\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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 641\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 642\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--> 643\u001b[0;31m use_multiprocessing=use_multiprocessing)\n\u001b[0m\u001b[1;32m 644\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 645\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.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, **kwargs)\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mvalidation_steps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_steps\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 663\u001b[0m \u001b[0mvalidation_freq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_freq\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 664\u001b[0;31m steps_name='steps_per_epoch')\n\u001b[0m\u001b[1;32m 665\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 666\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.py\u001b[0m in \u001b[0;36mmodel_iteration\u001b[0;34m(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)\u001b[0m\n\u001b[1;32m 381\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 382\u001b[0m \u001b[0;31m# Get outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 383\u001b[0;31m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mins_batch\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 384\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\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 385\u001b[0m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 3508\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath_ops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3509\u001b[0m \u001b[0mconverted_inputs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3510\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mconverted_inputs\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 3511\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3512\u001b[0m \u001b[0;31m# EagerTensor.numpy() will often make a copy to ensure memory safety.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 570\u001b[0m raise TypeError(\"Keyword arguments {} unknown. Expected {}.\".format(\n\u001b[1;32m 571\u001b[0m list(kwargs.keys()), list(self._arg_keywords)))\n\u001b[0;32m--> 572\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call_flat\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[0m\u001b[1;32m 573\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_filtered_call\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[0mkwargs\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[0;31m# Only need to override the gradient in graph mode and when we have outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 670\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 671\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_inference_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mctx\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[0m\u001b[1;32m 672\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 673\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_register_gradient\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args)\u001b[0m\n\u001b[1;32m 443\u001b[0m attrs=(\"executor_type\", executor_type,\n\u001b[1;32m 444\u001b[0m \"config_proto\", config),\n\u001b[0;32m--> 445\u001b[0;31m ctx=ctx)\n\u001b[0m\u001b[1;32m 446\u001b[0m \u001b[0;31m# Replace empty list with None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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: " + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "apSpY04_op7G", + "colab_type": "text" + }, + "source": [ + "# Kast Training" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Z_qa1ZZphR7b", + "colab_type": "code", + "colab": {} + }, + "source": [ + "os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + "os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "dq7R3gYehrjC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "label_dict = labels.kast_label_dict()\n", + "preproc_dict = preprocess.original_preproc_dict()\n", + "classify_dict = labels.kast_classify_dict(label_dict)\n", + "\n", + "# kast = c.Classifier(label_dict, preproc_dict, classify_dict)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Hea_JEG7hsRn", + "colab_type": "code", + "outputId": "e3570f27-de76-420c-b65d-5052676e9c78", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 309 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent = .05, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 775 samples, validate on 190 samples\n", + "Epoch 1/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 1.0628 - accuracy: 0.6137" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:17:44.021348 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 397s 513ms/sample - loss: 1.0643 - accuracy: 0.6129 - val_loss: 6.3602 - val_accuracy: 0.3105\n", + "Epoch 2/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.7081 - accuracy: 0.7636" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:24:15.517875 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 391s 505ms/sample - loss: 0.7103 - accuracy: 0.7626 - val_loss: 5.7390 - val_accuracy: 0.2737\n", + "Epoch 3/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.6472 - accuracy: 0.7894" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:30:46.915717 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 391s 505ms/sample - loss: 0.6493 - accuracy: 0.7884 - val_loss: 2.6473 - val_accuracy: 0.7474\n", + "Epoch 4/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.4367 - accuracy: 0.8592" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:37:19.759352 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 393s 507ms/sample - loss: 0.4405 - accuracy: 0.8581 - val_loss: 3.0710 - val_accuracy: 0.6053\n", + "Epoch 5/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.1889 - accuracy: 0.9432" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:43:51.642585 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 392s 506ms/sample - loss: 0.1941 - accuracy: 0.9419 - val_loss: 0.9323 - val_accuracy: 0.8579\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6lrQn4dJiIJJ", + "colab_type": "code", + "outputId": "2f82e367-d4ec-4210-aa23-10154d4bbeff", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "\n", + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\njWXvAgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "F5jRzrjpOlFq", + "colab_type": "text" + }, + "source": [ + "# train methods" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "j2gL32rpHo_h", + "colab_type": "code", + "colab": {} + }, + "source": [ + " os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + " os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"\n", + "\n", + " # might need to add subset\n", + " def _train(epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, test_model=None, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')):\n", + " \"\"\"\n", + "\n", + " Trains the classifier with given images, labels, and training parameters.\n", + "\n", + " Parameters:\n", + "\n", + " :param epochs:\n", + " Number of epochs of the training. \n", + " Must be an integer value.\n", + "\n", + " :param batch_size:\n", + " Size of the training batches formed in the process. \n", + " Must be an integer value.\n", + "\n", + " :param save_path:\n", + " Path to where the best model will be saved.\n", + "\n", + " :param train_images:\n", + " Set of images for model to train on.\n", + " Assume this is a numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param train_labels:\n", + " Set of test labels corresponding to test images.\n", + " Assume this is a rank 1 array with (batch_size, ) as its dimensions.\n", + "\n", + " :param validation_data:\n", + " Data to be used for the validation set. \n", + " Assume this is a tuple with (images, labels) with same dimensions as train_images, train_labels.\n", + " If None is specified, validation_data will be None.\n", + "\n", + " :param steps_per_epoch:\n", + " Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch.\n", + " Assume this is an integer value. If None is specified, this will be None. \n", + "\n", + " :param validation_freq:\n", + " Specifies how many training epochs to run before a new validation run is performed.\n", + " Assume this is an integer value or a collection containing the epochs at which to run validation (ie [1,2,10]).\n", + "\n", + " :param test_model:\n", + " An alternative choice for model to train on. Assume None.\n", + "\n", + " :param spit_path & param save_path:\n", + " Path to the spit images and where the model will be saved respectively.\n", + " ***Environmental variables must be set by caller or the path must be passed manually.***\n", + "\n", + " Returns:\n", + " :returns history:\n", + " Tensorflow History object containing loss and accuracy data over the training.\n", + "\n", + " \"\"\"\n", + " # choose the model\n", + " if test_model is None:\n", + " model = test_model\n", + " else:\n", + " model = test_model\n", + "\n", + " # if None is passed, then use the kast images\n", + " if train_images is None or train_labels is None:\n", + " # load training set\n", + " train = np.load(os.path.join(spit_path, 'Kast', 'kast_train.npz'))\n", + " train_images = train['images']\n", + " train_labels = train['labels']\n", + "\n", + " # load validation set\n", + " validate = np.load(os.path.join(spit_path, 'Kast', 'kast_validate.npz'))\n", + " v_images = validate['images']\n", + " v_labels = validate['labels']\n", + "\n", + " validation_data = (v_images, v_labels)\n", + "\n", + " # change to categorical and make subsets\n", + " if validation_data is not None:\n", + " valid_images, valid_labels = validation_data\n", + " if subset_percent is not None:\n", + " valid_images, valid_labels = split_array(valid_images, valid_labels, subset_percent)\n", + " valid_labels = keras.utils.to_categorical(valid_labels, num_classes=len(label_dict))\n", + " validation_data = (valid_images, valid_labels)\n", + "\n", + " if train_images is not None and train_labels is not None:\n", + " if subset_percent is not None:\n", + " train_images, train_labels = split_array(train_images, train_labels, subset_percent)\n", + " train_labels = keras.utils.to_categorical(train_labels, num_classes=len(label_dict))\n", + "\n", + " # checkpoint to track best model\n", + " checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_accuracy', save_best_only=True, mode='max')\n", + "\n", + " # train the model\n", + " history = model.fit(\n", + " train_images, \n", + " train_labels, \n", + " epochs=epochs, \n", + " batch_size=batch_size,\n", + " validation_data=validation_data,\n", + " steps_per_epoch=steps_per_epoch,\n", + " validation_freq=validation_freq,\n", + " callbacks=[checkpoint]\n", + " )\n", + " # loss and accuracy data\n", + " keys = history.history\n", + " # save to disc differently based on whether validation set was used\n", + " np.savez_compressed('history.npz', loss=keys['loss'], accuracy=keys['accuracy'], val_loss=keys['val_loss'], val_acc=keys['val_accuracy'])\n", + "\n", + " return history\n", + "\n", + " import math\n", + "\n", + " def split_array(images, labels, subset_percent):\n", + " \"\"\"\n", + " Splits dataset based on a percentage value.\n", + "\n", + " Parameters:\n", + " :param images:\n", + " Images from a dataset to be trained on.\n", + " 4-D Numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param labels:\n", + " Labels from a dataset to be trained on.\n", + " Rank 1 Numpy array with (batch_size,) as its dimensions.\n", + "\n", + " :param subset_percent:\n", + " Float value determining percentage of subset to remain.\n", + "\n", + " Returns:\n", + " :returns split_images:\n", + " Numpy array containing a fraction of the initial images parameter (batch_size*subset_percent)\n", + "\n", + " :returns split_labels:\n", + " Numpy array containing a fraction of the initial labels parameter (batch_size*subset_percent)\n", + " \"\"\"\n", + " split_images = []\n", + " split_labels = []\n", + " \n", + " # get all unique labels\n", + " uni_lbls = np.unique(labels)\n", + " \n", + " # find all instances of labels and subset based on that\n", + " for uni_lbl in uni_lbls:\n", + " idx = np.where(labels==uni_lbl)[0]\n", + " # 0 : len(idx)*subset_percent\n", + " lower = 0\n", + " upper = int(math.floor(len(idx)*subset_percent))\n", + " split_images.extend(images[idx[lower:upper]])\n", + " split_labels.extend(labels[idx[lower:upper]])\n", + " return np.asarray(split_images), np.asarray(split_labels)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "v6QIhZYLOoxN", + "colab_type": "code", + "outputId": "b64af59b-304c-4e82-8344-4d8a08f1e0a2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 309 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent = .10, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 1550 samples, validate on 385 samples\n", + "Epoch 1/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.8283 - accuracy: 0.7132" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:12:07.126094 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 804s 518ms/sample - loss: 0.8318 - accuracy: 0.7129 - val_loss: 2.4794 - val_accuracy: 0.6026\n", + "Epoch 2/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.4317 - accuracy: 0.8521" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:25:34.083913 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 807s 521ms/sample - loss: 0.4316 - accuracy: 0.8523 - val_loss: 1.0222 - val_accuracy: 0.6857\n", + "Epoch 3/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.3266 - accuracy: 0.8908" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:38:58.051750 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 804s 519ms/sample - loss: 0.3352 - accuracy: 0.8897 - val_loss: 11.9028 - val_accuracy: 0.2416\n", + "Epoch 4/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.3403 - accuracy: 0.8986" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:52:19.755737 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 802s 517ms/sample - loss: 0.3400 - accuracy: 0.8987 - val_loss: 4.3981 - val_accuracy: 0.5273\n", + "Epoch 5/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.2231 - accuracy: 0.9315" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 03:05:29.237051 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 789s 509ms/sample - loss: 0.2228 - accuracy: 0.9316 - val_loss: 0.2768 - val_accuracy: 0.8883\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "YTPoFffo1eZv", + "colab_type": "code", + "outputId": "e4aec47d-deab-4f23-ec86-0292b82d3dc1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xd4VEXbwOHfZDe990JLqFkQAoKg\n2CgiYEBERUVFARV7b8HKpyixoq/6+opKFUVFUSAURUBQUQE1IEnoAUJI7z27O98fu4kBA1kgm7Ob\nzH1duZLdPXPOkxD2ycyZeUZIKVEURVEUR+OidQCKoiiK0hiVoBRFURSHpBKUoiiK4pBUglIURVEc\nkkpQiqIoikNSCUpRFEVxSCpBKcpZEkL8TwjxbHMfqyhtnVDroJS2TgiRDtwupVyndSyKovxD9aAU\n5RSEEHqtY1CUtkolKKVNE0IsAjoCK4QQZUKIJ4QQUghxmxDiMLDeetyXQogsIUSxEGKTEKJXg3PM\nF0LMtH49RAiRIYR4VAiRI4Q4JoSYcobHBgshVgghSoQQW4UQM4UQP7XQj0ZRNKcSlNKmSSknAYeB\nsVJKH+AL60uXAgZgpPXxaqAbEAb8ASw+xWkjAH+gHXAb8J4QIvAMjn0PKLcec6v1Q1HaDJWgFKVx\nM6SU5VLKSgAp5VwpZamUshqYAcQJIfxP0rYWeEFKWSulXAWUAT1O51ghhA64BnheSlkhpUwBFjTf\nt6cojk8lKEVp3JG6L4QQOiFEohBivxCiBEi3vhRykrb5Ukpjg8cVgM9pHhsK6BvGccLXitLqqQSl\nKNDYVNaGz90IjAMuwzIcF219XtgxplzACLRv8FwHO15PURyOSlCKAtlA51O87gtUA/mAF/CyvQOS\nUpqAr4EZQggvIUQscIu9r6sojkQlKEWBWcAzQogi4NpGXl8IHAKOAinAry0U131YemxZwCLgMyyJ\nUlHaBLVQV1GchBDiFSBCSqlm8yltgupBKYqDEkLECiH6CIuBWKahL9M6LkVpKWqVvKI4Ll8sw3pR\nWO6TvQF8q2lEitKC1BCfoiiK4pDUEJ+iKIrikFrNEJ+Li4v09PTUOgxFURSHVVFRIaWUTtMxaTUJ\nytPTk/Lycq3DUBRFcVhCiEqtYzgdTpNJFUVRlLZFJShFURTFIakEpSiKogAghBglhNgthNgnhEho\n5PVOQogfhBA7hBAbhRDtGztPs8XTWqaZe3t7S3UPSlG0UVtbS0ZGBlVVVVqHogAeHh60b98eV1fX\n454XQlRIKb0ba2Pd4mUPMALIALYCE61bvdQd8yWwUkq5QAgxDJhi3VPNLlrNJAlFUbSTkZGBr68v\n0dHRCGHPIu9KU6SU5Ofnk5GRQUxMzOk0HQjsk1IeABBCLMFSxT+lwTE9gUesX28AvmmGkE9KDfEp\ninLWqqqqCA4OVsnJAQghCA4OPllvVi+E2NbgY1qD19px/J5jGdbnGkoGrrZ+PR7wFUIEN1fs/wrW\nXidWFKVtUcnJcZzi38IopRxwFqd+DHhXCDEZ2ISlwr/pLM53SipBKYqiOAEpJYUFpXi66fD0bfQ2\n0tk6yvGbYra3PtcwhkysPSghhA9wjZSyyB7BgBriUxRFcWjm2lpqc3Io2XuAoxVmcoor7HWprUA3\nIUSMEMINuAFY3vAAIUSIEKIub0wH5torGFA9KEVRFJsZjUb0evu/bUopMZeVYSoowFRaikSQ7R+B\nzgXahQfZ65pGIcR9wFpAB8yVUu4SQrwAbJNSLgeGALOEEBLLEN+9dgnGSvWgFEVpFa666ir69+9P\nr169mDNnDgBr1qzh3HPPJS4ujuHDhwNQVlbGlClT6N27N3369OGrr74CwMfHp/5cS5cuZfLkyQBM\nnjyZu+66i0GDBvHEE0/w+++/c8EFF9CvXz8GDx7M7t27ATCZTDz22GOcc8459OnTh3feeYf169dz\n1VVX1Z/3+++/Z/z48Sf9Hup6S9V79lBz6BDmykr0oaGUtoumSuhoF+SNXq9r1p9bQ1LKVVLK7lLK\nLlLKl6zPPWdNTkgpl0opu1mPuV1KadcdnlUPSlGUZpX18stUp6Y16zndDbFEPPXUKY+ZO3cuQUFB\nVFZWct555zFu3DjuuOMONm3aRExMDAUFBQC8+OKL+Pv7s3PnTgAKCwubvH5GRga//PILOp2OkpIS\nNm/ejF6vZ926dTz11FN89dVXzJkzh/T0dP766y/0ej0FBQUEBgZyzz33kJubS2hoKPPmzWPq1KnH\nnfvE3hKAi48PrhERuPj6UmU0k5NTToCXG/6ero2F12qpBKUoSqvwn//8h2XLLBsOHzlyhDlz5nDJ\nJZfUrwUKCrIMja1bt44lS5bUtwsMDGzy3BMmTECns/RciouLufXWW9m7dy9CCGpra+vPe9ddd9UP\nAdZdb9KkSXzyySdMmTKFLVu2sHDhQsDSWzIVFmIqLETW1iL0evQhoeiCAnFxc7McIyVHCivR6QRR\n/h5n/TNyNipBKYrSrJrq6djDxo0bWbduHVu2bMHLy4shQ4bQt29f0tJs78k1nJp94hoib+9/Zs09\n++yzDB06lGXLlpGens6QIUNOed4pU6YwduxYPDw8uPbaaxGVldQUFFp7S/K43pJwOf6uS05pNVW1\nJqKDvdHr2t4dmbb3HSuK0uoUFxcTGBiIl5cXaWlp/Prrr1RVVbFp0yYOHjwIUD/EN2LECN577736\ntnVDfOHh4aSmpmI2m+t7Yie7Vrt2lvWr8+fPr39+xIgRfPDBBxiNxuOuFxUVRWREBDNfeIGbhg61\n3luqQB8SjHu3brhHR6Pz9/9XcqqsMZJbUk2glxt+bWxor45KUIqiOL1Ro0ZhNBoxGAwkJCRw/vnn\nExoaypw5c7j66quJi4vj+uuvB+CZZ56hsLCQc845h7i4ODZs2ABAYmIiY8aMYfDgwURGRp70Wk88\n8QTTp0+nX79+9ckI4Pbbb6djx4706dOHuLg4Fi9ejKm0lJrDh7luyBDahYVh6NkTtw4dcO/e3dJr\ncndv9Bp1Q3t6nSCyDQ7t1VHFYhVFOWupqakYDAatw3AI/7q3pNPzyGuv0m/gQO646y6bzpFVXElO\naTXRId74eZxZ76mxf5NTFYt1ROoelKIoylmqn4lXWIipxHpvydsb14gIBg4bhre3N7Pff9+mc1XU\nGMktrSbIy+2Mk1NroRKUoijKGZK1tRgLizAVFlh7Szr0IcHoAgPrh++2b99u8/nMZsmRgkr0Ohci\nA9ru0F4dlaAURVFOg6W3VI6p0LpuSf7TW2psJt7pyC6totpoIibEG91ZnKe1UAlKURTFBrK2FmNR\nEaaCQmRtjaW3FHx8b+lslFdbh/a83fBt40N7dVSCUhRFOQkpJeby8n+qPFh7S/rwMHR+fmfVW2rI\nbJZkFFbipnMh0t+zWc7ZGqgEpSiKcoL63lJhIbLG2lsKCrZUeWiG3tKJskosQ3udQ7zRuah9teqo\nBKUoisJJekte3ujDmre3dKLyaiN5ZdUE+7jjo4b2jqMSlKIobY6Pjw9lZWUASKMRY926pfreUhC6\noCC79JYaMpklRworcNO7EOGnZu2dSCUoRVHaJFP9uqUSa2/Jy+69pRNlFJRRYzTTOdRHDe01QiUo\nRVGa1f+t2EVKZkmznrNnlB/Pj+110tcTEhLo0KED995r2T9vxowZ6PV6NmzYQGFhIbW1tcycOZMr\n4+MxFRaClNSkpzfaWyorK2PcuHHHtRs3bhwACxcu5PXXX0cIQZ8+fVi0aBHZ2dncddddHDhwAID3\n33+fqKgoxowZw99//w3A66+/TllZGTNmzKgvZLtp82aGXjGe3j1jueOt16ipqSE4OJjFixcTHh5O\nWVkZ999/P9u2bUMIwfPPP09xcTE7duzgrbfeAuDDDz8kJSWF2bNnN+vP21GoBKUoitO7/vrreeih\nh+oT1BdffMHatWt54IEH8PX1JefQIQYPGcKILl2o66e4tm/faG/Jw8ODZcuW4efnR15eHueffz5X\nXnklKSkpzJw5k19++YWQkJD6YrAPPPAAl156KcuWLcNkMlFWVtbkHlPV1dV8unIDQghCXGu59YZr\nEELw0Ucf8eqrr/LGG280um+Vq6srL730Eq+99hqurq7MmzePDz74oHl/mA5EJShFUZrVqXo69tKv\nXz9ycnLIzMwkNzeXwMBAwkNCeOi++9j8008IIcjMyiLfZKJdjx4gBPqAgEbPJaXkqaeeYtOmTbi4\nuHD06FGys7NZv349EyZMICQkBPhnv6f169fX7/Gk0+nw9/dvMkENj7+KGpOZLqE+HNiTzsSJN3Ds\n2DFqamrq96862b5Vw4YNY+XKlRgMBmpra+ndu/fZ/fAcmEpQiqK0ChMmTODLL7/k2JEjXHP55cx/\n801yjh5ly/LleISH07VvX0z+/rh4nHoywuLFi8nNzWX79u24uroSHR39r/2hmqLX6zGbzfWPG7Y3\nmSW1wo1QX3e83fXcf//9PPLII1x55ZVs3LiRGTNmnPLct99+Oy+//DKxsbFMmTLltOJyNqqWhqIo\nTk8ajVxz+eV8tmABXy1dyvihQykzm4mIicGnRw82//knhw4dsulcxcXFhIWF4erqyoYNG+rbDRs2\njC+//JL8/Hzgn/2ehg8fzvvWQrAmk4ni4mLCw8PJyckhPz+f6upqVq5caXndbKbaaMZV50K4r0f9\n9er2l1qwYEF9HCfbt2rQoEEcOXKETz/9lIkTJ57xz8wZqASlKIpTklJiKiun5sgRqnbvpntAAGXl\n5bTr0IHoiy7ilrvvZvtff9G7d28WLlxIbGysTee96aab2LZt27/a9erVi6effppLL72UuLg4Hnnk\n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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "71XvjqutG_OQ", + "colab_type": "code", + "outputId": "6e4a0509-c34d-4bb5-a141-da09c754354d", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 139 + } + }, + "source": [ + "history = _train(epochs=6, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/6\n", + "15534/15540 [============================>.] - ETA: 3s - loss: 0.2863 - accuracy: 0.9102" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 05:36:21.985853 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 8232s 530ms/sample - loss: 0.2862 - accuracy: 0.9102 - val_loss: 0.9629 - val_accuracy: 0.8585\n", + "Epoch 2/6\n", + "13482/15540 [=========================>....] - ETA: 17:26 - loss: 0.1069 - accuracy: 0.9684" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "V0NQvgNXHIXk", + "colab_type": "code", + "outputId": "dc96e509-4103-45fc-d828-3887afb40e77", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 377 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0725 08:30:08.438622 140174057060224 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.2652 - accuracy: 0.9178" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 10:45:40.559539 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 8128s 523ms/sample - loss: 0.2651 - accuracy: 0.9178 - val_loss: 0.0916 - val_accuracy: 0.9807\n", + "Epoch 2/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.1222 - accuracy: 0.9671" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 12:58:31.137780 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7971s 513ms/sample - loss: 0.1221 - accuracy: 0.9671 - val_loss: 0.0558 - val_accuracy: 0.9853\n", + "Epoch 3/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0862 - accuracy: 0.9764" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 15:08:45.694696 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7815s 503ms/sample - loss: 0.0862 - accuracy: 0.9764 - val_loss: 0.1374 - val_accuracy: 0.9796\n", + "Epoch 4/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0669 - accuracy: 0.9832" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 17:17:37.540996 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7732s 498ms/sample - loss: 0.0668 - accuracy: 0.9832 - val_loss: 0.0720 - val_accuracy: 0.9784\n", + "Epoch 5/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0647 - accuracy: 0.9835" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 19:27:23.475267 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7786s 501ms/sample - loss: 0.0647 - accuracy: 0.9835 - val_loss: 0.1236 - val_accuracy: 0.9678\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Gfuhr0qvPF_0", + "colab_type": "code", + "outputId": "2bf5f66a-9f5e-41bc-c9f4-0051429822ce", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xd4VFX6wPHvm15Jo4YAEUEyIARE\nkaKAKGsJRRAQVASkrL3/NFixZ1ddV9cKCAqKNAWBCCwdXUEB6SRSgwSkpZGQnjm/P+5NGGJChpDJ\nJJnzeZ55cufee+59J+K8OeeeIkopNE3TNK2mcXN2AJqmaZpWFp2gNE3TtBpJJyhN0zStRtIJStM0\nTauRdILSNE3TaiSdoDRN07QaSScoTSuHiHwqIi9W9bmaptlH9Dgora4SkSRgnFJqpbNj0TTt4uka\nlOaSRMTD2TFomnZhOkFpdZKIzASaA4tFJEtEnhERJSJjReQPYLV53jwROS4iGSKyXkTa2VzjCxF5\n3dzuLSLJIvKUiJwUkT9FZEwlzw0TkcUickZENonI6yLyUzX9ajSt1tAJSquTlFIjgT+A/kqpAGCu\neagXYAFuNt8vBVoDDYHfgK8vcNnGQBDQFBgLfCQiIZU49yPgrHnOKPOlaVopOkFprmaSUuqsUioH\nQCk1TSmVqZTKAyYB0SISVE7ZAuBVpVSBUuoHIAtoczHniog7cAfwslIqWym1B/iy6j6eptUdOkFp\nruZI8YaIuItInIgcEJEzQJJ5qH45ZVOUUoU277OBgIs8twHgYRtHqW1N00w6QWl1WVldVG333QUM\nBG7CaI6LNPeLA2M6BRQCETb7mjnwfppWa+kEpdVlJ4CWFzgeCOQBKYAf8KajA1JKFQHfAZNExE9E\nooB7HX1fTauNdILS6rK3gBdEJB0YUsbxGcBh4CiwB9hYTXE9jFFjOw7MBL7BSJSaptnQA3U1zclE\n5B9AY6WU7s2naTZ0DUrTqpmIRIlIBzF0weiGvsDZcWlaTaNH02ta9QvEaNYLx3hO9i7wvVMj0rQa\nSDfxaZqmaTWSbuLTNE3TaqQ608Tn5uamfH19nR2GpmlalcrOzlZKKZesTNSZBOXr68vZs2edHYam\naVqVEpEcZ8fgLC6ZlTVN07SaTycoTdM0rUbSCUrTNE2rkerMMyhN0y5OQUEBycnJ5ObmOjsUDfDx\n8SEiIgJPT09nh1Jj6ASlaS4qOTmZwMBAIiMjEXHkBO5aRZRSpKSkkJyczGWXXebscGoM3cSnaS4q\nNzeXsLAwnZxqABEhLCxM12ZL0QlK01yYTk41h/5v8Ve6iU8r08FTWeQWWGkbXs/ZoWiaQyiloHiq\nN9ufShmrWpZzrHjb2FTlHi+5h/nezd8fNy8vB36iukcnKO08Sim++fUIryzejVUp3ruzI/06hDs7\nLK2GU1Yr1uxsVJ65rJVSxnf3X77AofSXurrAseJ9qrwkYFPmoq9TzTwjInSCukg6QWklsvIKee67\nnSzafozrW9cnr8DKI99sJS27gJFdWzg7PK2GsRYUYM3MxJqVhTUrC2W1VlyouBlLBCl5LyDnHwMx\nf5y/77zz3NzONYuJIOVcp6ioEI/innHl3O+CsZjbYrNdXlxSqsx593B3r/j3UwkicgvwPuAOTFVK\nxZU63gKYBjQAUoF7lFLJ5rF/AjEYj3tWAI8ppZSIrAWaAMWzWPxNKXVSRLwxFvrsjLES9Z1KqSSH\nfDB0gtJMe46d4aFZv3E45Sz/d3MbHuh1OflFVh6etZUXF+4iJSuPx25srdvJXZhSCpWTQ1FmJtbM\nLKy5xneXeHriFhSMe2AA4ut7XtI47wu6jH87t99+O0eOHCE3N5fHHnuMCRMmsGzZMp577jmKioqo\nX78+q1atIisri0ceeYTNmzcjIrz88svccccdBAQEkJWVBcD8+fNZsmQJX3zxBaNHj8bHx4etW7fS\no0cPhg8fzmOPPUZubi6+vr5Mnz6dNm3aUFRUxLPPPsuyZctwc3Nj/PjxtGvXjg8++ICFCxcCsGLF\nCj7++GMWLKh5S3aJiDvwEdAXSAY2icgipdQem9PeAWYopb4UkT4YK02PFJHuQA+gg3neT0AvYK35\n/m6l1OZStxwLpCmlWonIcOAfwJ0O+GiATlAuTynFrF//4JXFewjx8+Sb8V25tmUYAD5u7nx6z1VM\n/G4n/165j5SsfCYNaIe7m05Sdc3xN98kLyHxL/sVCoqKUIVFxk+zaUzc3cHd3fjp5kZZ/yK8LVE0\nfu65C9532rRphIaGkpOTwzXXXMPAgQMZP34869ev57LLLiM1NRWA1157jaCgIHbu3AlAWlpahZ8p\nOTmZn3/+GXd3d86cOcOPP/6Ih4cHK1eu5LnnnuPbb79l8uTJJCUlsW3bNjw8PEhNTSUkJIQHH3yQ\n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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "TpiQ3SJOmnce", + "colab_type": "code", + "colab": {} + }, + "source": [ + "from tensorflow import keras\n", + "# need to add compression to either block, transition, or both to get it to be BC\n", + "\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(filters, kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "theta = .5\n", + "growth_rate = 4\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))\n", + "\n", + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HAZYaS86LHF6", + "colab_type": "code", + "outputId": "351d4e6e-265f-4843-d8f4-c9b7f61d650f", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + } + }, + "source": [ + "model.summary()" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Model: \"sequential\"\n", + "_________________________________________________________________\n", + "Layer (type) Output Shape Param # \n", + "=================================================================\n", + "conv2d (Conv2D) (None, 102, 322, 64) 3200 \n", + "_________________________________________________________________\n", + "max_pooling2d (MaxPooling2D) (None, 50, 160, 64) 0 \n", + "_________________________________________________________________\n", + "batch_normalization (BatchNo (None, 50, 160, 64) 256 \n", + "_________________________________________________________________\n", + "re_lu (ReLU) (None, 50, 160, 64) 0 \n", + "_________________________________________________________________\n", + "conv2d_1 (Conv2D) (None, 50, 160, 256) 16640 \n", + "_________________________________________________________________\n", + "dropout (Dropout) (None, 50, 160, 256) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_1 (Batch (None, 50, 160, 256) 1024 \n", + "_________________________________________________________________\n", + "re_lu_1 (ReLU) (None, 50, 160, 256) 0 \n", + "_________________________________________________________________\n", + "conv2d_2 (Conv2D) (None, 48, 158, 64) 147520 \n", + "_________________________________________________________________\n", + "dropout_1 (Dropout) (None, 48, 158, 64) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_2 (Batch (None, 48, 158, 64) 256 \n", + "_________________________________________________________________\n", + "re_lu_2 (ReLU) (None, 48, 158, 64) 0 \n", + "_________________________________________________________________\n", + "conv2d_3 (Conv2D) (None, 48, 158, 64) 4160 \n", + "_________________________________________________________________\n", + "dropout_2 (Dropout) (None, 48, 158, 64) 0 \n", + "_________________________________________________________________\n", + "average_pooling2d (AveragePo (None, 24, 79, 64) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_3 (Batch (None, 24, 79, 64) 256 \n", + "_________________________________________________________________\n", + "re_lu_3 (ReLU) (None, 24, 79, 64) 0 \n", + "_________________________________________________________________\n", + "conv2d_4 (Conv2D) (None, 24, 79, 256) 16640 \n", + "_________________________________________________________________\n", + "dropout_3 (Dropout) (None, 24, 79, 256) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_4 (Batch (None, 24, 79, 256) 1024 \n", + "_________________________________________________________________\n", + "re_lu_4 (ReLU) (None, 24, 79, 256) 0 \n", + "_________________________________________________________________\n", + "conv2d_5 (Conv2D) (None, 22, 77, 64) 147520 \n", + "_________________________________________________________________\n", + "dropout_4 (Dropout) (None, 22, 77, 64) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_5 (Batch (None, 22, 77, 64) 256 \n", + "_________________________________________________________________\n", + "re_lu_5 (ReLU) (None, 22, 77, 64) 0 \n", + "_________________________________________________________________\n", + "conv2d_6 (Conv2D) (None, 22, 77, 64) 4160 \n", + "_________________________________________________________________\n", + "dropout_5 (Dropout) (None, 22, 77, 64) 0 \n", + "_________________________________________________________________\n", + "average_pooling2d_1 (Average (None, 11, 38, 64) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_6 (Batch (None, 11, 38, 64) 256 \n", + "_________________________________________________________________\n", + "re_lu_6 (ReLU) (None, 11, 38, 64) 0 \n", + "_________________________________________________________________\n", + "conv2d_7 (Conv2D) (None, 11, 38, 256) 16640 \n", + "_________________________________________________________________\n", + "dropout_6 (Dropout) (None, 11, 38, 256) 0 \n", + "_________________________________________________________________\n", + "batch_normalization_7 (Batch (None, 11, 38, 256) 1024 \n", + "_________________________________________________________________\n", + "re_lu_7 (ReLU) (None, 11, 38, 256) 0 \n", + "_________________________________________________________________\n", + "conv2d_8 (Conv2D) (None, 9, 36, 64) 147520 \n", + "_________________________________________________________________\n", + "dropout_7 (Dropout) (None, 9, 36, 64) 0 \n", + "_________________________________________________________________\n", + "global_average_pooling2d (Gl (None, 64) 0 \n", + "_________________________________________________________________\n", + "flatten (Flatten) (None, 64) 0 \n", + "_________________________________________________________________\n", + "dense (Dense) (None, 5) 325 \n", + "=================================================================\n", + "Total params: 508,677\n", + "Trainable params: 506,501\n", + "Non-trainable params: 2,176\n", + "_________________________________________________________________\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "uLtlGV2pLPXU", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/docs/nb/DenseNetV1_2_.ipynb b/docs/nb/DenseNetV1_2_.ipynb new file mode 100644 index 0000000..a78c7c1 --- /dev/null +++ b/docs/nb/DenseNetV1_2_.ipynb @@ -0,0 +1,2169 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "DenseNetV1.2_.ipynb", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [ + "U74NGbY4508Z", + "08Eytj_3oYDI", + "2dnGV0FHocqH", + "Dvhr1SS2ojnf", + "apSpY04_op7G" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "U74NGbY4508Z", + "colab_type": "text" + }, + "source": [ + "# Import Tensorflow" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "rzmyPhhhvIRu", + "colab_type": "code", + "outputId": "b8122dde-165b-4df3-a13a-e451040c0d87", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 564 + } + }, + "source": [ + "!pip install tensorflow==2.0.0b1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Collecting tensorflow==2.0.0b1\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/29/6c/2c9a5c4d095c63c2fb37d20def0e4f92685f7aee9243d6aae25862694fd1/tensorflow-2.0.0b1-cp36-cp36m-manylinux1_x86_64.whl (87.9MB)\n", + "\u001b[K |████████████████████████████████| 87.9MB 1.3MB/s \n", + "\u001b[?25hRequirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.1.7)\n", + "Collecting tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 (from tensorflow==2.0.0b1)\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/32/dd/99c47dd007dcf10d63fd895611b063732646f23059c618a373e85019eb0e/tf_estimator_nightly-1.14.0.dev2019060501-py2.py3-none-any.whl (496kB)\n", + "\u001b[K |████████████████████████████████| 501kB 45.2MB/s \n", + "\u001b[?25hRequirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.7.1)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (3.7.1)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.8.0)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.2.2)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.16.4)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.12.0)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.15.0)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.33.4)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.11.2)\n", + "Collecting tb-nightly<1.14.0a20190604,>=1.14.0a20190603 (from tensorflow==2.0.0b1)\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/a4/96/571b875cd81dda9d5dfa1422a4f9d749e67c0a8d4f4f0b33a4e5f5f35e27/tb_nightly-1.14.0a20190603-py3-none-any.whl (3.1MB)\n", + "\u001b[K |████████████████████████████████| 3.1MB 36.6MB/s \n", + "\u001b[?25hRequirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.0.8)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.6.1->tensorflow==2.0.0b1) (41.0.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (0.15.5)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (3.1.1)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow==2.0.0b1) (2.8.0)\n", + "Installing collected packages: tf-estimator-nightly, tb-nightly, tensorflow\n", + " Found existing installation: tensorflow 1.14.0\n", + " Uninstalling tensorflow-1.14.0:\n", + " Successfully uninstalled tensorflow-1.14.0\n", + "Successfully installed tb-nightly-1.14.0a20190603 tensorflow-2.0.0b1 tf-estimator-nightly-1.14.0.dev2019060501\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1PMs0uCzygrQ", + "colab_type": "code", + "outputId": "1a972536-4a91-4c56-ec33-d9fa66e47611", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 445 + } + }, + "source": [ + "!pip install tensorflow-gpu==2.0.0-beta1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Collecting tensorflow-gpu==2.0.0-beta1\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/2b/53/e18c5e7a2263d3581a979645a185804782e59b8e13f42b9c3c3cfb5bb503/tensorflow_gpu-2.0.0b1-cp36-cp36m-manylinux1_x86_64.whl (348.9MB)\n", + "\u001b[K |████████████████████████████████| 348.9MB 45kB/s \n", + "\u001b[?25hRequirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.2.2)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.15.0)\n", + "Requirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.16.4)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.1.0)\n", + "Requirement already satisfied: tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.14.0.dev2019060501)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.11.2)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.1.0)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.33.4)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.12.0)\n", + "Requirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.1.7)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (3.7.1)\n", + "Requirement already satisfied: tb-nightly<1.14.0a20190604,>=1.14.0a20190603 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.14.0a20190603)\n", + "Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.7.1)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.0.8)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.8.0)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.6.1->tensorflow-gpu==2.0.0-beta1) (41.0.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow-gpu==2.0.0-beta1) (0.15.5)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow-gpu==2.0.0-beta1) (3.1.1)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow-gpu==2.0.0-beta1) (2.8.0)\n", + "Installing collected packages: tensorflow-gpu\n", + "Successfully installed tensorflow-gpu-2.0.0b1\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "08Eytj_3oYDI", + "colab_type": "text" + }, + "source": [ + "# SPIT Imports" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FIMdpjQ-f-nx", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "import numpy as np\n", + "import os\n", + "\n", + "from importlib import reload\n", + "from pkg_resources import resource_filename\n", + "from google.colab import drive\n", + "import imageio" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "EkgCyHlig-fl", + "colab_type": "code", + "outputId": "7cf90ef4-f15b-4fb6-e477-2edb7b763495", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "import tensorflow\n", + "tensorflow.__version__" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'2.0.0-beta1'" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 5 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "LqfsN-WdhAcm", + "colab_type": "code", + "outputId": "7f826b72-e7cd-4891-aee7-6aa042cfaf67", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 122 + } + }, + "source": [ + "drive.mount('/content/drive/')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdocs.test%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.photos.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fpeopleapi.readonly&response_type=code\n", + "\n", + "Enter your authorization code:\n", + "··········\n", + "Mounted at /content/drive/\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "znIJK2HDhBsO", + "colab_type": "code", + "outputId": "61c0d8c3-37c8-42ef-94c2-952c80da7f84", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136 + } + }, + "source": [ + "!git clone https://github.com/pypeit/spit.git" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Cloning into 'spit'...\n", + "remote: Enumerating objects: 166, done.\u001b[K\n", + "remote: Counting objects: 100% (166/166), done.\u001b[K\n", + "remote: Compressing objects: 100% (126/126), done.\u001b[K\n", + "remote: Total 850 (delta 111), reused 65 (delta 40), pack-reused 684\u001b[K\n", + "Receiving objects: 100% (850/850), 932.20 KiB | 13.91 MiB/s, done.\n", + "Resolving deltas: 100% (486/486), done.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "N1kzH-dghJlh", + "colab_type": "code", + "outputId": "24a6bafe-8a1b-453a-8aeb-378de5f783ed", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "%cd spit" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/content/spit\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "UCXppiJ_hLtu", + "colab_type": "code", + "outputId": "fb18cb04-a27d-4c41-ef0a-49924d0d4ef1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "!git checkout new_models" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Branch 'new_models' set up to track remote branch 'new_models' from 'origin'.\n", + "Switched to a new branch 'new_models'\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "gFBV0bnthNV8", + "colab_type": "code", + "outputId": "0387fd17-15b2-4755-f677-01a5c531077c", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!git pull" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Already up to date.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "sI3uoAU0hOwc", + "colab_type": "code", + "outputId": "7608ba3d-e98f-459c-8adb-c15793a998e1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 323 + } + }, + "source": [ + "!python setup.py develop" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "running develop\n", + "running egg_info\n", + "creating spit.egg-info\n", + "writing spit.egg-info/PKG-INFO\n", + "writing dependency_links to spit.egg-info/dependency_links.txt\n", + "writing top-level names to spit.egg-info/top_level.txt\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "running build_ext\n", + "Creating /usr/local/lib/python3.6/dist-packages/spit.egg-link (link to .)\n", + "Adding spit 0.1.dev0 to easy-install.pth file\n", + "Installing spit_png script to /usr/local/bin\n", + "Installing spit_classify_image script to /usr/local/bin\n", + "Installing spit_train script to /usr/local/bin\n", + "\n", + "Installed /content/spit\n", + "Processing dependencies for spit==0.1.dev0\n", + "Finished processing dependencies for spit==0.1.dev0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "p1o27AbvhP7c", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "from importlib import reload\n", + "\n", + "from spit import image_loader\n", + "from spit import labels\n", + "from spit import preprocess\n", + "from spit import classifier as c\n", + "from spit import utils" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2dnGV0FHocqH", + "colab_type": "text" + }, + "source": [ + "# Build DenseNet" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6UK-KubhvJ4E", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import tensorflow as tf\n", + "from tensorflow import keras" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Vg-eHZ3gfURL", + "colab_type": "code", + "outputId": "6f137ab0-0086-4424-a8ce-5818690a8f64", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "source": [ + "print(tf.test.is_gpu_available())\n", + "device_name = tf.test.gpu_device_name()\n", + "if device_name != '/device:GPU:0':\n", + " raise SystemError('GPU device not found')\n", + "print('Found GPU at: {}'.format(device_name))" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "True\n", + "Found GPU at: /device:GPU:0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "veTuJQk36S0Z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import math\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(math.floor(compression_factor*filters), kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return\n", + " " + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HozlILKAvVCE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "growth_rate = 4\n", + "compression_factor = .5\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "## TORCH IMPLEMENTATION ##\n", + "model.add(keras.layers.BatchNormalization())\n", + "model.add(keras.layers.ReLU())\n", + "## TORCH IMPLEMENTATION ##\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "\n", + "## TORCH IMPLEMENTATION ##\n", + "model.add(keras.layers.BatchNormalization())\n", + "model.add(keras.layers.ReLU())\n", + "## TORCH IMPLEMENTATION ##\n", + "\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "mwc1bmdCfmDT", + "colab_type": "code", + "colab": {} + }, + "source": [ + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])\n" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Dvhr1SS2ojnf", + "colab_type": "text" + }, + "source": [ + "# Fake Data" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1UOxTk6beV3M", + "colab_type": "code", + "colab": {} + }, + "source": [ + "x_train = np.random.random((100, 210, 650, 1))\n", + "train_labels = np.random.randint(5, size=(100, 1))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "3YbIjCS-fhEQ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "y_train = keras.utils.to_categorical(train_labels, num_classes=5)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zquoTIHjfild", + "colab_type": "code", + "outputId": "dfc5cff3-0d06-4cd2-e41d-84eafb485e80", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 429 + } + }, + "source": [ + " model.fit(\n", + " x_train, \n", + " y_train, \n", + " epochs=5, \n", + " batch_size=6 \n", + " )" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 100 samples\n", + "Epoch 1/5\n", + " 12/100 [==>...........................] - ETA: 2:54 - loss: 2.8118 - accuracy: 0.2500" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0my_train\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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 641\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 642\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--> 643\u001b[0;31m use_multiprocessing=use_multiprocessing)\n\u001b[0m\u001b[1;32m 644\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 645\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.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, **kwargs)\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mvalidation_steps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_steps\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 663\u001b[0m \u001b[0mvalidation_freq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_freq\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 664\u001b[0;31m steps_name='steps_per_epoch')\n\u001b[0m\u001b[1;32m 665\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 666\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.py\u001b[0m in \u001b[0;36mmodel_iteration\u001b[0;34m(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)\u001b[0m\n\u001b[1;32m 381\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 382\u001b[0m \u001b[0;31m# Get outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 383\u001b[0;31m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mins_batch\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 384\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\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 385\u001b[0m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 3508\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath_ops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3509\u001b[0m \u001b[0mconverted_inputs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3510\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mconverted_inputs\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 3511\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3512\u001b[0m \u001b[0;31m# EagerTensor.numpy() will often make a copy to ensure memory safety.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 570\u001b[0m raise TypeError(\"Keyword arguments {} unknown. Expected {}.\".format(\n\u001b[1;32m 571\u001b[0m list(kwargs.keys()), list(self._arg_keywords)))\n\u001b[0;32m--> 572\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call_flat\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[0m\u001b[1;32m 573\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_filtered_call\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[0mkwargs\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[0;31m# Only need to override the gradient in graph mode and when we have outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 670\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 671\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_inference_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mctx\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[0m\u001b[1;32m 672\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 673\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_register_gradient\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args)\u001b[0m\n\u001b[1;32m 443\u001b[0m attrs=(\"executor_type\", executor_type,\n\u001b[1;32m 444\u001b[0m \"config_proto\", config),\n\u001b[0;32m--> 445\u001b[0;31m ctx=ctx)\n\u001b[0m\u001b[1;32m 446\u001b[0m \u001b[0;31m# Replace empty list with None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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: " + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "apSpY04_op7G", + "colab_type": "text" + }, + "source": [ + "# Kast Training" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Z_qa1ZZphR7b", + "colab_type": "code", + "colab": {} + }, + "source": [ + "os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + "os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "dq7R3gYehrjC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "label_dict = labels.kast_label_dict()\n", + "preproc_dict = preprocess.original_preproc_dict()\n", + "classify_dict = labels.kast_classify_dict(label_dict)\n", + "\n", + "# kast = c.Classifier(label_dict, preproc_dict, classify_dict)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Hea_JEG7hsRn", + "colab_type": "code", + "outputId": "e3570f27-de76-420c-b65d-5052676e9c78", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 309 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent = .05, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 775 samples, validate on 190 samples\n", + "Epoch 1/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 1.0628 - accuracy: 0.6137" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:17:44.021348 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 397s 513ms/sample - loss: 1.0643 - accuracy: 0.6129 - val_loss: 6.3602 - val_accuracy: 0.3105\n", + "Epoch 2/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.7081 - accuracy: 0.7636" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:24:15.517875 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 391s 505ms/sample - loss: 0.7103 - accuracy: 0.7626 - val_loss: 5.7390 - val_accuracy: 0.2737\n", + "Epoch 3/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.6472 - accuracy: 0.7894" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:30:46.915717 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 391s 505ms/sample - loss: 0.6493 - accuracy: 0.7884 - val_loss: 2.6473 - val_accuracy: 0.7474\n", + "Epoch 4/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.4367 - accuracy: 0.8592" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:37:19.759352 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 393s 507ms/sample - loss: 0.4405 - accuracy: 0.8581 - val_loss: 3.0710 - val_accuracy: 0.6053\n", + "Epoch 5/5\n", + "774/775 [============================>.] - ETA: 0s - loss: 0.1889 - accuracy: 0.9432" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 01:43:51.642585 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r775/775 [==============================] - 392s 506ms/sample - loss: 0.1941 - accuracy: 0.9419 - val_loss: 0.9323 - val_accuracy: 0.8579\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6lrQn4dJiIJJ", + "colab_type": "code", + "outputId": "2f82e367-d4ec-4210-aa23-10154d4bbeff", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "\n", + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\njWXvAgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "F5jRzrjpOlFq", + "colab_type": "text" + }, + "source": [ + "# train methods" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "j2gL32rpHo_h", + "colab_type": "code", + "colab": {} + }, + "source": [ + " os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + " os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"\n", + "\n", + " # might need to add subset\n", + " def _train(epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, test_model=None, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')):\n", + " \"\"\"\n", + "\n", + " Trains the classifier with given images, labels, and training parameters.\n", + "\n", + " Parameters:\n", + "\n", + " :param epochs:\n", + " Number of epochs of the training. \n", + " Must be an integer value.\n", + "\n", + " :param batch_size:\n", + " Size of the training batches formed in the process. \n", + " Must be an integer value.\n", + "\n", + " :param save_path:\n", + " Path to where the best model will be saved.\n", + "\n", + " :param train_images:\n", + " Set of images for model to train on.\n", + " Assume this is a numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param train_labels:\n", + " Set of test labels corresponding to test images.\n", + " Assume this is a rank 1 array with (batch_size, ) as its dimensions.\n", + "\n", + " :param validation_data:\n", + " Data to be used for the validation set. \n", + " Assume this is a tuple with (images, labels) with same dimensions as train_images, train_labels.\n", + " If None is specified, validation_data will be None.\n", + "\n", + " :param steps_per_epoch:\n", + " Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch.\n", + " Assume this is an integer value. If None is specified, this will be None. \n", + "\n", + " :param validation_freq:\n", + " Specifies how many training epochs to run before a new validation run is performed.\n", + " Assume this is an integer value or a collection containing the epochs at which to run validation (ie [1,2,10]).\n", + "\n", + " :param test_model:\n", + " An alternative choice for model to train on. Assume None.\n", + "\n", + " :param spit_path & param save_path:\n", + " Path to the spit images and where the model will be saved respectively.\n", + " ***Environmental variables must be set by caller or the path must be passed manually.***\n", + "\n", + " Returns:\n", + " :returns history:\n", + " Tensorflow History object containing loss and accuracy data over the training.\n", + "\n", + " \"\"\"\n", + " # choose the model\n", + " if test_model is None:\n", + " model = test_model\n", + " else:\n", + " model = test_model\n", + "\n", + " # if None is passed, then use the kast images\n", + " if train_images is None or train_labels is None:\n", + " # load training set\n", + " train = np.load(os.path.join(spit_path, 'Kast', 'kast_train.npz'))\n", + " train_images = train['images']\n", + " train_labels = train['labels']\n", + "\n", + " # load validation set\n", + " validate = np.load(os.path.join(spit_path, 'Kast', 'kast_validate.npz'))\n", + " v_images = validate['images']\n", + " v_labels = validate['labels']\n", + "\n", + " validation_data = (v_images, v_labels)\n", + "\n", + " # change to categorical and make subsets\n", + " if validation_data is not None:\n", + " valid_images, valid_labels = validation_data\n", + " if subset_percent is not None:\n", + " valid_images, valid_labels = split_array(valid_images, valid_labels, subset_percent)\n", + " valid_labels = keras.utils.to_categorical(valid_labels, num_classes=len(label_dict))\n", + " validation_data = (valid_images, valid_labels)\n", + "\n", + " if train_images is not None and train_labels is not None:\n", + " if subset_percent is not None:\n", + " train_images, train_labels = split_array(train_images, train_labels, subset_percent)\n", + " train_labels = keras.utils.to_categorical(train_labels, num_classes=len(label_dict))\n", + "\n", + " # checkpoint to track best model\n", + " checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_accuracy', save_best_only=True, mode='max')\n", + "\n", + " # train the model\n", + " history = model.fit(\n", + " train_images, \n", + " train_labels, \n", + " epochs=epochs, \n", + " batch_size=batch_size,\n", + " validation_data=validation_data,\n", + " steps_per_epoch=steps_per_epoch,\n", + " validation_freq=validation_freq,\n", + " callbacks=[checkpoint]\n", + " )\n", + " # loss and accuracy data\n", + " keys = history.history\n", + " # save to disc differently based on whether validation set was used\n", + "# if len(history.history.keys()) == 2: # can we abstract this away?\n", + "# np.savez_compressed('history.npz', loss=keys['loss'], acc=keys['acc']) #can these keys be abstracted away?\n", + "# else:\n", + "# np.savez_compressed('history.npz', loss=keys['loss'], acc=keys['acc'], val_loss=keys['val_loss'], val_acc=keys['val_acc'])\n", + "\n", + " return history\n", + "\n", + " import math\n", + "\n", + " def split_array(images, labels, subset_percent):\n", + " \"\"\"\n", + " Splits dataset based on a percentage value.\n", + "\n", + " Parameters:\n", + " :param images:\n", + " Images from a dataset to be trained on.\n", + " 4-D Numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param labels:\n", + " Labels from a dataset to be trained on.\n", + " Rank 1 Numpy array with (batch_size,) as its dimensions.\n", + "\n", + " :param subset_percent:\n", + " Float value determining percentage of subset to remain.\n", + "\n", + " Returns:\n", + " :returns split_images:\n", + " Numpy array containing a fraction of the initial images parameter (batch_size*subset_percent)\n", + "\n", + " :returns split_labels:\n", + " Numpy array containing a fraction of the initial labels parameter (batch_size*subset_percent)\n", + " \"\"\"\n", + " split_images = []\n", + " split_labels = []\n", + " \n", + " # get all unique labels\n", + " uni_lbls = np.unique(labels)\n", + " \n", + " # find all instances of labels and subset based on that\n", + " for uni_lbl in uni_lbls:\n", + " idx = np.where(labels==uni_lbl)[0]\n", + " # 0 : len(idx)*subset_percent\n", + " lower = 0\n", + " upper = int(math.floor(len(idx)*subset_percent))\n", + " split_images.extend(images[idx[lower:upper]])\n", + " split_labels.extend(labels[idx[lower:upper]])\n", + " return np.asarray(split_images), np.asarray(split_labels)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "CcL6lUUUTu9v", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def load_model(file_name, file_path):\n", + " '''\n", + " :param file_name: The model name. Should be a string 'blah.h5'\n", + " file_path: The path that the user would like to save to.\n", + " In the form of 'blah/foo/bar/'\n", + " :return: the model loaded\n", + " '''\n", + "\n", + " loaded_model = keras.models.load_model(file_path+file_name)\n", + " return loaded_model" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "v6QIhZYLOoxN", + "colab_type": "code", + "outputId": "b64af59b-304c-4e82-8344-4d8a08f1e0a2", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 309 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent = .10, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 1550 samples, validate on 385 samples\n", + "Epoch 1/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.8283 - accuracy: 0.7132" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:12:07.126094 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 804s 518ms/sample - loss: 0.8318 - accuracy: 0.7129 - val_loss: 2.4794 - val_accuracy: 0.6026\n", + "Epoch 2/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.4317 - accuracy: 0.8521" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:25:34.083913 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 807s 521ms/sample - loss: 0.4316 - accuracy: 0.8523 - val_loss: 1.0222 - val_accuracy: 0.6857\n", + "Epoch 3/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.3266 - accuracy: 0.8908" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:38:58.051750 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 804s 519ms/sample - loss: 0.3352 - accuracy: 0.8897 - val_loss: 11.9028 - val_accuracy: 0.2416\n", + "Epoch 4/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.3403 - accuracy: 0.8986" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 02:52:19.755737 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 802s 517ms/sample - loss: 0.3400 - accuracy: 0.8987 - val_loss: 4.3981 - val_accuracy: 0.5273\n", + "Epoch 5/5\n", + "1548/1550 [============================>.] - ETA: 0s - loss: 0.2231 - accuracy: 0.9315" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 03:05:29.237051 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r1550/1550 [==============================] - 789s 509ms/sample - loss: 0.2228 - accuracy: 0.9316 - val_loss: 0.2768 - val_accuracy: 0.8883\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "YTPoFffo1eZv", + "colab_type": "code", + "outputId": "e4aec47d-deab-4f23-ec86-0292b82d3dc1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xd4VEXbwOHfZDe990JLqFkQAoKg\n2CgiYEBERUVFARV7b8HKpyixoq/6+opKFUVFUSAURUBQUQE1IEnoAUJI7z27O98fu4kBA1kgm7Ob\nzH1duZLdPXPOkxD2ycyZeUZIKVEURVEUR+OidQCKoiiK0hiVoBRFURSHpBKUoiiK4pBUglIURVEc\nkkpQiqIoikNSCUpRFEVxSCpBKcpZEkL8TwjxbHMfqyhtnVDroJS2TgiRDtwupVyndSyKovxD9aAU\n5RSEEHqtY1CUtkolKKVNE0IsAjoCK4QQZUKIJ4QQUghxmxDiMLDeetyXQogsIUSxEGKTEKJXg3PM\nF0LMtH49RAiRIYR4VAiRI4Q4JoSYcobHBgshVgghSoQQW4UQM4UQP7XQj0ZRNKcSlNKmSSknAYeB\nsVJKH+AL60uXAgZgpPXxaqAbEAb8ASw+xWkjAH+gHXAb8J4QIvAMjn0PKLcec6v1Q1HaDJWgFKVx\nM6SU5VLKSgAp5VwpZamUshqYAcQJIfxP0rYWeEFKWSulXAWUAT1O51ghhA64BnheSlkhpUwBFjTf\nt6cojk8lKEVp3JG6L4QQOiFEohBivxCiBEi3vhRykrb5Ukpjg8cVgM9pHhsK6BvGccLXitLqqQSl\nKNDYVNaGz90IjAMuwzIcF219XtgxplzACLRv8FwHO15PURyOSlCKAtlA51O87gtUA/mAF/CyvQOS\nUpqAr4EZQggvIUQscIu9r6sojkQlKEWBWcAzQogi4NpGXl8IHAKOAinAry0U131YemxZwCLgMyyJ\nUlHaBLVQV1GchBDiFSBCSqlm8yltgupBKYqDEkLECiH6CIuBWKahL9M6LkVpKWqVvKI4Ll8sw3pR\nWO6TvQF8q2lEitKC1BCfoiiK4pDUEJ+iKIrikFrNEJ+Li4v09PTUOgxFURSHVVFRIaWUTtMxaTUJ\nytPTk/Lycq3DUBRFcVhCiEqtYzgdTpNJFUVRlLZFJShFURTFIakEpSiKogAghBglhNgthNgnhEho\n5PVOQogfhBA7hBAbhRDtGztPs8XTWqaZe3t7S3UPSlG0UVtbS0ZGBlVVVVqHogAeHh60b98eV1fX\n454XQlRIKb0ba2Pd4mUPMALIALYCE61bvdQd8yWwUkq5QAgxDJhi3VPNLlrNJAlFUbSTkZGBr68v\n0dHRCGHPIu9KU6SU5Ofnk5GRQUxMzOk0HQjsk1IeABBCLMFSxT+lwTE9gUesX28AvmmGkE9KDfEp\ninLWqqqqCA4OVsnJAQghCA4OPllvVi+E2NbgY1qD19px/J5jGdbnGkoGrrZ+PR7wFUIEN1fs/wrW\nXidWFKVtUcnJcZzi38IopRxwFqd+DHhXCDEZ2ISlwr/pLM53SipBKYqiOAEpJYUFpXi66fD0bfQ2\n0tk6yvGbYra3PtcwhkysPSghhA9wjZSyyB7BgBriUxRFcWjm2lpqc3Io2XuAoxVmcoor7HWprUA3\nIUSMEMINuAFY3vAAIUSIEKIub0wH5torGFA9KEVRFJsZjUb0evu/bUopMZeVYSoowFRaikSQ7R+B\nzgXahQfZ65pGIcR9wFpAB8yVUu4SQrwAbJNSLgeGALOEEBLLEN+9dgnGSvWgFEVpFa666ir69+9P\nr169mDNnDgBr1qzh3HPPJS4ujuHDhwNQVlbGlClT6N27N3369OGrr74CwMfHp/5cS5cuZfLkyQBM\nnjyZu+66i0GDBvHEE0/w+++/c8EFF9CvXz8GDx7M7t27ATCZTDz22GOcc8459OnTh3feeYf169dz\n1VVX1Z/3+++/Z/z48Sf9Hup6S9V79lBz6BDmykr0oaGUtoumSuhoF+SNXq9r1p9bQ1LKVVLK7lLK\nLlLKl6zPPWdNTkgpl0opu1mPuV1KadcdnlUPSlGUZpX18stUp6Y16zndDbFEPPXUKY+ZO3cuQUFB\nVFZWct555zFu3DjuuOMONm3aRExMDAUFBQC8+OKL+Pv7s3PnTgAKCwubvH5GRga//PILOp2OkpIS\nNm/ejF6vZ926dTz11FN89dVXzJkzh/T0dP766y/0ej0FBQUEBgZyzz33kJubS2hoKPPmzWPq1KnH\nnfvE3hKAi48PrhERuPj6UmU0k5NTToCXG/6ero2F12qpBKUoSqvwn//8h2XLLBsOHzlyhDlz5nDJ\nJZfUrwUKCrIMja1bt44lS5bUtwsMDGzy3BMmTECns/RciouLufXWW9m7dy9CCGpra+vPe9ddd9UP\nAdZdb9KkSXzyySdMmTKFLVu2sHDhQsDSWzIVFmIqLETW1iL0evQhoeiCAnFxc7McIyVHCivR6QRR\n/h5n/TNyNipBKYrSrJrq6djDxo0bWbduHVu2bMHLy4shQ4bQt29f0tJs78k1nJp94hoib+9/Zs09\n++yzDB06lGXLlpGens6QIUNOed4pU6YwduxYPDw8uPbaaxGVldQUFFp7S/K43pJwOf6uS05pNVW1\nJqKDvdHr2t4dmbb3HSuK0uoUFxcTGBiIl5cXaWlp/Prrr1RVVbFp0yYOHjwIUD/EN2LECN577736\ntnVDfOHh4aSmpmI2m+t7Yie7Vrt2lvWr8+fPr39+xIgRfPDBBxiNxuOuFxUVRWREBDNfeIGbhg61\n3luqQB8SjHu3brhHR6Pz9/9XcqqsMZJbUk2glxt+bWxor45KUIqiOL1Ro0ZhNBoxGAwkJCRw/vnn\nExoaypw5c7j66quJi4vj+uuvB+CZZ56hsLCQc845h7i4ODZs2ABAYmIiY8aMYfDgwURGRp70Wk88\n8QTTp0+nX79+9ckI4Pbbb6djx4706dOHuLg4Fi9ejKm0lJrDh7luyBDahYVh6NkTtw4dcO/e3dJr\ncndv9Bp1Q3t6nSCyDQ7t1VHFYhVFOWupqakYDAatw3AI/7q3pNPzyGuv0m/gQO646y6bzpFVXElO\naTXRId74eZxZ76mxf5NTFYt1ROoelKIoylmqn4lXWIipxHpvydsb14gIBg4bhre3N7Pff9+mc1XU\nGMktrSbIy+2Mk1NroRKUoijKGZK1tRgLizAVFlh7Szr0IcHoAgPrh++2b99u8/nMZsmRgkr0Ohci\nA9ru0F4dlaAURVFOg6W3VI6p0LpuSf7TW2psJt7pyC6totpoIibEG91ZnKe1UAlKURTFBrK2FmNR\nEaaCQmRtjaW3FHx8b+lslFdbh/a83fBt40N7dVSCUhRFOQkpJeby8n+qPFh7S/rwMHR+fmfVW2rI\nbJZkFFbipnMh0t+zWc7ZGqgEpSiKcoL63lJhIbLG2lsKCrZUeWiG3tKJskosQ3udQ7zRuah9teqo\nBKUoisJJekte3ujDmre3dKLyaiN5ZdUE+7jjo4b2jqMSlKIobY6Pjw9lZWUASKMRY926pfreUhC6\noCC79JYaMpklRworcNO7EOGnZu2dSCUoRVHaJFP9uqUSa2/Jy+69pRNlFJRRYzTTOdRHDe01QiUo\nRVGa1f+t2EVKZkmznrNnlB/Pj+110tcTEhLo0KED995r2T9vxowZ6PV6NmzYQGFhIbW1tcycOZMr\n4+MxFRaClNSkpzfaWyorK2PcuHHHtRs3bhwACxcu5PXXX0cIQZ8+fVi0aBHZ2dncddddHDhwAID3\n33+fqKgoxowZw99//w3A66+/TllZGTNmzKgvZLtp82aGXjGe3j1jueOt16ipqSE4OJjFixcTHh5O\nWVkZ999/P9u2bUMIwfPPP09xcTE7duzgrbfeAuDDDz8kJSWF2bNnN+vP21GoBKUoitO7/vrreeih\nh+oT1BdffMHatWt54IEH8PX1JefQIQYPGcKILl2o66e4tm/faG/Jw8ODZcuW4efnR15eHueffz5X\nXnklKSkpzJw5k19++YWQkJD6YrAPPPAAl156KcuWLcNkMlFWVtbkHlPV1dV8unIDQghCXGu59YZr\nEELw0Ucf8eqrr/LGG280um+Vq6srL730Eq+99hqurq7MmzePDz74oHl/mA5EJShFUZrVqXo69tKv\nXz9ycnLIzMwkNzeXwMBAwkNCeOi++9j8008IIcjMyiLfZKJdjx4gBPqAgEbPJaXkqaeeYtOmTbi4\nuHD06FGys7NZv349EyZMICQkBPhnv6f169fX7/Gk0+nw9/dvMkENj7+KGpOZLqE+HNiTzsSJN3Ds\n2DFqamrq96862b5Vw4YNY+XKlRgMBmpra+ndu/fZ/fAcmEpQiqK0ChMmTODLL7/k2JEjXHP55cx/\n801yjh5ly/LleISH07VvX0z+/rh4nHoywuLFi8nNzWX79u24uroSHR39r/2hmqLX6zGbzfWPG7Y3\nmSW1wo1QX3e83fXcf//9PPLII1x55ZVs3LiRGTNmnPLct99+Oy+//DKxsbFMmTLltOJyNqqWhqIo\nTk8ajVxz+eV8tmABXy1dyvihQykzm4mIicGnRw82//knhw4dsulcxcXFhIWF4erqyoYNG+rbDRs2\njC+//JL8/Hzgn/2ehg8fzvvWQrAmk4ni4mLCw8PJyckhPz+f6upqVq5caXndbKbaaMZV50K4r0f9\n9er2l1qwYEF9HCfbt2rQoEEcOXKETz/9lIkTJ57xz8wZqASlKIpTklJiKiun5sgRqnbvpntAAGXl\n5bTr0IHoiy7ilrvvZvtff9G7d28WLlxIbGysTee96aab2LZt27/a9erVi6effppLL72UuLg4Hnnk\n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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "71XvjqutG_OQ", + "colab_type": "code", + "outputId": "6e4a0509-c34d-4bb5-a141-da09c754354d", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 139 + } + }, + "source": [ + "history = _train(epochs=6, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/6\n", + "15534/15540 [============================>.] - ETA: 3s - loss: 0.2863 - accuracy: 0.9102" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 05:36:21.985853 140479997958016 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 8232s 530ms/sample - loss: 0.2862 - accuracy: 0.9102 - val_loss: 0.9629 - val_accuracy: 0.8585\n", + "Epoch 2/6\n", + "13482/15540 [=========================>....] - ETA: 17:26 - loss: 0.1069 - accuracy: 0.9684" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "V0NQvgNXHIXk", + "colab_type": "code", + "outputId": "dc96e509-4103-45fc-d828-3887afb40e77", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 377 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0725 08:30:08.438622 140174057060224 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.2652 - accuracy: 0.9178" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 10:45:40.559539 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 8128s 523ms/sample - loss: 0.2651 - accuracy: 0.9178 - val_loss: 0.0916 - val_accuracy: 0.9807\n", + "Epoch 2/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.1222 - accuracy: 0.9671" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 12:58:31.137780 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7971s 513ms/sample - loss: 0.1221 - accuracy: 0.9671 - val_loss: 0.0558 - val_accuracy: 0.9853\n", + "Epoch 3/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0862 - accuracy: 0.9764" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 15:08:45.694696 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7815s 503ms/sample - loss: 0.0862 - accuracy: 0.9764 - val_loss: 0.1374 - val_accuracy: 0.9796\n", + "Epoch 4/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0669 - accuracy: 0.9832" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 17:17:37.540996 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7732s 498ms/sample - loss: 0.0668 - accuracy: 0.9832 - val_loss: 0.0720 - val_accuracy: 0.9784\n", + "Epoch 5/5\n", + "15534/15540 [============================>.] - ETA: 2s - loss: 0.0647 - accuracy: 0.9835" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "W0725 19:27:23.475267 140174057060224 callbacks.py:986] Can save best model only with val_acc available, skipping.\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r15540/15540 [==============================] - 7786s 501ms/sample - loss: 0.0647 - accuracy: 0.9835 - val_loss: 0.1236 - val_accuracy: 0.9678\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Gfuhr0qvPF_0", + "colab_type": "code", + "outputId": "2bf5f66a-9f5e-41bc-c9f4-0051429822ce", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAagAAAEYCAYAAAAJeGK1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzs3Xd4VFX6wPHvm15Jo4YAEUEyIARE\nkaKAKGsJRRAQVASkrL3/NFixZ1ddV9cKCAqKNAWBCCwdXUEB6SRSgwSkpZGQnjm/P+5NGGJChpDJ\nJJnzeZ55cufee+59J+K8OeeeIkopNE3TNK2mcXN2AJqmaZpWFp2gNE3TtBpJJyhN0zStRtIJStM0\nTauRdILSNE3TaiSdoDRN07QaSScoTSuHiHwqIi9W9bmaptlH9Dgora4SkSRgnFJqpbNj0TTt4uka\nlOaSRMTD2TFomnZhOkFpdZKIzASaA4tFJEtEnhERJSJjReQPYLV53jwROS4iGSKyXkTa2VzjCxF5\n3dzuLSLJIvKUiJwUkT9FZEwlzw0TkcUickZENonI6yLyUzX9ajSt1tAJSquTlFIjgT+A/kqpAGCu\neagXYAFuNt8vBVoDDYHfgK8vcNnGQBDQFBgLfCQiIZU49yPgrHnOKPOlaVopOkFprmaSUuqsUioH\nQCk1TSmVqZTKAyYB0SISVE7ZAuBVpVSBUuoHIAtoczHniog7cAfwslIqWym1B/iy6j6eptUdOkFp\nruZI8YaIuItInIgcEJEzQJJ5qH45ZVOUUoU277OBgIs8twHgYRtHqW1N00w6QWl1WVldVG333QUM\nBG7CaI6LNPeLA2M6BRQCETb7mjnwfppWa+kEpdVlJ4CWFzgeCOQBKYAf8KajA1JKFQHfAZNExE9E\nooB7HX1fTauNdILS6rK3gBdEJB0YUsbxGcBh4CiwB9hYTXE9jFFjOw7MBL7BSJSaptnQA3U1zclE\n5B9AY6WU7s2naTZ0DUrTqpmIRIlIBzF0weiGvsDZcWlaTaNH02ta9QvEaNYLx3hO9i7wvVMj0rQa\nSDfxaZqmaTWSbuLTNE3TaqQ608Tn5uamfH19nR2GpmlalcrOzlZKKZesTNSZBOXr68vZs2edHYam\naVqVEpEcZ8fgLC6ZlTVN07SaTycoTdM0rUbSCUrTNE2rkerMMyhN0y5OQUEBycnJ5ObmOjsUDfDx\n8SEiIgJPT09nh1Jj6ASlaS4qOTmZwMBAIiMjEXHkBO5aRZRSpKSkkJyczGWXXebscGoM3cSnaS4q\nNzeXsLAwnZxqABEhLCxM12ZL0QlK01yYTk41h/5v8Ve6iU8r08FTWeQWWGkbXs/ZoWiaQyiloHiq\nN9ufShmrWpZzrHjb2FTlHi+5h/nezd8fNy8vB36iukcnKO08Sim++fUIryzejVUp3ruzI/06hDs7\nLK2GU1Yr1uxsVJ65rJVSxnf3X77AofSXurrAseJ9qrwkYFPmoq9TzTwjInSCukg6QWklsvIKee67\nnSzafozrW9cnr8DKI99sJS27gJFdWzg7PK2GsRYUYM3MxJqVhTUrC2W1VlyouBlLBCl5LyDnHwMx\nf5y/77zz3NzONYuJIOVcp6ioEI/innHl3O+CsZjbYrNdXlxSqsx593B3r/j3UwkicgvwPuAOTFVK\nxZU63gKYBjQAUoF7lFLJ5rF/AjEYj3tWAI8ppZSIrAWaAMWzWPxNKXVSRLwxFvrsjLES9Z1KqSSH\nfDB0gtJMe46d4aFZv3E45Sz/d3MbHuh1OflFVh6etZUXF+4iJSuPx25srdvJXZhSCpWTQ1FmJtbM\nLKy5xneXeHriFhSMe2AA4ut7XtI47wu6jH87t99+O0eOHCE3N5fHHnuMCRMmsGzZMp577jmKioqo\nX78+q1atIisri0ceeYTNmzcjIrz88svccccdBAQEkJWVBcD8+fNZsmQJX3zxBaNHj8bHx4etW7fS\no0cPhg8fzmOPPUZubi6+vr5Mnz6dNm3aUFRUxLPPPsuyZctwc3Nj/PjxtGvXjg8++ICFCxcCsGLF\nCj7++GMWLKh5S3aJiDvwEdAXSAY2icgipdQem9PeAWYopb4UkT4YK02PFJHuQA+gg3neT0AvYK35\n/m6l1OZStxwLpCmlWonIcOAfwJ0O+GiATlAuTynFrF//4JXFewjx8+Sb8V25tmUYAD5u7nx6z1VM\n/G4n/165j5SsfCYNaIe7m05Sdc3xN98kLyHxL/sVCoqKUIVFxk+zaUzc3cHd3fjp5kZZ/yK8LVE0\nfu65C9532rRphIaGkpOTwzXXXMPAgQMZP34869ev57LLLiM1NRWA1157jaCgIHbu3AlAWlpahZ8p\nOTmZn3/+GXd3d86cOcOPP/6Ih4cHK1eu5LnnnuPbb79l8uTJJCUlsW3bNjw8PEhNTSUkJIQHH3yQ\n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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "TpiQ3SJOmnce", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gn87-HJKzeA_", + "colab_type": "text" + }, + "source": [ + "# Experiments" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "7F7-4LUTzfgM", + "colab_type": "code", + "outputId": "ad3aa489-595e-4649-fcdd-1ece8b9a0d45", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 292 + } + }, + "source": [ + "history = _train(epochs=5, batch_size=6, subset_percent=.10, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0726 19:43:29.996565 140657336223616 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 1550 samples, validate on 385 samples\n", + "Epoch 1/5\n", + "1550/1550 [==============================] - 29s 19ms/sample - loss: 0.5426 - accuracy: 0.8252 - val_loss: 2.0018 - val_accuracy: 0.6571\n", + "Epoch 2/5\n", + "1550/1550 [==============================] - 20s 13ms/sample - loss: 0.3188 - accuracy: 0.9168 - val_loss: 1.7734 - val_accuracy: 0.6078\n", + "Epoch 3/5\n", + "1550/1550 [==============================] - 20s 13ms/sample - loss: 0.2530 - accuracy: 0.9316 - val_loss: 2.8423 - val_accuracy: 0.3247\n", + "Epoch 4/5\n", + "1550/1550 [==============================] - 20s 13ms/sample - loss: 0.2532 - accuracy: 0.9252 - val_loss: 2.4096 - val_accuracy: 0.5922\n", + "Epoch 5/5\n", + "1550/1550 [==============================] - 20s 13ms/sample - loss: 0.1671 - accuracy: 0.9561 - val_loss: 2.1986 - val_accuracy: 0.3091\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "aWt7_pAyzlU0", + "colab_type": "code", + "outputId": "12f6a7f4-be35-4c2d-c7d6-0e87c0b6b0de", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 297 + } + }, + "source": [ + "utils.display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "display_data", + "data": { + "image/png": "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\nMYH0/wGDv+PJOUcFtgAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "v5c4P4cC0ZOP", + "colab_type": "code", + "outputId": "4d6fb63c-ca59-4c72-98f6-8e7fdccaa3e3", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 224 + } + }, + "source": [ + "# full train, compression and pytorch\n", + "history = _train(epochs=5, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/5\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.2321 - accuracy: 0.9316 - val_loss: 0.5205 - val_accuracy: 0.8508\n", + "Epoch 2/5\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.1229 - accuracy: 0.9661 - val_loss: 0.1808 - val_accuracy: 0.9644\n", + "Epoch 3/5\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0834 - accuracy: 0.9763 - val_loss: 0.7445 - val_accuracy: 0.8523\n", + "Epoch 4/5\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0652 - accuracy: 0.9822 - val_loss: 0.1716 - val_accuracy: 0.9273\n", + "Epoch 5/5\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0549 - accuracy: 0.9847 - val_loss: 0.8358 - val_accuracy: 0.8124\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Rn1syTNs0dH3", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# need to add compression to either block, transition, or both to get it to be BC\n", + "\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(math.floor(theta*filters), kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return\n", + " \n", + "#### DENSE NET ARCHITECTURE #####\n", + "#\n", + "# CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX\n", + "#\n", + "# BLOCK:\n", + "# BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output\n", + "#\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "theta = .5\n", + "growth_rate = 4\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))\n", + "\n", + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zk8xHB295caq", + "colab_type": "code", + "outputId": "e8c69a23-55d5-49a1-dd4b-8d5542ee89b8", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 224 + } + }, + "source": [ + "# full train, 1.1 + compression\n", + "history = _train(epochs=5, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/5\n", + "15540/15540 [==============================] - 214s 14ms/sample - loss: 0.2669 - accuracy: 0.9197 - val_loss: 0.1937 - val_accuracy: 0.9407\n", + "Epoch 2/5\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.1109 - accuracy: 0.9693 - val_loss: 2.4719 - val_accuracy: 0.6412\n", + "Epoch 3/5\n", + "15540/15540 [==============================] - 208s 13ms/sample - loss: 0.0820 - accuracy: 0.9787 - val_loss: 0.0658 - val_accuracy: 0.9814\n", + "Epoch 4/5\n", + "15540/15540 [==============================] - 207s 13ms/sample - loss: 0.0678 - accuracy: 0.9801 - val_loss: 0.0661 - val_accuracy: 0.9804\n", + "Epoch 5/5\n", + "15540/15540 [==============================] - 207s 13ms/sample - loss: 0.0614 - accuracy: 0.9828 - val_loss: 0.0600 - val_accuracy: 0.9820\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "MDHHXqtR52Nl", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# need to add compression to either block, transition, or both to get it to be BC\n", + "\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(filters, kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return\n", + " \n", + "#### DENSE NET ARCHITECTURE #####\n", + "#\n", + "# CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX\n", + "#\n", + "# BLOCK:\n", + "# BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output\n", + "#\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "theta = .5\n", + "growth_rate = 4\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))\n", + "\n", + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "YJK5uZ0T-TA_", + "colab_type": "code", + "outputId": "a453b7ef-2386-44c3-852d-e74fdca04200", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 139 + } + }, + "source": [ + "# full train, 1.1\n", + "history = _train(epochs=1, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0730 19:21:30.150702 140551516116864 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "15540/15540 [==============================] - 198s 13ms/sample - loss: 0.2714 - accuracy: 0.9163 - val_loss: 0.0962 - val_accuracy: 0.9745\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Ffb5-Md1-VP_", + "colab_type": "code", + "outputId": "2ea8a8b6-9a53-4285-ec2f-ba56fe013e6b", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 904 + } + }, + "source": [ + "# full train, 1.1, 100 epochs\n", + "history = _train(epochs=100, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0730 19:33:18.580949 140342255110016 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/100\n", + "15540/15540 [==============================] - 202s 13ms/sample - loss: 0.2809 - accuracy: 0.9158 - val_loss: 0.4953 - val_accuracy: 0.7688\n", + "Epoch 2/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.1238 - accuracy: 0.9669 - val_loss: 0.0508 - val_accuracy: 0.9845\n", + "Epoch 3/100\n", + "15540/15540 [==============================] - 193s 12ms/sample - loss: 0.0878 - accuracy: 0.9748 - val_loss: 0.1902 - val_accuracy: 0.9526\n", + "Epoch 4/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0739 - accuracy: 0.9813 - val_loss: 0.0406 - val_accuracy: 0.9881\n", + "Epoch 5/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0538 - accuracy: 0.9849 - val_loss: 0.6465 - val_accuracy: 0.8054\n", + "Epoch 6/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0525 - accuracy: 0.9847 - val_loss: 0.0715 - val_accuracy: 0.9838\n", + "Epoch 7/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0515 - accuracy: 0.9873 - val_loss: 0.0377 - val_accuracy: 0.9876\n", + "Epoch 8/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0427 - accuracy: 0.9888 - val_loss: 0.0591 - val_accuracy: 0.9861\n", + "Epoch 9/100\n", + "15540/15540 [==============================] - 188s 12ms/sample - loss: 0.0415 - accuracy: 0.9887 - val_loss: 0.1928 - val_accuracy: 0.9603\n", + "Epoch 10/100\n", + "15540/15540 [==============================] - 189s 12ms/sample - loss: 0.0395 - accuracy: 0.9898 - val_loss: 0.0237 - val_accuracy: 0.9959\n", + "Epoch 11/100\n", + "15540/15540 [==============================] - 188s 12ms/sample - loss: 0.0395 - accuracy: 0.9902 - val_loss: 0.0299 - val_accuracy: 0.9897\n", + "Epoch 12/100\n", + "15540/15540 [==============================] - 188s 12ms/sample - loss: 0.0313 - accuracy: 0.9917 - val_loss: 0.0278 - val_accuracy: 0.9933\n", + "Epoch 13/100\n", + "15540/15540 [==============================] - 188s 12ms/sample - loss: 0.0277 - accuracy: 0.9932 - val_loss: 0.0966 - val_accuracy: 0.9838\n", + "Epoch 14/100\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0236 - accuracy: 0.9933 - val_loss: 0.0433 - val_accuracy: 0.9861\n", + "Epoch 15/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0297 - accuracy: 0.9919 - val_loss: 0.0252 - val_accuracy: 0.9951\n", + "Epoch 16/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0208 - accuracy: 0.9945 - val_loss: 0.0328 - val_accuracy: 0.9951\n", + "Epoch 17/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0276 - accuracy: 0.9929 - val_loss: 0.1040 - val_accuracy: 0.9740\n", + "Epoch 18/100\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0221 - accuracy: 0.9941 - val_loss: 0.1574 - val_accuracy: 0.9701\n", + "Epoch 19/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0198 - accuracy: 0.9941 - val_loss: 0.0248 - val_accuracy: 0.9974\n", + "Epoch 20/100\n", + "15540/15540 [==============================] - 191s 12ms/sample - loss: 0.0227 - accuracy: 0.9938 - val_loss: 0.0298 - val_accuracy: 0.9894\n", + "Epoch 21/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0195 - accuracy: 0.9948 - val_loss: 0.0286 - val_accuracy: 0.9933\n", + "Epoch 22/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0166 - accuracy: 0.9954 - val_loss: 0.0287 - val_accuracy: 0.9933\n", + "Epoch 23/100\n", + " 3492/15540 [=====>........................] - ETA: 2:22 - loss: 0.0115 - accuracy: 0.9966Buffered data was truncated after reaching the output size limit." + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "kMg9sVTYGXys", + "colab_type": "code", + "colab": {} + }, + "source": [ + "best_model = keras.models.load_model(os.environ['SAVE_PATH']+'best_model.h5')" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "FTkRMtGLzA3_", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# full train, 1.1, 100 epochs\n", + "history = _train(epochs=100, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "2ZKLWkUIzajP", + "colab_type": "code", + "outputId": "a6ad4c3f-4677-4778-ddf5-3062df197850", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + } + }, + "source": [ + "# full train, 1.1, 100 epochs\n", + "history = _train(epochs=100, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0731 07:48:04.547430 140542354286464 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/100\n", + "15540/15540 [==============================] - 207s 13ms/sample - loss: 0.2814 - accuracy: 0.9147 - val_loss: 1.6060 - val_accuracy: 0.7448\n", + "Epoch 2/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.1205 - accuracy: 0.9638 - val_loss: 0.0938 - val_accuracy: 0.9675\n", + "Epoch 3/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0801 - accuracy: 0.9776 - val_loss: 0.2200 - val_accuracy: 0.9327\n", + "Epoch 4/100\n", + "15540/15540 [==============================] - 201s 13ms/sample - loss: 0.0664 - accuracy: 0.9812 - val_loss: 0.0703 - val_accuracy: 0.9758\n", + "Epoch 5/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0559 - accuracy: 0.9846 - val_loss: 0.1602 - val_accuracy: 0.9647\n", + "Epoch 6/100\n", + "15540/15540 [==============================] - 186s 12ms/sample - loss: 0.0487 - accuracy: 0.9855 - val_loss: 0.1140 - val_accuracy: 0.9686\n", + "Epoch 7/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0428 - accuracy: 0.9880 - val_loss: 0.0342 - val_accuracy: 0.9918\n", + "Epoch 8/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0380 - accuracy: 0.9894 - val_loss: 0.0242 - val_accuracy: 0.9956\n", + "Epoch 9/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0366 - accuracy: 0.9903 - val_loss: 0.0942 - val_accuracy: 0.9691\n", + "Epoch 10/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0346 - accuracy: 0.9904 - val_loss: 0.0181 - val_accuracy: 0.9966\n", + "Epoch 11/100\n", + "15540/15540 [==============================] - 189s 12ms/sample - loss: 0.0290 - accuracy: 0.9911 - val_loss: 0.0299 - val_accuracy: 0.9966\n", + "Epoch 12/100\n", + "15540/15540 [==============================] - 201s 13ms/sample - loss: 0.0244 - accuracy: 0.9927 - val_loss: 0.0255 - val_accuracy: 0.9925\n", + "Epoch 13/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0301 - accuracy: 0.9912 - val_loss: 0.0353 - val_accuracy: 0.9925\n", + "Epoch 14/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0218 - accuracy: 0.9939 - val_loss: 0.0412 - val_accuracy: 0.9918\n", + "Epoch 15/100\n", + "15540/15540 [==============================] - 201s 13ms/sample - loss: 0.0205 - accuracy: 0.9934 - val_loss: 0.0206 - val_accuracy: 0.9956\n", + "Epoch 16/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0211 - accuracy: 0.9938 - val_loss: 0.0339 - val_accuracy: 0.9894\n", + "Epoch 17/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0201 - accuracy: 0.9941 - val_loss: 0.0258 - val_accuracy: 0.9928\n", + "Epoch 18/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0152 - accuracy: 0.9958 - val_loss: 0.0204 - val_accuracy: 0.9959\n", + "Epoch 19/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0195 - accuracy: 0.9957 - val_loss: 0.0445 - val_accuracy: 0.9876\n", + "Epoch 20/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0165 - accuracy: 0.9958 - val_loss: 0.0505 - val_accuracy: 0.9905\n", + "Epoch 21/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0126 - accuracy: 0.9968 - val_loss: 0.0471 - val_accuracy: 0.9894\n", + "Epoch 22/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0195 - accuracy: 0.9951 - val_loss: 0.1251 - val_accuracy: 0.9753\n", + "Epoch 23/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0113 - accuracy: 0.9968 - val_loss: 0.0420 - val_accuracy: 0.9876\n", + "Epoch 24/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0141 - accuracy: 0.9963 - val_loss: 0.0264 - val_accuracy: 0.9938\n", + "Epoch 25/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0123 - accuracy: 0.9968 - val_loss: 0.0189 - val_accuracy: 0.9969\n", + "Epoch 26/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0146 - accuracy: 0.9961 - val_loss: 0.1183 - val_accuracy: 0.9747\n", + "Epoch 27/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0091 - accuracy: 0.9978 - val_loss: 0.0634 - val_accuracy: 0.9776\n", + "Epoch 28/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0127 - accuracy: 0.9970 - val_loss: 0.1145 - val_accuracy: 0.9820\n", + "Epoch 29/100\n", + "15540/15540 [==============================] - 190s 12ms/sample - loss: 0.0131 - accuracy: 0.9970 - val_loss: 0.0318 - val_accuracy: 0.9923\n", + "Epoch 30/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0071 - accuracy: 0.9981 - val_loss: 0.0522 - val_accuracy: 0.9897\n", + "Epoch 31/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0108 - accuracy: 0.9968 - val_loss: 0.0700 - val_accuracy: 0.9755\n", + "Epoch 32/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0127 - accuracy: 0.9966 - val_loss: 0.1997 - val_accuracy: 0.9675\n", + "Epoch 33/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0084 - accuracy: 0.9973 - val_loss: 0.0295 - val_accuracy: 0.9961\n", + "Epoch 34/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0078 - accuracy: 0.9974 - val_loss: 0.0456 - val_accuracy: 0.9925\n", + "Epoch 35/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0119 - accuracy: 0.9975 - val_loss: 0.0268 - val_accuracy: 0.9959\n", + "Epoch 36/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0093 - accuracy: 0.9976 - val_loss: 0.3253 - val_accuracy: 0.9503\n", + "Epoch 37/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0087 - accuracy: 0.9974 - val_loss: 0.0357 - val_accuracy: 0.9959\n", + "Epoch 38/100\n", + "15540/15540 [==============================] - 201s 13ms/sample - loss: 0.0074 - accuracy: 0.9981 - val_loss: 0.0265 - val_accuracy: 0.9974\n", + "Epoch 39/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0092 - accuracy: 0.9970 - val_loss: 0.0398 - val_accuracy: 0.9897\n", + "Epoch 40/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0076 - accuracy: 0.9979 - val_loss: 0.0355 - val_accuracy: 0.9912\n", + "Epoch 41/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0118 - accuracy: 0.9972 - val_loss: 0.0207 - val_accuracy: 0.9943\n", + "Epoch 42/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0049 - accuracy: 0.9986 - val_loss: 0.0279 - val_accuracy: 0.9943\n", + "Epoch 43/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0081 - accuracy: 0.9976 - val_loss: 0.0990 - val_accuracy: 0.9729\n", + "Epoch 44/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0096 - accuracy: 0.9970 - val_loss: 0.0325 - val_accuracy: 0.9946\n", + "Epoch 45/100\n", + "15540/15540 [==============================] - 201s 13ms/sample - loss: 0.0083 - accuracy: 0.9977 - val_loss: 0.0288 - val_accuracy: 0.9979\n", + "Epoch 46/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0069 - accuracy: 0.9980 - val_loss: 0.0361 - val_accuracy: 0.9964\n", + "Epoch 47/100\n", + "15540/15540 [==============================] - 194s 12ms/sample - loss: 0.0061 - accuracy: 0.9981 - val_loss: 0.0264 - val_accuracy: 0.9933\n", + "Epoch 48/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0078 - accuracy: 0.9980 - val_loss: 0.0916 - val_accuracy: 0.9897\n", + "Epoch 49/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0064 - accuracy: 0.9981 - val_loss: 0.0231 - val_accuracy: 0.9979\n", + "Epoch 50/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0064 - accuracy: 0.9981 - val_loss: 0.0705 - val_accuracy: 0.9897\n", + "Epoch 51/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0061 - accuracy: 0.9983 - val_loss: 0.0707 - val_accuracy: 0.9856\n", + "Epoch 52/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0109 - accuracy: 0.9976 - val_loss: 0.0768 - val_accuracy: 0.9907\n", + "Epoch 53/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0063 - accuracy: 0.9984 - val_loss: 0.0504 - val_accuracy: 0.9902\n", + "Epoch 54/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0049 - accuracy: 0.9987 - val_loss: 0.1251 - val_accuracy: 0.9784\n", + "Epoch 55/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0084 - accuracy: 0.9978 - val_loss: 0.0758 - val_accuracy: 0.9897\n", + "Epoch 56/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0080 - accuracy: 0.9982 - val_loss: 0.0347 - val_accuracy: 0.9943\n", + "Epoch 57/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0080 - accuracy: 0.9980 - val_loss: 0.1863 - val_accuracy: 0.9729\n", + "Epoch 58/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0070 - accuracy: 0.9982 - val_loss: 0.0559 - val_accuracy: 0.9905\n", + "Epoch 59/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0067 - accuracy: 0.9978 - val_loss: 0.0341 - val_accuracy: 0.9897\n", + "Epoch 60/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0040 - accuracy: 0.9988 - val_loss: 0.1328 - val_accuracy: 0.9755\n", + "Epoch 61/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0068 - accuracy: 0.9976 - val_loss: 0.0299 - val_accuracy: 0.9959\n", + "Epoch 62/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0069 - accuracy: 0.9983 - val_loss: 0.0463 - val_accuracy: 0.9853\n", + "Epoch 63/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0046 - accuracy: 0.9986 - val_loss: 0.0699 - val_accuracy: 0.9887\n", + "Epoch 64/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0060 - accuracy: 0.9983 - val_loss: 0.0669 - val_accuracy: 0.9879\n", + "Epoch 65/100\n", + "15540/15540 [==============================] - 194s 13ms/sample - loss: 0.0070 - accuracy: 0.9981 - val_loss: 0.0777 - val_accuracy: 0.9894\n", + "Epoch 66/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0055 - accuracy: 0.9985 - val_loss: 0.0368 - val_accuracy: 0.9943\n", + "Epoch 67/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0043 - accuracy: 0.9990 - val_loss: 0.0447 - val_accuracy: 0.9943\n", + "Epoch 68/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0050 - accuracy: 0.9986 - val_loss: 1.9445 - val_accuracy: 0.8418\n", + "Epoch 69/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0073 - accuracy: 0.9977 - val_loss: 0.0873 - val_accuracy: 0.9807\n", + "Epoch 70/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0055 - accuracy: 0.9987 - val_loss: 0.0330 - val_accuracy: 0.9915\n", + "Epoch 71/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0073 - accuracy: 0.9983 - val_loss: 0.0298 - val_accuracy: 0.9920\n", + "Epoch 72/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0111 - accuracy: 0.9975 - val_loss: 0.0637 - val_accuracy: 0.9861\n", + "Epoch 73/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0048 - accuracy: 0.9988 - val_loss: 0.0438 - val_accuracy: 0.9853\n", + "Epoch 74/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0096 - accuracy: 0.9980 - val_loss: 0.0540 - val_accuracy: 0.9907\n", + "Epoch 75/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0035 - accuracy: 0.9988 - val_loss: 0.0397 - val_accuracy: 0.9933\n", + "Epoch 76/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0043 - accuracy: 0.9986 - val_loss: 0.0369 - val_accuracy: 0.9920\n", + "Epoch 77/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0030 - accuracy: 0.9992 - val_loss: 0.0754 - val_accuracy: 0.9840\n", + "Epoch 78/100\n", + "15540/15540 [==============================] - 192s 12ms/sample - loss: 0.0047 - accuracy: 0.9985 - val_loss: 0.0700 - val_accuracy: 0.9884\n", + "Epoch 79/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0048 - accuracy: 0.9990 - val_loss: 0.0426 - val_accuracy: 0.9915\n", + "Epoch 80/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0044 - accuracy: 0.9990 - val_loss: 0.0735 - val_accuracy: 0.9892\n", + "Epoch 81/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0046 - accuracy: 0.9986 - val_loss: 0.0704 - val_accuracy: 0.9778\n", + "Epoch 82/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0047 - accuracy: 0.9990 - val_loss: 0.0507 - val_accuracy: 0.9928\n", + "Epoch 83/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0041 - accuracy: 0.9984 - val_loss: 0.0365 - val_accuracy: 0.9964\n", + "Epoch 84/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0055 - accuracy: 0.9981 - val_loss: 0.0457 - val_accuracy: 0.9879\n", + "Epoch 85/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0068 - accuracy: 0.9981 - val_loss: 0.0396 - val_accuracy: 0.9923\n", + "Epoch 86/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0032 - accuracy: 0.9988 - val_loss: 0.0836 - val_accuracy: 0.9778\n", + "Epoch 87/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0038 - accuracy: 0.9988 - val_loss: 0.0394 - val_accuracy: 0.9938\n", + "Epoch 88/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0043 - accuracy: 0.9985 - val_loss: 0.0876 - val_accuracy: 0.9827\n", + "Epoch 89/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0041 - accuracy: 0.9985 - val_loss: 0.0364 - val_accuracy: 0.9969\n", + "Epoch 90/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0037 - accuracy: 0.9988 - val_loss: 0.1570 - val_accuracy: 0.9722\n", + "Epoch 91/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0055 - accuracy: 0.9986 - val_loss: 0.0490 - val_accuracy: 0.9923\n", + "Epoch 92/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0044 - accuracy: 0.9986 - val_loss: 0.0658 - val_accuracy: 0.9861\n", + "Epoch 93/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0041 - accuracy: 0.9986 - val_loss: 0.0791 - val_accuracy: 0.9866\n", + "Epoch 94/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0035 - accuracy: 0.9988 - val_loss: 0.0890 - val_accuracy: 0.9773\n", + "Epoch 95/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0042 - accuracy: 0.9985 - val_loss: 0.0392 - val_accuracy: 0.9923\n", + "Epoch 96/100\n", + "15540/15540 [==============================] - 194s 13ms/sample - loss: 0.0069 - accuracy: 0.9984 - val_loss: 0.0598 - val_accuracy: 0.9845\n", + "Epoch 97/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0017 - accuracy: 0.9994 - val_loss: 0.0897 - val_accuracy: 0.9825\n", + "Epoch 98/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0034 - accuracy: 0.9987 - val_loss: 0.0387 - val_accuracy: 0.9920\n", + "Epoch 99/100\n", + "15540/15540 [==============================] - 199s 13ms/sample - loss: 0.0044 - accuracy: 0.9987 - val_loss: 0.0727 - val_accuracy: 0.9845\n", + "Epoch 100/100\n", + "15540/15540 [==============================] - 200s 13ms/sample - loss: 0.0029 - accuracy: 0.9988 - val_loss: 0.0536 - val_accuracy: 0.9907\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "WyDeQfFV_5Wk", + "colab_type": "code", + "outputId": "87da5f07-ac2a-46ae-e038-cfad49bc346c", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 105 + } + }, + "source": [ + "best_model = keras.models.load_model(os.environ['SAVE_PATH']+'best_model.h5')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0731 17:17:55.303345 140525386987392 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "RYhzs-TlB7fP", + "colab_type": "code", + "colab": {} + }, + "source": [ + "test = np.load(os.path.join(os.environ['SPIT_PATH'], 'Kast', 'kast_test.npz'))\n", + "test_images = test['images']\n", + "test_labels = test['labels']\n", + "test_labels = keras.utils.to_categorical(test_labels, num_classes=len(label_dict))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "S7sDrG-hDwI6", + "colab_type": "code", + "outputId": "a831632e-c51c-4fe8-d2ac-5a65e558ac2e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "best_model.evaluate(test_images, test_labels) " + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "4840/4840 [==============================] - 13s 3ms/sample - loss: 0.0498 - accuracy: 0.9950\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[0.04983410443976286, 0.9950413]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 21 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "yCRFaYL6D0MU", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/docs/nb/FinalDenseNet.ipynb b/docs/nb/FinalDenseNet.ipynb new file mode 100644 index 0000000..c501dcc --- /dev/null +++ b/docs/nb/FinalDenseNet.ipynb @@ -0,0 +1,7005 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "name": "FinalDenseNet.ipynb", + "version": "0.3.2", + "provenance": [], + "collapsed_sections": [ + "2dnGV0FHocqH", + "apSpY04_op7G", + "F5jRzrjpOlFq", + "gn87-HJKzeA_", + "sTyihTc1Tcsy" + ] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "accelerator": "GPU" + }, + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "U74NGbY4508Z", + "colab_type": "text" + }, + "source": [ + "# Import Tensorflow" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "rzmyPhhhvIRu", + "colab_type": "code", + "outputId": "5eb1ed7d-cfc2-4fd1-b31d-9657cc3eb1b4", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "source": [ + "!pip install tensorflow==2.0.0b1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Collecting tensorflow==2.0.0b1\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/29/6c/2c9a5c4d095c63c2fb37d20def0e4f92685f7aee9243d6aae25862694fd1/tensorflow-2.0.0b1-cp36-cp36m-manylinux1_x86_64.whl (87.9MB)\n", + "\u001b[K |████████████████████████████████| 87.9MB 21.8MB/s \n", + "\u001b[?25hRequirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.16.4)\n", + "Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.7.1)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.1.7)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.0.8)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.12.0)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.2.2)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (3.7.1)\n", + "Collecting tb-nightly<1.14.0a20190604,>=1.14.0a20190603 (from tensorflow==2.0.0b1)\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/a4/96/571b875cd81dda9d5dfa1422a4f9d749e67c0a8d4f4f0b33a4e5f5f35e27/tb_nightly-1.14.0a20190603-py3-none-any.whl (3.1MB)\n", + "\u001b[K |████████████████████████████████| 3.1MB 25.4MB/s \n", + "\u001b[?25hCollecting tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 (from tensorflow==2.0.0b1)\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/32/dd/99c47dd007dcf10d63fd895611b063732646f23059c618a373e85019eb0e/tf_estimator_nightly-1.14.0.dev2019060501-py2.py3-none-any.whl (496kB)\n", + "\u001b[K |████████████████████████████████| 501kB 42.2MB/s \n", + "\u001b[?25hRequirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.1.0)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.15.0)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.8.0)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (0.33.4)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow==2.0.0b1) (1.11.2)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow==2.0.0b1) (2.8.0)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.6.1->tensorflow==2.0.0b1) (41.0.1)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (3.1.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow==2.0.0b1) (0.15.5)\n", + "Installing collected packages: tb-nightly, tf-estimator-nightly, tensorflow\n", + " Found existing installation: tensorflow 1.14.0\n", + " Uninstalling tensorflow-1.14.0:\n", + " Successfully uninstalled tensorflow-1.14.0\n", + "Successfully installed tb-nightly-1.14.0a20190603 tensorflow-2.0.0b1 tf-estimator-nightly-1.14.0.dev2019060501\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1PMs0uCzygrQ", + "colab_type": "code", + "outputId": "59bff8dc-be29-4e14-b565-df0543249318", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "source": [ + "!pip install tensorflow-gpu==2.0.0-beta1" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Collecting tensorflow-gpu==2.0.0-beta1\n", + "\u001b[?25l Downloading https://files.pythonhosted.org/packages/2b/53/e18c5e7a2263d3581a979645a185804782e59b8e13f42b9c3c3cfb5bb503/tensorflow_gpu-2.0.0b1-cp36-cp36m-manylinux1_x86_64.whl (348.9MB)\n", + "\u001b[K |████████████████████████████████| 348.9MB 57kB/s \n", + "\u001b[?25hRequirement already satisfied: google-pasta>=0.1.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.1.7)\n", + "Requirement already satisfied: wrapt>=1.11.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.11.2)\n", + "Requirement already satisfied: six>=1.10.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.12.0)\n", + "Requirement already satisfied: grpcio>=1.8.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.15.0)\n", + "Requirement already satisfied: absl-py>=0.7.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.7.1)\n", + "Requirement already satisfied: keras-preprocessing>=1.0.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.1.0)\n", + "Requirement already satisfied: numpy<2.0,>=1.14.5 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.16.4)\n", + "Requirement already satisfied: protobuf>=3.6.1 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (3.7.1)\n", + "Requirement already satisfied: tb-nightly<1.14.0a20190604,>=1.14.0a20190603 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.14.0a20190603)\n", + "Requirement already satisfied: tf-estimator-nightly<1.14.0.dev2019060502,>=1.14.0.dev2019060501 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.14.0.dev2019060501)\n", + "Requirement already satisfied: gast>=0.2.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.2.2)\n", + "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.33.4)\n", + "Requirement already satisfied: keras-applications>=1.0.6 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.0.8)\n", + "Requirement already satisfied: termcolor>=1.1.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (1.1.0)\n", + "Requirement already satisfied: astor>=0.6.0 in /usr/local/lib/python3.6/dist-packages (from tensorflow-gpu==2.0.0-beta1) (0.8.0)\n", + "Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from protobuf>=3.6.1->tensorflow-gpu==2.0.0-beta1) (41.0.1)\n", + "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow-gpu==2.0.0-beta1) (3.1.1)\n", + "Requirement already satisfied: werkzeug>=0.11.15 in /usr/local/lib/python3.6/dist-packages (from tb-nightly<1.14.0a20190604,>=1.14.0a20190603->tensorflow-gpu==2.0.0-beta1) (0.15.5)\n", + "Requirement already satisfied: h5py in /usr/local/lib/python3.6/dist-packages (from keras-applications>=1.0.6->tensorflow-gpu==2.0.0-beta1) (2.8.0)\n", + "Installing collected packages: tensorflow-gpu\n", + "Successfully installed tensorflow-gpu-2.0.0b1\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "08Eytj_3oYDI", + "colab_type": "text" + }, + "source": [ + "# SPIT Imports" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "FIMdpjQ-f-nx", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "import numpy as np\n", + "import os\n", + "\n", + "from importlib import reload\n", + "from pkg_resources import resource_filename\n", + "from google.colab import drive\n", + "import imageio" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "EkgCyHlig-fl", + "colab_type": "code", + "outputId": "752cf915-22a5-4415-e552-09de4b83f54f", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "import tensorflow\n", + "tensorflow.__version__" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "'2.0.0-beta1'" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 5 + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "LqfsN-WdhAcm", + "colab_type": "code", + "outputId": "9da93112-c482-4671-c54b-6b4895214c63", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 122 + } + }, + "source": [ + "drive.mount('/content/drive/')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=email%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdocs.test%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.photos.readonly%20https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fpeopleapi.readonly&response_type=code\n", + "\n", + "Enter your authorization code:\n", + "··········\n", + "Mounted at /content/drive/\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "znIJK2HDhBsO", + "colab_type": "code", + "outputId": "da563e04-d72c-4d46-88ad-ad3b82d7f05a", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136 + } + }, + "source": [ + "!git clone https://github.com/pypeit/spit.git" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Cloning into 'spit'...\n", + "remote: Enumerating objects: 166, done.\u001b[K\n", + "remote: Counting objects: 100% (166/166), done.\u001b[K\n", + "remote: Compressing objects: 100% (126/126), done.\u001b[K\n", + "remote: Total 850 (delta 111), reused 65 (delta 40), pack-reused 684\u001b[K\n", + "Receiving objects: 100% (850/850), 932.20 KiB | 3.13 MiB/s, done.\n", + "Resolving deltas: 100% (486/486), done.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "N1kzH-dghJlh", + "colab_type": "code", + "outputId": "0b02c76f-28c0-4f5e-aa59-06985cc81d2e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "%cd spit" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "/content/spit\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "UCXppiJ_hLtu", + "colab_type": "code", + "outputId": "17696e5b-8ef7-4aa3-e1fa-23331308250a", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "!git checkout new_models" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Branch 'new_models' set up to track remote branch 'new_models' from 'origin'.\n", + "Switched to a new branch 'new_models'\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "gFBV0bnthNV8", + "colab_type": "code", + "outputId": "e2b26e18-01b0-4182-c225-9640cf7155fc", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "!git pull" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Already up to date.\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "sI3uoAU0hOwc", + "colab_type": "code", + "outputId": "f2c7906f-c805-432b-eee5-2ba2eef13db1", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 323 + } + }, + "source": [ + "!python setup.py develop" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "running develop\n", + "running egg_info\n", + "creating spit.egg-info\n", + "writing spit.egg-info/PKG-INFO\n", + "writing dependency_links to spit.egg-info/dependency_links.txt\n", + "writing top-level names to spit.egg-info/top_level.txt\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "writing manifest file 'spit.egg-info/SOURCES.txt'\n", + "running build_ext\n", + "Creating /usr/local/lib/python3.6/dist-packages/spit.egg-link (link to .)\n", + "Adding spit 0.1.dev0 to easy-install.pth file\n", + "Installing spit_train script to /usr/local/bin\n", + "Installing spit_png script to /usr/local/bin\n", + "Installing spit_classify_image script to /usr/local/bin\n", + "\n", + "Installed /content/spit\n", + "Processing dependencies for spit==0.1.dev0\n", + "Finished processing dependencies for spit==0.1.dev0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "p1o27AbvhP7c", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# imports\n", + "from importlib import reload\n", + "\n", + "from spit import image_loader\n", + "from spit import labels as spit_l\n", + "from spit import preprocess as spit_p\n", + "from spit import classifier as c\n", + "from spit import utils\n", + "from spit import classify as spit_classify\n", + "from spit import io as spit_io" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "2dnGV0FHocqH", + "colab_type": "text" + }, + "source": [ + "# Build DenseNet" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "6UK-KubhvJ4E", + "colab_type": "code", + "colab": {} + }, + "source": [ + "import tensorflow as tf\n", + "from tensorflow import keras" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Vg-eHZ3gfURL", + "colab_type": "code", + "outputId": "53afeb28-9324-4d22-996b-b4cb88c46eaa", + "colab": { + "base_uri": "https://localhost:8080/" + } + }, + "source": [ + "print(tf.test.is_gpu_available())\n", + "device_name = tf.test.gpu_device_name()\n", + "if device_name != '/device:GPU:0':\n", + " raise SystemError('GPU device not found')\n", + "print('Found GPU at: {}'.format(device_name))" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "True\n", + "Found GPU at: /device:GPU:0\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "veTuJQk36S0Z", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# need to add compression to either block, transition, or both to get it to be BC\n", + "\n", + "def dense_block(model):\n", + " \n", + " # 1x1 convolution bottleneck\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE ####\n", + " model.add(keras.layers.Conv2D(growth_rate*filters, kernel_size=1))\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " # 3x3 dense convolution\n", + " \n", + " model.add(keras.layers.BatchNormalization())\n", + " model.add(keras.layers.ReLU())\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Conv2D(filters, kernel_size=3))\n", + " #### HYPERPARAMETER ####\n", + " model.add(keras.layers.Dropout(rate=dropout_rate))\n", + " \n", + " return\n", + "\n", + "def transition_layer(model):\n", + " model.add(keras.layers.BatchNormalization()) # x = Batch_Normalization(x, training=self.training, scope=scope+'_batch1')\n", + " model.add(keras.layers.ReLU()) # x = Relu(x)\n", + " \n", + " model.add(keras.layers.Conv2D(filters, kernel_size=1))\n", + " \n", + " model.add(keras.layers.Dropout(rate=dropout_rate)) # x = Drop_out(x, rate=dropout_rate, training=self.training)\n", + " \n", + " model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2))\n", + " return" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "HozlILKAvVCE", + "colab_type": "code", + "colab": {} + }, + "source": [ + "#### DENSE NET ARCHITECTURE #####\n", + "#\n", + "# CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX\n", + "#\n", + "# BLOCK:\n", + "# BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output\n", + "#\n", + "\n", + "model = keras.Sequential()\n", + "\n", + "# hyperparameters\n", + "filters = 64\n", + "dropout_rate = .2\n", + "theta = .5\n", + "growth_rate = 4\n", + "\n", + "# add a conv layer\n", + "model.add(keras.layers.Conv2D(filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', \n", + " input_shape = (210, 650, 1)))\n", + "\n", + "# pool like in tf simple implementation\n", + "model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid'))\n", + "\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add transition\n", + "transition_layer(model)\n", + "# add block\n", + "dense_block(model)\n", + "# add pool\n", + "model.add(keras.layers.GlobalAveragePooling2D())\n", + "# add flatten\n", + "model.add(keras.layers.Flatten())\n", + "\n", + "# Produce 0-1 probabilities with softmax\n", + "model.add(keras.layers.Dense(5, activation='softmax'))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "mwc1bmdCfmDT", + "colab_type": "code", + "colab": {} + }, + "source": [ + "model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Dvhr1SS2ojnf", + "colab_type": "text" + }, + "source": [ + "# Fake Data" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "1UOxTk6beV3M", + "colab_type": "code", + "colab": {} + }, + "source": [ + "x_train = np.random.random((100, 210, 650, 1))\n", + "train_labels = np.random.randint(5, size=(100, 1))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "3YbIjCS-fhEQ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "y_train = keras.utils.to_categorical(train_labels, num_classes=5)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "zquoTIHjfild", + "colab_type": "code", + "outputId": "dfc5cff3-0d06-4cd2-e41d-84eafb485e80", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 429 + } + }, + "source": [ + " model.fit(\n", + " x_train, \n", + " y_train, \n", + " epochs=5, \n", + " batch_size=6 \n", + " )" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 100 samples\n", + "Epoch 1/5\n", + " 12/100 [==>...........................] - ETA: 2:54 - loss: 2.8118 - accuracy: 0.2500" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0my_train\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0mepochs\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m5\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mbatch_size\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m6\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m )\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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 641\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 642\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--> 643\u001b[0;31m use_multiprocessing=use_multiprocessing)\n\u001b[0m\u001b[1;32m 644\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 645\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.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, **kwargs)\u001b[0m\n\u001b[1;32m 662\u001b[0m \u001b[0mvalidation_steps\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_steps\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 663\u001b[0m \u001b[0mvalidation_freq\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mvalidation_freq\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 664\u001b[0;31m steps_name='steps_per_epoch')\n\u001b[0m\u001b[1;32m 665\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 666\u001b[0m def evaluate(self,\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/engine/training_arrays.py\u001b[0m in \u001b[0;36mmodel_iteration\u001b[0;34m(model, inputs, targets, sample_weights, batch_size, epochs, verbose, callbacks, val_inputs, val_targets, val_sample_weights, shuffle, initial_epoch, steps_per_epoch, validation_steps, validation_freq, mode, validation_in_fit, prepared_feed_values_from_dataset, steps_name, **kwargs)\u001b[0m\n\u001b[1;32m 381\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 382\u001b[0m \u001b[0;31m# Get outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 383\u001b[0;31m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mins_batch\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 384\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\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 385\u001b[0m \u001b[0mbatch_outs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mbatch_outs\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/backend.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, inputs)\u001b[0m\n\u001b[1;32m 3508\u001b[0m \u001b[0mvalue\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmath_ops\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcast\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtensor\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdtype\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3509\u001b[0m \u001b[0mconverted_inputs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvalue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 3510\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_graph_fn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mconverted_inputs\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 3511\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3512\u001b[0m \u001b[0;31m# EagerTensor.numpy() will often make a copy to ensure memory safety.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m__call__\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 570\u001b[0m raise TypeError(\"Keyword arguments {} unknown. Expected {}.\".format(\n\u001b[1;32m 571\u001b[0m list(kwargs.keys()), list(self._arg_keywords)))\n\u001b[0;32m--> 572\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_call_flat\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[0m\u001b[1;32m 573\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 574\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0m_filtered_call\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[0mkwargs\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36m_call_flat\u001b[0;34m(self, args)\u001b[0m\n\u001b[1;32m 669\u001b[0m \u001b[0;31m# Only need to override the gradient in graph mode and when we have outputs.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 670\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcontext\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecuting_eagerly\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moutputs\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 671\u001b[0;31m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_inference_function\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mctx\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[0m\u001b[1;32m 672\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 673\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_register_gradient\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/usr/local/lib/python3.6/dist-packages/tensorflow/python/eager/function.py\u001b[0m in \u001b[0;36mcall\u001b[0;34m(self, ctx, args)\u001b[0m\n\u001b[1;32m 443\u001b[0m attrs=(\"executor_type\", executor_type,\n\u001b[1;32m 444\u001b[0m \"config_proto\", config),\n\u001b[0;32m--> 445\u001b[0;31m ctx=ctx)\n\u001b[0m\u001b[1;32m 446\u001b[0m \u001b[0;31m# Replace empty list with None\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 447\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0moutputs\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/tensorflow/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: " + ] + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "apSpY04_op7G", + "colab_type": "text" + }, + "source": [ + "# Kast Training" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Z_qa1ZZphR7b", + "colab_type": "code", + "colab": {} + }, + "source": [ + "os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + "os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "dq7R3gYehrjC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "label_dict = spit_l.kast_label_dict()\n", + "preproc_dict = spit_p.original_preproc_dict()\n", + "classify_dict = spit_l.kast_classify_dict(label_dict)\n", + "\n", + "# kast = c.Classifier(label_dict, preproc_dict, classify_dict)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "F5jRzrjpOlFq", + "colab_type": "text" + }, + "source": [ + "# methods" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "j2gL32rpHo_h", + "colab_type": "code", + "colab": {} + }, + "source": [ + " os.environ['SPIT_PATH'] = \"/content/drive/My Drive/Colab Notebooks/SPIT_DATA\"\n", + " os.environ['SAVE_PATH'] = \"/content/drive/My Drive/Colab Notebooks/\"\n", + "\n", + " # might need to add subset\n", + " def _train(epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, test_model=None, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')):\n", + " \"\"\"\n", + "\n", + " Trains the classifier with given images, labels, and training parameters.\n", + "\n", + " Parameters:\n", + "\n", + " :param epochs:\n", + " Number of epochs of the training. \n", + " Must be an integer value.\n", + "\n", + " :param batch_size:\n", + " Size of the training batches formed in the process. \n", + " Must be an integer value.\n", + "\n", + " :param save_path:\n", + " Path to where the best model will be saved.\n", + "\n", + " :param train_images:\n", + " Set of images for model to train on.\n", + " Assume this is a numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param train_labels:\n", + " Set of test labels corresponding to test images.\n", + " Assume this is a rank 1 array with (batch_size, ) as its dimensions.\n", + "\n", + " :param validation_data:\n", + " Data to be used for the validation set. \n", + " Assume this is a tuple with (images, labels) with same dimensions as train_images, train_labels.\n", + " If None is specified, validation_data will be None.\n", + "\n", + " :param steps_per_epoch:\n", + " Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch.\n", + " Assume this is an integer value. If None is specified, this will be None. \n", + "\n", + " :param validation_freq:\n", + " Specifies how many training epochs to run before a new validation run is performed.\n", + " Assume this is an integer value or a collection containing the epochs at which to run validation (ie [1,2,10]).\n", + "\n", + " :param test_model:\n", + " An alternative choice for model to train on. Assume None.\n", + "\n", + " :param spit_path & param save_path:\n", + " Path to the spit images and where the model will be saved respectively.\n", + " ***Environmental variables must be set by caller or the path must be passed manually.***\n", + "\n", + " Returns:\n", + " :returns history:\n", + " Tensorflow History object containing loss and accuracy data over the training.\n", + "\n", + " \"\"\"\n", + " # choose the model\n", + " if test_model is None:\n", + " model = test_model\n", + " else:\n", + " model = test_model\n", + "\n", + " # if None is passed, then use the kast images\n", + " if train_images is None or train_labels is None:\n", + " # load training set\n", + " train = np.load(os.path.join(spit_path, 'Kast', 'kast_train.npz'))\n", + " train_images = train['images']\n", + " train_labels = train['labels']\n", + "\n", + " # load validation set\n", + " validate = np.load(os.path.join(spit_path, 'Kast', 'kast_validate.npz'))\n", + " v_images = validate['images']\n", + " v_labels = validate['labels']\n", + "\n", + " validation_data = (v_images, v_labels)\n", + "\n", + " # change to categorical and make subsets\n", + " if validation_data is not None:\n", + " valid_images, valid_labels = validation_data\n", + " if subset_percent is not None:\n", + " valid_images, valid_labels = split_array(valid_images, valid_labels, subset_percent)\n", + " valid_labels = keras.utils.to_categorical(valid_labels, num_classes=len(label_dict))\n", + " validation_data = (valid_images, valid_labels)\n", + "\n", + " if train_images is not None and train_labels is not None:\n", + " if subset_percent is not None:\n", + " train_images, train_labels = split_array(train_images, train_labels, subset_percent)\n", + " train_labels = keras.utils.to_categorical(train_labels, num_classes=len(label_dict))\n", + "\n", + " # checkpoint to track best model\n", + " checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_accuracy', save_best_only=True, mode='max')\n", + "\n", + " # train the model\n", + " history = model.fit(\n", + " train_images, \n", + " train_labels, \n", + " epochs=epochs, \n", + " batch_size=batch_size,\n", + " validation_data=validation_data,\n", + " steps_per_epoch=steps_per_epoch,\n", + " validation_freq=validation_freq,\n", + " callbacks=[checkpoint]\n", + " )\n", + " \n", + " # save loss and accuracy data\n", + " keys = history.history\n", + " np.savez_compressed('history.npz', loss=keys['loss'], accuracy=keys['accuracy'], val_loss=keys['val_loss'], val_accuracy=keys['val_accuracy'])\n", + " \n", + " return history\n", + "\n", + " import math\n", + "\n", + " def split_array(images, labels, subset_percent):\n", + " \"\"\"\n", + " Splits dataset based on a percentage value.\n", + "\n", + " Parameters:\n", + " :param images:\n", + " Images from a dataset to be trained on.\n", + " 4-D Numpy array with (batch_size, width, height, num_channels) as its dimensions.\n", + "\n", + " :param labels:\n", + " Labels from a dataset to be trained on.\n", + " Rank 1 Numpy array with (batch_size,) as its dimensions.\n", + "\n", + " :param subset_percent:\n", + " Float value determining percentage of subset to remain.\n", + "\n", + " Returns:\n", + " :returns split_images:\n", + " Numpy array containing a fraction of the initial images parameter (batch_size*subset_percent)\n", + "\n", + " :returns split_labels:\n", + " Numpy array containing a fraction of the initial labels parameter (batch_size*subset_percent)\n", + " \"\"\"\n", + " split_images = []\n", + " split_labels = []\n", + " \n", + " # get all unique labels\n", + " uni_lbls = np.unique(labels)\n", + " \n", + " # find all instances of labels and subset based on that\n", + " for uni_lbl in uni_lbls:\n", + " idx = np.where(labels==uni_lbl)[0]\n", + " # 0 : len(idx)*subset_percent\n", + " lower = 0\n", + " upper = int(math.floor(len(idx)*subset_percent))\n", + " split_images.extend(images[idx[lower:upper]])\n", + " split_labels.extend(labels[idx[lower:upper]])\n", + " return np.asarray(split_images), np.asarray(split_labels)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "CcL6lUUUTu9v", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def load_model(file_name, file_path):\n", + " '''\n", + " :param file_name: The model name. Should be a string 'blah.h5'\n", + " file_path: The path that the user would like to save to.\n", + " In the form of 'blah/foo/bar/'\n", + " :return: the model loaded\n", + " '''\n", + "\n", + " loaded_model = keras.models.load_model(file_path+file_name)\n", + " return loaded_model" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "mn9Hwj-5R5ah", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def predict_one_image(images, model):\n", + " \n", + " ishape = list(images.shape)\n", + " images = images.reshape(ishape+[1])\n", + " \n", + " prediction = model.predict(images)\n", + " return prediction" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "86K2i_7oSHxd", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def get_prediction(images_array, model, use_heuristics=False):\n", + " \"\"\"\n", + "\n", + " Returns\n", + " -------\n", + " value : int\n", + " Most common value or -1, if it is not the majority\n", + " results : list\n", + " All of the values for each flipped image\n", + " \"\"\"\n", + " from collections import Counter\n", + " \n", + " # Classify all 4\n", + " results = []\n", + " results.append(np.argmax(predict_one_image(images_array[0:1,:], model)))\n", + " results.append(np.argmax(predict_one_image(images_array[1:2,:], model)))\n", + " results.append(np.argmax(predict_one_image(images_array[2:3,:], model)))\n", + " results.append(np.argmax(predict_one_image(images_array[3:4,:], model)))\n", + " resultsCounter = Counter(results)\n", + "\n", + " # Heuristics\n", + " if use_heuristics:\n", + " if results.count(2) >= 2:\n", + " value = 2\n", + " elif results.count(1) >= 2:\n", + " value = 1\n", + " else:\n", + " value, _ = resultsCounter.most_common()[0]\n", + " else: # Majority rules\n", + " value, n_occur = resultsCounter.most_common()[0]\n", + " if n_occur <= 2:\n", + " value = -1\n", + " # Return\n", + " return value, results" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "Stz37NfnbBdC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "from matplotlib import pyplot as plt\n", + "\n", + "def display_training_trends(history, key1, key2, title='training'):\n", + " \"\"\"\n", + " Display the graphs of loss/accuracy during training\n", + " \n", + " :param history:\n", + " Tensorflow History object or Numpy Decompressed File object.\n", + " :param key1:\n", + " Key contained within history object that user can provide to plot as compared with other keys.\n", + " Assume key is a string contained in the history object.\n", + " :param key2:\n", + " Key contained within history object that user can provide to plot as compared with other keys.\n", + " Assume key is a string contained in the history object.\n", + " :param title:\n", + " Title of the graph. If caller doesn't specify, use default of 'training'.\n", + " \"\"\"\n", + " h = None\n", + " if 'tensorflow' in str(type(history)):\n", + " h = history.history\n", + " print(\"h is history.history\")\n", + " else:\n", + " h = history\n", + " print(\"h is history\")\n", + " print(h)\n", + " # make subplots\n", + " fig, ax1 = plt.subplots()\n", + "\n", + " # set title of graph\n", + " plt.title(title) \n", + "\n", + " # set x label\n", + " color = 'tab:red'\n", + " ax1.set_xlabel('epochs')\n", + "\n", + " # plot first key\n", + " ax1.set_ylabel(key1, color=color) # we already handled the x-label with ax1\n", + " lns1 = ax1.plot(h[key1], color=color, label = key1) # maybe improve labeling \n", + " ax1.tick_params(axis='y')\n", + "\n", + " color = 'tab:blue'\n", + " legend_loc = 'best'\n", + "\n", + " # instantiate a second axes that shares the same x-axis\n", + " ax2 = ax1.twinx() \n", + "\n", + " # plot second key\n", + " ax2.set_ylabel(key2, color=color) # we already handled the x-label with ax1\n", + " lns2 = ax2.plot(h[key2], color=color, label = key2)\n", + " ax2.tick_params(axis='y') #labelcolor=color\n", + "\n", + " # legend for two axes\n", + " lines, labels = ax1.get_legend_handles_labels()\n", + " lines2, labels2 = ax2.get_legend_handles_labels()\n", + " ax2.legend(lines + lines2, labels + labels2, loc=legend_loc)\n", + "\n", + " fig.tight_layout() # otherwise the right y-label is slightly clipped\n", + " plt.show()" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "gn87-HJKzeA_", + "colab_type": "text" + }, + "source": [ + "# Experiments" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "yCRFaYL6D0MU", + "colab_type": "code", + "outputId": "cf495336-faac-45e2-efd1-b3c2fce2b9da", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 136 + } + }, + "source": [ + "# test all methods working, 1.1, 100 epochs\n", + "history = _train(epochs=3, batch_size=6, subset_percent=0.01, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Train on 155 samples, validate on 35 samples\n", + "Epoch 1/3\n", + "155/155 [==============================] - 3s 18ms/sample - loss: 0.1421 - accuracy: 0.9742 - val_loss: 7.3406 - val_accuracy: 0.3714\n", + "Epoch 2/3\n", + "155/155 [==============================] - 2s 13ms/sample - loss: 0.0708 - accuracy: 0.9677 - val_loss: 5.2303 - val_accuracy: 0.6000\n", + "Epoch 3/3\n", + "155/155 [==============================] - 2s 13ms/sample - loss: 0.1345 - accuracy: 0.9613 - val_loss: 2.0834 - val_accuracy: 0.7143\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "Uzx0pjRrJJSq", + "colab_type": "code", + "outputId": "ece02477-7464-46b8-c74b-d82b3602756b", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 331 + } + }, + "source": [ + "# load history, make graph of accuracy vs. validation accuracy\n", + "# load history still\n", + "history = np.load('history.npz')\n", + "str(type(history))\n", + "display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "h is history\n", + "\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n9P8jK1U9nqVMRAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "mppUuQLlb1y0", + "colab_type": "code", + "outputId": "c7863927-51fb-4500-addb-e12dba864df4", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 351 + } + }, + "source": [ + "display_training_trends(history, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "h is history.history\n", + "{'loss': [0.14205214455235568, 0.07079402762615393, 0.13445983527260155], 'accuracy': [0.9741936, 0.9677419, 0.9612903], 'val_loss': [7.340566403525216, 5.230261066981725, 2.083380366223199], 'val_accuracy': [0.37142858, 0.6, 0.71428573]}\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n9P8jK1U9nqVMRAAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "louAKyNzTO_3", + "colab_type": "code", + "outputId": "5c667e69-30f9-432c-fe35-6ae6fe75634e", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "# do final evaluation on test data\n", + "\n", + "best_model = keras.models.load_model(os.environ['SAVE_PATH']+'best_model.h5')\n", + "test = np.load(os.path.join(os.environ['SPIT_PATH'], 'Kast', 'kast_test.npz'))\n", + "test_images = test['images']\n", + "test_labels = test['labels']\n", + "test_labels = keras.utils.to_categorical(test_labels, num_classes=len(label_dict))\n", + "best_model.evaluate(test_images, test_labels) " + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "4840/4840 [==============================] - 10s 2ms/sample - loss: 3.0653 - accuracy: 0.6748\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[3.0652541778069673, 0.67479336]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 61 + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "36Et1fSgpAKo", + "colab_type": "text" + }, + "source": [ + "# Run train and test" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "BZFRsXkNpCdp", + "colab_type": "code", + "outputId": "8e128448-0054-4955-9891-3d78dc20cd06", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + } + }, + "source": [ + "# full train, 1.1, 100 epochs\n", + "history = _train(epochs=100, batch_size=6, test_model=model)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0731 20:34:14.287537 139970689517440 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + }, + { + "output_type": "stream", + "text": [ + "Train on 15540 samples, validate on 3880 samples\n", + "Epoch 1/100\n", + "15540/15540 [==============================] - 195s 13ms/sample - loss: 0.3477 - accuracy: 0.8950 - val_loss: 0.1821 - val_accuracy: 0.9557\n", + "Epoch 2/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.1231 - accuracy: 0.9623 - val_loss: 2.2725 - val_accuracy: 0.7487\n", + "Epoch 3/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.1008 - accuracy: 0.9721 - val_loss: 0.0440 - val_accuracy: 0.9910\n", + "Epoch 4/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0744 - accuracy: 0.9784 - val_loss: 0.2489 - val_accuracy: 0.9242\n", + "Epoch 5/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0654 - accuracy: 0.9808 - val_loss: 0.0383 - val_accuracy: 0.9907\n", + "Epoch 6/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0668 - accuracy: 0.9819 - val_loss: 0.0403 - val_accuracy: 0.9884\n", + "Epoch 7/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0449 - accuracy: 0.9875 - val_loss: 0.0408 - val_accuracy: 0.9874\n", + "Epoch 8/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0469 - accuracy: 0.9872 - val_loss: 0.0732 - val_accuracy: 0.9812\n", + "Epoch 9/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0346 - accuracy: 0.9896 - val_loss: 0.0697 - val_accuracy: 0.9753\n", + "Epoch 10/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0310 - accuracy: 0.9909 - val_loss: 0.0698 - val_accuracy: 0.9781\n", + "Epoch 11/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0292 - accuracy: 0.9916 - val_loss: 0.0395 - val_accuracy: 0.9866\n", + "Epoch 12/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0279 - accuracy: 0.9924 - val_loss: 0.0236 - val_accuracy: 0.9969\n", + "Epoch 13/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0264 - accuracy: 0.9927 - val_loss: 0.0580 - val_accuracy: 0.9869\n", + "Epoch 14/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0262 - accuracy: 0.9920 - val_loss: 0.0474 - val_accuracy: 0.9871\n", + "Epoch 15/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0218 - accuracy: 0.9949 - val_loss: 0.0825 - val_accuracy: 0.9812\n", + "Epoch 16/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0199 - accuracy: 0.9940 - val_loss: 0.0380 - val_accuracy: 0.9912\n", + "Epoch 17/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0202 - accuracy: 0.9949 - val_loss: 0.0643 - val_accuracy: 0.9879\n", + "Epoch 18/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0145 - accuracy: 0.9959 - val_loss: 0.0319 - val_accuracy: 0.9902\n", + "Epoch 19/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0157 - accuracy: 0.9956 - val_loss: 0.0217 - val_accuracy: 0.9959\n", + "Epoch 20/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0191 - accuracy: 0.9950 - val_loss: 0.0485 - val_accuracy: 0.9804\n", + "Epoch 21/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0195 - accuracy: 0.9955 - val_loss: 0.0226 - val_accuracy: 0.9969\n", + "Epoch 22/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0150 - accuracy: 0.9962 - val_loss: 0.0431 - val_accuracy: 0.9881\n", + "Epoch 23/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0193 - accuracy: 0.9954 - val_loss: 0.0297 - val_accuracy: 0.9941\n", + "Epoch 24/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0129 - accuracy: 0.9968 - val_loss: 0.0631 - val_accuracy: 0.9861\n", + "Epoch 25/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0123 - accuracy: 0.9968 - val_loss: 0.1862 - val_accuracy: 0.9603\n", + "Epoch 26/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0141 - accuracy: 0.9962 - val_loss: 0.0328 - val_accuracy: 0.9912\n", + "Epoch 27/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0127 - accuracy: 0.9965 - val_loss: 0.0949 - val_accuracy: 0.9835\n", + "Epoch 28/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0158 - accuracy: 0.9955 - val_loss: 0.0473 - val_accuracy: 0.9920\n", + "Epoch 29/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0162 - accuracy: 0.9950 - val_loss: 0.0918 - val_accuracy: 0.9804\n", + "Epoch 30/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0121 - accuracy: 0.9970 - val_loss: 0.0265 - val_accuracy: 0.9933\n", + "Epoch 31/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0098 - accuracy: 0.9976 - val_loss: 0.0503 - val_accuracy: 0.9869\n", + "Epoch 32/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0111 - accuracy: 0.9968 - val_loss: 0.0195 - val_accuracy: 0.9972\n", + "Epoch 33/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0060 - accuracy: 0.9987 - val_loss: 0.0571 - val_accuracy: 0.9889\n", + "Epoch 34/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0129 - accuracy: 0.9967 - val_loss: 0.0193 - val_accuracy: 0.9974\n", + "Epoch 35/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0106 - accuracy: 0.9978 - val_loss: 0.0182 - val_accuracy: 0.9979\n", + "Epoch 36/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0119 - accuracy: 0.9970 - val_loss: 0.0521 - val_accuracy: 0.9907\n", + "Epoch 37/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0092 - accuracy: 0.9973 - val_loss: 0.0350 - val_accuracy: 0.9902\n", + "Epoch 38/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0083 - accuracy: 0.9977 - val_loss: 0.0444 - val_accuracy: 0.9887\n", + "Epoch 39/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0095 - accuracy: 0.9974 - val_loss: 0.0345 - val_accuracy: 0.9954\n", + "Epoch 40/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0078 - accuracy: 0.9977 - val_loss: 0.0323 - val_accuracy: 0.9866\n", + "Epoch 41/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0075 - accuracy: 0.9979 - val_loss: 0.0443 - val_accuracy: 0.9918\n", + "Epoch 42/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0089 - accuracy: 0.9976 - val_loss: 0.0400 - val_accuracy: 0.9897\n", + "Epoch 43/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0068 - accuracy: 0.9981 - val_loss: 0.0874 - val_accuracy: 0.9825\n", + "Epoch 44/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0068 - accuracy: 0.9981 - val_loss: 0.0417 - val_accuracy: 0.9902\n", + "Epoch 45/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0111 - accuracy: 0.9976 - val_loss: 0.1110 - val_accuracy: 0.9740\n", + "Epoch 46/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0048 - accuracy: 0.9986 - val_loss: 0.0625 - val_accuracy: 0.9943\n", + "Epoch 47/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0098 - accuracy: 0.9979 - val_loss: 0.1032 - val_accuracy: 0.9822\n", + "Epoch 48/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0067 - accuracy: 0.9985 - val_loss: 0.0553 - val_accuracy: 0.9889\n", + "Epoch 49/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0064 - accuracy: 0.9984 - val_loss: 0.0547 - val_accuracy: 0.9861\n", + "Epoch 50/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0063 - accuracy: 0.9984 - val_loss: 0.0409 - val_accuracy: 0.9910\n", + "Epoch 51/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0086 - accuracy: 0.9976 - val_loss: 0.0772 - val_accuracy: 0.9840\n", + "Epoch 52/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0117 - accuracy: 0.9972 - val_loss: 0.0388 - val_accuracy: 0.9918\n", + "Epoch 53/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0043 - accuracy: 0.9988 - val_loss: 0.0694 - val_accuracy: 0.9881\n", + "Epoch 54/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0111 - accuracy: 0.9974 - val_loss: 0.0410 - val_accuracy: 0.9933\n", + "Epoch 55/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0070 - accuracy: 0.9981 - val_loss: 0.0426 - val_accuracy: 0.9894\n", + "Epoch 56/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0068 - accuracy: 0.9979 - val_loss: 0.0575 - val_accuracy: 0.9894\n", + "Epoch 57/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0075 - accuracy: 0.9979 - val_loss: 0.0514 - val_accuracy: 0.9881\n", + "Epoch 58/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0055 - accuracy: 0.9988 - val_loss: 0.0882 - val_accuracy: 0.9858\n", + "Epoch 59/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0116 - accuracy: 0.9972 - val_loss: 0.0593 - val_accuracy: 0.9915\n", + "Epoch 60/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0057 - accuracy: 0.9985 - val_loss: 0.0348 - val_accuracy: 0.9948\n", + "Epoch 61/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0060 - accuracy: 0.9978 - val_loss: 0.0913 - val_accuracy: 0.9851\n", + "Epoch 62/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0073 - accuracy: 0.9979 - val_loss: 0.0624 - val_accuracy: 0.9892\n", + "Epoch 63/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0041 - accuracy: 0.9988 - val_loss: 0.0508 - val_accuracy: 0.9915\n", + "Epoch 64/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0134 - accuracy: 0.9976 - val_loss: 0.0629 - val_accuracy: 0.9912\n", + "Epoch 65/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0042 - accuracy: 0.9986 - val_loss: 0.0664 - val_accuracy: 0.9871\n", + "Epoch 66/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0057 - accuracy: 0.9985 - val_loss: 0.3607 - val_accuracy: 0.9536\n", + "Epoch 67/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0053 - accuracy: 0.9984 - val_loss: 0.0459 - val_accuracy: 0.9884\n", + "Epoch 68/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0062 - accuracy: 0.9978 - val_loss: 0.0483 - val_accuracy: 0.9915\n", + "Epoch 69/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0039 - accuracy: 0.9989 - val_loss: 0.0806 - val_accuracy: 0.9866\n", + "Epoch 70/100\n", + "15540/15540 [==============================] - 181s 12ms/sample - loss: 0.0048 - accuracy: 0.9986 - val_loss: 0.0428 - val_accuracy: 0.9946\n", + "Epoch 71/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0063 - accuracy: 0.9983 - val_loss: 0.0397 - val_accuracy: 0.9951\n", + "Epoch 72/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0063 - accuracy: 0.9981 - val_loss: 0.0492 - val_accuracy: 0.9892\n", + "Epoch 73/100\n", + "15540/15540 [==============================] - 182s 12ms/sample - loss: 0.0049 - accuracy: 0.9985 - val_loss: 0.0564 - val_accuracy: 0.9892\n", + "Epoch 74/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0050 - accuracy: 0.9984 - val_loss: 0.0357 - val_accuracy: 0.9943\n", + "Epoch 75/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0052 - accuracy: 0.9985 - val_loss: 0.0371 - val_accuracy: 0.9959\n", + "Epoch 76/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0045 - accuracy: 0.9990 - val_loss: 0.1074 - val_accuracy: 0.9827\n", + "Epoch 77/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0061 - accuracy: 0.9979 - val_loss: 0.0539 - val_accuracy: 0.9918\n", + "Epoch 78/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0042 - accuracy: 0.9986 - val_loss: 0.0491 - val_accuracy: 0.9956\n", + "Epoch 79/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0056 - accuracy: 0.9981 - val_loss: 0.0550 - val_accuracy: 0.9936\n", + "Epoch 80/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0039 - accuracy: 0.9989 - val_loss: 0.0423 - val_accuracy: 0.9915\n", + "Epoch 81/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0052 - accuracy: 0.9984 - val_loss: 0.0481 - val_accuracy: 0.9892\n", + "Epoch 82/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0065 - accuracy: 0.9981 - val_loss: 0.0473 - val_accuracy: 0.9920\n", + "Epoch 83/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0028 - accuracy: 0.9990 - val_loss: 0.0346 - val_accuracy: 0.9936\n", + "Epoch 84/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0057 - accuracy: 0.9981 - val_loss: 0.0427 - val_accuracy: 0.9936\n", + "Epoch 85/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0056 - accuracy: 0.9987 - val_loss: 0.0354 - val_accuracy: 0.9969\n", + "Epoch 86/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0024 - accuracy: 0.9993 - val_loss: 0.0576 - val_accuracy: 0.9943\n", + "Epoch 87/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0063 - accuracy: 0.9988 - val_loss: 0.0441 - val_accuracy: 0.9915\n", + "Epoch 88/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0049 - accuracy: 0.9983 - val_loss: 0.0494 - val_accuracy: 0.9923\n", + "Epoch 89/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0033 - accuracy: 0.9988 - val_loss: 0.0359 - val_accuracy: 0.9964\n", + "Epoch 90/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0082 - accuracy: 0.9976 - val_loss: 0.0915 - val_accuracy: 0.9871\n", + "Epoch 91/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0032 - accuracy: 0.9992 - val_loss: 0.0501 - val_accuracy: 0.9884\n", + "Epoch 92/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0056 - accuracy: 0.9983 - val_loss: 0.0335 - val_accuracy: 0.9979\n", + "Epoch 93/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0049 - accuracy: 0.9988 - val_loss: 0.0525 - val_accuracy: 0.9899\n", + "Epoch 94/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0051 - accuracy: 0.9988 - val_loss: 0.0476 - val_accuracy: 0.9928\n", + "Epoch 95/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0044 - accuracy: 0.9986 - val_loss: 0.0392 - val_accuracy: 0.9954\n", + "Epoch 96/100\n", + "15540/15540 [==============================] - 185s 12ms/sample - loss: 0.0044 - accuracy: 0.9984 - val_loss: 0.0701 - val_accuracy: 0.9905\n", + "Epoch 97/100\n", + "15540/15540 [==============================] - 184s 12ms/sample - loss: 0.0064 - accuracy: 0.9981 - val_loss: 0.0408 - val_accuracy: 0.9954\n", + "Epoch 98/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0026 - accuracy: 0.9991 - val_loss: 0.0840 - val_accuracy: 0.9835\n", + "Epoch 99/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0058 - accuracy: 0.9986 - val_loss: 0.0784 - val_accuracy: 0.9920\n", + "Epoch 100/100\n", + "15540/15540 [==============================] - 183s 12ms/sample - loss: 0.0069 - accuracy: 0.9980 - val_loss: 0.0337 - val_accuracy: 0.9959\n" + ], + "name": "stdout" + }, + { + "output_type": "stream", + "text": [ + "Exception ignored in: >\n", + "Traceback (most recent call last):\n", + " File \"/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py\", line 230, in __del__\n", + " self.close()\n", + " File \"/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py\", line 225, in close\n", + " self.fid.close()\n", + "OSError: [Errno 107] Transport endpoint is not connected\n", + "Exception ignored in: >\n", + "Traceback (most recent call last):\n", + " File \"/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py\", line 230, in __del__\n", + " self.close()\n", + " File \"/usr/local/lib/python3.6/dist-packages/numpy/lib/npyio.py\", line 225, in close\n", + " self.fid.close()\n", + "OSError: [Errno 107] Transport endpoint is not connected\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "KGwNwYNFpsy5", + "colab_type": "code", + "outputId": "b899a89a-5538-4eff-8f4b-0293382176bb", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 331 + } + }, + "source": [ + "# load history, make graph of accuracy vs. validation accuracy\n", + "h = np.load('history.npz')\n", + "display_training_trends(h, key1='accuracy', key2='val_accuracy')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "h is history\n", + "\n" + ], + "name": "stdout" + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "55fdt7SHpP64", + "colab_type": "code", + "outputId": "a3aae31a-adc8-4e0c-b43b-4b287d1e5073", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 105 + } + }, + "source": [ + "# load best model for evaluation\n", + "best_model = keras.models.load_model(os.environ['SAVE_PATH']+'best_model.h5')" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "WARNING: Logging before flag parsing goes to stderr.\n", + "W0801 19:57:40.582382 140149520967552 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/math_grad.py:1250: add_dispatch_support..wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n", + "Instructions for updating:\n", + "Use tf.where in 2.0, which has the same broadcast rule as np.where\n" + ], + "name": "stderr" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "HLJ-3bilpQyY", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# load test data\n", + "test = np.load(os.path.join(os.environ['SPIT_PATH'], 'Kast', 'kast_test.npz'))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "6Y2APAdjpWaC", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# parse test data\n", + "test_images = test['images']\n", + "test_labels = test['labels']" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "vmeCYZidpYmm", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# prepare labels for evaluation\n", + "test_labels = keras.utils.to_categorical(test_labels, num_classes=len(label_dict))" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "-mWesG-yphCV", + "colab_type": "code", + "outputId": "a7991f6f-4cd0-402e-9863-fe5e227144fb", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "# run evaluation\n", + "best_model.evaluate(test_images, test_labels) " + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "4840/4840 [==============================] - 10s 2ms/sample - loss: 0.0563 - accuracy: 0.9915\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "[0.05634400943170428, 0.9915289]" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 32 + } + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "sTyihTc1Tcsy", + "colab_type": "text" + }, + "source": [ + "# Confusion Matrix" + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "KJ0u2jXiTfw-", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# make confusion matrix\n", + "from sklearn.metrics import confusion_matrix" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "RQCrtJZgk1hi", + "colab_type": "code", + "colab": {} + }, + "source": [ + "values=[]\n", + "results=[]" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "l2mYutv1k2_t", + "colab_type": "code", + "outputId": "90d8f22e-3895-4fda-ea3b-471e3c9a86df", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + } + }, + "source": [ + "for image in test_images:\n", + " print(image)\n", + " flip_images = spit_p.flips(image)\n", + " images_array = np.array(list(flip_images))\n", + " value, result = get_prediction(images_array, best_model, use_heuristics=True)\n", + " values.append(value)\n", + " results.append(result)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "[[[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [54]\n", + " [54]\n", + " [ 0]]\n", + "\n", + " [[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [54]\n", + " [53]\n", + " [ 0]]\n", + "\n", + " [[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [54]\n", + " [53]\n", + " [ 0]]\n", + "\n", + " ...\n", + "\n", + " [[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [51]\n", + " [50]\n", + " [ 0]]\n", + "\n", + " [[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [50]\n", + " [50]\n", + " [ 0]]\n", + "\n", + " [[ 0]\n", + " [ 0]\n", + " [ 0]\n", + " ...\n", + " [50]\n", + " [50]\n", + " [ 0]]]\n" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "TypeError", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/PIL/Image.py\u001b[0m in \u001b[0;36mfromarray\u001b[0;34m(obj, mode)\u001b[0m\n\u001b[1;32m 2415\u001b[0m \u001b[0mtypekey\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mshape\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'typestr'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2416\u001b[0;31m \u001b[0mmode\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mrawmode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_fromarray_typemap\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mtypekey\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 2417\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyError\u001b[0m: ((1, 1, 1), '|u1')", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mimage\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtest_images\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimage\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mflip_images\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mspit_p\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mflips\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimage\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 4\u001b[0m \u001b[0mimages_array\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflip_images\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 5\u001b[0m \u001b[0mvalue\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mget_prediction\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimages_array\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbest_model\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0muse_heuristics\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;32mTrue\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/content/spit/spit/preprocess.py\u001b[0m in \u001b[0;36mflips\u001b[0;34m(image)\u001b[0m\n\u001b[1;32m 91\u001b[0m \u001b[0mFlipped\u001b[0m \u001b[0mboth\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 92\u001b[0m \"\"\"\n\u001b[0;32m---> 93\u001b[0;31m \u001b[0mpil_image\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mImage\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfromarray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimage\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 94\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 95\u001b[0m \u001b[0;31m# Generate flipped images\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/PIL/Image.py\u001b[0m in \u001b[0;36mfromarray\u001b[0;34m(obj, mode)\u001b[0m\n\u001b[1;32m 2417\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2418\u001b[0m \u001b[0;31m# print(typekey)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2419\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mTypeError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Cannot handle this data type\"\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 2420\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 2421\u001b[0m \u001b[0mrawmode\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmode\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: Cannot handle this data type" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "fte5kwcHk4u8", + "colab_type": "code", + "colab": {} + }, + "source": [ + "val_true = test['labels']" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "UJ-FTRrgUgOV", + "colab_type": "code", + "colab": {} + }, + "source": [ + "# import scikit learn confusion matrix\n", + "# load the best model\n", + "# load the test data\n", + "# use model.predict and save the values into predictions \n", + "predictions = best_model.predict(test_images)\n", + "# call confusion matrix with true_labels, predictions" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "6_yW70w6k7oZ", + "colab_type": "code", + "outputId": "beb20e4a-1474-45b8-ee30-f46b2140be37", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 307 + } + }, + "source": [ + "cm = confusion_matrix(test_labels, predictions)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "error", + "ename": "ValueError", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\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[0mcm\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mconfusion_matrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtest_labels\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mpredictions\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/usr/local/lib/python3.6/dist-packages/sklearn/metrics/classification.py\u001b[0m in \u001b[0;36mconfusion_matrix\u001b[0;34m(y_true, y_pred, labels, sample_weight)\u001b[0m\n\u001b[1;32m 251\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 252\u001b[0m \"\"\"\n\u001b[0;32m--> 253\u001b[0;31m \u001b[0my_type\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_true\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_pred\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_check_targets\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_true\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my_pred\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 254\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0my_type\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;34m\"binary\"\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m\"multiclass\"\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 255\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mValueError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"%s is not supported\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0my_type\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/sklearn/metrics/classification.py\u001b[0m in \u001b[0;36m_check_targets\u001b[0;34m(y_true, y_pred)\u001b[0m\n\u001b[1;32m 79\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0my_type\u001b[0m\u001b[0;34m)\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[1;32m 80\u001b[0m raise ValueError(\"Classification metrics can't handle a mix of {0} \"\n\u001b[0;32m---> 81\u001b[0;31m \"and {1} targets\".format(type_true, type_pred))\n\u001b[0m\u001b[1;32m 82\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 83\u001b[0m \u001b[0;31m# We can't have more than one value on y_type => The set is no more needed\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: Classification metrics can't handle a mix of multiclass and continuous-multioutput targets" + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "NE7_LgfFU2yk", + "colab_type": "code", + "outputId": "659ac85b-8f5b-4caa-9579-aa3d1dbf8ce0", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 238 + } + }, + "source": [ + "print(predictions)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "[[2.85231066e-16 1.79409751e-17 3.06095007e-14 1.49503822e-25\n", + " 1.00000000e+00]\n", + " [4.58994449e-16 1.26381336e-17 2.18457691e-14 8.49186578e-26\n", + " 1.00000000e+00]\n", + " [2.35157878e-12 1.23956607e-12 3.07840246e-11 1.83119176e-19\n", + " 1.00000000e+00]\n", + " ...\n", + " [1.80569292e-11 1.00000000e+00 6.79828527e-10 1.08981726e-15\n", + " 5.19909981e-18]\n", + " [1.37923174e-13 1.00000000e+00 2.29849598e-10 1.33276689e-17\n", + " 9.08066113e-21]\n", + " [2.39914425e-12 1.00000000e+00 1.75397241e-09 1.19341822e-17\n", + " 4.30210459e-19]]\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "wwTPeXWxXfOf", + "colab_type": "code", + "outputId": "3014cfd6-9071-4855-9db6-ad9eec277daa", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 34 + } + }, + "source": [ + "print(test_labels)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "[4 4 4 ... 1 1 1]\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "TbU3cZo4Xxom", + "colab_type": "code", + "outputId": "afb93da9-94d3-4324-b008-83626e2d58b6", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "maxElement = np.amax(predictions[0])\n", + "maxIndex = np.where(predictions[0] == maxElement)\n", + "print(maxElement)\n", + "print(maxIndex[0][0])\n" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "1.0\n", + "4\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "KoAGQamPYJLs", + "colab_type": "code", + "colab": {} + }, + "source": [ + "pred = []\n", + "for p in enumerate(predictions):\n", + " # index of loop\n", + " i = p[0]\n", + " # particular prediction array for this image\n", + " p_array = p[1]\n", + " # find and append prediction\n", + " maxIndex = np.where(p_array == np.amax(p_array))\n", + " pred.append(maxIndex[0][0])" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "73fppFMyZxdQ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "cm = confusion_matrix(test_labels, pred)" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "SSAEGyHLcBDZ", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def plot_confusion_matrix(y_true, y_pred, classes,\n", + " normalize=False,\n", + " title=None,\n", + " cmap=plt.cm.Blues):\n", + " \"\"\"\n", + " This function prints and plots the confusion matrix.\n", + " Normalization can be applied by setting `normalize=True`.\n", + " \"\"\"\n", + " if not title:\n", + " if normalize:\n", + " title = 'Normalized confusion matrix'\n", + " else:\n", + " title = 'Confusion matrix, without normalization'\n", + "\n", + " # Compute confusion matrix\n", + " cm = confusion_matrix(y_true, y_pred)\n", + "# # Only use the labels that appear in the data\n", + "# classes = classes[unique_labels(y_true, y_pred)]\n", + " if normalize:\n", + " cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis]\n", + " print(\"Normalized confusion matrix\")\n", + " else:\n", + " print('Confusion matrix, without normalization')\n", + "\n", + " print(cm)\n", + "\n", + " fig, ax = plt.subplots()\n", + " im = ax.imshow(cm, interpolation='nearest', cmap=cmap)\n", + " ax.figure.colorbar(im, ax=ax)\n", + " # We want to show all ticks...\n", + " ax.set(xticks=np.arange(cm.shape[1]),\n", + " yticks=np.arange(cm.shape[0]),\n", + " # ... and label them with the respective list entries\n", + " xticklabels=classes, yticklabels=classes,\n", + " title=title,\n", + " ylabel='True label',\n", + " xlabel='Predicted label')\n", + "\n", + " # Rotate the tick labels and set their alignment.\n", + " plt.setp(ax.get_xticklabels(), rotation=45, ha=\"right\",\n", + " rotation_mode=\"anchor\")\n", + "\n", + " # Loop over data dimensions and create text annotations.\n", + " fmt = '.2f' if normalize else 'd'\n", + " thresh = cm.max() / 2.\n", + " for i in range(cm.shape[0]):\n", + " for j in range(cm.shape[1]):\n", + " ax.text(j, i, format(cm[i, j], fmt),\n", + " ha=\"center\", va=\"center\",\n", + " color=\"white\" if cm[i, j] > thresh else \"black\")\n", + " fig.tight_layout()\n", + " return ax" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "ZWMaLPgJeW5d", + "colab_type": "code", + "outputId": "5b2c8a15-66b9-4cfd-db7b-130208351d7d", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 51 + } + }, + "source": [ + "# plot_confusion_matrix(test_labels, pred, )\n", + "print(label_dict)\n", + "classes = []\n", + "for label in label_dict:\n", + " if '_label' in label:\n", + " label = label.replace('_label','')\n", + " classes.append(label)\n", + "print(classes)\n", + "# classes = {x.replace('_label', '') for x in classes}\n", + "# print(classes)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "OrderedDict([('bias_label', 0), ('science_label', 1), ('standard_label', 2), ('arc_label', 3), ('flat_label', 4)])\n", + "['bias', 'science', 'standard', 'arc', 'flat']\n" + ], + "name": "stdout" + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "EZJ05u96eu2f", + "colab_type": "code", + "outputId": "d1b8d2a5-700a-4ee2-896a-ecb9b81f7839", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 416 + } + }, + "source": [ + "plot_confusion_matrix(test_labels, pred, classes)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "Confusion matrix, without normalization\n", + "[[968 0 0 0 0]\n", + " [ 0 960 8 0 0]\n", + " [ 0 31 937 0 0]\n", + " [ 0 0 0 968 0]\n", + " [ 2 0 0 0 966]]\n" + ], + "name": "stdout" + }, + { + "output_type": "execute_result", + "data": { + "text/plain": [ + "" + ] + }, + "metadata": { + "tags": [] + }, + "execution_count": 28 + }, + { + "output_type": "display_data", + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "tags": [] + } + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "osD11krukQu7", + "colab_type": "code", + "outputId": "c7fae7a6-2dc2-4db6-f8c3-7c20fbeb8be8", + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000 + } + }, + "source": [ + "flip_images = []\n", + "for image in test_images:\n", + " flip_images.extend(flips(image.astype(np.uint8)))\n", + "print(flip_images)" + ], + "execution_count": 0, + "outputs": [ + { + "output_type": "stream", + "text": [ + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n", + "finished flip\n" + ], + "name": "stdout" + }, + { + "output_type": "error", + "ename": "KeyboardInterrupt", + "evalue": "ignored", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mimage\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mtest_images\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[0mflip_images\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mextend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflips\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mimage\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mastype\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0muint8\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----> 4\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mflip_images\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/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36m_array_repr_implementation\u001b[0;34m(arr, max_line_width, precision, suppress_small, array2string)\u001b[0m\n\u001b[1;32m 1417\u001b[0m \u001b[0;32melif\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\u001b[0m \u001b[0;34m==\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[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1418\u001b[0m lst = array2string(arr, max_line_width, precision, suppress_small,\n\u001b[0;32m-> 1419\u001b[0;31m ', ', prefix, suffix=suffix)\n\u001b[0m\u001b[1;32m 1420\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# show zero-length shape unless it is (0,)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1421\u001b[0m \u001b[0mlst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"[], shape=%s\"\u001b[0m \u001b[0;34m%\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mrepr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mshape\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/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36marray2string\u001b[0;34m(a, max_line_width, precision, suppress_small, separator, prefix, style, formatter, threshold, edgeitems, sign, floatmode, suffix, **kwarg)\u001b[0m\n\u001b[1;32m 688\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;34m\"[]\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 689\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 690\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0m_array2string\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mseparator\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mprefix\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 691\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 692\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36mwrapper\u001b[0;34m(self, *args, **kwargs)\u001b[0m\n\u001b[1;32m 468\u001b[0m \u001b[0mrepr_running\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0madd\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 469\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--> 470\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\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 471\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 472\u001b[0m \u001b[0mrepr_running\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdiscard\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mkey\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36m_array2string\u001b[0;34m(a, options, separator, prefix)\u001b[0m\n\u001b[1;32m 503\u001b[0m lst = _formatArray(a, format_function, options['linewidth'],\n\u001b[1;32m 504\u001b[0m \u001b[0mnext_line_prefix\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mseparator\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'edgeitems'\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--> 505\u001b[0;31m summary_insert, options['legacy'])\n\u001b[0m\u001b[1;32m 506\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mlst\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 507\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36m_formatArray\u001b[0;34m(a, format_function, line_width, next_line_prefix, separator, edge_items, summary_insert, legacy)\u001b[0m\n\u001b[1;32m 816\u001b[0m return recurser(index=(),\n\u001b[1;32m 817\u001b[0m \u001b[0mhanging_indent\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mnext_line_prefix\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 818\u001b[0;31m curr_width=line_width)\n\u001b[0m\u001b[1;32m 819\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 820\u001b[0m \u001b[0;31m# recursive closures have a cyclic reference to themselves, which\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36mrecurser\u001b[0;34m(index, hanging_indent, curr_width)\u001b[0m\n\u001b[1;32m 802\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtrailing_items\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\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[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 803\u001b[0m nested = recurser(index + (-i,), next_hanging_indent,\n\u001b[0;32m--> 804\u001b[0;31m next_width)\n\u001b[0m\u001b[1;32m 805\u001b[0m \u001b[0ms\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0mhanging_indent\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mnested\u001b[0m \u001b[0;34m+\u001b[0m \u001b[0mline_sep\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 806\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/usr/local/lib/python3.6/dist-packages/numpy/core/arrayprint.py\u001b[0m in \u001b[0;36mrecurser\u001b[0;34m(index, hanging_indent, curr_width)\u001b[0m\n\u001b[1;32m 749\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0maxes_left\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[1;32m 750\u001b[0m \u001b[0;31m# the length up until the beginning of the separator / bracket\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 751\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mlegacy\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m'1.13'\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 752\u001b[0m \u001b[0melem_width\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mcurr_width\u001b[0m \u001b[0;34m-\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mseparator\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrstrip\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[1;32m 753\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;31mKeyboardInterrupt\u001b[0m: " + ] + } + ] + }, + { + "cell_type": "code", + "metadata": { + "id": "GEH2x6UauHyd", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def horizontal_flip(image_array):\n", + " # horizontal flip doesn't need skimage, it's easy as flipping the image array of pixels !\n", + " return image_array[:, ::-1]" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "hg-km-KGzYAW", + "colab_type": "code", + "colab": {} + }, + "source": [ + "def flips(image_array, rotations=4):\n", + " flips = []\n", + " for i in range(rotations):\n", + " image_array = horizontal_flip(image_array)\n", + " flips.extend(image_array)\n", + " print(\"finished flip\")\n", + " return flips" + ], + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "metadata": { + "id": "MiFrpAbf0Hdq", + "colab_type": "code", + "colab": {} + }, + "source": [ + "" + ], + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/spit/classifier.py b/spit/classifier.py index 5237b53..dee5004 100644 --- a/spit/classifier.py +++ b/spit/classifier.py @@ -17,21 +17,29 @@ class Classifier(object): # For Kast, label_dict = labels.kast_label_dict() # preproc_dict = preprocess.original_preproc_dict() # classify_dict = labels.kast_classify_dict(label_dict) - def __init__(self, label_dict, preproc_dict, classify_dict, **kwargs): + def __init__(self, label_dict, preproc_dict, classify_dict, architecture="DenseNet", **kwargs): self.label_dict = label_dict.copy() self.preproc_dict = preproc_dict.copy() # is this for prediction? <---- self.classify_dict = classify_dict.copy() - # Set up tensorflow/keras model - self.init_session() + # hyperparameters + self.filters = 64 + self.dropout_rate = .2 + # self.theta = .5 + self.growth_rate = 4 + if "DenseNet" in architecture: + self.init_dense_net() + else: + # Set up cnn + self.init_cnn() # One major change from tf1.0 to tf2.0 # is that tf.layers module no longer relies on tf.variable_scope # and no more use of tf.placeholder # no more session.run() although not actual functioning originally - def init_session(self): + def init_cnn(self): # building a simple model # linear stack of layers @@ -59,7 +67,86 @@ def init_session(self): self.model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])#, rate=1e-4) return + # need to add compression to either block, transition, or both to get it to be BC + def dense_block(self): + """ + Adds a dense block to the densenet model + Parameters: None + Returns: None + """ + # 1x1 convolution bottleneck + self.model.add(keras.layers.BatchNormalization()) + self.model.add(keras.layers.ReLU()) + #### HYPERPARAMETERS: GROWTH RATE AND DROPOUT RATE #### + self.model.add(keras.layers.Conv2D(self.growth_rate*self.filters, kernel_size=1)) + self.model.add(keras.layers.Dropout(rate=self.dropout_rate)) + # 3x3 dense convolution + self.model.add(keras.layers.BatchNormalization()) + self.model.add(keras.layers.ReLU()) + #### HYPERPARAMETER #### + self.model.add(keras.layers.Conv2D(self.filters, kernel_size=3)) + #### HYPERPARAMETER #### + self.model.add(keras.layers.Dropout(rate=self.dropout_rate)) + + return + + def transition_layer(self): + """ + Adds a transition layer to the DenseNet. + + Parameters: None + Returns: None + """ + self.model.add(keras.layers.BatchNormalization()) + self.model.add(keras.layers.ReLU()) + self.model.add(keras.layers.Conv2D(self.filters, kernel_size=1)) + self.model.add(keras.layers.Dropout(rate=self.dropout_rate)) + self.model.add(keras.layers.AveragePooling2D(pool_size=(2,2), strides=2)) + return + + def init_dense_net(self): + #### DENSE NET ARCHITECTURE ##### + # + # CONV --> BLOCK --> TRANSITION --> BLOCK --> TRANSITION --> BLOCK --> POOL --> SOFTMAX + # + # BLOCK: + # BatchNorm --> ReLu --> Conv (1x1) --> DropOut --> BatchNorm --> ReLu --> Conv (3x3) --> DropOut --> output + """ + Builds a DenseNet-B model for the Classifier. + + Parameters: None + Returns: None + """ + self.model = keras.Sequential() + + # add a conv layer + self.model.add(keras.layers.Conv2D(self.filters, kernel_size=7, strides=(2, 2), padding='valid', activation='relu', + input_shape = (210, 650, 1))) + + # pool like in tf simple implementation + self.model.add(keras.layers.MaxPooling2D(pool_size=(3, 3), strides=2, padding='valid')) + + # add block + self.dense_block() + # add transition + self.transition_layer() + # add block + self.dense_block() + # add transition + self.transition_layer() + # add block + self.dense_block() + # add pool + self.model.add(keras.layers.GlobalAveragePooling2D()) + # add flatten + self.model.add(keras.layers.Flatten()) + + # Produce 0-1 probabilities with softmax + self.model.add(keras.layers.Dense(len(self.label_dict), activation='softmax')) + + self.model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) + def load_model(self, file_name, file_path): ''' diff --git a/spit/train.py b/spit/train.py index 08caf9c..880a988 100644 --- a/spit/train.py +++ b/spit/train.py @@ -31,43 +31,62 @@ # Counter for total number of iterations performed so far. total_iterations = 0 -def train_model(model, epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')): +def train_model(epochs, batch_size, subset_percent=None, train_images=None, train_labels=None, validation_data=None, steps_per_epoch=None, validation_freq=1, test_model=None, spit_path=os.getenv('SPIT_PATH'), save_path=os.getenv('SAVE_PATH')): """ + Trains the classifier with given images, labels, and training parameters. + Parameters: - :param model: - A Keras model to be trained. + :param epochs: Number of epochs of the training. Must be an integer value. + :param batch_size: Size of the training batches formed in the process. Must be an integer value. + :param save_path: Path to where the best model will be saved. + :param train_images: Set of images for model to train on. Assume this is a numpy array with (batch_size, width, height, num_channels) as its dimensions. + :param train_labels: Set of test labels corresponding to test images. Assume this is a rank 1 array with (batch_size, ) as its dimensions. + :param validation_data: Data to be used for the validation set. Assume this is a tuple with (images, labels) with same dimensions as train_images, train_labels. If None is specified, validation_data will be None. + :param steps_per_epoch: Total number of steps (batches of samples) before declaring one epoch finished and starting the next epoch. Assume this is an integer value. If None is specified, this will be None. + :param validation_freq: Specifies how many training epochs to run before a new validation run is performed. Assume this is an integer value or a collection containing the epochs at which to run validation (ie [1,2,10]). + + :param test_model: + An alternative choice for model to train on. Assume None. + :param spit_path & param save_path: Path to the spit images and where the model will be saved respectively. ***Environmental variables must be set by caller or the path must be passed manually.*** + Returns: :returns history: Tensorflow History object containing loss and accuracy data over the training. + """ + # choose the model + if test_model is None: + model = test_model + else: + model = test_model # if None is passed, then use the kast images if train_images is None or train_labels is None: @@ -87,17 +106,17 @@ def train_model(model, epochs, batch_size, subset_percent=None, train_images=Non if validation_data is not None: valid_images, valid_labels = validation_data if subset_percent is not None: - valid_images, valid_labels = self.model.split_array(valid_images, valid_labels, subset_percent) + valid_images, valid_labels = split_array(valid_images, valid_labels, subset_percent) valid_labels = keras.utils.to_categorical(valid_labels, num_classes=len(label_dict)) validation_data = (valid_images, valid_labels) if train_images is not None and train_labels is not None: if subset_percent is not None: - train_images, train_labels = self.model.split_array(train_images, train_labels, subset_percent) + train_images, train_labels = split_array(train_images, train_labels, subset_percent) train_labels = keras.utils.to_categorical(train_labels, num_classes=len(label_dict)) # checkpoint to track best model - checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_acc', save_best_only=True, mode='max') + checkpoint=keras.callbacks.ModelCheckpoint(save_path+'best_model.h5', monitor='val_accuracy', save_best_only=True, mode='max') # train the model history = model.fit( @@ -110,14 +129,11 @@ def train_model(model, epochs, batch_size, subset_percent=None, train_images=Non validation_freq=validation_freq, callbacks=[checkpoint] ) - # loss and accuracy data + + # save loss and accuracy data keys = history.history - # save to disc differently based on whether validation set was used - if len(history.history.keys()) == 2: # can we abstract this away? - np.savez_compressed('history.npz', loss=keys['loss'], accuracy=keys['accuracy']) #can these keys be abstracted away? - else: - np.savez_compressed('history.npz', loss=keys['loss'], accuracy=keys['accuracy'], val_loss=keys['val_loss'], val_accuracy=keys['val_accuracy']) - + np.savez_compressed('history.npz', loss=keys['loss'], accuracy=keys['accuracy'], val_loss=keys['val_loss'], val_accuracy=keys['val_accuracy']) + return history def split_array(images, labels, subset_percent): diff --git a/spit/utils.py b/spit/utils.py index 5d15131..bb8032a 100644 --- a/spit/utils.py +++ b/spit/utils.py @@ -137,7 +137,7 @@ def display_training_trends(history, key1, key2, title='training'): Display the graphs of loss/accuracy during training :param history: - Tensorflow History object given after calling Keras' fit() method on your model. + Tensorflow History object or Numpy Decompressed File object. :param key1: Key contained within history object that user can provide to plot as compared with other keys. Assume key is a string contained in the history object. @@ -147,6 +147,11 @@ def display_training_trends(history, key1, key2, title='training'): :param title: Title of the graph. If caller doesn't specify, use default of 'training'. """ + h = None + if 'tensorflow' in str(type(history)): + h = history.history + else: + h = history # make subplots fig, ax1 = plt.subplots() @@ -159,18 +164,18 @@ def display_training_trends(history, key1, key2, title='training'): # plot first key ax1.set_ylabel(key1, color=color) # we already handled the x-label with ax1 - lns1 = ax1.plot(history.history[key1], color=color, label = key1) # maybe improve labeling + lns1 = ax1.plot(h[key1], color=color, label = key1) # maybe improve labeling ax1.tick_params(axis='y') color = 'tab:blue' - legend_loc = 'upper right' + legend_loc = 'best' # instantiate a second axes that shares the same x-axis ax2 = ax1.twinx() # plot second key ax2.set_ylabel(key2, color=color) # we already handled the x-label with ax1 - lns2 = ax2.plot(history.history[key2], color=color, label = key2) + lns2 = ax2.plot(h[key2], color=color, label = key2) ax2.tick_params(axis='y') #labelcolor=color # legend for two axes