{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"},{"sourceId":9042680,"sourceType":"datasetVersion","datasetId":5451632}],"dockerImageVersionId":30747,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#imports\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport os\nimport tensorflow as tf\nimport tensorflow.keras.layers as tfl\nimport pandas as pd\n\nfrom tensorflow.keras.preprocessing import image_dataset_from_directory","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-07-26T23:21:31.987384Z","iopub.execute_input":"2024-07-26T23:21:31.98767Z","iopub.status.idle":"2024-07-26T23:21:44.277618Z","shell.execute_reply.started":"2024-07-26T23:21:31.987645Z","shell.execute_reply":"2024-07-26T23:21:44.276828Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#seed for stable results\nseed = 7","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:22:24.430716Z","iopub.execute_input":"2024-07-26T23:22:24.431127Z","iopub.status.idle":"2024-07-26T23:22:24.437741Z","shell.execute_reply.started":"2024-07-26T23:22:24.431094Z","shell.execute_reply":"2024-07-26T23:22:24.436761Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"BATCH_SIZE = 32\nIMG_SIZE = (160, 160)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:22:37.249697Z","iopub.execute_input":"2024-07-26T23:22:37.250062Z","iopub.status.idle":"2024-07-26T23:22:37.255036Z","shell.execute_reply.started":"2024-07-26T23:22:37.250034Z","shell.execute_reply":"2024-07-26T23:22:37.254041Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!unzip -qq ../input/dogs-vs-cats/test1.zip -d ../working\n!unzip -qq ../input/dogs-vs-cats/train.zip -d ../working\n\n!mkdir ../working/train/dog\n!mkdir ../working/train/cat\n\n!cd ../working/train ; ls  | grep \"cat.*.jpg\" | xargs mv -t cat/\n!cd ../working/train ; ls  | grep \"dog.*.jpg\" | xargs mv -t dog/\n\n!ls -l ../working/train/dog | wc -l\n!ls -l ../working/train/cat | wc -l","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:22:40.622019Z","iopub.execute_input":"2024-07-26T23:22:40.622349Z","iopub.status.idle":"2024-07-26T23:23:02.775456Z","shell.execute_reply.started":"2024-07-26T23:22:40.622325Z","shell.execute_reply":"2024-07-26T23:23:02.774302Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"directory = \"../working/train\"\ntrain_dataset = image_dataset_from_directory(directory,\n                                             shuffle=True,\n                                             batch_size=BATCH_SIZE,\n                                             image_size=IMG_SIZE,\n                                             validation_split=0.8,\n                                             subset='training',\n                                             seed=seed)\n\nvalidation_dataset = image_dataset_from_directory(directory,\n                                             shuffle=True,\n                                             batch_size=BATCH_SIZE,\n                                             image_size=IMG_SIZE,\n                                             validation_split=0.2,\n                                             subset='validation',\n                                             seed=seed)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:08.146855Z","iopub.execute_input":"2024-07-26T23:23:08.147306Z","iopub.status.idle":"2024-07-26T23:23:14.398262Z","shell.execute_reply.started":"2024-07-26T23:23:08.147251Z","shell.execute_reply":"2024-07-26T23:23:14.397418Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dataset.class_names","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:20.376142Z","iopub.execute_input":"2024-07-26T23:23:20.376963Z","iopub.status.idle":"2024-07-26T23:23:20.383751Z","shell.execute_reply.started":"2024-07-26T23:23:20.376928Z","shell.execute_reply":"2024-07-26T23:23:20.382858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names = train_dataset.class_names\nplt.figure(figsize=(10, 10))\nfor images, labels in train_dataset.take(1):\n    for i in range(9):\n        ax = plt.subplot(3, 3, i + 1)\n        plt.imshow(images[i].numpy().astype(\"uint8\"))\n        plt.title(class_names[labels[i]])\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:22.897844Z","iopub.execute_input":"2024-07-26T23:23:22.898513Z","iopub.status.idle":"2024-07-26T23:23:24.178528Z","shell.execute_reply.started":"2024-07-26T23:23:22.898482Z","shell.execute_reply":"2024-07-26T23:23:24.177453Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#prefetching settings\nAUTOTUNE = tf.data.experimental.AUTOTUNE\ntrain_dataset = train_dataset.prefetch(buffer_size=AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:42.708871Z","iopub.execute_input":"2024-07-26T23:23:42.709765Z","iopub.status.idle":"2024-07-26T23:23:42.715473Z","shell.execute_reply.started":"2024-07-26T23:23:42.709731Z","shell.execute_reply":"2024-07-26T23:23:42.714544Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def data_augmenter():\n    '''\n    Create a Sequential model composed of 2 layers\n    Returns:\n        tf.keras.Sequential\n    '''\n    data_augmentation = tf.keras.Sequential()\n    data_augmentation.add(tfl.RandomFlip('horizontal'))\n    data_augmentation.add(tfl.RandomRotation(0.2))\n    return data_augmentation","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:44.593415Z","iopub.execute_input":"2024-07-26T23:23:44.593739Z","iopub.status.idle":"2024-07-26T23:23:44.599085Z","shell.execute_reply.started":"2024-07-26T23:23:44.593715Z","shell.execute_reply":"2024-07-26T23:23:44.598114Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation = data_augmenter()\nfor image, _ in train_dataset.take(1):\n    plt.figure(figsize=(10, 10))\n    first_image = image[0]\n    for i in range(9):\n        ax = plt.subplot(3, 3, i + 1)\n        augmented_image = data_augmentation(tf.expand_dims(first_image, 0))\n        plt.imshow(augmented_image[0] / 255)\n        plt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:23:48.733459Z","iopub.execute_input":"2024-07-26T23:23:48.733832Z","iopub.status.idle":"2024-07-26T23:23:50.873584Z","shell.execute_reply.started":"2024-07-26T23:23:48.733805Z","shell.execute_reply":"2024-07-26T23:23:50.87271Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"preprocess_input = tf.keras.applications.resnet50.preprocess_input\n\n\ndef classification_model(image_shape=IMG_SIZE, data_augmentation=data_augmenter()):\n    ''' Define a tf.keras model for binary classification out of the MobileNetV2 model\n    Arguments:\n        image_shape -- Image width and height\n        data_augmentation -- data augmentation function\n    Returns:\n    Returns:\n        tf.keras.model\n    '''\n    \n    \n    input_shape = IMG_SIZE + (3,)\n    base_model = tf.keras.applications.ResNet50(input_shape=input_shape,\n                                                   include_top=False, \n                                                   weights='imagenet') # From imageNet\n    \n   \n    #freeze base model\n    base_model.trainable = False \n\n    inputs = tf.keras.Input(shape=input_shape) \n    x = data_augmentation(inputs)\n    x = preprocess_input(x)\n    x = base_model(x, training=False) \n    x = tfl.GlobalAveragePooling2D()(x)\n    x = tfl.Dropout(0.2)(x)\n    outputs = tfl.Dense(1)(x)\n    \n    model = tf.keras.Model(inputs, outputs)\n    return model","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:33:24.422453Z","iopub.execute_input":"2024-07-26T23:33:24.423407Z","iopub.status.idle":"2024-07-26T23:33:24.439894Z","shell.execute_reply.started":"2024-07-26T23:33:24.423373Z","shell.execute_reply":"2024-07-26T23:33:24.439048Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model2 = classification_model(IMG_SIZE, data_augmentation)\nbase_learning_rate = 0.001\nmodel2.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=base_learning_rate),\n              loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),\n              metrics=['accuracy'])\ninitial_epochs = 10\nhistory = model2.fit(train_dataset, validation_data=validation_dataset, epochs=initial_epochs)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:34:06.154791Z","iopub.execute_input":"2024-07-26T23:34:06.1557Z","iopub.status.idle":"2024-07-26T23:38:26.065087Z","shell.execute_reply.started":"2024-07-26T23:34:06.155667Z","shell.execute_reply":"2024-07-26T23:38:26.064064Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#plot metrics\nacc = [0.] + history.history['accuracy']\nval_acc = [0.] + history.history['val_accuracy']\n\nloss = history.history['loss']\nval_loss = history.history['val_loss']\n\nplt.figure(figsize=(8, 8))\nplt.subplot(2, 1, 1)\nplt.plot(acc, label='Training Accuracy')\nplt.plot(val_acc, label='Validation Accuracy')\nplt.legend(loc='lower right')\nplt.ylabel('Accuracy')\nplt.ylim([min(plt.ylim()),1])\nplt.title('Training and Validation Accuracy')\n\nplt.subplot(2, 1, 2)\nplt.plot(loss, label='Training Loss')\nplt.plot(val_loss, label='Validation Loss')\nplt.legend(loc='upper right')\nplt.ylabel('Cross Entropy')\nplt.ylim([0,1.0])\nplt.title('Training and Validation Loss')\nplt.xlabel('epoch')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:38:26.066608Z","iopub.execute_input":"2024-07-26T23:38:26.066874Z","iopub.status.idle":"2024-07-26T23:38:26.536202Z","shell.execute_reply.started":"2024-07-26T23:38:26.06685Z","shell.execute_reply":"2024-07-26T23:38:26.535284Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model2.summary()","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:39:34.658259Z","iopub.execute_input":"2024-07-26T23:39:34.659066Z","iopub.status.idle":"2024-07-26T23:39:34.701413Z","shell.execute_reply.started":"2024-07-26T23:39:34.659029Z","shell.execute_reply":"2024-07-26T23:39:34.700546Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"base_model = model2.layers[2]\nbase_model.trainable = True\n# Let's take a look to see how many layers are in the base model\nprint(\"Number of layers in the base model: \", len(base_model.layers))","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:41:33.755862Z","iopub.execute_input":"2024-07-26T23:41:33.756444Z","iopub.status.idle":"2024-07-26T23:41:33.76619Z","shell.execute_reply.started":"2024-07-26T23:41:33.75641Z","shell.execute_reply":"2024-07-26T23:41:33.765276Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Fine-tune from this layer onwards\nfine_tune_at = 150\n\n### START CODE HERE\n\n# Freeze all the layers before the `fine_tune_at` layer\nfor layer in base_model.layers[:fine_tune_at]:\n    layer.trainable = False\n    \n# Define a BinaryCrossentropy loss function. Use from_logits=True\nloss_function = tf.keras.losses.BinaryCrossentropy(from_logits=True)\n# Define an Adam optimizer with a learning rate of 0.1 * base_learning_rate\noptimizer = tf.keras.optimizers.Adam(learning_rate=base_learning_rate * 0.1)\n# Use accuracy as evaluation metric\nmetrics=['accuracy']\n\n### END CODE HERE\n\nmodel2.compile(loss=loss_function,\n              optimizer = optimizer,\n              metrics=metrics)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:42:49.339366Z","iopub.execute_input":"2024-07-26T23:42:49.339771Z","iopub.status.idle":"2024-07-26T23:42:49.356227Z","shell.execute_reply.started":"2024-07-26T23:42:49.33974Z","shell.execute_reply":"2024-07-26T23:42:49.355222Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"fine_tune_epochs = 5\ntotal_epochs =  initial_epochs + fine_tune_epochs\n\nhistory_fine = model2.fit(train_dataset,\n                         epochs=total_epochs,\n                         initial_epoch=history.epoch[-1],\n                         validation_data=validation_dataset)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:43:18.531025Z","iopub.execute_input":"2024-07-26T23:43:18.531727Z","iopub.status.idle":"2024-07-26T23:46:37.486655Z","shell.execute_reply.started":"2024-07-26T23:43:18.531692Z","shell.execute_reply":"2024-07-26T23:46:37.485726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_directory = \"/kaggle/working/test1\"\nfiles = os.listdir(test_directory)\nids = [os.path.splitext(f)[0] for f in files]\npredictions = []\ntest_dataset = image_dataset_from_directory(test_directory,\n                                             shuffle=False,\n                                             batch_size=512,\n                                             image_size=IMG_SIZE,\n                                             label_mode = None,\n                                             seed=seed)\n\n\nfor batch in test_dataset:\n    prediction = model2.predict(batch)\n    prediction = tf.math.sigmoid(tf.squeeze(prediction))\n    prediction = tf.cast(prediction > 0.5, tf.int32).numpy()\n    predictions.extend(prediction)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:47:13.603948Z","iopub.execute_input":"2024-07-26T23:47:13.60434Z","iopub.status.idle":"2024-07-26T23:47:43.919286Z","shell.execute_reply.started":"2024-07-26T23:47:13.604305Z","shell.execute_reply":"2024-07-26T23:47:43.918478Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(len(ids))\nprint(len(predictions))","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:47:49.167056Z","iopub.execute_input":"2024-07-26T23:47:49.167416Z","iopub.status.idle":"2024-07-26T23:47:49.172162Z","shell.execute_reply.started":"2024-07-26T23:47:49.167388Z","shell.execute_reply":"2024-07-26T23:47:49.171275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data = {'id': ids, 'label': predictions}\ndf = pd.DataFrame(data)\ndf.to_csv('submission.csv', encoding='utf-8', index=False, header=True)","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:47:55.036185Z","iopub.execute_input":"2024-07-26T23:47:55.036519Z","iopub.status.idle":"2024-07-26T23:47:55.169437Z","shell.execute_reply.started":"2024-07-26T23:47:55.036493Z","shell.execute_reply":"2024-07-26T23:47:55.168381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class_names = ['cat', 'dog']\nplt.figure(figsize=(10, 10))\nfor images in test_dataset.take(1):\n    prediction = model2.predict(images)\n    prediction = tf.math.sigmoid(tf.squeeze(prediction))\n    prediction = tf.cast(prediction > 0.5, tf.int32).numpy()\n    \n    for i in range(9):\n        ax = plt.subplot(3, 3, i + 1)\n        plt.imshow(images[i].numpy().astype(\"uint8\"))\n        plt.title(class_names[labels[i]])\n        plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2024-07-26T23:48:04.649522Z","iopub.execute_input":"2024-07-26T23:48:04.650208Z","iopub.status.idle":"2024-07-26T23:48:07.249194Z","shell.execute_reply.started":"2024-07-26T23:48:04.650174Z","shell.execute_reply":"2024-07-26T23:48:07.248054Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Summarize feature map shapes\nfor i in range(len(base_model.layers)):\n    layer = base_model.layers[i]\n    # Check for convolutional layer\n    if 'conv' not in layer.name:\n        continue\n    # Summarize output shape\n    print(i, layer.name, layer.output.shape)\n","metadata":{"execution":{"iopub.status.busy":"2024-07-27T00:07:38.09926Z","iopub.execute_input":"2024-07-27T00:07:38.100122Z","iopub.status.idle":"2024-07-27T00:07:38.129013Z","shell.execute_reply.started":"2024-07-27T00:07:38.100087Z","shell.execute_reply":"2024-07-27T00:07:38.128034Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# **Layer Visualisation**","metadata":{}},{"cell_type":"code","source":"\nfrom keras.preprocessing.image import load_img\nfrom keras.preprocessing.image import img_to_array\nfrom keras.models import Model\nfrom matplotlib import pyplot\nfrom numpy import expand_dims\n\n\n# Redefine model to output right after the first convolutional layer\n\n# redefine model to output right after the first hidden layer\n\nmodel = Model(inputs=base_model.inputs, outputs=base_model.layers[2].output)\nmodel.summary()\n\n# Load the image with the required shape\nimg = load_img('/kaggle/input/test-dog/cute-dog-1.jpg', target_size=(160, 160))\n# Convert the image to an array\nimg = img_to_array(img)\n# Expand dimensions so that it represents a single 'sample'\nimg = expand_dims(img, axis=0)\n# Prepare the image (e.g., scale pixel values for ResNet50)\nimg = preprocess_input(img)\n# Get feature map for first hidden layer\nfeature_maps = model.predict(img)\n\n# Plot all 64 maps in an 8x8 square\nsquare = 3\nix = 1\nfor _ in range(square):\n    for _ in range(square):\n        # Specify subplot and turn off axis\n        ax = pyplot.subplot(square, square, ix)\n        ax.set_xticks([])\n        ax.set_yticks([])\n        # Plot filter channel in grayscale\n        pyplot.imshow(feature_maps[0, :, :, ix-1], cmap='gray')\n        ix += 1\n# Show the figure\npyplot.show()","metadata":{"execution":{"iopub.status.busy":"2024-07-27T00:27:58.158997Z","iopub.execute_input":"2024-07-27T00:27:58.159412Z","iopub.status.idle":"2024-07-27T00:27:58.720836Z","shell.execute_reply.started":"2024-07-27T00:27:58.159379Z","shell.execute_reply":"2024-07-27T00:27:58.719941Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}