{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30919,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# Importing all the necessary libraries\nimport numpy as np\nimport matplotlib.pyplot as plt\nimport tensorflow.keras.backend as K\nimport tensorflow as tf\nfrom tensorflow.keras.models import Model, Sequential\nfrom tensorflow.keras.layers import Input, Dense, Flatten, Dropout\nfrom tensorflow.keras import optimizers\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.preprocessing import image\n\nfrom tensorflow.keras.applications import VGG16","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:47:54.594572Z","iopub.execute_input":"2025-04-06T11:47:54.594847Z","iopub.status.idle":"2025-04-06T11:48:06.984724Z","shell.execute_reply.started":"2025-04-06T11:47:54.594825Z","shell.execute_reply":"2025-04-06T11:48:06.983976Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Import the zipfile module to work with zip files\nimport zipfile\n\n# Define a function to extract a zip file to a specified directory\ndef extract_zip(input_zip, output_dir=\".\"):\n    with zipfile.ZipFile(input_zip, \"r\") as z:\n        z.extractall(output_dir)\n\n# Paths to the zip files for training and testing datasets\ntrain_zip_path = \"/kaggle/input/dogs-vs-cats/test1.zip\"\ntest_zip_path = \"/kaggle/input/dogs-vs-cats/train.zip\"\n\nextract_zip(train_zip_path)\nextract_zip(test_zip_path)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:06.985838Z","iopub.execute_input":"2025-04-06T11:48:06.986400Z","iopub.status.idle":"2025-04-06T11:48:20.196461Z","shell.execute_reply.started":"2025-04-06T11:48:06.986360Z","shell.execute_reply":"2025-04-06T11:48:20.195540Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Import necessary libraries\nimport os\nimport pandas as pd\n\n#Get the list of file names in the \"train\" folder\nfilenames = os.listdir(\"/kaggle/working/train\")\n\n# Initialize an empty list to store labels\nlabels = []\n\n# Loop through each filename to determine its label based on its name\nfor filename in filenames:\n    if \"cat\" in filename:\n        labels.append('cat')  # Append 'cat' if the filename contains \"cat\"\n    elif \"dog\" in filename:\n        labels.append('dog')  # Append 'dog' if the filename contains \"dog\"\n    \n# Create a DataFrame with filenames and their corresponding labels\ndf = pd.DataFrame({\n    'Filename': filenames,\n    'Label': labels\n})\n\n# Display the first five rows of the DataFrame\ndf.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:20.197937Z","iopub.execute_input":"2025-04-06T11:48:20.198263Z","iopub.status.idle":"2025-04-06T11:48:20.244839Z","shell.execute_reply.started":"2025-04-06T11:48:20.198235Z","shell.execute_reply":"2025-04-06T11:48:20.243961Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Importing VGG16 Model","metadata":{}},{"cell_type":"markdown","source":"#### Prepares image data generators for training and validation. Rescales the pixel values of the images and splits the dataset into training and validation subsets.","metadata":{}},{"cell_type":"code","source":"# Define image dimensions and batch size\nIMAGE_WIDTH, IMAGE_HEIGHT = 150, 150\nBATCH_SIZE = 32\n\n# Create an image data generator with rescaling and validation split\ndatagen = ImageDataGenerator(rescale=1./255, validation_split=0.2)\n\n# Generate training data from DataFrame with specified parameters\ntrain_generator = datagen.flow_from_dataframe(\n    dataframe=df,\n    directory='train/',\n    x_col='Filename',\n    y_col='Label',\n    target_size=(IMAGE_WIDTH, IMAGE_HEIGHT),\n    batch_size=BATCH_SIZE,\n    class_mode='binary',\n    subset='training'\n)\n\n# Generate validation data from DataFrame with specified parameters\nvalidation_generator = datagen.flow_from_dataframe(\n    dataframe=df,\n    directory='train/',\n    x_col='Filename',\n    y_col='Label',\n    target_size=(IMAGE_WIDTH, IMAGE_HEIGHT),\n    batch_size=BATCH_SIZE,\n    class_mode='binary',\n    subset='validation'\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:20.246183Z","iopub.execute_input":"2025-04-06T11:48:20.246417Z","iopub.status.idle":"2025-04-06T11:48:20.603907Z","shell.execute_reply.started":"2025-04-06T11:48:20.246398Z","shell.execute_reply":"2025-04-06T11:48:20.603184Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load VGG16 without the top layer (fully connected layers)\nmodel = VGG16(weights='imagenet', include_top=False, input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, 3))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:20.604655Z","iopub.execute_input":"2025-04-06T11:48:20.604941Z","iopub.status.idle":"2025-04-06T11:48:23.336053Z","shell.execute_reply.started":"2025-04-06T11:48:20.604914Z","shell.execute_reply":"2025-04-06T11:48:23.335107Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Freeze the convolutional base so that it's not trained again\nmodel.trainable = False\n\n# Summary of the VGG16 base model\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:23.336932Z","iopub.execute_input":"2025-04-06T11:48:23.337185Z","iopub.status.idle":"2025-04-06T11:48:23.364969Z","shell.execute_reply.started":"2025-04-06T11:48:23.337164Z","shell.execute_reply":"2025-04-06T11:48:23.364345Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Explanation:\n<ul>\n<li>\ninclude_top=False: This excludes the fully connected layers at the top of the network; we only want the convolutional base.\n</li><li>\ninput_shape=(150, 150, 3): This is the shape of the input images. We resize the input to 150x150 pixels with 3 color channels (RGB).\n</li><li>\nFreezing the base: \"model.trainable = False\" freezes the convolutional base, so its weights are not updated during training. This way, we use the features VGG16 has already learned without retraining it from scratch.\n</li></ul>","metadata":{}},{"cell_type":"markdown","source":"#### Adding new layers to the top","metadata":{}},{"cell_type":"code","source":"# Create a custom model on top of the pretrained VGG16 model\n\n# Flatten the output of the base model\nnew_top = Flatten()(model.output)  \n\n# Add a fully connected layer with 512 units and ReLU activation\nnew_top = Dense(512, activation='relu')(new_top)  \n\n# Apply dropout regularization to prevent overfitting\nnew_top = Dropout(0.5)(new_top)  \n\n# Add a final output layer with sigmoid activation for binary classification\npredictions = Dense(1, activation='sigmoid')(new_top) \n\n # Define the input and output of the custom model\nmodel = Model(inputs=model.input, outputs=predictions)  \n\n# Summary of the final model\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:23.365669Z","iopub.execute_input":"2025-04-06T11:48:23.365939Z","iopub.status.idle":"2025-04-06T11:48:23.417467Z","shell.execute_reply.started":"2025-04-06T11:48:23.365918Z","shell.execute_reply":"2025-04-06T11:48:23.416622Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Suppress warnings for a cleaner output\nimport warnings\nwarnings.filterwarnings('ignore')\n\nmodel.compile(loss='binary_crossentropy', optimizer=optimizers.Adam(learning_rate=0.0001), metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:23.419179Z","iopub.execute_input":"2025-04-06T11:48:23.419408Z","iopub.status.idle":"2025-04-06T11:48:23.431461Z","shell.execute_reply.started":"2025-04-06T11:48:23.419388Z","shell.execute_reply":"2025-04-06T11:48:23.430651Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Model Training\nThe provided code segment initiates the training of the Keras model with the following configurations:\n\n<ul>\n<li><b>Training Data:</b><br>\nThe train_generator is used to provide training data batches.</li>\n<li><b>Validation Data:</b><br> \nThe validation_generator is used to provide validation data batches.</li>\n<li><b>Steps per Epoch:</b><br> \nThe number of steps per epoch is determined by train_generator.samples // BATCH_SIZE, ensuring that each sample in the training dataset is seen once per epoch.</li>\n<li><b>Validation Steps:</b><br> \nSimilarly, the number of validation steps per epoch is determined by validation_generator.samples // BATCH_SIZE.</li>\n<li><b>Epochs:</b><br> \nThe model is trained for 10 epochs.</li>\n</ul>\n\nThis training procedure updates the model's weights using the training data, while also monitoring its performance on the validation data to prevent overfitting.","metadata":{}},{"cell_type":"code","source":"history = model.fit(train_generator, steps_per_epoch=137, \n                      validation_data= validation_generator,  validation_steps=35, \n                      epochs=15,\n                      verbose=2)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:48:23.432341Z","iopub.execute_input":"2025-04-06T11:48:23.432551Z","iopub.status.idle":"2025-04-06T11:50:17.610741Z","shell.execute_reply.started":"2025-04-06T11:48:23.432532Z","shell.execute_reply":"2025-04-06T11:50:17.609988Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Model Evaluation\nThe provided code segment plots the training and validation accuracy of the model over epochs. The following details are illustrated:\n\n<ul>\n<li>X-axis: Represents the number of epochs during model training.</li>\n<li>Y-axis: Indicates the corresponding accuracy values achieved by the model.</li>\n<li>Training Accuracy: The accuracy of the model on the training dataset.</li>\n<li>Validation Accuracy: The accuracy of the model on the validation dataset.</li>\n<li>Title: Title of the plot indicating \"Model Accuracy over Epochs\".</li>\n<li>Legend: Indicates the training and validation accuracy lines in the plot.</li>\n</ul>","metadata":{}},{"cell_type":"code","source":"# Visualize model training and validation accuracy\nplt.plot(history.history['accuracy'], label='Training Accuracy')\nplt.plot(history.history['val_accuracy'], label='Validation Accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.ylim([0.8, 1])  # Set y-axis limits for clarity\nplt.legend(loc='lower right')\nplt.title('Model Accuracy over Epochs')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:50:17.612250Z","iopub.execute_input":"2025-04-06T11:50:17.612602Z","iopub.status.idle":"2025-04-06T11:50:17.859071Z","shell.execute_reply.started":"2025-04-06T11:50:17.612547Z","shell.execute_reply":"2025-04-06T11:50:17.858184Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Model Fine-Tuning\nThe provided code segment unfreezes the last 10 layers of the base model for fine-tuning. It then compiles the model with the following configurations:\n\n<ul>\n<li>Optimizer: Adam optimizer with a learning rate of 0.0001.</li>\n<li>Loss Function: Binary crossentropy, suitable for binary classification tasks.</li>\n<li>Metrics: Accuracy metric is used to evaluate the model's performance during training.</li>\n</ul>","metadata":{}},{"cell_type":"code","source":"# Unfreeze the last 10 layers of the base model for fine-tuning\nfor layer in model.layers[-10:]:\n    layer.trainable = True\n\n# Compile the model with Adam optimizer, binary crossentropy loss, and accuracy metric\nmodel.compile(optimizer=optimizers.Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:50:17.860511Z","iopub.execute_input":"2025-04-06T11:50:17.860865Z","iopub.status.idle":"2025-04-06T11:50:17.869461Z","shell.execute_reply.started":"2025-04-06T11:50:17.860833Z","shell.execute_reply":"2025-04-06T11:50:17.868683Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Continue training the model with fine-tuning\nhistory_fine = model.fit(\n    train_generator,\n    steps_per_epoch=train_generator.samples // BATCH_SIZE,\n    validation_data=validation_generator,\n    validation_steps=validation_generator.samples // BATCH_SIZE,\n    epochs=10 \n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:50:17.870428Z","iopub.execute_input":"2025-04-06T11:50:17.870721Z","iopub.status.idle":"2025-04-06T11:53:51.038717Z","shell.execute_reply.started":"2025-04-06T11:50:17.870699Z","shell.execute_reply":"2025-04-06T11:53:51.037803Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Evaluating the Fine-Tuned Model\nThis code segment visualizes the accuracy of the fine-tuned model over epochs. It plots both training and validation accuracy to assess the model's performance after fine-tuning. Adjust the y-axis limits as needed for better visualization.","metadata":{}},{"cell_type":"code","source":"# Visualize the accuracy of the fine-tuned model\nplt.plot(history_fine.history['accuracy'], label='accuracy')\nplt.plot(history_fine.history['val_accuracy'], label='val_accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.ylim([0.92, 1])\nplt.legend(loc='lower right')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:53:51.040547Z","iopub.execute_input":"2025-04-06T11:53:51.040801Z","iopub.status.idle":"2025-04-06T11:53:51.240102Z","shell.execute_reply.started":"2025-04-06T11:53:51.040780Z","shell.execute_reply":"2025-04-06T11:53:51.239223Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Loading and Preparing Test Data\nThis code segment extracts the test data from the provided ZIP file and creates a DataFrame to store the filenames of the test images. The DataFrame allows easy access to the test data for further processing or evaluation.","metadata":{}},{"cell_type":"code","source":"# Extracting the test data from the ZIP file\nwith zipfile.ZipFile('/kaggle/input/dogs-vs-cats/test1.zip', 'r') as test1_zip:\n    test1_zip.extractall('.') \n\n# Define the directory path for the test data\ntest_dir = \"test1/\"\n\n# List the filenames of the test images\nfilenames = os.listdir(test_dir)\n\n# Create a DataFrame to store the filenames of the test images\ntest_data = pd.DataFrame({\"Filename\": filenames})\n\n# Display the first few rows of the test data DataFrame\ntest_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:54:57.233348Z","iopub.execute_input":"2025-04-06T11:54:57.233659Z","iopub.status.idle":"2025-04-06T11:55:00.436262Z","shell.execute_reply.started":"2025-04-06T11:54:57.233637Z","shell.execute_reply":"2025-04-06T11:55:00.435400Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Preparing Test Data Generator\nThis code segment sets up an ImageDataGenerator to preprocess the test data and creates a generator to yield batches of test images. The generator allows efficient processing of large test datasets in batches, which is essential for evaluation or prediction tasks.","metadata":{}},{"cell_type":"code","source":"# Create an ImageDataGenerator for test data preprocessing\ntest_gen = ImageDataGenerator(rescale=1./255)\n\n# Generate batches of test data from the DataFrame\ntest_generator = test_gen.flow_from_dataframe(\n    dataframe=test_data,\n    directory='test1/',\n    x_col='Filename',\n    y_col=None,\n    target_size=(IMAGE_WIDTH, IMAGE_HEIGHT),\n    batch_size=BATCH_SIZE,\n    class_mode=None,\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:55:08.340133Z","iopub.execute_input":"2025-04-06T11:55:08.340473Z","iopub.status.idle":"2025-04-06T11:55:08.426528Z","shell.execute_reply.started":"2025-04-06T11:55:08.340447Z","shell.execute_reply":"2025-04-06T11:55:08.425851Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Performing Predictions on Test Data\nThis code snippet utilizes the trained model to perform predictions on the test data generated by the test data generator. The predict method of the model is called on the test generator to obtain the predictions for each image in the test dataset. The resulting array contains the predicted probabilities for each image being in the positive class (dog).","metadata":{}},{"cell_type":"code","source":"# Perform predictions on the test data using the trained model\ntest1_predict = model.predict(test_generator)\ntest1_predict","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T11:55:16.326917Z","iopub.execute_input":"2025-04-06T11:55:16.327226Z","iopub.status.idle":"2025-04-06T11:55:36.682987Z","shell.execute_reply.started":"2025-04-06T11:55:16.327201Z","shell.execute_reply":"2025-04-06T11:55:36.682073Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Assigning Labels to Test Data\nIn this code snippet, a threshold of 0.5 is set for binary classification. The predicted probabilities obtained earlier are compared to this threshold, and based on the comparison, labels ('dog' or 'cat') are assigned to the test data. If the predicted probability is greater than the threshold, the label is set to 'dog'; otherwise, it is set to 'cat'.","metadata":{}},{"cell_type":"code","source":"# Set the threshold for binary classification\nthreshold = 0.5\n\n# Assign labels to the test data based on the predicted probabilities\ntest_data['Label'] = np.where(test1_predict > threshold, 'dog', 'cat')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T12:00:22.185769Z","iopub.execute_input":"2025-04-06T12:00:22.186107Z","iopub.status.idle":"2025-04-06T12:00:22.192258Z","shell.execute_reply.started":"2025-04-06T12:00:22.186079Z","shell.execute_reply":"2025-04-06T12:00:22.191443Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"#### Sample Test Images with Predicted Labels\nIn this code snippet, a sample of 6 test images along with their predicted labels are displayed using Matplotlib. The 'sample_test' DataFrame contains randomly selected rows from the test data, and for each row, the corresponding image is loaded and displayed along with its predicted label. The titles of the subplots represent the predicted labels ('dog' or 'cat').","metadata":{}},{"cell_type":"code","source":"# Image processing\nimport matplotlib.image as mpimg\n\n# Display a sample of test images with predicted labels\nsample_test = test_data.sample(n=6)\nplt.figure(figsize=(24, 8))\n\nsubplot_index = 1\nfor _, row in sample_test.iterrows():\n    image_path = os.path.join(test_dir, row['Filename'])\n    img = mpimg.imread(image_path)\n    plt.subplot(2, 3, subplot_index)\n    plt.imshow(img)\n    plt.title(row['Label'])\n    plt.axis('off')\n    subplot_index += 1\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-06T12:03:04.012703Z","iopub.execute_input":"2025-04-06T12:03:04.013010Z","iopub.status.idle":"2025-04-06T12:03:04.767724Z","shell.execute_reply.started":"2025-04-06T12:03:04.012987Z","shell.execute_reply":"2025-04-06T12:03:04.766634Z"}},"outputs":[],"execution_count":null}]}