diff --git a/notebooks/04_Image_Data_CNN.ipynb b/notebooks/04_Image_Data_CNN.ipynb index e09edb3..fe1daab 100644 --- a/notebooks/04_Image_Data_CNN.ipynb +++ b/notebooks/04_Image_Data_CNN.ipynb @@ -1,7 +1,6 @@ { "cells": [ { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -15,7 +14,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -26,7 +24,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -34,13 +31,12 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "If we consider the simplified network inputs are passed to the neurons in the network. \n", - "Each input is weighted by a value, $w_{ij}$ and the sum of these weighted inputs is operated on by a response or activation function $f(\\theta)$, which transform the input signal so that it varies between 0 and 1 through the application of a nonlinear response. T\n", - "he output from any neuron is then given by,\n", + "Each input is weighted by a value, $w_{ij}$ and the sum of these weighted inputs is operated on by a response or activation function $f(\\theta)$, which transform the input signal so that it varies between 0 and 1 through the application of a nonlinear response. \n", + "The output from any neuron is then given by,\n", "\n", "$$\n", "a_j = f \\left( \\sum_i w_{ij} x_i + b_j \\right)\n", @@ -50,7 +46,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -95,7 +90,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -114,7 +108,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -188,7 +181,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -224,9 +216,11 @@ "val_frac = 0.1\n", "test_frac = 0.2\n", "# Note: we have to use train_test_split twice\n", - "data_train_val, data_test, class_train_val, class_test = train_test_split(input_stamps, stamp_class, test_size=test_frac)\n", + "data_train_val, data_test, class_train_val, class_test = train_test_split(\n", + " input_stamps, stamp_class, test_size=test_frac, random_state=42\n", + ")\n", "data_train, data_val, class_train, class_val = train_test_split(\n", - " input_stamps, stamp_class, test_size=val_frac / (train_frac + val_frac)\n", + " input_stamps, stamp_class, test_size=val_frac / (train_frac + val_frac), random_state=42\n", ")\n", "\n", "data_train, class_train = reshape_arrays(data_train, class_train)\n", @@ -234,12 +228,15 @@ "data_test, class_test = reshape_arrays(data_test, class_test)\n", "\n", "print(\n", - " f\"Number of samples in the training ({data_train.shape[0]}); test ({data_train.shape[0]}); and validation ({data_val.shape[0]}) data sets\"\n", + " f\"Number of samples in the training ({data_train.shape[0]}); test ({data_test.shape[0]}); and validation ({data_val.shape[0]}) data sets\"\n", + ")\n", + "\n", + "print(\n", + " f\"Fraction of true samples in the training ({np.sum(class_train[:,0])/data_train.shape[0]}); test ({np.sum(class_test[:,0])/data_test.shape[0]}); and validation ({np.sum(class_val[:,0])/data_val.shape[0]}) data sets\"\n", ")" ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -268,7 +265,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -286,7 +282,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -297,7 +292,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -364,7 +358,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -427,7 +420,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -501,7 +493,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -523,7 +514,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -531,7 +521,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -591,21 +580,22 @@ " model = Sequential(name=\"VGG6\")\n", " # input: 21x21 images with 1 channel -> (21, 21, 1) tensors.\n", " # this applies 16 convolution filters of size 3x3 each.\n", - " model.add(Conv2D(16, (3, 3), activation=\"relu\", input_shape=input_shape, name=\"conv1\"))\n", - " model.add(Conv2D(16, (3, 3), activation=\"relu\", name=\"conv2\"))\n", - " model.add(MaxPooling2D(pool_size=(2, 2)))\n", - " model.add(Dropout(0.25))\n", + " model.add(Conv2D(16, (3, 3), input_shape=input_shape, name=\"conv1\", padding=\"same\"))\n", + " model.add(BatchNormalization(axis=3, name=\"bn_1\"))\n", + " model.add(Activation(\"relu\", name=\"relu_1\"))\n", + " model.add(MaxPooling2D(pool_size=(2, 2), name=\"pool_1\"))\n", + " model.add(Dropout(0.25, name=\"dropout_1\"))\n", "\n", - " model.add(Conv2D(32, (3, 3), activation=\"relu\", name=\"conv3\"))\n", - " model.add(Conv2D(32, (3, 3), activation=\"relu\", name=\"conv4\"))\n", + " model.add(Conv2D(32, (3, 3), name=\"conv2\", padding=\"same\"))\n", " model.add(BatchNormalization(axis=3, name=\"bn_2\"))\n", - " model.add(MaxPooling2D(pool_size=(4, 4)))\n", - " model.add(Dropout(0.25))\n", + " model.add(Activation(\"relu\", name=\"relu_2\"))\n", + " model.add(MaxPooling2D(pool_size=(2, 2), name=\"pool_2\"))\n", + " model.add(Dropout(0.25, name=\"dropout_2\"))\n", "\n", - " model.add(Flatten())\n", + " model.add(Flatten(name=\"flatten_1\"))\n", "\n", " model.add(Dense(256, activation=\"relu\", name=\"fc_1\"))\n", - " model.add(Dropout(0.5))\n", + " model.add(Dropout(0.5, name=\"dropout_4\"))\n", " # output layer\n", " activation = \"sigmoid\" if n_classes == 1 else \"softmax\"\n", " model.add(Dense(n_classes, activation=activation, name=\"fc_out\"))\n", @@ -614,7 +604,6 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -664,7 +653,9 @@ "metadata": {}, "outputs": [], "source": [ - "# plot the confusion matrix" + "# plot the confusion matrix\n", + "\n", + "plot_confusion_matrix(np.argmax(class_test, axis=1), np.argmax(classes, axis=1), normalize=True)" ] }, { @@ -714,14 +705,13 @@ ] }, { - "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "### Interpreting networks: where is a network looking\n", "\n", "Occulsion maps, saliency maps, class activation maps are all techniques for expressing which pixels contribute to classification. These are attempts to reduce the \"black box\" nature of the networks.\n", - "The simplest of these is the occlusion map where we part of an image and calculate the probability of it belonging to a class.\n", + "The simplest of these is the occlusion map where we mask part of an image and calculate the probability of it belonging to a class.\n", "If the probability decreases the occluded part of the image is assumed to be important. If there is no change in probability the occluded pixels are not assumed to be important.\n", "A simple implementation of this is shown here." ] @@ -733,7 +723,7 @@ "outputs": [], "source": [ "model = vgg_model\n", - "image_number = 11\n", + "image_number = 15\n", "\n", "kernel_size = 5\n", "input_stamp = data_test[image_number].reshape(21, 21)\n", @@ -1034,7 +1024,7 @@ "formats": "ipynb,md:myst" }, "kernelspec": { - "display_name": "phys2c", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, @@ -1048,7 +1038,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.9.5" }, "toc": { "base_numbering": 1,