{"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":"# Import libraries\nimport os\nimport shutil\nimport zipfile\nimport random\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.image as mpimg\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.preprocessing import image_dataset_from_directory\nfrom tensorflow.keras import layers\nfrom tensorflow.keras import Model\nfrom tensorflow.keras import losses\nfrom tensorflow.keras import optimizers","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:02.099389Z","iopub.execute_input":"2023-04-14T10:40:02.100595Z","iopub.status.idle":"2023-04-14T10:40:16.768664Z","shell.execute_reply.started":"2023-04-14T10:40:02.100521Z","shell.execute_reply":"2023-04-14T10:40:16.767171Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create helper functions\n    \ndef walk_through_path(path):\n    '''\n    A function for inspecting folders and files in a path\n    '''\n    for dir_path, dir_names, file_names in os.walk(path):\n        print(f'There are {len(dir_names)} folders and {len(file_names)} files in {dir_path}')\n        \ndef plot_loss_curves(history):\n    accuracy = history.history[\"accuracy\"]\n    val_accuracy = history.history[\"val_accuracy\"]\n    loss = history.history[\"loss\"]\n    val_loss = history.history[\"val_loss\"]\n    epochs = range(1, len(accuracy) + 1)\n    plt.plot(epochs, accuracy, \"bo\", label=\"Training accuracy\")\n    plt.plot(epochs, val_accuracy, \"b\", label=\"Validation accuracy\")\n    plt.title(\"Training and validation accuracy\")\n    plt.legend()\n    plt.figure()\n    plt.plot(epochs, loss, \"bo\", label=\"Training loss\")\n    plt.plot(epochs, val_loss, \"b\", label=\"Validation loss\")\n    plt.title(\"Training and validation loss\")\n    plt.legend()\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2023-04-14T13:14:58.839661Z","iopub.execute_input":"2023-04-14T13:14:58.840754Z","iopub.status.idle":"2023-04-14T13:14:58.852522Z","shell.execute_reply.started":"2023-04-14T13:14:58.840690Z","shell.execute_reply":"2023-04-14T13:14:58.850646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's exammine our data folder\nDATA_FOLDER = '/kaggle/input/dogs-vs-cats'\nprint(os.listdir(DATA_FOLDER))","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:16.807077Z","iopub.execute_input":"2023-04-14T10:40:16.809775Z","iopub.status.idle":"2023-04-14T10:40:16.822588Z","shell.execute_reply.started":"2023-04-14T10:40:16.809733Z","shell.execute_reply":"2023-04-14T10:40:16.821226Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Our train and test folder are in zip file so we must unzip them\n\n# Extract train data\n!unzip -qq /kaggle/input/dogs-vs-cats/train\n\n# Extract test data\n!unzip -qq /kaggle/input/dogs-vs-cats/test1","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:16.827690Z","iopub.execute_input":"2023-04-14T10:40:16.829296Z","iopub.status.idle":"2023-04-14T10:40:35.730322Z","shell.execute_reply.started":"2023-04-14T10:40:16.829254Z","shell.execute_reply":"2023-04-14T10:40:35.728969Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# :et's inspect our data folder after extracting train and test zip files\nos.listdir('/kaggle/working/')","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:35.733603Z","iopub.execute_input":"2023-04-14T10:40:35.734413Z","iopub.status.idle":"2023-04-14T10:40:35.744211Z","shell.execute_reply.started":"2023-04-14T10:40:35.734367Z","shell.execute_reply":"2023-04-14T10:40:35.742885Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create our train and test paths\ntrain_path = '/kaggle/working/train/'\ntest_path = '/kaggle/working/test1/'","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:35.746023Z","iopub.execute_input":"2023-04-14T10:40:35.746919Z","iopub.status.idle":"2023-04-14T10:40:35.751896Z","shell.execute_reply.started":"2023-04-14T10:40:35.746878Z","shell.execute_reply":"2023-04-14T10:40:35.750646Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Inspect our train folder\nwalk_through_path(train_path)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:35.753682Z","iopub.execute_input":"2023-04-14T10:40:35.754566Z","iopub.status.idle":"2023-04-14T10:40:35.789836Z","shell.execute_reply.started":"2023-04-14T10:40:35.754526Z","shell.execute_reply":"2023-04-14T10:40:35.788775Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Inspect our test folder\nwalk_through_path(test_path)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:35.791184Z","iopub.execute_input":"2023-04-14T10:40:35.791723Z","iopub.status.idle":"2023-04-14T10:40:35.812327Z","shell.execute_reply.started":"2023-04-14T10:40:35.791681Z","shell.execute_reply":"2023-04-14T10:40:35.811310Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Visualize a random sample from train dataset\nrandom_image = random.choice(os.listdir(train_path))\nimg = mpimg.imread(train_path + random_image)\nplt.imshow(img)\nplt.title(random_image.split('.')[0])\nplt.axis('off')","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:35.813728Z","iopub.execute_input":"2023-04-14T10:40:35.814153Z","iopub.status.idle":"2023-04-14T10:40:36.099256Z","shell.execute_reply.started":"2023-04-14T10:40:35.814117Z","shell.execute_reply":"2023-04-14T10:40:36.098290Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's see number of imagse of each class\n\n# Define two lists for store dogs and cats file paths\ncat_images = []\ndog_images = []\n\n# Loop through all files and sperate cats and dogs images\nfor file in os.listdir(train_path):\n    if file.split('.')[0] == 'cat':\n        cat_images.append(train_path + file)\n    elif file.split('.')[0] == 'dog':\n        dog_images.append(train_path + file)\nprint(f'cats: {len(cat_images)}\\n dogs:{len(dog_images)}')","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:36.103282Z","iopub.execute_input":"2023-04-14T10:40:36.104694Z","iopub.status.idle":"2023-04-14T10:40:36.142637Z","shell.execute_reply.started":"2023-04-14T10:40:36.104655Z","shell.execute_reply":"2023-04-14T10:40:36.141343Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Let's create two folder in train data folder,to seprate cats and dog pictures\n\n# Create a new folder for store our train images\nos.makedirs('kaggle/working/cats_vs_dogs/train')\n\n# Create cat folder in train folder\nos.mkdir('kaggle/working/cats_vs_dogs/train/cat/')\ncat_train_dir = 'kaggle/working/cats_vs_dogs/train/cat/'\n\n# Create dog folder in train folder\nos.mkdir('kaggle/working/cats_vs_dogs/train/dog/')\ndog_train_dir = 'kaggle/working/cats_vs_dogs/train/dog/'\n\n# Our original dataset not have a validation set, we created one with 1000 images\n\n# Create a new folder for store our train images\nos.mkdir('kaggle/working/cats_vs_dogs/val')\n\n# Create cat folder in train folder\nos.mkdir('kaggle/working/cats_vs_dogs/val/cat/')\ncat_val_dir = 'kaggle/working/cats_vs_dogs/val/cat/'\n\n# Create dog folder in train folder\nos.mkdir('kaggle/working/cats_vs_dogs/val/dog/')\ndog_val_dir = 'kaggle/working/cats_vs_dogs/val/dog/'\n\n# Copy our files to new directories\nfor file in cat_images[:12000]:\n    shutil.copyfile(src=file, dst=cat_train_dir + file.split('/')[-1])\n\nfor file in dog_images[:12000]:\n    shutil.copyfile(src=file, dst=dog_train_dir + file.split('/')[-1])\n    \nfor file in cat_images[12000:]:\n    shutil.copyfile(src=file, dst=cat_val_dir + file.split('/')[-1])\\\n    \nfor file in dog_images[12000:]:\n    shutil.copyfile(src=file, dst=dog_val_dir + file.split('/')[-1])","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:36.145625Z","iopub.execute_input":"2023-04-14T10:40:36.145899Z","iopub.status.idle":"2023-04-14T10:40:38.627310Z","shell.execute_reply.started":"2023-04-14T10:40:36.145873Z","shell.execute_reply":"2023-04-14T10:40:38.626246Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_dir = 'kaggle/working/cats_vs_dogs/train'\nval_dir = 'kaggle/working/cats_vs_dogs/val'","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:38.628636Z","iopub.execute_input":"2023-04-14T10:40:38.629353Z","iopub.status.idle":"2023-04-14T10:40:38.633966Z","shell.execute_reply.started":"2023-04-14T10:40:38.629306Z","shell.execute_reply":"2023-04-14T10:40:38.632996Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"walk_through_path(train_dir)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:38.635833Z","iopub.execute_input":"2023-04-14T10:40:38.637038Z","iopub.status.idle":"2023-04-14T10:40:38.669875Z","shell.execute_reply.started":"2023-04-14T10:40:38.636995Z","shell.execute_reply":"2023-04-14T10:40:38.668993Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"walk_through_path(val_dir)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:38.671583Z","iopub.execute_input":"2023-04-14T10:40:38.672297Z","iopub.status.idle":"2023-04-14T10:40:38.684663Z","shell.execute_reply.started":"2023-04-14T10:40:38.672260Z","shell.execute_reply":"2023-04-14T10:40:38.683018Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set random seed\ntf.random.set_seed(42)\n\n# Set image size\nIMAGE_SIZE = (224, 224)\n\n# Set batch size\nBATCH_SIZE = 32\n\nprint('Creating train dataset...')\ntrain_data = image_dataset_from_directory(directory=train_dir,\n                                          image_size=IMAGE_SIZE,\n                                          batch_size=32,\n                                          shuffle=True,\n                                          label_mode='binary')\n\nprint('Creating validation dataset...')\nval_data = image_dataset_from_directory(directory=val_dir,\n                                        image_size=IMAGE_SIZE,\n                                        batch_size=BATCH_SIZE,\n                                        shuffle=True,\n                                        label_mode='binary')","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:38.686043Z","iopub.execute_input":"2023-04-14T10:40:38.686868Z","iopub.status.idle":"2023-04-14T10:40:46.289404Z","shell.execute_reply.started":"2023-04-14T10:40:38.686830Z","shell.execute_reply":"2023-04-14T10:40:46.288181Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"data_augmentation = keras.Sequential([\n    layers.RandomFlip('horizontal'),\n    layers.RandomRotation(0.2),\n    layers.RandomZoom(0.2),\n    layers.RandomBrightness(factor=0.2),\n], name='data_augmentation')","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:46.290995Z","iopub.execute_input":"2023-04-14T10:40:46.291378Z","iopub.status.idle":"2023-04-14T10:40:46.320402Z","shell.execute_reply.started":"2023-04-14T10:40:46.291339Z","shell.execute_reply":"2023-04-14T10:40:46.319433Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a model\ninputs = layers.Input(shape=(224, 224, 3), name='input_layer')\nx = data_augmentation(inputs)\nx = layers.Rescaling(1/255.)(x)\nx = layers.Conv2D(filters=32, kernel_size=(3, 3), activation='relu', name='conv_1')(x)\nx = layers.MaxPooling2D(pool_size=(2, 2), name='pooling_1')(x)\nx = layers.Conv2D(filters=64, kernel_size=(3, 3), activation='relu', name='conv_2')(x)\nx = layers.MaxPooling2D(pool_size=(2, 2), name='pooling_2')(x)\nx = layers.Conv2D(filters=128, kernel_size=(3, 3), activation='relu', name='conv_3')(x)\nx = layers.MaxPooling2D(pool_size=(2, 2), name='pooling_3')(x)\nx = layers.Conv2D(filters=256, kernel_size=(3, 3), activation='relu', name='conv_4')(x)\nx = layers.Flatten()(x)\nx = layers.Dropout(0.5)(x)\noutputs = layers.Dense(1, activation='sigmoid', name='output_layer')(x)\nmodel = Model(inputs, outputs)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:46.321855Z","iopub.execute_input":"2023-04-14T10:40:46.322219Z","iopub.status.idle":"2023-04-14T10:40:49.179068Z","shell.execute_reply.started":"2023-04-14T10:40:46.322182Z","shell.execute_reply":"2023-04-14T10:40:49.178079Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Inspect our model's layers\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:49.183721Z","iopub.execute_input":"2023-04-14T10:40:49.186483Z","iopub.status.idle":"2023-04-14T10:40:49.247796Z","shell.execute_reply.started":"2023-04-14T10:40:49.186443Z","shell.execute_reply":"2023-04-14T10:40:49.247125Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.compile(loss=losses.BinaryCrossentropy(),\n         optimizer=optimizers.Adam(),\n         metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:49.248896Z","iopub.execute_input":"2023-04-14T10:40:49.249246Z","iopub.status.idle":"2023-04-14T10:40:49.291013Z","shell.execute_reply.started":"2023-04-14T10:40:49.249212Z","shell.execute_reply":"2023-04-14T10:40:49.290106Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"tf.random.set_seed(42)\n\nhistory = model.fit(train_data,\n          epochs=50,\n          steps_per_epoch=len(train_data),\n          validation_data=val_data,\n          validation_steps=int(0.25 * len(val_data)),\n          callbacks=[keras.callbacks.ModelCheckpoint(filepath='model.keras',\n                                                     save_best_only=True,\n                                                     monitor='val_loss')])","metadata":{"execution":{"iopub.status.busy":"2023-04-14T10:40:49.292365Z","iopub.execute_input":"2023-04-14T10:40:49.293008Z","iopub.status.idle":"2023-04-14T13:13:04.442621Z","shell.execute_reply.started":"2023-04-14T10:40:49.292971Z","shell.execute_reply":"2023-04-14T13:13:04.441557Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_model = keras.models.load_model(\n \"model.keras\")\ntest_loss, test_acc = test_model.evaluate(val_data)\nprint(f\"Test accuracy: {test_acc:.3f}\")","metadata":{"execution":{"iopub.status.busy":"2023-04-14T13:13:04.444654Z","iopub.execute_input":"2023-04-14T13:13:04.445085Z","iopub.status.idle":"2023-04-14T13:13:17.424154Z","shell.execute_reply.started":"2023-04-14T13:13:04.445031Z","shell.execute_reply":"2023-04-14T13:13:17.423031Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"pd.DataFrame(history.history).plot()","metadata":{"execution":{"iopub.status.busy":"2023-04-14T13:13:17.427322Z","iopub.execute_input":"2023-04-14T13:13:17.427627Z","iopub.status.idle":"2023-04-14T13:13:17.779015Z","shell.execute_reply.started":"2023-04-14T13:13:17.427599Z","shell.execute_reply":"2023-04-14T13:13:17.778091Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"plot_loss_curves(history)","metadata":{"execution":{"iopub.status.busy":"2023-04-14T13:15:19.003255Z","iopub.execute_input":"2023-04-14T13:15:19.003647Z","iopub.status.idle":"2023-04-14T13:15:19.428254Z","shell.execute_reply.started":"2023-04-14T13:15:19.003614Z","shell.execute_reply":"2023-04-14T13:15:19.427122Z"},"trusted":true},"execution_count":null,"outputs":[]}]}