{"metadata":{"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"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"!pip install visualkeras >> /dev/null\nimport visualkeras\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\nimport os\nimport zipfile\nimport glob\nimport shutil\nfrom tqdm import tqdm\nimport pathlib as pl\nimport cv2\nimport tqdm\nimport seaborn as sns\nimport matplotlib.pyplot as plt\nimport gc\ngc.collect()\n# TF\nimport tensorflow as tf\nimport keras\nfrom tensorflow.keras.optimizers import Adam, SGD\nfrom keras.utils.np_utils import to_categorical\nfrom keras.models import Sequential\nfrom keras.layers import (Conv2D, MaxPooling2D, Flatten, Dense, \n                          Dropout, Rescaling, RandomFlip, RandomRotation, BatchNormalization)\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.metrics import accuracy_score, classification_report\nfrom sklearn.metrics import confusion_matrix\nfrom tensorflow import keras","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-02-15T08:22:34.494466Z","iopub.execute_input":"2023-02-15T08:22:34.495469Z","iopub.status.idle":"2023-02-15T08:22:54.699543Z","shell.execute_reply.started":"2023-02-15T08:22:34.495366Z","shell.execute_reply":"2023-02-15T08:22:54.698454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 1. Organize image data into folders","metadata":{}},{"cell_type":"code","source":"def remove_folder_contents(folder):\n    for the_file in os.listdir(folder):\n        file_path = os.path.join(folder, the_file)\n        try:\n            if os.path.isfile(file_path):\n                os.unlink(file_path)\n            elif os.path.isdir(file_path):\n                remove_folder_contents(file_path)\n                os.rmdir(file_path)\n        except Exception as e:\n            print(e)\n\nfolder_path = '/kaggle/working'\nremove_folder_contents(folder_path)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:22:54.701907Z","iopub.execute_input":"2023-02-15T08:22:54.702604Z","iopub.status.idle":"2023-02-15T08:22:54.714280Z","shell.execute_reply.started":"2023-02-15T08:22:54.702559Z","shell.execute_reply":"2023-02-15T08:22:54.712008Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_zip_path = pl.Path(\"/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip\")\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip', 'r') as train_zip:\n    train_zip.extractall('')\ntrain_path = pl.Path(\"train\")    \n\ntest_zip_path = pl.Path(\"/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip\")\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip', 'r') as test_zip:\n    test_zip.extractall('')\ntest_path = pl.Path(\"test\")","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:22:54.718239Z","iopub.execute_input":"2023-02-15T08:22:54.718893Z","iopub.status.idle":"2023-02-15T08:23:13.813058Z","shell.execute_reply.started":"2023-02-15T08:22:54.718854Z","shell.execute_reply":"2023-02-15T08:23:13.811984Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_dir = 'data'\nos.mkdir(data_dir)\n\n# create new folders inside train_dir\ndog_folder = os.path.join(data_dir, 'Dog')\nos.mkdir(dog_folder)\ncat_folder = os.path.join(data_dir, 'Cat')\nos.mkdir(cat_folder)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:13.817709Z","iopub.execute_input":"2023-02-15T08:23:13.818032Z","iopub.status.idle":"2023-02-15T08:23:13.824642Z","shell.execute_reply.started":"2023-02-15T08:23:13.818002Z","shell.execute_reply":"2023-02-15T08:23:13.823534Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_images = {\n    \"Dog\":list(train_path.glob(\"dog*.jpg\")),\n    \"Cat\":list(train_path.glob(\"cat*.jpg\"))\n}\n\nfor label, images in train_images.items():\n    if label == 'Dog':\n        for image in tqdm.tqdm(images):\n            dst = os.path.join(dog_folder, image.name)\n            shutil.copyfile(image, dst)\n    if label == 'Cat':\n        for image in tqdm.tqdm(images):\n            dst = os.path.join(cat_folder, image.name)\n            shutil.copyfile(image, dst)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:13.827349Z","iopub.execute_input":"2023-02-15T08:23:13.830175Z","iopub.status.idle":"2023-02-15T08:23:16.931183Z","shell.execute_reply.started":"2023-02-15T08:23:13.830143Z","shell.execute_reply":"2023-02-15T08:23:16.929121Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# check how many train images we have in each folder\nprint(f\"# images in data/Dog: {len(os.listdir('data/Dog/'))}\")\nprint(f\"# images in data/Cat: {len(os.listdir('data/Cat/'))}\")","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:16.932791Z","iopub.execute_input":"2023-02-15T08:23:16.934352Z","iopub.status.idle":"2023-02-15T08:23:16.974200Z","shell.execute_reply.started":"2023-02-15T08:23:16.934307Z","shell.execute_reply":"2023-02-15T08:23:16.969951Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 2. Create TensorFlow datasets containing the images for train and validation","metadata":{}},{"cell_type":"markdown","source":"We use TF dataset because there is not enough RAM to contain all the training data in numpy arrays.","metadata":{}},{"cell_type":"code","source":"img_height,img_width = 224, 224\nbatch_size = 32\n\ntrain_ds = tf.keras.preprocessing.image_dataset_from_directory(\n    '/kaggle/working/data/',\n    validation_split=0.2,\n    subset=\"training\",\n    seed=42,\n    image_size=(img_height, img_width),\n    batch_size=batch_size,\n    shuffle=True,\n    labels='inferred')\n     \n    \nval_ds = tf.keras.preprocessing.image_dataset_from_directory(\n    '/kaggle/working/data/',\n    validation_split=0.2,\n    subset=\"validation\",\n    seed=42,\n    image_size=(img_height, img_width),\n    batch_size=batch_size,\n    shuffle=True,\n    labels='inferred')\n\nclass_names = train_ds.class_names","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:16.977211Z","iopub.execute_input":"2023-02-15T08:23:16.978956Z","iopub.status.idle":"2023-02-15T08:23:21.253885Z","shell.execute_reply.started":"2023-02-15T08:23:16.978901Z","shell.execute_reply":"2023-02-15T08:23:21.252919Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 10))\nfor images, labels in train_ds.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].numpy()])\n    plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:21.255187Z","iopub.execute_input":"2023-02-15T08:23:21.255610Z","iopub.status.idle":"2023-02-15T08:23:22.720504Z","shell.execute_reply.started":"2023-02-15T08:23:21.255572Z","shell.execute_reply":"2023-02-15T08:23:22.719185Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 3. Perform data scaling and aumengtation","metadata":{}},{"cell_type":"code","source":"# rescale = Sequential([\n#   Rescaling(1./255)\n# ])\n\n# data_augmentation = Sequential([\n#   RandomFlip(\"horizontal\"),\n#   RandomRotation(0.2),\n# ])","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:22.722796Z","iopub.execute_input":"2023-02-15T08:23:22.723678Z","iopub.status.idle":"2023-02-15T08:23:22.733045Z","shell.execute_reply.started":"2023-02-15T08:23:22.723622Z","shell.execute_reply":"2023-02-15T08:23:22.731852Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# normalized_ds = train_ds.map(lambda x, y: (rescale(x), y))\n# normalized_ds = normalized_ds.map(lambda x, y: (data_augmentation(x), y))\n# image_batch, labels_batch = next(iter(normalized_ds))\n# first_image = image_batch[0]\n# # Notice the pixel values are now in `[0,1]`.\n# print(np.min(first_image), np.max(first_image))\n# plt.imshow(first_image.numpy())\n# plt.axis(\"off\")","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:22.745040Z","iopub.execute_input":"2023-02-15T08:23:22.745933Z","iopub.status.idle":"2023-02-15T08:23:22.752978Z","shell.execute_reply.started":"2023-02-15T08:23:22.745881Z","shell.execute_reply":"2023-02-15T08:23:22.751837Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 4. Create our transfer-learning model using resNet50","metadata":{}},{"cell_type":"code","source":"resNet50 = tf.keras.applications.ResNet50(include_top=False,\n                   input_shape=(224,224,3),\n                   pooling='avg',\n                   weights='imagenet', classes=2)\n\nfor layer in resNet50.layers:\n        layer.trainable=False","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:22.755531Z","iopub.execute_input":"2023-02-15T08:23:22.761265Z","iopub.status.idle":"2023-02-15T08:23:24.965867Z","shell.execute_reply.started":"2023-02-15T08:23:22.761203Z","shell.execute_reply":"2023-02-15T08:23:24.964871Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualkeras.layered_view(resNet50, legend = True)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:24.967394Z","iopub.execute_input":"2023-02-15T08:23:24.967744Z","iopub.status.idle":"2023-02-15T08:23:26.437246Z","shell.execute_reply.started":"2023-02-15T08:23:24.967707Z","shell.execute_reply":"2023-02-15T08:23:26.436163Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model = Sequential()\nmodel.add(resNet50)\nmodel.add(Flatten())\nmodel.add(Dense(256, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dense(1, activation='sigmoid'))","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:26.438954Z","iopub.execute_input":"2023-02-15T08:23:26.439620Z","iopub.status.idle":"2023-02-15T08:23:27.033192Z","shell.execute_reply.started":"2023-02-15T08:23:26.439583Z","shell.execute_reply":"2023-02-15T08:23:27.032275Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"visualkeras.layered_view(model, legend = True)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:27.034406Z","iopub.execute_input":"2023-02-15T08:23:27.034994Z","iopub.status.idle":"2023-02-15T08:23:27.052720Z","shell.execute_reply.started":"2023-02-15T08:23:27.034900Z","shell.execute_reply":"2023-02-15T08:23:27.051715Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"early_stop = EarlyStopping(monitor=\"val_loss\",min_delta=0, patience=5,\n                           verbose=0, mode=\"min\", baseline=None, restore_best_weights=True)\n\nlearning_rate_reduction = ReduceLROnPlateau(monitor='val_loss', \n                                            patience=3, \n                                            verbose=1, \n                                            factor=0.5, \n                                            min_lr=0.00001)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:27.056051Z","iopub.execute_input":"2023-02-15T08:23:27.059704Z","iopub.status.idle":"2023-02-15T08:23:27.298661Z","shell.execute_reply.started":"2023-02-15T08:23:27.059662Z","shell.execute_reply":"2023-02-15T08:23:27.297405Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss=tf.keras.losses.BinaryCrossentropy(),\n              optimizer=SGD(learning_rate = 0.001, momentum = 0.1, decay = 0.0),\n              metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:27.300567Z","iopub.execute_input":"2023-02-15T08:23:27.302005Z","iopub.status.idle":"2023-02-15T08:23:27.328196Z","shell.execute_reply.started":"2023-02-15T08:23:27.301966Z","shell.execute_reply":"2023-02-15T08:23:27.327341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.1 Prefetch and cache data for faster training","metadata":{}},{"cell_type":"code","source":"#train_ds = train_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)\ntrain_ds = train_ds.prefetch(tf.data.AUTOTUNE)\n\n#val_ds = val_ds.cache().prefetch(buffer_size=tf.data.AUTOTUNE)\nval_ds = val_ds.cache().prefetch(tf.data.AUTOTUNE)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:27.332343Z","iopub.execute_input":"2023-02-15T08:23:27.334519Z","iopub.status.idle":"2023-02-15T08:23:27.343277Z","shell.execute_reply.started":"2023-02-15T08:23:27.334480Z","shell.execute_reply":"2023-02-15T08:23:27.342255Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.2 Train our model","metadata":{}},{"cell_type":"code","source":"num_epoch = 25\nhistory = model.fit(train_ds,\n                    epochs=num_epoch,\n                    verbose=1,\n                    validation_data=val_ds,\n                    callbacks = [early_stop, learning_rate_reduction])","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:23:27.348264Z","iopub.execute_input":"2023-02-15T08:23:27.350587Z","iopub.status.idle":"2023-02-15T08:24:29.607937Z","shell.execute_reply.started":"2023-02-15T08:23:27.350548Z","shell.execute_reply":"2023-02-15T08:24:29.606858Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## 4.3 Evaluate model","metadata":{}},{"cell_type":"code","source":"def graphLossAcurracy(loss, val_loss, accuracy, val_accuracy):\n    fig, ax = plt.subplots(1,2, figsize=(16,8))\n    ax[0].plot(loss, color='b', label=\"Training loss\")\n    ax[0].plot(val_loss, color='r', label=\"validation loss\",axes =ax[0])\n    legend = ax[0].legend(loc='best', shadow=True)\n\n    ax[1].plot(accuracy, color='b', label=\"Training accuracy\")\n    ax[1].plot(val_accuracy, color='r',label=\"Validation accuracy\")\n    legend = ax[1].legend(loc='best', shadow=True)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:29.609658Z","iopub.execute_input":"2023-02-15T08:24:29.610023Z","iopub.status.idle":"2023-02-15T08:24:29.618231Z","shell.execute_reply.started":"2023-02-15T08:24:29.609985Z","shell.execute_reply":"2023-02-15T08:24:29.616358Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"graphLossAcurracy(history.history['loss'], history.history['val_loss'], history.history['accuracy'], history.history['val_accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:29.619896Z","iopub.execute_input":"2023-02-15T08:24:29.620321Z","iopub.status.idle":"2023-02-15T08:24:30.403017Z","shell.execute_reply.started":"2023-02-15T08:24:29.620271Z","shell.execute_reply":"2023-02-15T08:24:30.401956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def get_labels(images, labels):\n    return labels\n\ny_val = np.concatenate([label.numpy() for label in val_ds.map(get_labels)])","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:30.410115Z","iopub.execute_input":"2023-02-15T08:24:30.410505Z","iopub.status.idle":"2023-02-15T08:24:30.620501Z","shell.execute_reply.started":"2023-02-15T08:24:30.410465Z","shell.execute_reply":"2023-02-15T08:24:30.611853Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Y_pred = model.predict(val_ds)\nY_pred = np.where(Y_pred < 0.5, 0, 1)\n\nplt.figure(figsize = (8,8))\n\nsns.heatmap(confusion_matrix(y_val, Y_pred),annot = True, fmt='g')\nplt.title(\"CONFUSION MATRIX\")\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"True\")\n\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:30.621729Z","iopub.execute_input":"2023-02-15T08:24:30.622121Z","iopub.status.idle":"2023-02-15T08:24:39.988934Z","shell.execute_reply.started":"2023-02-15T08:24:30.622065Z","shell.execute_reply":"2023-02-15T08:24:39.987992Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# 5. Predictions","metadata":{}},{"cell_type":"code","source":"test_ds = tf.keras.preprocessing.image_dataset_from_directory(\n  '/kaggle/working/test/',\n  image_size=(img_height, img_width),\n  batch_size=32,\n  label_mode=None,\n  shuffle=False)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:39.990344Z","iopub.execute_input":"2023-02-15T08:24:39.991282Z","iopub.status.idle":"2023-02-15T08:24:40.263622Z","shell.execute_reply.started":"2023-02-15T08:24:39.991243Z","shell.execute_reply":"2023-02-15T08:24:40.262594Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"y_pred = model.predict(test_ds)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:24:40.265153Z","iopub.execute_input":"2023-02-15T08:24:40.265770Z","iopub.status.idle":"2023-02-15T08:25:01.601613Z","shell.execute_reply.started":"2023-02-15T08:24:40.265731Z","shell.execute_reply":"2023-02-15T08:25:01.600523Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv')\nsub.label = np.where(y_pred < 0.5, 0, 1)\nsub","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:25:01.603280Z","iopub.execute_input":"2023-02-15T08:25:01.604052Z","iopub.status.idle":"2023-02-15T08:25:01.652113Z","shell.execute_reply.started":"2023-02-15T08:25:01.604013Z","shell.execute_reply":"2023-02-15T08:25:01.651211Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"sub.to_csv('submission.csv', index = False)","metadata":{"execution":{"iopub.status.busy":"2023-02-15T08:25:01.653544Z","iopub.execute_input":"2023-02-15T08:25:01.658166Z","iopub.status.idle":"2023-02-15T08:25:01.686482Z","shell.execute_reply.started":"2023-02-15T08:25:01.658128Z","shell.execute_reply":"2023-02-15T08:25:01.685599Z"},"trusted":true},"execution_count":null,"outputs":[]}]}