{"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":"none","dataSources":[{"sourceId":3362,"databundleVersionId":31148,"sourceType":"competition"}],"dockerImageVersionId":30580,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"#Import os libs\nimport os\nimport shutil\nimport itertools\nimport pathlib\nfrom PIL import Image\n\n#Import data handling libs\nimport cv2\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nsns.set_style('whitegrid')\nfrom sklearn.metrics import confusion_matrix,\nclassification_report,ConfusionMatrixDisplay\nfrom sklearn.model_selection import train_test_split\n\n#Import deep learning tools\nimport tensorflow as tf\nfrom tensorflow import keras\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D , MaxPooling2D,\nDense , BatchNormalization , Dropout,Flatten , Activation\nfrom tensorflow.keras.optimizers import Adam , Adamax\nfrom tensorflow.keras import regularizers\n\n#Warnings\nimport warnings\nwarnings.filterwarnings('ignore')","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:41:00.796701Z","iopub.execute_input":"2024-01-20T11:41:00.797070Z","iopub.status.idle":"2024-01-20T11:41:13.006330Z","shell.execute_reply.started":"2024-01-20T11:41:00.797028Z","shell.execute_reply":"2024-01-20T11:41:13.005382Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Upload data and unzip data from kaggle\n!unzip /kaggle/input/dogs-vs-cats/train.zip","metadata":{"_kg_hide-input":false,"_kg_hide-output":true,"execution":{"iopub.status.busy":"2024-01-20T11:41:20.352192Z","iopub.execute_input":"2024-01-20T11:41:20.352833Z","iopub.status.idle":"2024-01-20T11:41:31.793324Z","shell.execute_reply.started":"2024-01-20T11:41:20.352802Z","shell.execute_reply":"2024-01-20T11:41:31.792230Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Upload data and unzip data from kaggle\n!unzip /kaggle/input/dogs-vs-cats/test1.zip","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:41:33.767911Z","iopub.execute_input":"2024-01-20T11:41:33.768861Z","iopub.status.idle":"2024-01-20T11:41:39.905935Z","shell.execute_reply.started":"2024-01-20T11:41:33.768822Z","shell.execute_reply":"2024-01-20T11:41:39.905033Z"},"collapsed":true,"jupyter":{"outputs_hidden":true},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Calculate the total images download\npath , dirs , files = next(os.walk('/kaggle/working/train'))\nfile_count = len(files)\nprint(file_count)\n\n#Create a directory to save different sets\nbase_dir = '/kaggle/working/dogs_vs_cats_small'\nos.mkdir(base_dir)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:22.712696Z","iopub.execute_input":"2024-01-20T11:42:22.713436Z","iopub.status.idle":"2024-01-20T11:42:22.748326Z","shell.execute_reply.started":"2024-01-20T11:42:22.713398Z","shell.execute_reply":"2024-01-20T11:42:22.747461Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Create Directories for Train , Test and Validation data\ntrain_dir = os.path.join(base_dir , 'train')\nos.mkdir(train_dir) #make a new train directory inside my base directory\n\nvalid_dir= os.path.join(base_dir , 'validation')\nos.mkdir(valid_dir) #make a new validation directory inside my base directory\n\ntest_dir = os.path.join(base_dir , 'test')\nos.mkdir(test_dir) #make a new test directory inside my base directory\n\ntrain_cats_dir = os.path.join(train_dir , 'cats')\nos.mkdir(train_cats_dir) #make a new cats directory inside my train directory\n\ntrain_dogs_dir = os.path.join(train_dir , 'dogs')\nos.mkdir(train_dogs_dir) #make a new dogs directory inside my train directory\n\nvalid_cats_dir = os.path.join(valid_dir, 'cats')\nos.mkdir(valid_cats_dir) #make a new cats directory inside my validation directory\n\nvalid_dogs_dir = os.path.join(valid_dir , 'dogs')\nos.mkdir(valid_dogs_dir) #make a new dogs directory inside my validation directory\n\ntest_cats_dir = os.path.join(test_dir , 'cats')\nos.mkdir(test_cats_dir) #make a new cats directory inside my test directory\n\ntest_dogs_dir = os.path.join(test_dir , 'dogs')\nos.mkdir(test_dogs_dir) #make a new dogs directory inside my test directory","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:29.261196Z","iopub.execute_input":"2024-01-20T11:42:29.262092Z","iopub.status.idle":"2024-01-20T11:42:30.003904Z","shell.execute_reply.started":"2024-01-20T11:42:29.262058Z","shell.execute_reply":"2024-01-20T11:42:30.002634Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Count total cat and dog images\ndir_path = '/kaggle/working/train'\n\ncat_count = 0\ndog_count= 0\nfor i in os.listdir(dir_path):\n    if i.startswith('cat.'):\n        cat_count += 1\n    elif i.startswith('dog.'):\n        dog_count += 1\n        \nprint(f\"Number of cat images: {cat_count}\")\nprint(f\"Number of dog images: {dog_count}\")","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:32.129117Z","iopub.execute_input":"2024-01-20T11:42:32.130095Z","iopub.status.idle":"2024-01-20T11:42:32.160033Z","shell.execute_reply.started":"2024-01-20T11:42:32.130036Z","shell.execute_reply":"2024-01-20T11:42:32.159143Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Splitting data into training, validation and test sets\noriginal_dataset_dir = '/kaggle/working/train'\n\nfnames = ['cat.{}.jpg'.format(i) for i in range(5000)] #5000 cat images for training set\nfor fname in fnames:\n  src = os.path.join(original_dataset_dir , fname)\n  dst = os.path.join(train_cats_dir , fname)\n  shutil.copyfile(src , dst)\n\nfnames = ['cat.{}.jpg'.format(i) for i in range(5001,5501)] #500 cat images validation set\nfor fname in fnames:\n  src = os.path.join(original_dataset_dir , fname)\n  dst = os.path.join(valid_cats_dir , fname)\n  shutil.copyfile(src,dst)\n\nfnames = ['cat.{}.jpg'.format(i) for i in range(5502,6002)] #500 cat images test set\nfor fname in fnames:\n  src= os.path.join(original_dataset_dir , fname)\n  dst= os.path.join(test_cats_dir, fname)\n  shutil.copyfile(src,dst)\n\nfnames = ['dog.{}.jpg'.format(i) for i in range(5000)] #5000 dog images for training set\nfor fname in fnames:\n  src = os.path.join(original_dataset_dir , fname)\n  dst = os.path.join(train_dogs_dir ,fname)\n  shutil.copyfile(src,dst)\n\nfnames = ['dog.{}.jpg'.format(i) for i in range(5001,5501)] #500 dog images validation set\nfor fname in fnames:\n  src = os.path.join(original_dataset_dir,fname)\n  dst = os.path.join(valid_dogs_dir , fname)\n  shutil.copyfile(src,dst)\n\nfnames = ['dog.{}.jpg'.format(i) for i in range(5502,6002)] #500 dog images test set\nfor fname in fnames:\n  src= os.path.join(original_dataset_dir, fname)\n  dst = os.path.join(test_dogs_dir , fname)\n  shutil.copyfile(src, dst)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:34.603165Z","iopub.execute_input":"2024-01-20T11:42:34.603836Z","iopub.status.idle":"2024-01-20T11:42:35.838298Z","shell.execute_reply.started":"2024-01-20T11:42:34.603799Z","shell.execute_reply":"2024-01-20T11:42:35.837320Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Print total images count of each training, validation and test sets\nprint(f'Total training cat images {len(os.listdir(train_cats_dir))}')\nprint(f'Total validation cat images {len(os.listdir(valid_cats_dir))}')\nprint(f'Total test cat images {len(os.listdir(test_cats_dir))}')\nprint('\\n')\nprint(f'Total training dog images {len(os.listdir(train_dogs_dir))}')\nprint(f'Total validation cat images {len(os.listdir(valid_dogs_dir))}')\nprint(f'Total test cat images {len(os.listdir(test_dogs_dir))}')","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:39.000890Z","iopub.execute_input":"2024-01-20T11:42:39.001591Z","iopub.status.idle":"2024-01-20T11:42:39.014600Z","shell.execute_reply.started":"2024-01-20T11:42:39.001555Z","shell.execute_reply":"2024-01-20T11:42:39.013658Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Data augmentation\nimg_size = (224 , 224) # Define image size, batch size, and image shape\nbatch_size = 32\nimg_shape = (img_size[0] , img_size[1] , 3)\n\ntr_gen = ImageDataGenerator()\nts_gen = ImageDataGenerator()\n\n#Generate batches of augmented data for training, validation, and testing sets\ntrain_gen = tr_gen.flow_from_directory(train_dir , target_size = img_size, \n                                       class_mode = 'binary' ,color_mode = 'rgb', \n                                       shuffle = True , batch_size = batch_size)\nvalid_gen = ts_gen.flow_from_directory(valid_dir , target_size = img_size,\n                                       class_mode = 'binary' ,color_mode = 'rgb',\n                                       shuffle = True , batch_size = batch_size)\ntest_gen = ts_gen.flow_from_directory(test_dir , target_size = img_size,\n                                      class_mode = 'binary',color_mode = 'rgb',\n                                      shuffle = False , batch_size = batch_size)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:40.823588Z","iopub.execute_input":"2024-01-20T11:42:40.824438Z","iopub.status.idle":"2024-01-20T11:42:41.156729Z","shell.execute_reply.started":"2024-01-20T11:42:40.824401Z","shell.execute_reply":"2024-01-20T11:42:41.155988Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Print sample images from training set\ng_dict = train_gen.class_indices\nclasses = list(g_dict.keys())\n\n#Generate a batch of images and labels from the training set\nimages, labels = next(train_gen)\nnum_samples = len(images)\n\n#Plot a 4x4 grid of sample images\nplt.figure(figsize=(20, 20))\nfor i in range(min(16, num_samples)):\n    plt.subplot(4, 4, i + 1)\n    image = images[i] / 255\n    plt.imshow(image)\n    class_index = int(labels[i])\n    class_name = classes[class_index]\n    plt.title(class_name, color='blue', fontsize=12)\n    plt.axis('off')\nplt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:43.617977Z","iopub.execute_input":"2024-01-20T11:42:43.618362Z","iopub.status.idle":"2024-01-20T11:42:47.695279Z","shell.execute_reply.started":"2024-01-20T11:42:43.618331Z","shell.execute_reply":"2024-01-20T11:42:47.694299Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Define the input shape\nimg_shape = (img_size[0] , img_size[1] , 3)\n\n# Create a base model using EfficientNetB5\nbase_model = tf.keras.applications.efficientnet.EfficientNetB5(include_top= False, weights='imagenet', input_shape=img_shape,pooling='max')\n\n# Freeze the weights of the pre-trained layers\nbase_model.trainable= False\n\n#Construct the model architecture by adding additional layers\nnum_classes = len(classes)\nmodel = Sequential([\n    base_model,\n    BatchNormalization(axis = -1 , momentum = 0.99 , epsilon = 0.001),\n    Dense(256, kernel_regularizer = regularizers.l2(l= 0.016) , \n         activity_regularizer = regularizers.l1(0.006),\n         bias_regularizer= regularizers.l1(0.006) , activation = 'relu'),\n    Dropout(rate = 0.4 , seed = 40),\n    Dense(1 , activation= 'sigmoid' )\n])\n\n#Compile the model and display a summary of the model architecture\nmodel.compile(Adamax(learning_rate = 0.001) ,loss='binary_crossentropy' ,metrics=['accuracy'])\nmodel.summary()","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:42:54.230629Z","iopub.execute_input":"2024-01-20T11:42:54.231350Z","iopub.status.idle":"2024-01-20T11:43:03.392355Z","shell.execute_reply.started":"2024-01-20T11:42:54.231316Z","shell.execute_reply":"2024-01-20T11:43:03.391454Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Train the model and display the training history\nhistory = model.fit(x= train_gen ,validation_data= valid_gen ,epochs= 10,\n                    verbose = 1,validation_steps = None ,shuffle = False)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:43:06.026958Z","iopub.execute_input":"2024-01-20T11:43:06.027341Z","iopub.status.idle":"2024-01-20T11:51:19.813931Z","shell.execute_reply.started":"2024-01-20T11:43:06.027309Z","shell.execute_reply":"2024-01-20T11:51:19.813080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Check the model performance \n\n#Extract training and validation metrics from the training history\ntrain_acc = history.history['accuracy']\ntrain_loss = history.history['loss']\nval_acc = history.history['val_accuracy']\nval_loss = history.history['val_loss']\n\n#Find the index of the epoch with the lowest validation loss and highest validation accuracy\nindex_loss = np.argmin(val_loss)\nindex_acc = np.argmax(val_acc)\n\n#Extract the corresponding validation loss and accuracy values\nval_lowest = val_loss[index_loss]\nval_highest = val_acc[index_acc]\n\nEpochs = [i+1 for i in range(len(train_acc))]\n\n#Labels for displaying the best epoch on the plots\nloss_label = f'Best Epoch = {str(index_loss + 1)}'\nacc_label = f'Best Epoch = {str(index_acc + 1)}'\n\n#Plot the training and validation loss graph\nplt.figure(figsize= (20,8))\nplt.style.use('fivethirtyeight')\nplt.subplot(1,2,1)\nplt.plot(Epochs , train_loss , 'r', label = 'Training Loss')\nplt.plot(Epochs , val_loss , 'g' , label = 'Validation Loss')\nplt.scatter(index_loss +1, val_lowest, s=150, c='blue', label=loss_label)\nplt.title('Training vs Validation (loss)')\nplt.xlabel('Epochs')\nplt.ylabel('Loss')\nplt.legend()\n\n#Plot the training and validation accuracy graph\nplt.subplot(1,2,2)\nplt.plot(Epochs , train_acc , 'r', label= 'Training Accuracy')\nplt.plot(Epochs , val_acc , 'g' , label = 'Validation Accuracy')\nplt.scatter(index_acc +1, val_highest, s=150, c='blue', label=acc_label)\nplt.title('Training vs Validation (Accuracy)')\nplt.xlabel('Epochs')\nplt.ylabel('Accuracy')\nplt.legend()\nplt.tight_layout\nplt.show();","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:51:29.243970Z","iopub.execute_input":"2024-01-20T11:51:29.244913Z","iopub.status.idle":"2024-01-20T11:51:30.028527Z","shell.execute_reply.started":"2024-01-20T11:51:29.244876Z","shell.execute_reply":"2024-01-20T11:51:30.027572Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Model evaluation\ntrain_score = model.evaluate(train_gen , steps= 32 , verbose = 1)\nval_score = model.evaluate(valid_gen , steps = 32 , verbose = 1)\ntest_score = model.evaluate(test_gen , steps = 32 , verbose = 1)\n\n#Print the loss and accuracy value for all sets\nprint(f'Train loss = {train_score[0] }')\nprint(f'Train Accuracy = {train_score[1]}')\nprint(f'Validation loss = {val_score[0]}')\nprint(f'Validation Accuracy = {val_score[1]}')\nprint(f'Test loss = {test_score[0]}')\nprint(f'Test Accuracy = {test_score[1]}')","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:51:55.785286Z","iopub.execute_input":"2024-01-20T11:51:55.786241Z","iopub.status.idle":"2024-01-20T11:52:08.510474Z","shell.execute_reply.started":"2024-01-20T11:51:55.786202Z","shell.execute_reply":"2024-01-20T11:52:08.509617Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Make predictions on the test set\npreds = model.predict(test_gen)\n\n# Convert the predictions to binary classes (0 or 1)\npredicted_classes = (preds > 0.5).astype(int)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:52:19.331392Z","iopub.execute_input":"2024-01-20T11:52:19.332102Z","iopub.status.idle":"2024-01-20T11:52:26.969813Z","shell.execute_reply.started":"2024-01-20T11:52:19.332062Z","shell.execute_reply":"2024-01-20T11:52:26.968959Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Get the true labels from the generator\ntrue_classes = test_gen.classes\n\n#Calculate the confusion matrix\nconfusion = confusion_matrix(true_classes, predicted_classes)\n\n#Display the confusion matrix as a heatmap\ndisp = ConfusionMatrixDisplay(confusion_matrix=confusion, display_labels=test_gen.class_indices)\ndisp.plot(cmap='viridis', values_format='d')","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:52:38.194221Z","iopub.execute_input":"2024-01-20T11:52:38.194980Z","iopub.status.idle":"2024-01-20T11:52:38.519254Z","shell.execute_reply.started":"2024-01-20T11:52:38.194947Z","shell.execute_reply":"2024-01-20T11:52:38.518312Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Generate and print the classification report\nclassification_rep = classification_report(true_classes,predicted_classes, target_names=test_gen.class_indices)\nprint(\"\\nClassification Report:\")\nprint(classification_rep)","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:52:46.356096Z","iopub.execute_input":"2024-01-20T11:52:46.356614Z","iopub.status.idle":"2024-01-20T11:52:46.381568Z","shell.execute_reply.started":"2024-01-20T11:52:46.356573Z","shell.execute_reply":"2024-01-20T11:52:46.380492Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"#Make predictions on the test set\npreds = model.predict(test_gen)\n\n#Get a random sample of 5 indices from the test set\nrandom_indices = np.random.choice(len(test_gen.filenames), size=5, replace=False)\n\n#Display results for the 10 random images\nfor idx in random_indices:\n    #Get the filename and true class\n    filename = test_gen.filenames[idx]\n    true_class = filename.split('/')[0]  \n    \n    #Get the predicted class and confidence\n    pred = preds[idx]\n    predicted_class = 'dog' if pred > 0.5 else 'cat'\n    confidence = pred[0] if predicted_class == 'dog' else 1 - pred[0]  \n    # Confidence for the predicted class\n    \n    #Load and display the image\n    img_path = os.path.join(test_dir, filename)\n    img = Image.open(img_path)\n    plt.imshow(img)\n    plt.title(f'True Class: {true_class}\\nPredicted Class: {predicted_class}\\nConfidence: {confidence:.2%}')\n    plt.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2024-01-20T11:54:44.483262Z","iopub.execute_input":"2024-01-20T11:54:44.484139Z","iopub.status.idle":"2024-01-20T11:54:49.917711Z","shell.execute_reply.started":"2024-01-20T11:54:44.484091Z","shell.execute_reply":"2024-01-20T11:54:49.916779Z"},"trusted":true},"execution_count":null,"outputs":[]}]}