Skip to content

Instantly share code, notes, and snippets.

@shadaj
Last active October 8, 2021 21:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shadaj/29d77180aeefc41a749273026f7d1fd9 to your computer and use it in GitHub Desktop.
Save shadaj/29d77180aeefc41a749273026f7d1fd9 to your computer and use it in GitHub Desktop.
Scala CNN Training on GPUs with Tensorflow.ipynb
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Scala CNN Training on GPUs with Tensorflow.ipynb",
"provenance": [],
"collapsed_sections": [],
"toc_visible": true,
"include_colab_link": true
},
"kernelspec": {
"display_name": "Scala",
"language": "scala",
"name": "scala"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/shadaj/29d77180aeefc41a749273026f7d1fd9/scala-cnn-training-on-gpus-with-tensorflow.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "up2G8zDbhsEN"
},
"source": [
"# Scala CNN Training on GPUs with Tensorflow\n",
"\n",
"In this notebook, based on the [Intro to CNNs](https://github.com/tensorflow/docs/blob/master/site/en/r2/tutorials/images/intro_to_cnns.ipynb) notebook in the TensorFlow docs, we'll set up a CNN based model to classify images in the MNIST dataset. This is a good example of where GPUs can accelerate neural network training. To test out running Scala notebooks with GPU acceleration, go to `Runtime > Change Runtime Type` and switch the `Hardware accelerator` to `GPU`."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "sL1Vq6r6J6dA"
},
"source": [
"## Install the Scala Kernel\n",
"If you get a \"scala\" kernel not recognized warning when loading up the notebook for the first time, start by running the two cells below. Once you are done **reload the page** to load the notebook in the installed Scala kernel."
]
},
{
"cell_type": "code",
"metadata": {
"id": "RoCcdvTCAqeR"
},
"source": [
"%%shell\n",
"SCALA_VERSION=2.12.8 ALMOND_VERSION=0.3.0+16-548dc10f-SNAPSHOT\n",
"curl -Lo coursier https://git.io/coursier-cli\n",
"chmod +x coursier\n",
"./coursier bootstrap \\\n",
" -r jitpack -r sonatype:snapshots \\\n",
" -i user -I user:sh.almond:scala-kernel-api_$SCALA_VERSION:$ALMOND_VERSION \\\n",
" sh.almond:scala-kernel_$SCALA_VERSION:$ALMOND_VERSION \\\n",
" --sources --default=true \\\n",
" -o almond-snapshot --embed-files=false\n",
"rm coursier\n",
"./almond-snapshot --install --global --force\n",
"rm almond-snapshot"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "BZchIo9sArF4"
},
"source": [
"%%shell\n",
"echo \"{\n",
" \\\"language\\\" : \\\"scala\\\",\n",
" \\\"display_name\\\" : \\\"Scala\\\",\n",
" \\\"argv\\\" : [\n",
" \\\"bash\\\",\n",
" \\\"-c\\\",\n",
" \\\"env SCALAPY_PYTHON_LIBRARY=python3.6m java -Djna.library.path=/usr/lib/x86_64-linux-gnu/ -jar /usr/local/share/jupyter/kernels/scala/launcher.jar --connection-file {connection_file}\\\"\n",
" ]\n",
"}\" > /usr/local/share/jupyter/kernels/scala/kernel.json"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"metadata": {
"id": "rKC7qVeNERA0"
},
"source": [
"## Load ScalaPy and TensorFlow\n",
"First, we install ScalaPy and initialize a Python bridge with it."
]
},
{
"cell_type": "code",
"metadata": {
"id": "a9z0PxRg_iOp",
"outputId": "b6ce99b4-c724-46f1-9398-fa82883858c2",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"import $ivy.`me.shadaj::scalapy-core:0.4.0`\n",
"\n",
"import me.shadaj.scalapy.py\n",
"import me.shadaj.scalapy.py.SeqConverters"
],
"execution_count": 1,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[32mimport \u001b[39m\u001b[36m$ivy.$ \n",
"\n",
"\u001b[39m\n",
"\u001b[32mimport \u001b[39m\u001b[36mme.shadaj.scalapy.py\n",
"\u001b[39m\n",
"\u001b[32mimport \u001b[39m\u001b[36mme.shadaj.scalapy.py.SeqConverters\u001b[39m"
]
},
"metadata": {
"tags": []
},
"execution_count": 1
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "06odcMWf7iMJ"
},
"source": [
"We install a small hook (that will soon be part of ScalaPy) that redirects Python's output so that we can see it in the notebook."
]
},
{
"cell_type": "code",
"metadata": {
"id": "cNYA6LGK5yT6",
"outputId": "f8ddae36-7666-4cae-aa63-87218aa16d17",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"import me.shadaj.scalapy.interpreter.CPythonInterpreter\n",
"val sys = py.module(\"sys\")\n",
"CPythonInterpreter.execManyLines(\n",
" \"\"\"class OutputRedirector:\n",
" | def __init__(self, write_fn, flush_fn):\n",
" | self.write_fn = write_fn\n",
" | self.flush_fn = flush_fn\n",
" | def write(self, text):\n",
" | self.write_fn(text)\n",
" | def flush(self):\n",
" | self.flush_fn()\"\"\".stripMargin\n",
")\n",
"\n",
"val stdoutRedirector = py.Dynamic.global.OutputRedirector(\n",
" py.Any.from((text: String) => {\n",
" System.out.print(text)\n",
" py.None\n",
" }),\n",
" py.Any.from(() => {\n",
" System.out.flush()\n",
" py.None\n",
" })\n",
")\n",
"\n",
"sys.stdout = stdoutRedirector\n",
"\n",
"val stderrRedirector = py.Dynamic.global.OutputRedirector(\n",
" py.Any.from((text: String) => {\n",
" System.err.print(text)\n",
" py.None\n",
" }),\n",
" py.Any.from(() => {\n",
" System.err.flush()\n",
" py.None\n",
" })\n",
")\n",
"\n",
"sys.stderr = stderrRedirector"
],
"execution_count": 2,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[32mimport \u001b[39m\u001b[36mme.shadaj.scalapy.interpreter.CPythonInterpreter\n",
"\u001b[39m\n",
"\u001b[36msys\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mModule\u001b[39m = <module 'sys' (built-in)>\n",
"\u001b[36mstdoutRedirector\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <OutputRedirector object at 0x7f65e79510b8>\n",
"\u001b[36mstderrRedirector\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <OutputRedirector object at 0x7f65e79512b0>"
]
},
"metadata": {
"tags": []
},
"execution_count": 2
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "3kCyr5CJEhpo"
},
"source": [
"With ScalaPy loaded, we can now import NumPy and TensorFlow. Note that for now the modules are being treated as dynamic types, because static definitions for Keras are [not yet ready](https://github.com/shadaj/scalapy-tensorflow/issues/2)."
]
},
{
"cell_type": "code",
"metadata": {
"id": "P0GAG5u0E8nU",
"outputId": "c0cce7a7-8dc0-470c-8b82-458021dbfb96",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"val np = py.module(\"numpy\")\n",
"val tf = py.module(\"tensorflow\")"
],
"execution_count": 3,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mnp\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mModule\u001b[39m = <module 'numpy' from '/usr/local/lib/python3.6/dist-packages/numpy/__init__.py'>\n",
"\u001b[36mtf\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mModule\u001b[39m = <module 'tensorflow' from '/usr/local/lib/python3.6/dist-packages/tensorflow/__init__.py'>"
]
},
"metadata": {
"tags": []
},
"execution_count": 3
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "twQgZnO0FTI_"
},
"source": [
"## Download and prepare the MNIST dataset"
]
},
{
"cell_type": "code",
"metadata": {
"id": "1SxIrEEgFVIC",
"outputId": "b6308474-f1b3-4a8c-80d5-004a1a8623c8",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"val (mnistTrain, mnistTest) = tf.keras.datasets.mnist.load_data()\n",
" .as[((py.Dynamic, py.Dynamic), (py.Dynamic, py.Dynamic))]\n",
"\n",
"val trainImagesRaw = mnistTrain._1.reshape((60000, 28, 28, 1))\n",
"val testImagesRaw = mnistTest._1.reshape((10000, 28, 28, 1))\n",
"\n",
"val trainLabels = mnistTrain._2\n",
"val testLabels = mnistTest._2\n",
"\n",
"// Normalize pixel values to be between 0 and 1\n",
"val trainImages = trainImagesRaw / 255.0\n",
"val testImages = testImagesRaw / 255.0"
],
"execution_count": 4,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mmnistTrain\u001b[39m: (\u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m, \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m) = (\n",
" [[[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" ...\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
"...\n",
"\u001b[36mmnistTest\u001b[39m: (\u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m, \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m) = (\n",
" [[[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" ...\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]]\n",
"\n",
" [[0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" [0 0 0 ... 0 0 0]\n",
" ...\n",
"...\n",
"\u001b[36mtrainImagesRaw\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [[[[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" ...\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
"...\n",
"\u001b[36mtestImagesRaw\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [[[[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" ...\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
" [0]\n",
" [0]]\n",
"\n",
" [[0]\n",
" [0]\n",
" [0]\n",
" ...\n",
" [0]\n",
"...\n",
"\u001b[36mtrainLabels\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [5 0 4 ... 5 6 8]\n",
"\u001b[36mtestLabels\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [7 2 1 ... 4 5 6]\n",
"\u001b[36mtrainImages\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [[[[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" ...\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
"...\n",
"\u001b[36mtestImages\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = [[[[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" ...\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
" [0.]\n",
" [0.]]\n",
"\n",
" [[0.]\n",
" [0.]\n",
" [0.]\n",
" ...\n",
" [0.]\n",
"..."
]
},
"metadata": {
"tags": []
},
"execution_count": 4
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5NqvcyyJGZoD"
},
"source": [
"## Create the convolutional base\n",
"The lines of code below define the convolutional base using a common pattern: a stack of Conv2D and MaxPooling2D layers.\n",
"\n",
"As input, a CNN takes tensors of shape (image_height, image_width, color_channels), ignoring the batch size. If you are new to color channels, MNIST has one (because the images are grayscale), whereas a color image has three (R,G,B). In this example, we will configure our CNN to process inputs of shape (28, 28, 1), which is the format of MNIST images. We do this by passing the argument input_shape to our first layer."
]
},
{
"cell_type": "code",
"metadata": {
"id": "dThibDe7GcL7",
"outputId": "58fdcfa9-26fa-406f-c454-a09c458003d1",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"val models = tf.keras.models\n",
"val layers = tf.keras.layers\n",
"\n",
"val model = models.Sequential()\n",
"model.add(layers.Conv2D(filters = 32, kernel_size = (3, 3), activation = \"relu\", input_shape = (28, 28, 1)))\n",
"model.add(layers.MaxPooling2D((2, 2)))\n",
"model.add(layers.Conv2D(filters = 64, kernel_size = (3, 3), activation = \"relu\"))\n",
"model.add(layers.MaxPooling2D((2, 2)))\n",
"model.add(layers.Conv2D(filters = 64, kernel_size = (3, 3), activation = \"relu\"))"
],
"execution_count": 5,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mmodels\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <module 'tensorflow.keras.models' from '/usr/local/lib/python3.6/dist-packages/tensorflow/keras/models/__init__.py'>\n",
"\u001b[36mlayers\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <module 'tensorflow.keras.layers' from '/usr/local/lib/python3.6/dist-packages/tensorflow/keras/layers/__init__.py'>\n",
"\u001b[36mmodel\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <tensorflow.python.keras.engine.sequential.Sequential object at 0x7f65dff23358>\n",
"\u001b[36mres4_3\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres4_4\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres4_5\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres4_6\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres4_7\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None"
]
},
"metadata": {
"tags": []
},
"execution_count": 5
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Klf3qUYl7UkH"
},
"source": [
"Let's display the architecture of our model so far."
]
},
{
"cell_type": "code",
"metadata": {
"id": "UmPF69ZY7OcA",
"outputId": "e65d2a4f-afc7-4b4b-a645-d2d0be99eaed",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"model.summary()"
],
"execution_count": 6,
"outputs": [
{
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"conv2d (Conv2D) (None, 26, 26, 32) 320 \n",
"_________________________________________________________________\n",
"max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0 \n",
"_________________________________________________________________\n",
"conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 \n",
"_________________________________________________________________\n",
"max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 \n",
"=================================================================\n",
"Total params: 55,744\n",
"Trainable params: 55,744\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mres5\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None"
]
},
"metadata": {
"tags": []
},
"execution_count": 6
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XVT285fz94Nw"
},
"source": [
"Above, you can see that the output of every Conv2D and MaxPooling2D layer is a 3D tensor of shape (height, width, channels). The width and height dimensions tend to shrink as we go deeper in the network. The number of output channels for each Conv2D layer is controlled by the first argument (e.g., 32 or 64). Typically, as the width and height shrink, we can afford (computationally) to add more output channels in each Conv2D layer."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "gJ294pF0IL6t"
},
"source": [
"## Add Dense layers on top\n",
"To complete our model, we will feed the last output tensor from the convolutional base (of shape (3, 3, 64)) into one or more Dense layers to perform classification. Dense layers take vectors as input (which are 1D), while the current output is a 3D tensor. First, we will flatten (or unroll) the 3D output to 1D, then add one or more Dense layers on top. MNIST has 10 output classes, so we use a final Dense layer with 10 outputs and a softmax activation."
]
},
{
"cell_type": "code",
"metadata": {
"id": "WayPSv83IN2i",
"outputId": "3e030b13-751c-4063-80e0-fff4aeac133a",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"model.add(layers.Flatten())\n",
"model.add(layers.Dense(units = 64, activation = \"relu\"))\n",
"model.add(layers.Dense(units = 10, activation = \"softmax\"))"
],
"execution_count": 7,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mres6_0\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres6_1\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres6_2\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None"
]
},
"metadata": {
"tags": []
},
"execution_count": 7
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "oJEPAIH87bY8"
},
"source": [
"Here's the complete architecture of our model."
]
},
{
"cell_type": "code",
"metadata": {
"id": "KtXNDArL7dfy",
"outputId": "e8295df1-eced-4bee-9b1d-9bab0520610c",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"model.summary()"
],
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"text": [
"Model: \"sequential\"\n",
"_________________________________________________________________\n",
"Layer (type) Output Shape Param # \n",
"=================================================================\n",
"conv2d (Conv2D) (None, 26, 26, 32) 320 \n",
"_________________________________________________________________\n",
"max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0 \n",
"_________________________________________________________________\n",
"conv2d_1 (Conv2D) (None, 11, 11, 64) 18496 \n",
"_________________________________________________________________\n",
"max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64) 0 \n",
"_________________________________________________________________\n",
"conv2d_2 (Conv2D) (None, 3, 3, 64) 36928 \n",
"_________________________________________________________________\n",
"flatten (Flatten) (None, 576) 0 \n",
"_________________________________________________________________\n",
"dense (Dense) (None, 64) 36928 \n",
"_________________________________________________________________\n",
"dense_1 (Dense) (None, 10) 650 \n",
"=================================================================\n",
"Total params: 93,322\n",
"Trainable params: 93,322\n",
"Non-trainable params: 0\n",
"_________________________________________________________________\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mres7\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None"
]
},
"metadata": {
"tags": []
},
"execution_count": 8
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "fikkpRsC99P3"
},
"source": [
"As you can see, our (3, 3, 64) outputs were flattened into vectors of shape (576) before going through two Dense layers."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "T77j61MfIYCz"
},
"source": [
"## Compile and train the model"
]
},
{
"cell_type": "code",
"metadata": {
"id": "d2NZxwAbIa_U",
"outputId": "9df1fd0c-ab47-44e2-b6e7-cdf44a4aafaf",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"model.compile(optimizer = \"adam\",\n",
" loss = \"sparse_categorical_crossentropy\",\n",
" metrics = py.Dynamic.global.list(Seq(\"accuracy\").toPythonProxy))\n",
"model.fit(x = trainImages, y = trainLabels, epochs = 5)"
],
"execution_count": 9,
"outputs": [
{
"output_type": "stream",
"text": [
"Epoch 1/5\n",
"1875/1875 [==============================] - 6s 3ms/step - loss: 0.1462 - accuracy: 0.9552\n",
"Epoch 2/5\n",
"1875/1875 [==============================] - 5s 3ms/step - loss: 0.0471 - accuracy: 0.9850\n",
"Epoch 3/5\n",
"1875/1875 [==============================] - 5s 3ms/step - loss: 0.0327 - accuracy: 0.9896\n",
"Epoch 4/5\n",
"1875/1875 [==============================] - 5s 3ms/step - loss: 0.0240 - accuracy: 0.9926\n",
"Epoch 5/5\n",
"1875/1875 [==============================] - 5s 3ms/step - loss: 0.0188 - accuracy: 0.9937\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mres8_0\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = None\n",
"\u001b[36mres8_1\u001b[39m: \u001b[32mpy\u001b[39m.\u001b[32mDynamic\u001b[39m = <tensorflow.python.keras.callbacks.History object at 0x7f6590137f60>"
]
},
"metadata": {
"tags": []
},
"execution_count": 9
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "LUoVzi8lJrPz"
},
"source": [
"## Evaluate the model"
]
},
{
"cell_type": "code",
"metadata": {
"id": "kI0PNJJcJs7o",
"outputId": "450ac6a8-3fd7-4735-9565-4b84a211906b",
"colab": {
"base_uri": "https://localhost:8080/"
}
},
"source": [
"val Seq(testLoss, testAcc) = model.evaluate(testImages, testLabels).as[Seq[Double]]"
],
"execution_count": 10,
"outputs": [
{
"output_type": "stream",
"text": [
"313/313 [==============================] - 1s 2ms/step - loss: 0.0300 - accuracy: 0.9916\n"
],
"name": "stdout"
},
{
"output_type": "execute_result",
"data": {
"text/plain": [
"\u001b[36mtestLoss\u001b[39m: \u001b[32mDouble\u001b[39m = \u001b[32m0.02996871992945671\u001b[39m\n",
"\u001b[36mtestAcc\u001b[39m: \u001b[32mDouble\u001b[39m = \u001b[32m0.991599977016449\u001b[39m"
]
},
"metadata": {
"tags": []
},
"execution_count": 10
}
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "mb3nMADG-Cwd"
},
"source": [
"As you can see, our simple CNN has achieved a test accuracy of over 99%. Not bad for a few lines of code!"
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment