{"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":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"},{"sourceId":6125,"sourceType":"modelInstanceVersion","modelInstanceId":4596}],"dockerImageVersionId":30664,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\nfor dirname, _, filenames in os.walk('dogs-vs-cats'):\n    print(dirname)\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n        break\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2024-03-03T15:16:03.810715Z","iopub.execute_input":"2024-03-03T15:16:03.811158Z","iopub.status.idle":"2024-03-03T15:16:04.339084Z","shell.execute_reply.started":"2024-03-03T15:16:03.811125Z","shell.execute_reply":"2024-03-03T15:16:04.336413Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Pre-processing","metadata":{}},{"cell_type":"code","source":"import os\nimport zipfile\n\ntraining_zip_path = '/kaggle/input/dogs-vs-cats/train.zip'\ntest_zip_path = '/kaggle/input/dogs-vs-cats/test1.zip'\ndataset_path = 'dogs-vs-cats/'\nwith zipfile.ZipFile(training_zip_path, 'r') as zip_ref:\n    zip_ref.extractall(dataset_path)\nwith zipfile.ZipFile(test_zip_path, 'r') as zip_ref:\n    zip_ref.extractall(dataset_path)\n\ntrain_folder = 'dogs-vs-cats/train'\ncat_folder = 'dogs-vs-cats/training/cat'\ndog_folder = 'dogs-vs-cats/training/dog'\n\nos.makedirs(cat_folder)\nos.makedirs(dog_folder)\nfor filename in os.listdir(train_folder):\n    if filename.split('.')[0] == 'cat':\n        os.rename(\n            os.path.join(train_folder, filename),\n            os.path.join(cat_folder, '.'.join(filename.split('.')[1:])))\n    else:\n        os.rename(\n            os.path.join(train_folder, filename),\n            os.path.join(dog_folder, '.'.join(filename.split('.')[1:])))\n\nfor filename in os.listdir('dogs-vs-cats/training'):\n    print(filename)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T15:16:07.341585Z","iopub.execute_input":"2024-03-03T15:16:07.343100Z","iopub.status.idle":"2024-03-03T15:16:25.562639Z","shell.execute_reply.started":"2024-03-03T15:16:07.343030Z","shell.execute_reply":"2024-03-03T15:16:25.561070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Exploratory Data Analysis","metadata":{}},{"cell_type":"code","source":"print('#Cat Images:', len(os.listdir('dogs-vs-cats/training/cat')))\nprint('#Dog Images:', len(os.listdir('dogs-vs-cats/training/dog')))","metadata":{"execution":{"iopub.status.busy":"2024-03-03T15:16:25.564790Z","iopub.execute_input":"2024-03-03T15:16:25.565918Z","iopub.status.idle":"2024-03-03T15:16:25.589437Z","shell.execute_reply.started":"2024-03-03T15:16:25.565882Z","shell.execute_reply":"2024-03-03T15:16:25.588537Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:33:03.968854Z","iopub.execute_input":"2024-03-03T10:33:03.969252Z","iopub.status.idle":"2024-03-03T10:33:19.389430Z","shell.execute_reply.started":"2024-03-03T10:33:03.969213Z","shell.execute_reply":"2024-03-03T10:33:19.388109Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import keras\n\ncat_image = keras.utils.load_img('dogs-vs-cats/training/cat/0.jpg')\ndog_image = keras.utils.load_img('dogs-vs-cats/training/dog/0.jpg')","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:33:19.557061Z","iopub.execute_input":"2024-03-03T10:33:19.557541Z","iopub.status.idle":"2024-03-03T10:33:19.563642Z","shell.execute_reply.started":"2024-03-03T10:33:19.557494Z","shell.execute_reply":"2024-03-03T10:33:19.562671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(cat_image)\ncat_image","metadata":{},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"cat_image.resize((256, 256))","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:33:19.565151Z","iopub.execute_input":"2024-03-03T10:33:19.565772Z","iopub.status.idle":"2024-03-03T10:33:19.613373Z","shell.execute_reply.started":"2024-03-03T10:33:19.565740Z","shell.execute_reply":"2024-03-03T10:33:19.612549Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"print(dog_image)\ndog_image","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:33:26.209061Z","iopub.execute_input":"2024-03-03T10:33:26.209492Z","iopub.status.idle":"2024-03-03T10:33:26.312625Z","shell.execute_reply.started":"2024-03-03T10:33:26.209459Z","shell.execute_reply":"2024-03-03T10:33:26.311431Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output_image = keras.utils.load_img('dogs-vs-cats/test1/1.jpg')\noutput_image","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:36:38.173847Z","iopub.execute_input":"2024-03-03T10:36:38.174365Z","iopub.status.idle":"2024-03-03T10:36:38.301840Z","shell.execute_reply.started":"2024-03-03T10:36:38.174327Z","shell.execute_reply":"2024-03-03T10:36:38.300471Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data Preprocessing","metadata":{}},{"cell_type":"code","source":"training_path = 'dogs-vs-cats/training'\ntest_path = 'dogs-vs-cats/test1'\ntraining_dataset, validation_dataset = keras.utils.image_dataset_from_directory(\n    training_path,\n    validation_split=0.2,\n    subset=\"both\",\n    seed=0,\n    batch_size=50)\ntest_dataset = keras.utils.image_dataset_from_directory(\n    test_path,\n    labels=None,\n    batch_size=50)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:40:59.277750Z","iopub.execute_input":"2024-03-03T10:40:59.278281Z","iopub.status.idle":"2024-03-03T10:41:02.483007Z","shell.execute_reply.started":"2024-03-03T10:40:59.278236Z","shell.execute_reply":"2024-03-03T10:41:02.481819Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Training data details:","metadata":{}},{"cell_type":"code","source":"training_dataset.element_spec","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:41:46.323881Z","iopub.execute_input":"2024-03-03T10:41:46.324411Z","iopub.status.idle":"2024-03-03T10:41:46.332353Z","shell.execute_reply.started":"2024-03-03T10:41:46.324372Z","shell.execute_reply":"2024-03-03T10:41:46.331105Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_dataset.cardinality().numpy()","metadata":{"execution":{"iopub.status.busy":"2024-03-03T07:26:20.179097Z","iopub.execute_input":"2024-03-03T07:26:20.179575Z","iopub.status.idle":"2024-03-03T07:26:20.187890Z","shell.execute_reply.started":"2024-03-03T07:26:20.179545Z","shell.execute_reply":"2024-03-03T07:26:20.186575Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_iter = iter(training_dataset)\nprint(training_iter.get_next())","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:43:14.828560Z","iopub.execute_input":"2024-03-03T10:43:14.828988Z","iopub.status.idle":"2024-03-03T10:43:15.269276Z","shell.execute_reply.started":"2024-03-03T10:43:14.828958Z","shell.execute_reply":"2024-03-03T10:43:15.268227Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Data pre-processing\nNeed to do one-hot encoding since the model that we are going to use has its last layer as `(None, 2)`. <br />\nAdditional data pre-processing like rescaling, augmentation, etc can be done if needed after fitting model with this data.","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\n\ndef one_hot_encode(labels, num_classes=2):\n    return tf.one_hot(labels, depth=num_classes)\n\ntraining_dataset = training_dataset.map(lambda x, y: (x, one_hot_encode(y)))\nvalidation_dataset = validation_dataset.map(lambda x, y: (x, one_hot_encode(y)))","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:49:23.610564Z","iopub.execute_input":"2024-03-03T10:49:23.610948Z","iopub.status.idle":"2024-03-03T10:49:23.725306Z","shell.execute_reply.started":"2024-03-03T10:49:23.610919Z","shell.execute_reply":"2024-03-03T10:49:23.724414Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"training_dataset.element_spec","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:49:34.055893Z","iopub.execute_input":"2024-03-03T10:49:34.056393Z","iopub.status.idle":"2024-03-03T10:49:34.066124Z","shell.execute_reply.started":"2024-03-03T10:49:34.056354Z","shell.execute_reply":"2024-03-03T10:49:34.064446Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"validation_dataset.element_spec","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:49:47.173016Z","iopub.execute_input":"2024-03-03T10:49:47.173949Z","iopub.status.idle":"2024-03-03T10:49:47.181087Z","shell.execute_reply.started":"2024-03-03T10:49:47.173906Z","shell.execute_reply":"2024-03-03T10:49:47.180106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Modelling: EfficientNetV2 as Image Classifier's Backbone","metadata":{}},{"cell_type":"code","source":"import keras_cv\n\nbackbone = keras_cv.models.EfficientNetV2Backbone.from_preset(\"efficientnetv2_b0_imagenet\")\nmodel = keras_cv.models.ImageClassifier(\n    backbone=backbone,\n    num_classes=2,\n    activation='sigmoid'\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:50:50.545215Z","iopub.execute_input":"2024-03-03T10:50:50.545606Z","iopub.status.idle":"2024-03-03T10:51:03.387621Z","shell.execute_reply.started":"2024-03-03T10:50:50.545576Z","shell.execute_reply":"2024-03-03T10:51:03.386213Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.output_shape","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:51:03.390034Z","iopub.execute_input":"2024-03-03T10:51:03.390440Z","iopub.status.idle":"2024-03-03T10:51:03.397314Z","shell.execute_reply.started":"2024-03-03T10:51:03.390407Z","shell.execute_reply":"2024-03-03T10:51:03.395474Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(\n    loss='binary_crossentropy',\n    optimizer=keras.optimizers.Adam(learning_rate=1e-5),\n    metrics=['accuracy']\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:53:31.523961Z","iopub.execute_input":"2024-03-03T10:53:31.524504Z","iopub.status.idle":"2024-03-03T10:53:31.542374Z","shell.execute_reply.started":"2024-03-03T10:53:31.524464Z","shell.execute_reply":"2024-03-03T10:53:31.540980Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.fit(\n    training_dataset,\n    validation_data=validation_dataset,\n    epochs=1)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T10:56:53.598498Z","iopub.execute_input":"2024-03-03T10:56:53.598898Z","iopub.status.idle":"2024-03-03T12:05:15.568690Z","shell.execute_reply.started":"2024-03-03T10:56:53.598866Z","shell.execute_reply":"2024-03-03T12:05:15.567126Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"predictions = model.predict(test_dataset)\npredictions","metadata":{"execution":{"iopub.status.busy":"2024-03-03T12:35:10.639542Z","iopub.execute_input":"2024-03-03T12:35:10.640076Z","iopub.status.idle":"2024-03-03T12:43:07.779248Z","shell.execute_reply.started":"2024-03-03T12:35:10.640030Z","shell.execute_reply":"2024-03-03T12:43:07.777988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"with open('dogs-vs-cats/predictions.npy', 'wb') as f:\n    np.save(f, predictions)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T12:43:08.448870Z","iopub.execute_input":"2024-03-03T12:43:08.449391Z","iopub.status.idle":"2024-03-03T12:43:08.456263Z","shell.execute_reply.started":"2024-03-03T12:43:08.449332Z","shell.execute_reply":"2024-03-03T12:43:08.455070Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"labels = np.argmax(predictions, axis=1)\noutput = pd.Series(labels).reset_index().rename(columns={\"index\": \"id\", 0: \"label\"})\noutput.id = output.id + 1\noutput","metadata":{"execution":{"iopub.status.busy":"2024-03-03T12:51:27.660235Z","iopub.execute_input":"2024-03-03T12:51:27.660711Z","iopub.status.idle":"2024-03-03T12:51:27.681249Z","shell.execute_reply.started":"2024-03-03T12:51:27.660671Z","shell.execute_reply":"2024-03-03T12:51:27.679914Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"output.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T14:44:55.703686Z","iopub.execute_input":"2024-03-03T14:44:55.704226Z","iopub.status.idle":"2024-03-03T14:44:56.164400Z","shell.execute_reply.started":"2024-03-03T14:44:55.704184Z","shell.execute_reply":"2024-03-03T14:44:56.162831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Augmenting dataset: Random Flip, RandAugment, CutMix","metadata":{}},{"cell_type":"code","source":"import keras_cv\n\naugmenter = keras_cv.layers.Augmenter(\n    [\n        keras_cv.layers.RandomFlip(),\n        keras_cv.layers.RandAugment(value_range=(0, 255)),\n        keras_cv.layers.CutMix(),\n    ],\n)","metadata":{"execution":{"iopub.status.busy":"2024-03-03T06:26:10.270494Z","iopub.status.idle":"2024-03-03T06:26:10.270874Z","shell.execute_reply.started":"2024-03-03T06:26:10.270685Z","shell.execute_reply":"2024-03-03T06:26:10.270701Z"},"trusted":true},"execution_count":null,"outputs":[]}]}