{"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":"markdown","source":"# Cat vs Dog Classification","metadata":{}},{"cell_type":"markdown","source":"This notebook demonstrates the steps involved in building a cat vs dog image classification model using a Convolutional Neural Network (CNN).\n\n### Step 1: Dataset Preparation\n\nThe first step is to prepare the dataset for training and testing the model.\n\n1. Download the dataset containing images of cats and dogs.\n2. Extract the contents of the dataset to a directory on your local machine.\n3. Split the dataset into training and testing sets.\n\n### Step 2: Model Architecture\n\nNext, we define the architecture of the CNN model that will be used for cat vs dog classification.\n\n1. Create a sequential model.\n2. Add convolutional layers with batch normalization, pooling, and dropout.\n3. Flatten the feature maps and add fully connected layers.\n4. Compile the model with appropriate loss function, optimizer, and evaluation metric.\n\n### Step 3: Data Augmentation\n\nTo improve the model's performance and generalization, data augmentation techniques are applied to the training set.\n\n1. Define an image data generator for data augmentation.\n2. Specify the augmentation options, such as rotation, rescaling, shearing, and flipping.\n3. Generate augmented training data using the data generator.\n\n### Step 4: Training the Model\n\nIn this step, we train the CNN model using the augmented training data.\n\n1. Set the number of training epochs and batch size.\n2. Fit the model on the training data and validate it on the validation data.\n3. Monitor the training progress and evaluate the model's performance.\n\n### Step 5: Evaluating the Model\n\nAfter training the model, we evaluate its performance on the testing set.\n\n1. Generate augmented testing data.\n2. Use the trained model to make predictions on the testing data.\n3. Evaluate the model's accuracy and other performance metrics.\n\n### Step 6: Predictions\n\nFinally, we can use the trained model to make predictions on new, unseen images.\n\n1. Load and preprocess the new image(s).\n2. Feed the image(s) to the model for prediction.\n3. Interpret the model's output and determine if the image contains a cat or a dog.\n\n","metadata":{}},{"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# 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))\n\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":"2023-06-28T14:41:35.715510Z","iopub.execute_input":"2023-06-28T14:41:35.715922Z","iopub.status.idle":"2023-06-28T14:41:35.724215Z","shell.execute_reply.started":"2023-06-28T14:41:35.715889Z","shell.execute_reply":"2023-06-28T14:41:35.723131Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Import Libraries","metadata":{}},{"cell_type":"code","source":"import os\nimport shutil\nimport zipfile\nimport pandas as pd\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, BatchNormalization, MaxPooling2D, Dropout, Flatten, Dense\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom PIL import Image","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:35.795465Z","iopub.execute_input":"2023-06-28T14:41:35.795843Z","iopub.status.idle":"2023-06-28T14:41:35.802156Z","shell.execute_reply.started":"2023-06-28T14:41:35.795806Z","shell.execute_reply":"2023-06-28T14:41:35.801214Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Dataset Preparation","metadata":{}},{"cell_type":"markdown","source":"## Setting Image Dimensions and Channels\n\nIn this step, we define the dimensions and channels of the input images that will be used for cat vs dog classification.\n\n### Image Width and Height\n\nThe image width and height determine the size of the input images that the model will process. In this case, we set the dimensions to 128x128 pixels. Adjusting the image dimensions can impact the model's performance, as larger images may require more computational resources and training time.\n\n### Image Channels\n\nImages can have different color channels, such as grayscale (1 channel) or RGB (3 channels). Here, we specify that the input images have 3 channels, which correspond to the red, green, and blue color channels. This is commonly used in color image classification tasks.\n\n### Image Size\n\nThe image size is a tuple containing the width and height values, representing the final dimensions of the images. In this case, the image size is set to (128, 128) pixels.\n\nDefining the image dimensions and channels is an important step to ensure consistency in the input data for the model. It enables proper processing and analysis of the images during training and inference.","metadata":{}},{"cell_type":"code","source":"# Set image dimensions and channels\nimage_width = 128\nimage_height = 128\nimage_channels = 3\nimage_size = (image_width, image_height)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:35.804207Z","iopub.execute_input":"2023-06-28T14:41:35.804902Z","iopub.status.idle":"2023-06-28T14:41:35.820270Z","shell.execute_reply.started":"2023-06-28T14:41:35.804870Z","shell.execute_reply":"2023-06-28T14:41:35.819306Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Extract Data from Zip file.","metadata":{}},{"cell_type":"code","source":"# Function to create a directory\ndef make_dir(dir_path):\n    if os.path.exists(dir_path):\n        shutil.rmtree(dir_path)\n    os.makedirs(dir_path)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:35.822062Z","iopub.execute_input":"2023-06-28T14:41:35.822452Z","iopub.status.idle":"2023-06-28T14:41:35.830638Z","shell.execute_reply.started":"2023-06-28T14:41:35.822420Z","shell.execute_reply":"2023-06-28T14:41:35.829726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set dataset path\ndataset_path = '../output/dogs-vs-cats'\n\n# Create dataset directory\nmake_dir(dataset_path)\n\n# Extract train.zip to dataset_path\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/train.zip\", \"r\") as zip_ref:\n    zip_ref.extractall(dataset_path)\n\n# Extract test1.zip to dataset_path\nwith zipfile.ZipFile(\"../input/dogs-vs-cats/test1.zip\", \"r\") as zip_ref:\n    zip_ref.extractall(dataset_path)\n\n# Get paths to train and test directories\nTrain_data = os.path.sep.join([dataset_path,\"train\"])\nTest_data=os.path.sep.join([dataset_path,\"test1\"])\n\ntrain_files=os.listdir(Train_data)\ntest_files= os.listdir(Test_data)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:35.875115Z","iopub.execute_input":"2023-06-28T14:41:35.875430Z","iopub.status.idle":"2023-06-28T14:41:45.872989Z","shell.execute_reply.started":"2023-06-28T14:41:35.875404Z","shell.execute_reply":"2023-06-28T14:41:45.871987Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Create a list to store categories\ncategories = []\n\n# Iterate over train files and assign categories\nfor filename in os.listdir(train_data):\n    category = filename.split(\".\")[0]\n    if category == \"dog\":\n        categories.append(1)\n    else:\n        categories.append(0)\n\n# Create a DataFrame to store filenames and categories\ndf = pd.DataFrame({\"filename\": os.listdir(train_data), \"category\": categories})","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:45.875018Z","iopub.execute_input":"2023-06-28T14:41:45.875388Z","iopub.status.idle":"2023-06-28T14:41:45.954840Z","shell.execute_reply.started":"2023-06-28T14:41:45.875354Z","shell.execute_reply":"2023-06-28T14:41:45.953303Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Displace some images","metadata":{}},{"cell_type":"code","source":"Image.open(os.path.sep.join([Train_data,train_files[10]]))","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:45.956151Z","iopub.execute_input":"2023-06-28T14:41:45.956499Z","iopub.status.idle":"2023-06-28T14:41:46.261574Z","shell.execute_reply.started":"2023-06-28T14:41:45.956465Z","shell.execute_reply":"2023-06-28T14:41:46.260705Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"Image.open(os.path.sep.join([Test_data,test_files[30]]))","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.264039Z","iopub.execute_input":"2023-06-28T14:41:46.265051Z","iopub.status.idle":"2023-06-28T14:41:46.385981Z","shell.execute_reply.started":"2023-06-28T14:41:46.265014Z","shell.execute_reply":"2023-06-28T14:41:46.385025Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Visualization","metadata":{}},{"cell_type":"code","source":"label=[\"Dog\",\"Cat\"]\ndf[\"category\"].value_counts().plot.pie(autopct='%1.2f%%',labels=label)\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.387403Z","iopub.execute_input":"2023-06-28T14:41:46.387942Z","iopub.status.idle":"2023-06-28T14:41:46.497656Z","shell.execute_reply.started":"2023-06-28T14:41:46.387911Z","shell.execute_reply":"2023-06-28T14:41:46.496699Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Creating the CNN Model\n\nIn this step, we create a Convolutional Neural Network (CNN) model for cat vs dog classification.\n\nA CNN is a deep learning architecture designed for image processing tasks. It consists of multiple layers that extract features from images and make predictions based on those features.\n\n### Model Architecture\n\nThe CNN model is created using the Sequential API from the Keras library. Here is the architecture of the model:\n\n1. **Convolutional Layers:** The model starts with a `Conv2D` layer with 32 filters, a kernel size of (3, 3), and the ReLU activation function. This layer processes the input images by convolving the filters over the image pixels, capturing local patterns and features.\n\n2. **Batch Normalization:** After each convolutional layer, a `BatchNormalization` layer is added. Batch normalization normalizes the activations of the previous layer, making the training process more stable and accelerating convergence.\n\n3. **Max Pooling Layers:** Following each batch normalization layer, a `MaxPooling2D` layer is included with a pool size of (2, 2). Max pooling reduces the spatial dimensions of the feature maps, focusing on the most important information while reducing the computational complexity.\n\n4. **Dropout Layers:** To prevent overfitting, `Dropout` layers are added after each max pooling layer. Dropout randomly sets a fraction of the input units to 0 during training, which helps to prevent the model from relying too much on specific features.\n\n5. **Flatten Layer:** After the last dropout layer, a `Flatten` layer is used to flatten the 2D feature maps into a 1D vector. This prepares the data for the fully connected layers.\n\n6. **Dense Layers:** Two fully connected `Dense` layers are added. The first dense layer has 512 units and uses the ReLU activation function. The second dense layer has 2 units (corresponding to the cat and dog classes) and uses the softmax activation function to output the probabilities for each class.\n\n### Model Compilation\n\nBefore training the model, we need to compile it by specifying the loss function, optimizer, and evaluation metrics. Here are the compilation settings:\n\n- **Loss Function:** The `categorical_crossentropy` loss function is used since we have a multi-class classification problem with two classes (cat and dog).\n\n- **Optimizer:** The Adam optimizer is used, which is an efficient optimization algorithm that adapts the learning rate during training.\n\n- **Metrics:** We specify `accuracy` as the evaluation metric to monitor the model's performance during training and evaluation.\n\nCompiling the model prepares it for training by configuring the necessary settings for the optimization process.","metadata":{}},{"cell_type":"code","source":"# Create the CNN model\nmodel = Sequential()\nmodel.add(Conv2D(32, (3, 3), activation=\"relu\", input_shape=(image_width, image_height, image_channels)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.1))\n\nmodel.add(Conv2D(64, (3, 3), activation=\"relu\"))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))\n\nmodel.add(Conv2D(128, (3, 3), activation=\"relu\"))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.1))\n\nmodel.add(Flatten())\nmodel.add(Dense(512, activation=\"relu\"))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(2, activation=\"softmax\"))\n\n# Compile the model\nmodel.compile(loss=\"categorical_crossentropy\", optimizer=\"adam\", metrics=['accuracy'])","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.499143Z","iopub.execute_input":"2023-06-28T14:41:46.500076Z","iopub.status.idle":"2023-06-28T14:41:46.704255Z","shell.execute_reply.started":"2023-06-28T14:41:46.500042Z","shell.execute_reply":"2023-06-28T14:41:46.701338Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Print model summary\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.705601Z","iopub.execute_input":"2023-06-28T14:41:46.706156Z","iopub.status.idle":"2023-06-28T14:41:46.749575Z","shell.execute_reply.started":"2023-06-28T14:41:46.706123Z","shell.execute_reply":"2023-06-28T14:41:46.748851Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Early Stopping and Learning Rate Reduction Callbacks\n\nIn this step, we set up two callbacks to monitor the training progress and make adjustments during the training process: Early Stopping and Learning Rate Reduction.\n\n### Early Stopping\n\nEarly stopping is a technique used to prevent overfitting and find the optimal number of training epochs. It monitors a specified metric (in this case, validation accuracy) and stops the training process if the metric doesn't improve for a certain number of epochs.\n\nHere's how we set up the Early Stopping callback:","metadata":{}},{"cell_type":"code","source":"early_stop = EarlyStopping(patience=10)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.750833Z","iopub.execute_input":"2023-06-28T14:41:46.751543Z","iopub.status.idle":"2023-06-28T14:41:46.813929Z","shell.execute_reply.started":"2023-06-28T14:41:46.751506Z","shell.execute_reply":"2023-06-28T14:41:46.812778Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- `patience=10` indicates that if the validation accuracy doesn't improve for 5 consecutive epochs, the training process will be stopped. This helps prevent overfitting by avoiding unnecessary training epochs when the model's performance plateaus.\n\n### Learning Rate Reduction\n\nLearning rate reduction is a technique used to adjust the learning rate during training, which can help the model converge faster and improve generalization. It reduces the learning rate if the validation metric (in this case, validation accuracy) doesn't improve for a certain number of epochs.\n\nHere's how we set up the Learning Rate Reduction callback:","metadata":{}},{"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor=\"val_accuracy\", patience=10)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.815319Z","iopub.execute_input":"2023-06-28T14:41:46.816243Z","iopub.status.idle":"2023-06-28T14:41:46.889675Z","shell.execute_reply.started":"2023-06-28T14:41:46.816209Z","shell.execute_reply":"2023-06-28T14:41:46.888643Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"- `monitor=\"val_accuracy\"` specifies that the callback should monitor the validation accuracy to decide when to reduce the learning rate.\n\n- `patience=10` indicates that if the validation accuracy doesn't improve for 5 consecutive epochs, the learning rate will be reduced.\n\nBy using these callbacks, we can automatically stop the training process when it's no longer improving and adjust the learning rate to facilitate better convergence. These techniques help us achieve better model performance and avoid overfitting.","metadata":{}},{"cell_type":"markdown","source":"## Preparing Data for Training and Validation\n\nIn this section, we perform the following steps to prepare our data for training and validation:\n\n### Replace Category Values\n\nThe original category values in the DataFrame `df` are represented as integers: 0 for \"cat\" and 1 for \"dog\". To make it more readable and intuitive, we replace the integer values with their corresponding labels:","metadata":{}},{"cell_type":"code","source":"df[\"category\"] = df[\"category\"].replace({0: 'cat', 1: 'dog'})","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.895030Z","iopub.execute_input":"2023-06-28T14:41:46.895644Z","iopub.status.idle":"2023-06-28T14:41:46.974052Z","shell.execute_reply.started":"2023-06-28T14:41:46.895605Z","shell.execute_reply":"2023-06-28T14:41:46.972873Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This step ensures that the category values are represented as strings, which will be helpful during data exploration and analysis.\n\n### Split DataFrame into Train and Validation Sets\n\nNext, we split the DataFrame `df` into training and validation sets using the `train_test_split` function from the `sklearn.model_selection` module. The splitting is performed based on a specified test size (in this case, 20% of the data) and a random seed (random_state) for reproducibility:","metadata":{}},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size=0.2, random_state=7)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:46.975645Z","iopub.execute_input":"2023-06-28T14:41:46.976362Z","iopub.status.idle":"2023-06-28T14:41:47.023924Z","shell.execute_reply.started":"2023-06-28T14:41:46.976325Z","shell.execute_reply":"2023-06-28T14:41:47.022956Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"The resulting `train_df` and `validate_df` DataFrames contain the training and validation samples, respectively.\n\n### Reset Index for Train and Validation DataFrames\n\nAfter splitting the DataFrame, the index values may not be sequential. To ensure that the index is reset and starts from 0 for both the `train_df` and `validate_df` DataFrames, we use the `reset_index` method with the `drop=True` parameter:","metadata":{}},{"cell_type":"code","source":"train_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:47.025743Z","iopub.execute_input":"2023-06-28T14:41:47.026492Z","iopub.status.idle":"2023-06-28T14:41:47.072267Z","shell.execute_reply.started":"2023-06-28T14:41:47.026456Z","shell.execute_reply":"2023-06-28T14:41:47.071094Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"This step ensures that the index values reflect the new order of the samples after the split.\n\n### Set Total Number of Training and Validation Samples\n\nFinally, we calculate and store the total number of training and validation samples for later use. The `shape[0]` attribute of a DataFrame returns the number of rows (samples), so we assign these values to the variables `total_train` and `total_validate`, respectively:","metadata":{}},{"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:47.077624Z","iopub.execute_input":"2023-06-28T14:41:47.080935Z","iopub.status.idle":"2023-06-28T14:41:47.129525Z","shell.execute_reply.started":"2023-06-28T14:41:47.078412Z","shell.execute_reply":"2023-06-28T14:41:47.128588Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"These variables will be used to specify the steps per epoch and validation steps during the model training process.","metadata":{}},{"cell_type":"markdown","source":"## Data Augmentation for Training Images","metadata":{}},{"cell_type":"markdown","source":"We set the batch size to 10, which determines the number of samples processed in each training batch. Then, we create an `ImageDataGenerator` instance called `train_datagen` to perform data augmentation on the training images. This includes various transformations such as rotation, rescaling, shearing, zooming, flipping, and shifting. Finally, we use the `flow_from_dataframe` method to generate augmented training data by providing the training DataFrame, directory path of the training images, column names for filenames and categories, target image size, class mode, and batch size. Data augmentation helps increase training data diversity and reduces the risk of overfitting.","metadata":{}},{"cell_type":"code","source":"# Set batch size\nbatch_size = 25\n\n# Set up data augmentation for training images\ntrain_datagen = ImageDataGenerator(\n    rotation_range=15,\n    rescale=1./255,\n    shear_range=0.1,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    width_shift_range=0.1,\n    height_shift_range=0.1\n)\n\n# Generate augmented training data\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df,\n    train_data,\n    x_col='filename',\n    y_col='category',\n    target_size=image_size,\n    class_mode=\"categorical\",\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:02:48.105365Z","iopub.execute_input":"2023-06-28T15:02:48.105740Z","iopub.status.idle":"2023-06-28T15:02:48.362044Z","shell.execute_reply.started":"2023-06-28T15:02:48.105710Z","shell.execute_reply":"2023-06-28T15:02:48.360735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We create another `ImageDataGenerator` instance called `validation_datagen` to apply data augmentation on the validation images. In this case, we only perform rescaling by dividing the pixel values by 255 to normalize them. Then, we use the `flow_from_dataframe` method with the validation DataFrame, directory path of the training images, column names for filenames and categories, target image size, class mode, and batch size to generate the validation data. The purpose of data augmentation on validation images is to maintain consistency with the preprocessing applied to the training images, allowing for fair evaluation of the model's performance.","metadata":{}},{"cell_type":"code","source":"# Set up data augmentation for validation images\nvalidation_datagen = ImageDataGenerator(rescale=1./255)\n\n# Generate validation data\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df,\n    train_data,\n    x_col='filename',\n    y_col='category',\n    target_size=image_size,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:47.565074Z","iopub.execute_input":"2023-06-28T14:41:47.565480Z","iopub.status.idle":"2023-06-28T14:41:47.883822Z","shell.execute_reply.started":"2023-06-28T14:41:47.565445Z","shell.execute_reply":"2023-06-28T14:41:47.882918Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We create an `ImageDataGenerator` instance called `test_datagen` to rescale the pixel values of the testing images by dividing them by 255. This ensures that the testing images are normalized similar to the training and validation images.\n\nThen, we use the `flow_from_directory` method with the directory path of the testing images, target image size, batch size, class mode set to None, and shuffle set to False. This configuration allows us to generate the augmented testing data without shuffling the order of the images.\n\nThe purpose of this data augmentation is to ensure consistency in preprocessing between the training, validation, and testing images, making the predictions on the testing data more reliable.","metadata":{}},{"cell_type":"code","source":"# Set up data augmentation for testing images\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\n# Generate augmented testing data\ntest_generator = test_datagen.flow_from_directory(\n    test_data,\n    target_size=image_size,\n    batch_size=batch_size,\n    class_mode=None,\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:47.885305Z","iopub.execute_input":"2023-06-28T14:41:47.885889Z","iopub.status.idle":"2023-06-28T14:41:48.040782Z","shell.execute_reply.started":"2023-06-28T14:41:47.885852Z","shell.execute_reply":"2023-06-28T14:41:48.039741Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Set up early stopping and learning rate reduction callbacks\nearly_stop = EarlyStopping(patience=5)\nlearning_rate_reduction = ReduceLROnPlateau(monitor=\"val_accuracy\", patience=5)\ncallbacks = [early_stop, learning_rate_reduction] ","metadata":{"execution":{"iopub.status.busy":"2023-06-28T14:41:48.046149Z","iopub.execute_input":"2023-06-28T14:41:48.046723Z","iopub.status.idle":"2023-06-28T14:41:48.051920Z","shell.execute_reply.started":"2023-06-28T14:41:48.046695Z","shell.execute_reply":"2023-06-28T14:41:48.050836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"We set the number of epochs to 5. Then we use the `fit` method of the model to train the model using the training data generated by `train_generator`. \n\nWe pass the following parameters to the `fit` method:\n- `epochs`: The number of epochs to train the model.\n- `validation_data`: The validation data generated by `validation_generator`.\n- `validation_steps`: The number of steps to validate the model per epoch. In this case, we divide the total number of validation samples by the batch size.\n- `steps_per_epoch`: The number of steps to take per epoch during training. In this case, we divide the total number of training samples by the batch size.\n- `callbacks`: The list of callbacks to be applied during training. This includes the early stopping and learning rate reduction callbacks defined earlier.\n\nThe training process will update the model's weights and monitor the validation accuracy to determine if early stopping should be applied or if the learning rate should be reduced. The training progress and evaluation metrics will be stored in the `history` object.","metadata":{}},{"cell_type":"code","source":"epochs = 10\nhistory = model.fit(\n    train_generator, \n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=total_validate // batch_size,\n    steps_per_epoch=total_train // batch_size,\n    callbacks=callbacks\n)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:03:03.125219Z","iopub.execute_input":"2023-06-28T15:03:03.125600Z","iopub.status.idle":"2023-06-28T15:23:48.289385Z","shell.execute_reply.started":"2023-06-28T15:03:03.125570Z","shell.execute_reply":"2023-06-28T15:23:48.288341Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"model.save(\"model1_catsVSdogs.h5\")","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:25:39.660184Z","iopub.execute_input":"2023-06-28T15:25:39.660575Z","iopub.status.idle":"2023-06-28T15:25:40.157815Z","shell.execute_reply.started":"2023-06-28T15:25:39.660542Z","shell.execute_reply":"2023-06-28T15:25:40.156508Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"# Model Evaluation Plot","metadata":{}},{"cell_type":"markdown","source":"The code retrieves the filenames of the test images, creates a DataFrame to store the filenames, and calculates the number of test samples or images in the test dataset.","metadata":{}},{"cell_type":"code","source":"test_filenames = os.listdir(test_data)\ntest_df = pd.DataFrame({\n    'filename': test_filenames\n})\nsamples = test_df.shape[0]","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:04.039285Z","iopub.execute_input":"2023-06-28T15:27:04.039659Z","iopub.status.idle":"2023-06-28T15:27:04.055555Z","shell.execute_reply.started":"2023-06-28T15:27:04.039628Z","shell.execute_reply":"2023-06-28T15:27:04.054583Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_gen = ImageDataGenerator(rescale=1./255)\ntest_generator = test_gen.flow_from_dataframe(\n    test_df,\n    test_data, \n    x_col='filename',\n    y_col=None,\n    class_mode=None,\n    target_size=image_size,\n    batch_size=batch_size,\n    shuffle=False\n)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:06.858443Z","iopub.execute_input":"2023-06-28T15:27:06.858825Z","iopub.status.idle":"2023-06-28T15:27:07.000654Z","shell.execute_reply.started":"2023-06-28T15:27:06.858775Z","shell.execute_reply":"2023-06-28T15:27:06.999713Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Predict the classes of the test images by passing the test generator to the model.predict() function.","metadata":{}},{"cell_type":"code","source":"predict = model.predict(test_generator, steps = np.ceil(samples/batch_size))","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:26:16.819007Z","iopub.execute_input":"2023-06-28T15:26:16.819468Z","iopub.status.idle":"2023-06-28T15:26:35.916853Z","shell.execute_reply.started":"2023-06-28T15:26:16.819433Z","shell.execute_reply":"2023-06-28T15:26:35.915779Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Add prdicted classes to test_df\ntest_df[\"predict\"]=np.argmax(predict,axis=-1)\ntest_df","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:13.633672Z","iopub.execute_input":"2023-06-28T15:27:13.634355Z","iopub.status.idle":"2023-06-28T15:27:13.647990Z","shell.execute_reply.started":"2023-06-28T15:27:13.634321Z","shell.execute_reply":"2023-06-28T15:27:13.646860Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Replace classes\ntest_df[\"predict\"]=test_df[\"predict\"].replace({1:\"Dog\",0:\"Cat\"})\ntest_df","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:17.143614Z","iopub.execute_input":"2023-06-28T15:27:17.143999Z","iopub.status.idle":"2023-06-28T15:27:17.160676Z","shell.execute_reply.started":"2023-06-28T15:27:17.143967Z","shell.execute_reply":"2023-06-28T15:27:17.159831Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"test_df[\"predict\"].value_counts().plot(kind=\"bar\")","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:20.923480Z","iopub.execute_input":"2023-06-28T15:27:20.923867Z","iopub.status.idle":"2023-06-28T15:27:21.146625Z","shell.execute_reply.started":"2023-06-28T15:27:20.923836Z","shell.execute_reply":"2023-06-28T15:27:21.145697Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"submission_df = test_df.copy()\nsubmission_df['id'] = submission_df['filename'].str.split('.').str[0]\nsubmission_df['label'] = submission_df['predict']\nsubmission_df.drop(['filename', 'predict'], axis=1, inplace=True)\nsubmission_df.to_csv('submission.csv', index=False)","metadata":{"execution":{"iopub.status.busy":"2023-06-28T15:27:28.219283Z","iopub.execute_input":"2023-06-28T15:27:28.219646Z","iopub.status.idle":"2023-06-28T15:27:28.279963Z","shell.execute_reply.started":"2023-06-28T15:27:28.219614Z","shell.execute_reply":"2023-06-28T15:27:28.279003Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"In summary, the code builds a CNN model for cat vs dog classification. It includes steps such as setting image dimensions, creating the model architecture, compiling the model, setting up callbacks for early stopping and learning rate reduction, preprocessing the data, setting data augmentation for training and validation images, generating augmented data, training the model, plotting the training and validation loss, and predicting the test data.","metadata":{}},{"cell_type":"markdown","source":"## Thank You!!!","metadata":{}}]}