{"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11.11","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":31013,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true},"papermill":{"default_parameters":{},"duration":3101.621212,"end_time":"2024-09-21T21:27:52.657629","environment_variables":{},"exception":null,"input_path":"__notebook__.ipynb","output_path":"__notebook__.ipynb","parameters":{},"start_time":"2024-09-21T20:36:11.036417","version":"2.6.0"}},"nbformat_minor":4,"nbformat":4,"cells":[{"id":"d905e67d","cell_type":"code","source":"import numpy as np\nimport pandas as pd \nimport random\nimport os\nimport zipfile\nfrom PIL import Image\nimport seaborn as sns\nimport shutil\nimport cv2\n\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\n\nfrom keras.models import Sequential,Model\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, BatchNormalization,Input,GlobalAveragePooling2D\nfrom sklearn.metrics import confusion_matrix , classification_report, ConfusionMatrixDisplay\nfrom keras.callbacks import (ModelCheckpoint, LearningRateScheduler,\n                             EarlyStopping, ReduceLROnPlateau)\nfrom tensorflow.keras.optimizers import Adam\nfrom keras.regularizers import l2\nfrom tensorflow.keras.applications.resnet50 import ResNet50\nfrom tensorflow.keras.applications.resnet50 import preprocess_input\nfrom sklearn.model_selection import train_test_split\n\n\nprint(os.listdir(\"../input\"))","metadata":{"_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","execution":{"iopub.status.busy":"2025-04-30T15:23:06.238116Z","iopub.execute_input":"2025-04-30T15:23:06.238272Z","iopub.status.idle":"2025-04-30T15:23:22.194518Z","shell.execute_reply.started":"2025-04-30T15:23:06.238257Z","shell.execute_reply":"2025-04-30T15:23:22.193844Z"},"papermill":{"duration":23.733089,"end_time":"2024-09-21T20:36:38.810335","exception":false,"start_time":"2024-09-21T20:36:15.077246","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"828be91e","cell_type":"markdown","source":"# Unzip and Load The Data ","metadata":{"papermill":{"duration":0.016221,"end_time":"2024-09-21T20:36:38.844999","exception":false,"start_time":"2024-09-21T20:36:38.828778","status":"completed"},"tags":[]}},{"id":"a5b5fba1","cell_type":"code","source":"# Set the path for the input directory where the zip files are located\ninput_path = '/kaggle/input/dogs-vs-cats'\n\n# Define the paths for the train and test zip files\ntrain_zip = os.path.join(input_path, 'train.zip')\ntest_zip = os.path.join(input_path, 'test1.zip')\n\n# Set the output paths where the unzipped data will be extracted\noutput_train_path = '/kaggle/working/train'\noutput_test_path = '/kaggle/working/test'\n\n# Unzip the training data to the specified output path\nwith zipfile.ZipFile(train_zip, 'r') as zip_ref:\n    zip_ref.extractall(output_train_path)\n    print(\"Unzipping training data complete.\")\n\n# Unzip the test data to the specified output path\nwith zipfile.ZipFile(test_zip, 'r') as zip_ref:\n    zip_ref.extractall(output_test_path)\n    print(\"Unzipping testing data complete.\")\n","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:22.195182Z","iopub.execute_input":"2025-04-30T15:23:22.195788Z","iopub.status.idle":"2025-04-30T15:23:35.719726Z","shell.execute_reply.started":"2025-04-30T15:23:22.195760Z","shell.execute_reply":"2025-04-30T15:23:35.718952Z"},"papermill":{"duration":16.765446,"end_time":"2024-09-21T20:36:55.626710","exception":false,"start_time":"2024-09-21T20:36:38.861264","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"8648c521","cell_type":"code","source":"train_data_path='/kaggle/working/train/train'\ntest_data_path='/kaggle/working/test/test1'\n\ntrain_images=os.listdir(train_data_path)\ntest_images=os.listdir(test_data_path)","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:35.720645Z","iopub.execute_input":"2025-04-30T15:23:35.720882Z","iopub.status.idle":"2025-04-30T15:23:35.741157Z","shell.execute_reply.started":"2025-04-30T15:23:35.720865Z","shell.execute_reply":"2025-04-30T15:23:35.740666Z"},"papermill":{"duration":0.04482,"end_time":"2024-09-21T20:36:55.688386","exception":false,"start_time":"2024-09-21T20:36:55.643566","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"f0497f10","cell_type":"markdown","source":"# Get the images into DataFrame","metadata":{"papermill":{"duration":0.016201,"end_time":"2024-09-21T20:36:55.721752","exception":false,"start_time":"2024-09-21T20:36:55.705551","status":"completed"},"tags":[]}},{"id":"969635c9","cell_type":"code","source":"image_name=[]\ncategory=[]\ncode=[]\nsize=[]\naspect_ratio=[]\n\nfor image in train_images:\n    image_name.append(image)\n    cate=image.split('.')[0]\n    category.append(cate)\n    code.append(1) if cate=='dog'  else code.append(0)\n    \n    img_path=os.path.join(train_data_path,image)    \n    # Read the image to get its size (height, width)\n    img=cv2.imread(img_path)\n    size.append((img.shape[0],img.shape[1]))\n    # Calculate and append the aspect ratio (height/width) of the image\n    aspect_ratio.append(img.shape[0]/img.shape[1])\n\ntrain_df=pd.DataFrame({'Image_Name':image_name,'Category':category,'Code':code,\"Size\":size,'Aspect_ratio':aspect_ratio})\ntrain_df","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:35.741887Z","iopub.execute_input":"2025-04-30T15:23:35.742570Z","iopub.status.idle":"2025-04-30T15:23:54.392240Z","shell.execute_reply.started":"2025-04-30T15:23:35.742551Z","shell.execute_reply":"2025-04-30T15:23:54.391431Z"},"papermill":{"duration":19.868225,"end_time":"2024-09-21T20:37:15.606509","exception":false,"start_time":"2024-09-21T20:36:55.738284","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"15561062","cell_type":"code","source":"# Define a function to display the first 9 images from a DataFrame \ndef display_first_9(path,df):\n    plt.figure(figsize=[30,30])\n    for i in range(9):\n        plt.subplot(3,3,i+1)\n        img_path=os.path.join(path,df['Image_Name'].iloc[i])\n        plt.title(df['Image_Name'][i])\n        img=Image.open(img_path)\n        plt.imshow(img)\n        plt.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:54.393239Z","iopub.execute_input":"2025-04-30T15:23:54.393553Z","iopub.status.idle":"2025-04-30T15:23:54.398095Z","shell.execute_reply.started":"2025-04-30T15:23:54.393528Z","shell.execute_reply":"2025-04-30T15:23:54.397402Z"},"papermill":{"duration":0.026388,"end_time":"2024-09-21T20:37:15.651140","exception":false,"start_time":"2024-09-21T20:37:15.624752","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"46b139c0","cell_type":"code","source":"df_sorted=train_df.sort_values(by='Aspect_ratio',ascending=False)\ndisplay_first_9(train_data_path,df_sorted)","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:54.400379Z","iopub.execute_input":"2025-04-30T15:23:54.400669Z","iopub.status.idle":"2025-04-30T15:23:55.774913Z","shell.execute_reply.started":"2025-04-30T15:23:54.400651Z","shell.execute_reply":"2025-04-30T15:23:55.773881Z"},"papermill":{"duration":1.861661,"end_time":"2024-09-21T20:37:17.529479","exception":false,"start_time":"2024-09-21T20:37:15.667818","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"519fb88f","cell_type":"code","source":"df_sorted=train_df.sort_values(by='Aspect_ratio',ascending=True)\ndisplay_first_9(train_data_path,df_sorted)","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:55.776125Z","iopub.execute_input":"2025-04-30T15:23:55.776994Z","iopub.status.idle":"2025-04-30T15:23:56.965209Z","shell.execute_reply.started":"2025-04-30T15:23:55.776957Z","shell.execute_reply":"2025-04-30T15:23:56.964152Z"},"papermill":{"duration":1.896291,"end_time":"2024-09-21T20:37:19.472393","exception":false,"start_time":"2024-09-21T20:37:17.576102","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"6d16eca1","cell_type":"markdown","source":"now we can find that there are 3 image that dosen't belong to out data and they might have come from scraping some websites","metadata":{"papermill":{"duration":0.068886,"end_time":"2024-09-21T20:37:19.611611","exception":false,"start_time":"2024-09-21T20:37:19.542725","status":"completed"},"tags":[]}},{"id":"ad171bde","cell_type":"code","source":"ax=sns.countplot(data=train_df,x='Category',palette='viridis')\nax.bar_label(ax.containers[0])\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:56.966233Z","iopub.execute_input":"2025-04-30T15:23:56.966482Z","iopub.status.idle":"2025-04-30T15:23:57.082005Z","shell.execute_reply.started":"2025-04-30T15:23:56.966457Z","shell.execute_reply":"2025-04-30T15:23:57.081246Z"},"papermill":{"duration":0.330572,"end_time":"2024-09-21T20:37:22.032605","exception":false,"start_time":"2024-09-21T20:37:21.702033","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"7d16c016","cell_type":"markdown","source":"# Split the training data into training, test, and validation sets \nThis is done to evaluate the model and understand its performance.\n","metadata":{"papermill":{"duration":0.088097,"end_time":"2024-09-21T20:37:22.215375","exception":false,"start_time":"2024-09-21T20:37:22.127278","status":"completed"},"tags":[]}},{"id":"581b8c63","cell_type":"code","source":"# First split: 80% training and 20% temporary (validation + test)\ntrain_df, temp_df = train_test_split(train_df, test_size=0.2, random_state=42, stratify=train_df['Category'])\n\n# Second split: 50% of temp_df for validation and 50% for test (10% of original data each)\nval_df, test_df = train_test_split(temp_df, test_size=0.5, random_state=42, stratify=temp_df['Category'])","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.082825Z","iopub.execute_input":"2025-04-30T15:23:57.083135Z","iopub.status.idle":"2025-04-30T15:23:57.118836Z","shell.execute_reply.started":"2025-04-30T15:23:57.083116Z","shell.execute_reply":"2025-04-30T15:23:57.118144Z"},"papermill":{"duration":0.153526,"end_time":"2024-09-21T20:37:22.456249","exception":false,"start_time":"2024-09-21T20:37:22.302723","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"cabdf1d6","cell_type":"code","source":"train_df.sort_values(by='Size',ascending=False)","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.119953Z","iopub.execute_input":"2025-04-30T15:23:57.120231Z","iopub.status.idle":"2025-04-30T15:23:57.156875Z","shell.execute_reply.started":"2025-04-30T15:23:57.120207Z","shell.execute_reply":"2025-04-30T15:23:57.156328Z"},"papermill":{"duration":0.143449,"end_time":"2024-09-21T20:37:23.724527","exception":false,"start_time":"2024-09-21T20:37:23.581078","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"5fb3dc65","cell_type":"markdown","source":"# Image Data Generator","metadata":{"papermill":{"duration":0.087638,"end_time":"2024-09-21T20:37:23.908254","exception":false,"start_time":"2024-09-21T20:37:23.820616","status":"completed"},"tags":[]}},{"id":"8ab5624b","cell_type":"code","source":"image_size=(224,224)\nimage_channels=3\nimage_shape=(image_size[0],image_size[1],3)\nbatch_size = 32\nepochs = 5","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.157623Z","iopub.execute_input":"2025-04-30T15:23:57.157875Z","iopub.status.idle":"2025-04-30T15:23:57.161766Z","shell.execute_reply.started":"2025-04-30T15:23:57.157852Z","shell.execute_reply":"2025-04-30T15:23:57.161027Z"},"papermill":{"duration":0.1005,"end_time":"2024-09-21T20:37:24.096533","exception":false,"start_time":"2024-09-21T20:37:23.996033","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"8abd7ebb","cell_type":"code","source":"train_data_gen = ImageDataGenerator(preprocessing_function=preprocess_input,\n                                    horizontal_flip=True,\n                                    zoom_range=0.2,\n                                    width_shift_range=0.3,\n                                    height_shift_range=0.3,\n                                    rotation_range=0.3,\n                                    shear_range=0.2,\n                                    fill_mode='nearest')\n\ntrain_generator = train_data_gen.flow_from_dataframe(\n                                    dataframe=train_df,          \n                                    directory=train_data_path,   \n                                    x_col='Image_Name',\n                                    y_col='Category',\n                                    batch_size=batch_size, \n                                    shuffle=True,\n                                    class_mode=\"binary\",\n                                    target_size=image_size)\n","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.162510Z","iopub.execute_input":"2025-04-30T15:23:57.162749Z","iopub.status.idle":"2025-04-30T15:23:57.321672Z","shell.execute_reply.started":"2025-04-30T15:23:57.162715Z","shell.execute_reply":"2025-04-30T15:23:57.321117Z"},"papermill":{"duration":0.360527,"end_time":"2024-09-21T20:37:24.723302","exception":false,"start_time":"2024-09-21T20:37:24.362775","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"471be876","cell_type":"code","source":"val_data_gen = ImageDataGenerator(preprocessing_function=preprocess_input)\n\nval_generator = val_data_gen.flow_from_dataframe(\n                                    dataframe=val_df,            \n                                    directory=train_data_path,   \n                                    x_col='Image_Name',\n                                    y_col='Category',\n                                    batch_size=batch_size, \n                                    shuffle=False,\n                                    class_mode=\"binary\",\n                                    target_size=image_size)\n\n\ntest_generator = val_data_gen.flow_from_dataframe(\n                                    dataframe=test_df,            \n                                   directory=train_data_path,   \n                                    x_col='Image_Name',\n                                    y_col='Category',\n                                    batch_size=batch_size, \n                                    shuffle=False,\n                                    class_mode=\"binary\",\n                                    target_size=image_size)","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.322491Z","iopub.execute_input":"2025-04-30T15:23:57.323007Z","iopub.status.idle":"2025-04-30T15:23:57.371340Z","shell.execute_reply.started":"2025-04-30T15:23:57.322982Z","shell.execute_reply":"2025-04-30T15:23:57.370735Z"},"papermill":{"duration":0.175518,"end_time":"2024-09-21T20:37:24.990570","exception":false,"start_time":"2024-09-21T20:37:24.815052","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"34b12526","cell_type":"markdown","source":"You can still apply the preprocessing_function=preprocess_input to your validation and test data because it ensures consistency with how the model was trained.","metadata":{"papermill":{"duration":0.088785,"end_time":"2024-09-21T20:37:25.168925","exception":false,"start_time":"2024-09-21T20:37:25.080140","status":"completed"},"tags":[]}},{"id":"f8d34477","cell_type":"code","source":"sample_batch=next(train_generator)\nimages,labels=sample_batch","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.372185Z","iopub.execute_input":"2025-04-30T15:23:57.372410Z","iopub.status.idle":"2025-04-30T15:23:57.707085Z","shell.execute_reply.started":"2025-04-30T15:23:57.372394Z","shell.execute_reply":"2025-04-30T15:23:57.706342Z"},"papermill":{"duration":0.44094,"end_time":"2024-09-21T20:37:25.877427","exception":false,"start_time":"2024-09-21T20:37:25.436487","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"38557bec","cell_type":"code","source":"\nplt.figure(figsize=(15,15))\nfor i in range(batch_size):\n    plt.subplot(8,4,i+1)\n    plt.imshow(images[i])\n    label_index = np.argmax(labels[i])\n    label='Cat' if label_index ==0 else 'Dog'\n    plt.title(label)\n    plt.axis('off')\nplt.tight_layout()\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:57.707807Z","iopub.execute_input":"2025-04-30T15:23:57.707989Z","iopub.status.idle":"2025-04-30T15:23:59.479407Z","shell.execute_reply.started":"2025-04-30T15:23:57.707974Z","shell.execute_reply":"2025-04-30T15:23:59.478631Z"},"papermill":{"duration":5.106335,"end_time":"2024-09-21T20:37:31.072788","exception":false,"start_time":"2024-09-21T20:37:25.966453","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"756c626d","cell_type":"markdown","source":"# ReseNet Model","metadata":{"papermill":{"duration":0.098344,"end_time":"2024-09-21T20:37:31.275984","exception":false,"start_time":"2024-09-21T20:37:31.177640","status":"completed"},"tags":[]}},{"id":"c9b25c91","cell_type":"code","source":"ResNet=ResNet50(weights='imagenet',include_top=False,input_shape=(image_size[0],image_size[1],3))","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:23:59.480017Z","iopub.execute_input":"2025-04-30T15:23:59.480248Z","iopub.status.idle":"2025-04-30T15:24:07.684761Z","shell.execute_reply.started":"2025-04-30T15:23:59.480229Z","shell.execute_reply":"2025-04-30T15:24:07.683922Z"},"papermill":{"duration":3.502583,"end_time":"2024-09-21T20:37:34.874667","exception":false,"start_time":"2024-09-21T20:37:31.372084","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"9c5d8bd3","cell_type":"code","source":"ResNet.summary()","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:24:07.685868Z","iopub.execute_input":"2025-04-30T15:24:07.686140Z","iopub.status.idle":"2025-04-30T15:24:07.833509Z","shell.execute_reply.started":"2025-04-30T15:24:07.686117Z","shell.execute_reply":"2025-04-30T15:24:07.832839Z"},"papermill":{"duration":0.346809,"end_time":"2024-09-21T20:37:35.318747","exception":false,"start_time":"2024-09-21T20:37:34.971938","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"e2adc877-ba49-4443-904f-c57f578368ba","cell_type":"markdown","source":"# Overfiting issue  remove by Dropout and   L2 regularization\n","metadata":{}},{"id":"92861356","cell_type":"code","source":"# Get the output from the pre-trained ResNet model\nresnet_output = ResNet.output\n\n# Apply Global Average Pooling to reduce the dimensionality of the feature maps\ngb = GlobalAveragePooling2D()(resnet_output)\n\n# Add a Dropout layer to help prevent overfitting during training\ndrop = Dropout(0.5)(gb)\n\n# Add a fully connected Dense layer with 1024 units and ReLU activation\n# Apply L2 regularization to prevent overfitting\ndense = Dense(1024, activation='relu', kernel_regularizer=l2(5e-4))(drop)\n\n# Add another Dropout layer after the Dense layer\ndrop = Dropout(0.5)(dense)\n\n# Create the output layer with 1 unit (binary classification: dog or cat) using sigmoid activation\npredictions = Dense(1, activation='sigmoid')(drop)\n\n# Define the model with the specified inputs (ResNet input) and outputs (predictions)\nmodel = Model(inputs=ResNet.input, outputs=predictions)\n\n# Display the model summary to show the architecture\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:24:07.834205Z","iopub.execute_input":"2025-04-30T15:24:07.834411Z","iopub.status.idle":"2025-04-30T15:24:08.060082Z","shell.execute_reply.started":"2025-04-30T15:24:07.834395Z","shell.execute_reply":"2025-04-30T15:24:08.059491Z"},"papermill":{"duration":0.390256,"end_time":"2024-09-21T20:37:35.816592","exception":false,"start_time":"2024-09-21T20:37:35.426336","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"8cc142f7","cell_type":"code","source":"checkpoint = ModelCheckpoint('../working/Resnet50_best.weights.h5', monitor='val_loss', verbose=1, \n                             save_best_only=True, mode='min', save_weights_only=True)\n\nreduceLROnPlat = ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3,\n                                   verbose=1, mode='auto', epsilon=0.0001)\n\nearly = EarlyStopping(monitor=\"val_loss\", mode=\"min\", patience=5)\n\ncallbacks_list = [checkpoint, reduceLROnPlat, early]","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:24:08.060876Z","iopub.execute_input":"2025-04-30T15:24:08.061113Z","iopub.status.idle":"2025-04-30T15:24:08.066386Z","shell.execute_reply.started":"2025-04-30T15:24:08.061093Z","shell.execute_reply":"2025-04-30T15:24:08.065819Z"},"papermill":{"duration":0.116089,"end_time":"2024-09-21T20:37:36.252916","exception":false,"start_time":"2024-09-21T20:37:36.136827","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"83a0685b","cell_type":"code","source":"#the total number of images we have:\ntrain_size = len(train_generator.filenames)\n#train_steps is how many steps per epoch Keras runs the genrator. One step is batch_size*images\ntrain_steps = train_size/batch_size\n#use 2* number of images to get more augmentations in. some do, some dont. up to you\ntrain_steps = int(2*train_steps)\n\n#same for the validation set\nvalid_size = len(val_generator.filenames)\nvalid_steps = valid_size/batch_size\nvalid_steps = int(2*valid_steps) \n\n#same for the test set\ntest_size = len(test_generator.filenames)\ntest_steps = test_size/batch_size\ntest_steps = int(2*test_steps) ","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:24:08.067083Z","iopub.execute_input":"2025-04-30T15:24:08.067273Z","iopub.status.idle":"2025-04-30T15:24:08.081140Z","shell.execute_reply.started":"2025-04-30T15:24:08.067259Z","shell.execute_reply":"2025-04-30T15:24:08.080523Z"},"papermill":{"duration":0.115976,"end_time":"2024-09-21T20:37:36.472622","exception":false,"start_time":"2024-09-21T20:37:36.356646","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"dcf2cbc0","cell_type":"code","source":"# Step 1: Freeze the ResNet layers\nfor layer in ResNet.layers:\n    layer.trainable = False\n\n# Step 2: Compile the model with frozen layers\nmodel.compile(optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'])\n\n# Step 3: Train the model with frozen ResNet layers\nhistory=model.fit(\n    train_generator,\n    steps_per_epoch=train_steps,\n    epochs=epochs,\n    validation_data=val_generator,\n    validation_steps=valid_steps,\n    callbacks=callbacks_list,\n    verbose=1\n)\n","metadata":{"execution":{"iopub.status.busy":"2025-04-30T15:24:08.084786Z","iopub.execute_input":"2025-04-30T15:24:08.085162Z","iopub.status.idle":"2025-04-30T15:42:33.884783Z","shell.execute_reply.started":"2025-04-30T15:24:08.085137Z","shell.execute_reply":"2025-04-30T15:42:33.884200Z"},"papermill":{"duration":1174.17368,"end_time":"2024-09-21T20:57:10.752965","exception":false,"start_time":"2024-09-21T20:37:36.579285","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"id":"e928ce54","cell_type":"code","source":"# Step 4: Unfreeze the ResNet layers for fine-tuning\nfor layer in ResNet.layers:\n    layer.trainable = True\n\n# Step 5: Re-compile the model after unfreezing the layers (with potentially a lower learning rate)\nmodel.compile(optimizer=Adam(learning_rate=0.0001), loss='binary_crossentropy', metrics=['accuracy'])\n\n# Step 6: Train the model again with the unfrozen ResNet layers (fine-tuning)\nnew_history=model.fit(\n    train_generator,\n    steps_per_epoch=train_steps,\n    epochs=epochs,\n    validation_data=val_generator,\n    validation_steps=valid_steps,\n    callbacks=callbacks_list,\n    verbose=1\n)","metadata":{"papermill":{"duration":1275.888358,"end_time":"2024-09-21T21:18:27.003111","exception":false,"start_time":"2024-09-21T20:57:11.114753","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T15:42:33.885648Z","iopub.execute_input":"2025-04-30T15:42:33.885876Z","iopub.status.idle":"2025-04-30T16:02:23.466733Z","shell.execute_reply.started":"2025-04-30T15:42:33.885860Z","shell.execute_reply":"2025-04-30T16:02:23.465938Z"}},"outputs":[],"execution_count":null},{"id":"9f7f0ad3","cell_type":"code","source":"history.history['loss'] += new_history.history['loss']\nhistory.history['val_loss'] += new_history.history['val_loss']\nhistory.history['accuracy'] += new_history.history['accuracy']\nhistory.history['val_accuracy'] += new_history.history['val_accuracy']","metadata":{"papermill":{"duration":0.619159,"end_time":"2024-09-21T21:18:28.278974","exception":false,"start_time":"2024-09-21T21:18:27.659815","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.467847Z","iopub.execute_input":"2025-04-30T16:02:23.468170Z","iopub.status.idle":"2025-04-30T16:02:23.472475Z","shell.execute_reply.started":"2025-04-30T16:02:23.468149Z","shell.execute_reply":"2025-04-30T16:02:23.471779Z"}},"outputs":[],"execution_count":null},{"id":"fd29361e","cell_type":"code","source":"history.history.keys()","metadata":{"papermill":{"duration":0.673274,"end_time":"2024-09-21T21:18:29.565002","exception":false,"start_time":"2024-09-21T21:18:28.891728","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.473195Z","iopub.execute_input":"2025-04-30T16:02:23.473507Z","iopub.status.idle":"2025-04-30T16:02:23.489058Z","shell.execute_reply.started":"2025-04-30T16:02:23.473484Z","shell.execute_reply":"2025-04-30T16:02:23.488515Z"}},"outputs":[],"execution_count":null},{"id":"8f2bde8b","cell_type":"code","source":"loss=history.history['loss']\nval_loss=history.history['val_loss']\nacc=history.history['accuracy']\nval_acc=history.history['val_accuracy']\n\n# Find the epoch with the minimum validation loss (best performance in terms of loss)\nindex_loss = np.argmin(val_loss)\n# Find the epoch with the maximum validation accuracy (best performance in terms of accuracy)\nindex_acc = np.argmax(val_acc)\n\n# Get the lowest validation loss value at the best epoch\nval_lowest = val_loss[index_loss]\n# Get the highest validation accuracy value at the best epoch\nval_highest = val_acc[index_acc]\n\n# Create a list of epoch numbers, starting from 1, for plotting purposes\nepochs=[i+1 for i in range(len(acc))]\n\n# Create labels for plotting the best epoch in terms of loss and accuracy\nloss_label = f'Best Epoch = {str(index_loss + 1)}'\nacc_label = f'Best Epoch = {str(index_acc + 1)}'","metadata":{"papermill":{"duration":0.637268,"end_time":"2024-09-21T21:18:30.804033","exception":false,"start_time":"2024-09-21T21:18:30.166765","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.489821Z","iopub.execute_input":"2025-04-30T16:02:23.490066Z","iopub.status.idle":"2025-04-30T16:02:23.500529Z","shell.execute_reply.started":"2025-04-30T16:02:23.490042Z","shell.execute_reply":"2025-04-30T16:02:23.499936Z"}},"outputs":[],"execution_count":null},{"id":"3708fbb0","cell_type":"code","source":"# Set the style of the plot using 'fivethirtyeight' for a cleaner look\nplt.style.use('fivethirtyeight')\nplt.figure(figsize=(15,8))\n\n# Create the first subplot (1 row, 2 columns, this is the first plot)\nplt.subplot(1,2,1)\n# Plot training loss across epochs\nplt.plot(epochs, loss, 'r', label='Training Loss')\n# Plot validation loss across epochs\nplt.plot(epochs, val_loss, 'g', label='Validation Loss')\n# Highlight the point with the lowest validation loss with a blue dot\nplt.scatter((index_loss+1), val_lowest, label=loss_label, s=150, c='b')\n# Set the title, x-axis label, and y-axis label for the loss plot\nplt.title('Training vs Validation (Loss)')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\n# Show the legend to differentiate between training and validation curves\nplt.legend()\n\n# Create the second subplot (2nd plot of the 1 row, 2 column layout)\nplt.subplot(1,2,2)\n# Plot training accuracy across epochs\nplt.plot(epochs, acc, 'r', label='Training Accuracy')\n# Plot validation accuracy across epochs\nplt.plot(epochs, val_acc, 'g', label='Validation Accuracy')\n# Highlight the point with the highest validation accuracy with a blue dot\nplt.scatter((index_acc+1), val_highest, label=acc_label, s=150, c='b')\n# Set the title, x-axis label, and y-axis label for the accuracy plot\nplt.title('Training vs Validation (Accuracy)')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\n# Show the legend to differentiate between training and validation curves\nplt.legend()\n\nplt.tight_layout()\nplt.show()","metadata":{"papermill":{"duration":1.596415,"end_time":"2024-09-21T21:18:33.023551","exception":false,"start_time":"2024-09-21T21:18:31.427136","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.501291Z","iopub.execute_input":"2025-04-30T16:02:23.501496Z","iopub.status.idle":"2025-04-30T16:02:23.942164Z","shell.execute_reply.started":"2025-04-30T16:02:23.501482Z","shell.execute_reply":"2025-04-30T16:02:23.941336Z"}},"outputs":[],"execution_count":null},{"id":"396bea8a","cell_type":"code","source":"history.history","metadata":{"papermill":{"duration":0.620527,"end_time":"2024-09-21T21:18:34.270655","exception":false,"start_time":"2024-09-21T21:18:33.650128","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.943032Z","iopub.execute_input":"2025-04-30T16:02:23.943270Z","iopub.status.idle":"2025-04-30T16:02:23.948617Z","shell.execute_reply.started":"2025-04-30T16:02:23.943252Z","shell.execute_reply":"2025-04-30T16:02:23.947885Z"}},"outputs":[],"execution_count":null},{"id":"1b44bedc","cell_type":"code","source":"# Exclude learning_rate if it's of a different length\nhistory_dict = {k: v for k, v in history.history.items() if len(v) == len(history.history['accuracy'])}\n    \n# Create DataFrame\ndf_history = pd.DataFrame(history_dict)\ndf_history","metadata":{"papermill":{"duration":0.625191,"end_time":"2024-09-21T21:18:35.543983","exception":false,"start_time":"2024-09-21T21:18:34.918792","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.949413Z","iopub.execute_input":"2025-04-30T16:02:23.949690Z","iopub.status.idle":"2025-04-30T16:02:23.967488Z","shell.execute_reply.started":"2025-04-30T16:02:23.949667Z","shell.execute_reply":"2025-04-30T16:02:23.966751Z"}},"outputs":[],"execution_count":null},{"id":"66406b14","cell_type":"code","source":"val_generator.reset()\ndf_valid = pd.DataFrame()","metadata":{"papermill":{"duration":0.612903,"end_time":"2024-09-21T21:18:39.356911","exception":false,"start_time":"2024-09-21T21:18:38.744008","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.968359Z","iopub.execute_input":"2025-04-30T16:02:23.968597Z","iopub.status.idle":"2025-04-30T16:02:23.979415Z","shell.execute_reply.started":"2025-04-30T16:02:23.968580Z","shell.execute_reply":"2025-04-30T16:02:23.978801Z"}},"outputs":[],"execution_count":null},{"id":"318d1c41","cell_type":"code","source":"# Initialize lists to store differences, predictions, categories, and labels\ndiffs = []\npredictions = []\ncat_or_dog = []\nlabels = []\n\n# Iterate through each filename in the validation generator\nfor file in val_generator.filenames:\n    # Create the full image path\n    img_path = os.path.join(train_data_path, file)\n    img = Image.open(img_path)\n    # Resize the image to the specified dimensions\n    img = img.resize((image_size[0], image_size[1]))\n    # Convert the image to a NumPy array\n    img = np.array(img)\n    \n    # Determine the reference label based on the filename\n    if 'cat' == file.split('.')[0]:\n        ref = 0  \n        cat_or_dog.append('cat')   \n    else:\n        ref = 1   \n        cat_or_dog.append('dog')   \n    \n    labels.append(ref)\n    pred = model.predict(preprocess_input(img[np.newaxis]))\n    predictions.append(pred)\n    diffs.append(np.abs(pred[0][0] - ref))","metadata":{"_kg_hide-output":true,"papermill":{"duration":184.06801,"end_time":"2024-09-21T21:21:45.287685","exception":false,"start_time":"2024-09-21T21:18:41.219675","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:02:23.980102Z","iopub.execute_input":"2025-04-30T16:02:23.980354Z","iopub.status.idle":"2025-04-30T16:05:28.205387Z","shell.execute_reply.started":"2025-04-30T16:02:23.980333Z","shell.execute_reply":"2025-04-30T16:05:28.204790Z"},"collapsed":true,"jupyter":{"outputs_hidden":true}},"outputs":[],"execution_count":null},{"id":"72440bc2","cell_type":"code","source":"df_valid[\"filename\"] = val_generator.filenames\ndf_valid[\"cat_or_dog\"] = cat_or_dog\ndf_valid[\"label\"] = labels\ndf_valid[\"diff\"] = diffs\ndf_valid[\"prediction\"] = predictions","metadata":{"papermill":{"duration":1.028682,"end_time":"2024-09-21T21:21:47.413951","exception":false,"start_time":"2024-09-21T21:21:46.385269","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:05:28.206175Z","iopub.execute_input":"2025-04-30T16:05:28.206470Z","iopub.status.idle":"2025-04-30T16:05:28.216621Z","shell.execute_reply.started":"2025-04-30T16:05:28.206449Z","shell.execute_reply":"2025-04-30T16:05:28.215863Z"}},"outputs":[],"execution_count":null},{"id":"0ca741ac","cell_type":"code","source":"sorted_diffs=df_valid.sort_values(by='diff',ascending=False)","metadata":{"papermill":{"duration":1.023671,"end_time":"2024-09-21T21:21:49.482895","exception":false,"start_time":"2024-09-21T21:21:48.459224","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:05:28.217607Z","iopub.execute_input":"2025-04-30T16:05:28.217941Z","iopub.status.idle":"2025-04-30T16:05:28.229231Z","shell.execute_reply.started":"2025-04-30T16:05:28.217921Z","shell.execute_reply":"2025-04-30T16:05:28.228661Z"}},"outputs":[],"execution_count":null},{"id":"9827d48a","cell_type":"markdown","source":"# Evalute the model","metadata":{"papermill":{"duration":1.114874,"end_time":"2024-09-21T21:22:03.764830","exception":false,"start_time":"2024-09-21T21:22:02.649956","status":"completed"},"tags":[]}},{"id":"a2e15bf9-ed75-4996-b197-bfee3f72541a","cell_type":"code","source":"\n# Plot training & validation accuracy values\nplt.plot(history.history['accuracy'])\nplt.plot(history.history['val_accuracy'])\nplt.title('Model accuracy')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n\n# Plot training & validation loss values\nplt.plot(history.history['loss'])\nplt.plot(history.history['val_loss'])\nplt.title('Model loss')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend(['Train', 'Validation'], loc='upper left')\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:13:22.325608Z","iopub.execute_input":"2025-04-30T16:13:22.325867Z","iopub.status.idle":"2025-04-30T16:13:22.653034Z","shell.execute_reply.started":"2025-04-30T16:13:22.325850Z","shell.execute_reply":"2025-04-30T16:13:22.652132Z"}},"outputs":[],"execution_count":null},{"id":"ca8c7bbd-29a4-4c47-b15f-14b38eda7115","cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\n\n# Predict on the validation set\npredictions = model.predict(val_generator, verbose=1)\npredictions = (predictions > 0.5)  # Convert probabilities to binary class\n\n# Evaluate the performance with confusion matrix and classification report\nprint(\"Confusion Matrix\")\nprint(confusion_matrix(val_generator.classes, predictions))\nprint(\"Classification Report\")\nprint(classification_report(val_generator.classes, predictions))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:14:30.341750Z","iopub.execute_input":"2025-04-30T16:14:30.342015Z","iopub.status.idle":"2025-04-30T16:14:43.682252Z","shell.execute_reply.started":"2025-04-30T16:14:30.341994Z","shell.execute_reply":"2025-04-30T16:14:43.681574Z"}},"outputs":[],"execution_count":null},{"id":"054780d5-93cf-4415-9917-e8e69e1cfe18","cell_type":"code","source":"# Display the model architecture\nmodel.summary()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:16:22.649811Z","iopub.execute_input":"2025-04-30T16:16:22.650496Z","iopub.status.idle":"2025-04-30T16:16:22.664718Z","shell.execute_reply.started":"2025-04-30T16:16:22.650472Z","shell.execute_reply":"2025-04-30T16:16:22.663983Z"}},"outputs":[],"execution_count":null},{"id":"ac6240c9","cell_type":"markdown","source":"# Predictions","metadata":{"papermill":{"duration":1.145951,"end_time":"2024-09-21T21:26:31.713360","exception":false,"start_time":"2024-09-21T21:26:30.567409","status":"completed"},"tags":[]}},{"id":"3700103b-7e75-4912-88aa-6968c2e545b3","cell_type":"code","source":"def plot_top_N(N, sorted_df):\n    from math import ceil\n    # Initialize index for subplot tracking\n    i = 0\n    rows = int(ceil(N / 3))  # Calculate number of rows needed\n    height = rows * 10  # Determine plot height based on rows\n    plt.figure(figsize=[30, height])  # Set figure size (width fixed, height scales)\n\n    # Iterate over each row in the sorted DataFrame\n    for index, row in sorted_df.iterrows():\n        # Create subplot for the current image\n        plt.subplot(rows, 3, i + 1)\n        \n        # Extract data from the DataFrame row\n        file_name = row[\"filename\"]\n        category = row[\"cat_or_dog\"]  # True label as string ('cat' or 'dog')\n        true_label = row[\"label\"]  # True label as 0 or 1\n        diffs = row[\"diff\"]  # Difference between prediction and actual\n        predictions = row[\"prediction\"]  # Predicted probability\n\n        # Determine predicted label based on model prediction\n        pred_label = 1 if predictions[0][0] > 0.5 else 0  # 1 = dog, 0 = cat\n        predicted_category = 'dog' if pred_label == 1 else 'cat'  # Predicted category as string\n        \n        # Open and display image\n        img = Image.open(f\"{train_data_path}/{file_name}\")\n        plt.imshow(img)\n\n        # Set title with model prediction and difference\n        plt.title(f'It is a {category}, model predicted as {predicted_category} with {predictions[0][0]:.2f}, error {diffs:.2f}')\n\n        i += 1  \n        img.close()  # Close image to free memory\n\n        if i >= N:  # Stop when the top N images are plotted\n            break","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:31:44.561768Z","iopub.execute_input":"2025-04-30T16:31:44.562026Z","iopub.status.idle":"2025-04-30T16:31:44.568209Z","shell.execute_reply.started":"2025-04-30T16:31:44.562007Z","shell.execute_reply":"2025-04-30T16:31:44.567471Z"}},"outputs":[],"execution_count":null},{"id":"78e68054-336b-4015-9864-dec9685ed181","cell_type":"code","source":"plot_top_N(10,sorted_diffs)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-30T16:31:47.378898Z","iopub.execute_input":"2025-04-30T16:31:47.379204Z","iopub.status.idle":"2025-04-30T16:31:51.403165Z","shell.execute_reply.started":"2025-04-30T16:31:47.379180Z","shell.execute_reply":"2025-04-30T16:31:51.401956Z"}},"outputs":[],"execution_count":null}]}