{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## This is an example from Francois chollet book \"Deep learning with Python\" CH:08 and CH:09\n","metadata":{}},{"cell_type":"code","source":"!unzip -qq \"/kaggle/input/dogs-vs-cats/train.zip\"","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:00:41.822765Z","iopub.execute_input":"2023-09-05T17:00:41.823076Z","iopub.status.idle":"2023-09-05T17:00:53.924298Z","shell.execute_reply.started":"2023-09-05T17:00:41.823033Z","shell.execute_reply":"2023-09-05T17:00:53.922770Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import os, shutil, pathlib\n\n\n#Path to the directory where the original dataset was uncompressed\noriginal_dir = pathlib.Path(\"train\")\n\n#Directory where we will store our smaller dataset\nnew_base_dir = pathlib.Path(\"cats_vs_dogs_small\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:00:53.927184Z","iopub.execute_input":"2023-09-05T17:00:53.927941Z","iopub.status.idle":"2023-09-05T17:00:53.933926Z","shell.execute_reply.started":"2023-09-05T17:00:53.927901Z","shell.execute_reply":"2023-09-05T17:00:53.932904Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def make_subset(subset_name, start_index, end_index):\n  \"\"\" Utility function to copy cat (and dog) images from index\n       start_index to index end_index to the subdirectory\n        new_base_dir/{subset_name}/cat (and /dog). The\n        'subset_name' will be either 'train', 'validation', or 'test'. \"\"\"\n  for category in (\"cat\", \"dog\"):\n    dir = new_base_dir / subset_name / category\n    os.makedirs(dir)\n    fnames = [f\"{category}.{i}.jpg\" for i in range(start_index, end_index)]\n    for fname in fnames:\n        shutil.copyfile(src=original_dir / fname, dst=dir / fname)\n\n#Create the training subset with the first 1,000 images of each category.\nmake_subset(\"train\", start_index=0, end_index=1000)\n\n#Create the validation subset with the next 500 images of each category.\nmake_subset(\"validation\", start_index=1000, end_index=1500)\n\n#Create the test subset with the next 1,000 images of each category.\nmake_subset(\"test\", start_index=1500, end_index=2500)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:00:53.935556Z","iopub.execute_input":"2023-09-05T17:00:53.936252Z","iopub.status.idle":"2023-09-05T17:00:54.603974Z","shell.execute_reply.started":"2023-09-05T17:00:53.936218Z","shell.execute_reply":"2023-09-05T17:00:54.602664Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Build the model\nfrom tensorflow import keras\nfrom tensorflow.keras import layers\n\ninputs = keras.Input(shape=(180, 180, 3))\n#Rescale inputs to the [0, 1] range by dividing them by 255.\nx = layers.Rescaling(1./255)(inputs)\nx = layers.Conv2D(filters=32, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPool2D(pool_size=2)(x)\nx = layers.Conv2D(filters=64, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPool2D(pool_size=2)(x)\nx = layers.Conv2D(filters=128, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPooling2D(pool_size=2)(x)\nx = layers.Conv2D(filters=256, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPooling2D(pool_size=2)(x)\nx = layers.Conv2D(filters=256, kernel_size=3, activation=\"relu\")(x)\nx = layers.Flatten()(x)\noutputs = layers.Dense(1, activation=\"sigmoid\")(x)\nmodel = keras.Model(inputs=inputs, outputs=outputs)\n\n#summary of the model\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:00:54.606899Z","iopub.execute_input":"2023-09-05T17:00:54.607518Z","iopub.status.idle":"2023-09-05T17:01:09.019036Z","shell.execute_reply.started":"2023-09-05T17:00:54.607482Z","shell.execute_reply":"2023-09-05T17:01:09.018253Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Create a graphical representation of the model\nkeras.utils.plot_model(model, \"Dogs_Cats_Model.png\", show_shapes=True)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:01:09.020170Z","iopub.execute_input":"2023-09-05T17:01:09.020695Z","iopub.status.idle":"2023-09-05T17:01:09.338910Z","shell.execute_reply.started":"2023-09-05T17:01:09.020668Z","shell.execute_reply":"2023-09-05T17:01:09.337758Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Configuring the model for training\nmodel.compile(loss = \"binary_crossentropy\",\n              optimizer=\"rmsprop\",\n              metrics=[\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:01:09.340377Z","iopub.execute_input":"2023-09-05T17:01:09.340752Z","iopub.status.idle":"2023-09-05T17:01:09.362053Z","shell.execute_reply.started":"2023-09-05T17:01:09.340716Z","shell.execute_reply":"2023-09-05T17:01:09.361191Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Using image_dataset_from_directory to read images\nfrom tensorflow.keras.utils import image_dataset_from_directory\n\ntrain_dataset = image_dataset_from_directory(new_base_dir/\"train\",\n                                             image_size=(180, 180),\n                                             batch_size=32)\nvalidation_dataset = image_dataset_from_directory(new_base_dir/\"validation\",\n                                             image_size=(180, 180),\n                                             batch_size=32)\ntest_dataset = image_dataset_from_directory(new_base_dir/\"test\",\n                                             image_size=(180, 180),\n                                             batch_size=32)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:01:09.363496Z","iopub.execute_input":"2023-09-05T17:01:09.363837Z","iopub.status.idle":"2023-09-05T17:01:09.871478Z","shell.execute_reply.started":"2023-09-05T17:01:09.363807Z","shell.execute_reply":"2023-09-05T17:01:09.870553Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Displaying the shapes of the data and labels yielded by the Dataset\nfor data_batch, labels_batch in train_dataset:\n  print(\"data batch shape:\", data_batch.shape)\n  print(\"labels batch shape:\", labels_batch.shape)\n  break","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:01:09.873114Z","iopub.execute_input":"2023-09-05T17:01:09.873462Z","iopub.status.idle":"2023-09-05T17:01:10.278719Z","shell.execute_reply.started":"2023-09-05T17:01:09.873429Z","shell.execute_reply":"2023-09-05T17:01:10.277630Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Fitting the model using a Dataset\ncallbacks =[\n    keras.callbacks.ModelCheckpoint(\n    filepath=\"convnet_from_scratch.keras\",\n    save_best_only=True,\n    monitor=\"val_loss\")]\n\nhistory = model.fit(\ntrain_dataset,\nepochs=30,\nvalidation_data=validation_dataset,\ncallbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:01:10.280440Z","iopub.execute_input":"2023-09-05T17:01:10.280799Z","iopub.status.idle":"2023-09-05T17:03:55.529538Z","shell.execute_reply.started":"2023-09-05T17:01:10.280766Z","shell.execute_reply":"2023-09-05T17:03:55.528342Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\naccuracy = history.history[\"accuracy\"]\nval_accuracy = history.history[\"val_accuracy\"]\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\nepochs = range(1, len(accuracy) + 1)\nplt.plot(epochs, accuracy, \"bo\", label=\"Training accuracy\")\nplt.plot(epochs, val_accuracy, \"b\", label=\"Validation accuracy\")\nplt.title(\"Training and validation accuracy\")\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, \"bo\", label=\"Training loss\")\nplt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\nplt.title(\"Training and validation loss\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:03:55.534818Z","iopub.execute_input":"2023-09-05T17:03:55.535160Z","iopub.status.idle":"2023-09-05T17:03:56.146542Z","shell.execute_reply.started":"2023-09-05T17:03:55.535131Z","shell.execute_reply":"2023-09-05T17:03:56.145592Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Evaluating the model on the test set\ntest_model = keras.models.load_model(\"convnet_from_scratch.keras\")\ntest_loss, test_acc = test_model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:03:56.147804Z","iopub.execute_input":"2023-09-05T17:03:56.148675Z","iopub.status.idle":"2023-09-05T17:04:01.554822Z","shell.execute_reply.started":"2023-09-05T17:03:56.148637Z","shell.execute_reply":"2023-09-05T17:04:01.553780Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Define a data augmentation stage to add to an image model\ndata_augmentation = keras.Sequential([\n   layers.RandomFlip(\"horizontal\"),\n   layers.RandomRotation(0.1),\n   layers.RandomZoom(0.2),])\n\nplt.figure(figsize=(10, 10))\nfor images, _ in train_dataset.take(1):\n  for i in range(9):\n    augmented_images = data_augmentation(images)\n    ax = plt.subplot(3, 3, i + 1)\n    plt.imshow(augmented_images[0].numpy().astype(\"uint8\"))\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:04:01.556015Z","iopub.execute_input":"2023-09-05T17:04:01.557216Z","iopub.status.idle":"2023-09-05T17:04:03.044271Z","shell.execute_reply.started":"2023-09-05T17:04:01.557179Z","shell.execute_reply":"2023-09-05T17:04:03.043148Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"inputs = keras.Input(shape=(180, 180, 3))\n#Rescale inputs to the [0, 1] range by dividing them by 255.\nx = data_augmentation(inputs)\nx = layers.Rescaling(1./255)(x)\nx = layers.Conv2D(filters=32, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPool2D(pool_size=2)(x)\nx = layers.Conv2D(filters=64, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPool2D(pool_size=2)(x)\nx = layers.Conv2D(filters=128, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPooling2D(pool_size=2)(x)\nx = layers.Conv2D(filters=256, kernel_size=3, activation=\"relu\")(x)\nx = layers.MaxPooling2D(pool_size=2)(x)\nx = layers.Conv2D(filters=256, kernel_size=3, activation=\"relu\")(x)\nx = layers.Flatten()(x)\noutputs = layers.Dense(1, activation=\"sigmoid\")(x)\nmodel = keras.Model(inputs=inputs, outputs=outputs)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:04:03.045804Z","iopub.execute_input":"2023-09-05T17:04:03.046154Z","iopub.status.idle":"2023-09-05T17:04:03.414945Z","shell.execute_reply.started":"2023-09-05T17:04:03.046124Z","shell.execute_reply":"2023-09-05T17:04:03.413967Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss=\"binary_crossentropy\",\noptimizer=\"rmsprop\",\nmetrics=[\"accuracy\"])\n\n#Training the regularized convnet\ncallbacks = [\n    keras.callbacks.ModelCheckpoint(\n        filepath=\"convnet_from_scratch_with_augmentation.keras\",\n        save_best_only=True,\n        monitor=\"val_loss\")\n]\nhistory = model.fit(\n             train_dataset,\n             epochs=100,\n             validation_data=validation_dataset,\n             callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:04:03.416291Z","iopub.execute_input":"2023-09-05T17:04:03.416635Z","iopub.status.idle":"2023-09-05T17:12:03.142969Z","shell.execute_reply.started":"2023-09-05T17:04:03.416602Z","shell.execute_reply":"2023-09-05T17:12:03.141878Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"accuracy = history.history[\"accuracy\"]\nval_accuracy = history.history[\"val_accuracy\"]\nloss = history.history[\"loss\"]\nval_loss = history.history[\"val_loss\"]\nepochs = range(1, len(accuracy) + 1)\nplt.plot(epochs, accuracy, \"bo\", label=\"Training accuracy\")\nplt.plot(epochs, val_accuracy, \"b\", label=\"Validation accuracy\")\nplt.title(\"Training and validation accuracy\")\nplt.legend()\nplt.figure()\nplt.plot(epochs, loss, \"bo\", label=\"Training loss\")\nplt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\nplt.title(\"Training and validation loss\")\nplt.legend()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:03.144332Z","iopub.execute_input":"2023-09-05T17:12:03.145220Z","iopub.status.idle":"2023-09-05T17:12:03.758865Z","shell.execute_reply.started":"2023-09-05T17:12:03.145183Z","shell.execute_reply":"2023-09-05T17:12:03.757970Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_model = keras.models.load_model(\"convnet_from_scratch_with_augmentation.keras\")\ntest_loss, test_acc = test_model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:03.760481Z","iopub.execute_input":"2023-09-05T17:12:03.761188Z","iopub.status.idle":"2023-09-05T17:12:06.880639Z","shell.execute_reply.started":"2023-09-05T17:12:03.761152Z","shell.execute_reply":"2023-09-05T17:12:06.879502Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Instantiating the VGG16 convolutional base\nconv_base = keras.applications.vgg16.VGG16(\n    weights = \"imagenet\",\n    include_top = False,\n    input_shape=(180, 180, 3))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:06.882195Z","iopub.execute_input":"2023-09-05T17:12:06.882928Z","iopub.status.idle":"2023-09-05T17:12:08.027975Z","shell.execute_reply.started":"2023-09-05T17:12:06.882891Z","shell.execute_reply":"2023-09-05T17:12:08.026929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Instantiating the VGG16 convolutional base\nconv_base = keras.applications.vgg16.VGG16(\n    weights = \"imagenet\",\n    include_top = False,\n    input_shape=(180, 180, 3))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:08.034350Z","iopub.execute_input":"2023-09-05T17:12:08.034656Z","iopub.status.idle":"2023-09-05T17:12:08.370904Z","shell.execute_reply.started":"2023-09-05T17:12:08.034629Z","shell.execute_reply":"2023-09-05T17:12:08.369922Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Instantiating the VGG16 convolutional base\nconv_base  = keras.applications.vgg16.VGG16(\n    weights=\"imagenet\",\n    include_top=False)\nconv_base.trainable = False","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:08.372396Z","iopub.execute_input":"2023-09-05T17:12:08.372731Z","iopub.status.idle":"2023-09-05T17:12:08.689305Z","shell.execute_reply.started":"2023-09-05T17:12:08.372700Z","shell.execute_reply":"2023-09-05T17:12:08.688302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation = keras.Sequential(\n    [\n        layers.RandomFlip(\"horizontal\"),\n        layers.RandomRotation(0.1),\n        layers.RandomZoom(0.2),\n    ]\n)\n\ninputs = keras.Input(shape=(180, 180, 3))\nx = data_augmentation(inputs)\nx = keras.applications.vgg16.preprocess_input(x)\nx = conv_base(x)\nx = layers.Flatten()(x)\nx = layers.Dense(256)(x)\nx = layers.Dropout(0.5)(x)\noutputs = layers.Dense(1, activation=\"sigmoid\")(x)\nmodel = keras.Model(inputs, outputs)\nmodel.compile(loss=\"binary_crossentropy\",\n              optimizer=\"rmsprop\",\n              metrics=[\"accuracy\"])","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:08.690802Z","iopub.execute_input":"2023-09-05T17:12:08.691187Z","iopub.status.idle":"2023-09-05T17:12:09.082251Z","shell.execute_reply.started":"2023-09-05T17:12:08.691153Z","shell.execute_reply":"2023-09-05T17:12:09.081297Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"callbacks = [\n    keras.callbacks.ModelCheckpoint(\n        filepath=\"feature_extraction_with_data_augmentation.keras\",\n        save_best_only=True,\n        monitor=\"val_loss\")\n]\nhistory = model.fit(\n    train_dataset,\n    epochs=50,\n    validation_data=validation_dataset,\n    callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:12:09.083728Z","iopub.execute_input":"2023-09-05T17:12:09.084056Z","iopub.status.idle":"2023-09-05T17:21:05.548279Z","shell.execute_reply.started":"2023-09-05T17:12:09.084024Z","shell.execute_reply":"2023-09-05T17:21:05.547284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_model = keras.models.load_model(\n    \"feature_extraction_with_data_augmentation.keras\")\ntest_loss, test_acc = test_model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:21:05.549900Z","iopub.execute_input":"2023-09-05T17:21:05.550289Z","iopub.status.idle":"2023-09-05T17:21:16.659224Z","shell.execute_reply.started":"2023-09-05T17:21:05.550253Z","shell.execute_reply":"2023-09-05T17:21:16.658141Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"conv_base.trainable = True\nfor layer in conv_base.layers[:-4]:\n    layer.trainable = False","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:21:16.660866Z","iopub.execute_input":"2023-09-05T17:21:16.661622Z","iopub.status.idle":"2023-09-05T17:21:16.668633Z","shell.execute_reply.started":"2023-09-05T17:21:16.661586Z","shell.execute_reply":"2023-09-05T17:21:16.667652Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss=\"binary_crossentropy\",\n              optimizer=keras.optimizers.RMSprop(learning_rate=1e-5),\n              metrics=[\"accuracy\"])\n\ncallbacks = [\n    keras.callbacks.ModelCheckpoint(\n        filepath=\"fine_tuning.keras\",\n        save_best_only=True,\n        monitor=\"val_loss\")\n]\nhistory = model.fit(\n    train_dataset,\n    epochs=100,\n    validation_data=validation_dataset,\n    callbacks=callbacks)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:21:16.670258Z","iopub.execute_input":"2023-09-05T17:21:16.670779Z","iopub.status.idle":"2023-09-05T17:42:42.350188Z","shell.execute_reply.started":"2023-09-05T17:21:16.670747Z","shell.execute_reply":"2023-09-05T17:42:42.349205Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = keras.models.load_model(\"fine_tuning.keras\")\ntest_loss, test_acc = model.evaluate(test_dataset)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:42.358628Z","iopub.execute_input":"2023-09-05T17:42:42.358923Z","iopub.status.idle":"2023-09-05T17:42:49.886665Z","shell.execute_reply.started":"2023-09-05T17:42:42.358897Z","shell.execute_reply":"2023-09-05T17:42:49.885745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = keras.models.load_model(\n\"convnet_from_scratch_with_augmentation.keras\")\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:49.888014Z","iopub.execute_input":"2023-09-05T17:42:49.888742Z","iopub.status.idle":"2023-09-05T17:42:50.711988Z","shell.execute_reply.started":"2023-09-05T17:42:49.888705Z","shell.execute_reply":"2023-09-05T17:42:50.711189Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = keras.models.load_model(\n    \"convnet_from_scratch_with_augmentation.keras\")\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:50.713083Z","iopub.execute_input":"2023-09-05T17:42:50.713439Z","iopub.status.idle":"2023-09-05T17:42:51.183621Z","shell.execute_reply.started":"2023-09-05T17:42:50.713395Z","shell.execute_reply":"2023-09-05T17:42:51.182866Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#\nimg_path = keras.utils.get_file(\n    fname = \"cat.jpg\",\n    origin=\"https://img-datasets.s3.amazonaws.com/cat.jpg\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:51.191351Z","iopub.execute_input":"2023-09-05T17:42:51.191709Z","iopub.status.idle":"2023-09-05T17:42:51.513973Z","shell.execute_reply.started":"2023-09-05T17:42:51.191675Z","shell.execute_reply":"2023-09-05T17:42:51.512890Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#\nimport numpy as np \ndef get_img_array(img_path, target_size):\n    img = keras.utils.load_img(\n    img_path, target_size=target_size)\n    array = keras.utils.img_to_array(img)\n    array = np.expand_dims(array, axis=0)\n    return array\n\nimg_tensor = get_img_array(img_path, target_size=(180, 180))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:51.515703Z","iopub.execute_input":"2023-09-05T17:42:51.516715Z","iopub.status.idle":"2023-09-05T17:42:51.539181Z","shell.execute_reply.started":"2023-09-05T17:42:51.516680Z","shell.execute_reply":"2023-09-05T17:42:51.538273Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Displaying the test picture\nimport matplotlib.pyplot as plt\nplt.axis(\"off\")\nplt.imshow(img_tensor[0].astype(\"uint8\"))\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:51.540748Z","iopub.execute_input":"2023-09-05T17:42:51.541640Z","iopub.status.idle":"2023-09-05T17:42:51.745624Z","shell.execute_reply.started":"2023-09-05T17:42:51.541606Z","shell.execute_reply":"2023-09-05T17:42:51.744688Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Instantiating a model that returns layer activations\nlayer_outputs = []\nlayer_names = []\nfor layer in model.layers:\n    if isinstance(layer, (layers.Conv2D, layers.MaxPooling2D)):\n        layer_outputs.append(layer.output)\n        layer_names.append(layer.name)\n\nactivation_model = keras.Model(inputs=model.input, outputs=layer_outputs)\n        \n# Using the model to compute layer activations\nactivations = activation_model.predict(img_tensor)\nfirst_layer_activation = activations[0]\nprint(first_layer_activation.shape)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:51.746889Z","iopub.execute_input":"2023-09-05T17:42:51.747408Z","iopub.status.idle":"2023-09-05T17:42:52.253293Z","shell.execute_reply.started":"2023-09-05T17:42:51.747378Z","shell.execute_reply":"2023-09-05T17:42:52.252137Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Visualizing the fifth channel\nimport matplotlib.pyplot as plt\nplt.matshow(first_layer_activation[0, :, :, 5], cmap=\"viridis\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:52.255135Z","iopub.execute_input":"2023-09-05T17:42:52.255523Z","iopub.status.idle":"2023-09-05T17:42:52.744990Z","shell.execute_reply.started":"2023-09-05T17:42:52.255487Z","shell.execute_reply":"2023-09-05T17:42:52.743995Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"images_per_row = 16\nfor layer_name, layer_activation in zip(layer_names, activations):\n    n_features = layer_activation.shape[-1]\n    size = layer_activation.shape[1]\n    n_cols = n_features // images_per_row\n    display_grid = np.zeros(((size + 1) * n_cols - 1,\n                             images_per_row * (size + 1) - 1))\n    for col in range(n_cols):\n        for row in range(images_per_row):\n            channel_index = col * images_per_row + row\n            channel_image = layer_activation[0, :, :, channel_index].copy()\n            if channel_image.sum() != 0:\n                channel_image -= channel_image.mean()\n                channel_image /= channel_image.std()\n                channel_image *= 64\n                channel_image += 128\n            channel_image = np.clip(channel_image, 0, 255).astype(\"uint8\")\n            display_grid[\n                col * (size + 1): (col + 1) * size + col,\n                row * (size + 1) : (row + 1) * size + row] = channel_image\n    scale = 1. / size\n    plt.figure(figsize=(scale * display_grid.shape[1],\n                        scale * display_grid.shape[0]))\n    plt.title(layer_name)\n    plt.grid(False)\n    plt.axis(\"off\")\n    plt.imshow(display_grid, aspect=\"auto\", cmap=\"viridis\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:52.746827Z","iopub.execute_input":"2023-09-05T17:42:52.747622Z","iopub.status.idle":"2023-09-05T17:42:56.619207Z","shell.execute_reply.started":"2023-09-05T17:42:52.747580Z","shell.execute_reply":"2023-09-05T17:42:56.618016Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Visualizing convnet filters\n#convolutional base\nmodel = keras.applications.xception.Xception(\n    weights=\"imagenet\",\n    include_top=False)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:56.620704Z","iopub.execute_input":"2023-09-05T17:42:56.621340Z","iopub.status.idle":"2023-09-05T17:42:58.545863Z","shell.execute_reply.started":"2023-09-05T17:42:56.621303Z","shell.execute_reply":"2023-09-05T17:42:58.544699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Printing the names of all convolutional layers in Xception\nfor layer in model.layers: \n    if isinstance(layer, (keras.layers.Conv2D, keras.layers.SeparableConv2D)):\n        print(layer.name)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.547633Z","iopub.execute_input":"2023-09-05T17:42:58.548022Z","iopub.status.idle":"2023-09-05T17:42:58.557104Z","shell.execute_reply.started":"2023-09-05T17:42:58.547982Z","shell.execute_reply":"2023-09-05T17:42:58.554415Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Creating a feature extractor model\nlayer_name = \"block7_sepconv1\"\nlayer = model.get_layer(name=layer_name)\nfeature_extractor = keras.Model(inputs=model.input, outputs=layer.output)\n","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.558943Z","iopub.execute_input":"2023-09-05T17:42:58.559324Z","iopub.status.idle":"2023-09-05T17:42:58.575412Z","shell.execute_reply.started":"2023-09-05T17:42:58.559291Z","shell.execute_reply":"2023-09-05T17:42:58.574411Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Using the feature extractor\nactivation = feature_extractor(\n    keras.applications.xception.preprocess_input(img_tensor))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.576715Z","iopub.execute_input":"2023-09-05T17:42:58.577172Z","iopub.status.idle":"2023-09-05T17:42:58.810840Z","shell.execute_reply.started":"2023-09-05T17:42:58.577137Z","shell.execute_reply":"2023-09-05T17:42:58.809871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#The loss function takes an image tensor and the index of the filter \n#we are considering (an integer).\ndef compute_loss(image, filter_index):\n    activation = feature_extractor(image)\n    filter_activation = activation[:, 2:-2, 2:-2, filter_index]\n    return tf.reduce_mean(filter_activation)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.812397Z","iopub.execute_input":"2023-09-05T17:42:58.812778Z","iopub.status.idle":"2023-09-05T17:42:58.818750Z","shell.execute_reply.started":"2023-09-05T17:42:58.812741Z","shell.execute_reply":"2023-09-05T17:42:58.817516Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import tensorflow as tf \n#Loss maximization via stochastic gradient ascent\n@tf.function \ndef gradient_ascent_step(image, filter_index, learning_rate):\n    with tf.GradientTape() as tape: \n        tape.watch(image)\n        loss = compute_loss(image, filter_index)\n    grads = tape.gradient(loss, image)\n    grads = tf.math.l2_normalize(grads)\n    image += learning_rate * grads \n    return image ","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.821190Z","iopub.execute_input":"2023-09-05T17:42:58.822266Z","iopub.status.idle":"2023-09-05T17:42:58.834904Z","shell.execute_reply.started":"2023-09-05T17:42:58.822227Z","shell.execute_reply":"2023-09-05T17:42:58.833726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Function to generate filter visualizations\nimg_width = 200\nimg_height = 200\n\ndef generate_filter_pattern(filter_index):\n    iterations = 30\n    learning_rate = 10\n    image = tf.random.uniform(\n          minval = 0.4,\n          maxval = 0.6,\n          shape=(1, img_width, img_height, 3))\n    for i in range(iterations):\n        image = gradient_ascent_step(image, filter_index, learning_rate)\n    return image[0].numpy()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.836554Z","iopub.execute_input":"2023-09-05T17:42:58.836955Z","iopub.status.idle":"2023-09-05T17:42:58.847186Z","shell.execute_reply.started":"2023-09-05T17:42:58.836919Z","shell.execute_reply":"2023-09-05T17:42:58.846101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Utility function to convert a tensor into a valid image\ndef deprocess_image(image):\n    image -= image.mean()\n    image /= image.std()\n    image *= 64\n    image += 128\n    image = np.clip(image, 0, 255).astype(\"uint8\")\n    image = image[25:-25, 25:-25, :]\n    return image\n\nplt.axis(\"off\")\nplt.imshow(deprocess_image(generate_filter_pattern(filter_index=2)))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:42:58.848420Z","iopub.execute_input":"2023-09-05T17:42:58.848909Z","iopub.status.idle":"2023-09-05T17:43:00.394940Z","shell.execute_reply.started":"2023-09-05T17:42:58.848873Z","shell.execute_reply":"2023-09-05T17:43:00.393985Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#start visualizing every filter in the layer\n#Generating a grid of all filter response patterns in a layer\nall_images = []\nfor filter_index in range(64):\n    print(f\"Processing filter {filter_index}\")\n    image = deprocess_image(\n        generate_filter_pattern(filter_index)\n    )\n    all_images.append(image)\n\nmargin = 5\nn = 8\ncropped_width = img_width - 25 * 2\ncropped_height = img_height - 25 * 2\nwidth = n * cropped_width + (n - 1) * margin\nheight = n * cropped_height + (n - 1) * margin\nstitched_filters = np.zeros((width, height, 3))\n\nfor i in range(n):\n    for j in range(n):\n        image = all_images[i * n + j]\n        stitched_filters[\n            (cropped_width + margin) * i : (cropped_width + margin) * i + cropped_width,\n            (cropped_height + margin) * j : (cropped_height + margin) * j\n            + cropped_height,\n            :,] = image\n\nkeras.utils.save_img(\nf\"filters_for_layer_{layer_name}.png\", stitched_filters)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:00.396338Z","iopub.execute_input":"2023-09-05T17:43:00.397319Z","iopub.status.idle":"2023-09-05T17:43:51.873101Z","shell.execute_reply.started":"2023-09-05T17:43:00.397273Z","shell.execute_reply":"2023-09-05T17:43:51.872119Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Loading the Xception network with pretrained weights\n#Note that we include the densely connected classifier on top; \n#in all previous cases, we discarded it.\nmodel = keras.applications.xception.Xception(weights=\"imagenet\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:51.874442Z","iopub.execute_input":"2023-09-05T17:43:51.874804Z","iopub.status.idle":"2023-09-05T17:43:53.935974Z","shell.execute_reply.started":"2023-09-05T17:43:51.874768Z","shell.execute_reply":"2023-09-05T17:43:53.935017Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Preprocessing an input image for Xception\nimg_path = keras.utils.get_file(fname=\"elephant.jpg\",\n            origin=\"https://img-datasets.s3.amazonaws.com/elephant.jpg\")","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:53.937260Z","iopub.execute_input":"2023-09-05T17:43:53.937608Z","iopub.status.idle":"2023-09-05T17:43:54.302105Z","shell.execute_reply.started":"2023-09-05T17:43:53.937575Z","shell.execute_reply":"2023-09-05T17:43:54.301021Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_img_array(img_path, target_size):\n    img = keras.utils.load_img(img_path, target_size=target_size)\n    array = keras.utils.img_to_array(img)\n    array = np.expand_dims(array, axis=0)\n    array = keras.applications.xception.preprocess_input(array)\n    return array\n\nimg_array = get_img_array(img_path, target_size=(299, 299))\n\n#Displaying the test picture\nimport matplotlib.pyplot as plt\nplt.axis(\"off\")\nplt.imshow(img_array[0])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:54.304299Z","iopub.execute_input":"2023-09-05T17:43:54.304914Z","iopub.status.idle":"2023-09-05T17:43:54.534758Z","shell.execute_reply.started":"2023-09-05T17:43:54.304872Z","shell.execute_reply":"2023-09-05T17:43:54.533947Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#decode the preds vector bach to human-readable format\npreds = model.predict(img_array)\nprint(keras.applications.xception.decode_predictions(preds, top=5)[0])\nprint(np.argmax(preds[0]))","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:54.536250Z","iopub.execute_input":"2023-09-05T17:43:54.536872Z","iopub.status.idle":"2023-09-05T17:43:56.013054Z","shell.execute_reply.started":"2023-09-05T17:43:54.536838Z","shell.execute_reply":"2023-09-05T17:43:56.012106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#To visualize which parts of the image are the most African-elephant–like, let’s set up\n#the Grad-CAM process.\n#Setting up a model that returns the last convolutional output\n\nlast_conv_layer_name = \"block14_sepconv2_act\"\nclassifier_layer_names = [\n    \"avg_pool\",\n    \"predictions\",]\n\nlast_conv_layer = model.get_layer(last_conv_layer_name)\nlast_conv_layer_model = keras.Model(model.inputs, last_conv_layer.output)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.014697Z","iopub.execute_input":"2023-09-05T17:43:56.015116Z","iopub.status.idle":"2023-09-05T17:43:56.036006Z","shell.execute_reply.started":"2023-09-05T17:43:56.015078Z","shell.execute_reply":"2023-09-05T17:43:56.034963Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Reapplying the classifier on top of the last convolutional output\nclassifier_input = keras.Input(shape=last_conv_layer.output.shape[1:])\nx = classifier_input\nfor layer_name in classifier_layer_names:\n    x = model.get_layer(layer_name)(x)\nclassifier_model = keras.Model(classifier_input, x)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.039318Z","iopub.execute_input":"2023-09-05T17:43:56.039625Z","iopub.status.idle":"2023-09-05T17:43:56.060934Z","shell.execute_reply.started":"2023-09-05T17:43:56.039602Z","shell.execute_reply":"2023-09-05T17:43:56.059990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Retrieving the gradients of the top predicted class\nimport tensorflow as tf \n\nwith tf.GradientTape() as tape:\n    last_conv_layer_output = last_conv_layer_model(img_array)\n    tape.watch(last_conv_layer_output)\n    preds = classifier_model(last_conv_layer_output)\n    top_pred_index = tf.argmax(preds[0])\n    top_class_channel = preds[:, top_pred_index]\n\ngrads = tape.gradient(top_class_channel, last_conv_layer_output)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.062311Z","iopub.execute_input":"2023-09-05T17:43:56.062644Z","iopub.status.idle":"2023-09-05T17:43:56.471954Z","shell.execute_reply.started":"2023-09-05T17:43:56.062612Z","shell.execute_reply":"2023-09-05T17:43:56.471051Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Gradient pooling and channel-importance weighting\n#This is a vector where each entry is the mean intensity of the\n#gradient for a given channel. It quantifies the importance of\n#each channel with regard to the top predicted class.\npooled_grads = tf.reduce_mean(grads, axis=(0, 1, 2)).numpy()\nlast_conv_layer_output = last_conv_layer_output.numpy()[0]\nfor i in range(pooled_grads.shape[-1]):\n    last_conv_layer_output[:, :, i] *= pooled_grads[i]\nheatmap = np.mean(last_conv_layer_output, axis=-1)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.473404Z","iopub.execute_input":"2023-09-05T17:43:56.473739Z","iopub.status.idle":"2023-09-05T17:43:56.493304Z","shell.execute_reply.started":"2023-09-05T17:43:56.473706Z","shell.execute_reply":"2023-09-05T17:43:56.492447Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Heatmap post-processing\nheatmap = np.maximum(heatmap, 0)\nheatmap /= np.max(heatmap)\nplt.matshow(heatmap)","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.494758Z","iopub.execute_input":"2023-09-05T17:43:56.495123Z","iopub.status.idle":"2023-09-05T17:43:56.869562Z","shell.execute_reply.started":"2023-09-05T17:43:56.495092Z","shell.execute_reply":"2023-09-05T17:43:56.868417Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Superimposing the heatmap on the original picture\nimport matplotlib.cm as cm\n\nimg = keras.utils.load_img(img_path)\nimg = keras.utils.img_to_array(img)\n\n#Rescale the heatmap to the range 0–255\nheatmap = np.uint8(255 * heatmap)\n\n#Use the \"jet\" colormap to recolorize the heatmap\njet = cm.get_cmap(\"jet\")\njet_colors = jet(np.arange(256))[:, :3]\njet_heatmap = jet_colors[heatmap]\n\n#Create an image that contains the recolorized heatmap\njet_heatmap = keras.utils.array_to_img(jet_heatmap)\njet_heatmap = jet_heatmap.resize((img.shape[1], img.shape[0]))\njet_heatmap = keras.utils.img_to_array(jet_heatmap)\n\nsuperimposed_img = jet_heatmap * 0.4 + img\nsuperimposed_img = keras.utils.array_to_img(superimposed_img)\n\nsave_path = \"elephant_cam.jpg\"\nsuperimposed_img.save(save_path)\n\n# Display the image\nplt.imshow(superimposed_img)\nplt.axis('off') \nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-09-05T17:43:56.875414Z","iopub.execute_input":"2023-09-05T17:43:56.875881Z","iopub.status.idle":"2023-09-05T17:43:57.431236Z","shell.execute_reply.started":"2023-09-05T17:43:56.875836Z","shell.execute_reply":"2023-09-05T17:43:57.430320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}],"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}}