{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"sourceType":"competition"}],"dockerImageVersionId":31089,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"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","trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:13:06.983918Z","iopub.execute_input":"2025-09-24T15:13:06.984208Z","iopub.status.idle":"2025-09-24T15:13:09.866563Z","shell.execute_reply.started":"2025-09-24T15:13:06.984177Z","shell.execute_reply":"2025-09-24T15:13:09.865587Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# import \"os\" module \nimport os\n\n# setting the path to the unzipped training address\nimage_dir = '/kaggle/working/train'\n\n# extracting the names from filename and saving it in new col named label \nfilenames = os.listdir(image_dir)\nlabels = [x.split('.')[0] for x in filenames]\ndata = pd.DataFrame({'filename': filenames, 'label': labels})\n\n# display data\ndata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:14:00.802121Z","iopub.execute_input":"2025-09-24T15:14:00.802473Z","iopub.status.idle":"2025-09-24T15:14:00.870973Z","shell.execute_reply.started":"2025-09-24T15:14:00.802440Z","shell.execute_reply":"2025-09-24T15:14:00.870030Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as imread\n\n# displaying the sample image from dogs train dataset of images\nplt.figure(figsize = (20, 20))\nfor i in range(10):\n    plt.subplot(1, 10, i + 1)\n    filename = 'train/dog.' + str(i) + '.jpg'\n    image = plt.imread(filename)\n    plt.imshow(image)\n    plt.title('dog')\n    plt.axis('off')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:14:19.654489Z","iopub.execute_input":"2025-09-24T15:14:19.654803Z","iopub.status.idle":"2025-09-24T15:14:20.940230Z","shell.execute_reply.started":"2025-09-24T15:14:19.654777Z","shell.execute_reply":"2025-09-24T15:14:20.939097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# displaying the sample image from cats train dataset of images\nplt.figure(figsize = (20, 20))\nfor i in range(10):\n    plt.subplot(1, 10, i + 1)\n    filename = 'train/cat.' + str(i) + '.jpg'\n    image = plt.imread(filename)\n    plt.imshow(image)\n    plt.title('cat')\n    plt.axis('off')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:14:45.176867Z","iopub.execute_input":"2025-09-24T15:14:45.177210Z","iopub.status.idle":"2025-09-24T15:14:46.098958Z","shell.execute_reply.started":"2025-09-24T15:14:45.177185Z","shell.execute_reply":"2025-09-24T15:14:46.097984Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# creating Train Test split\nfrom sklearn.model_selection import train_test_split\nX_train, X_val = train_test_split(data, stratify = data.label, random_state = 42)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:15:05.007145Z","iopub.execute_input":"2025-09-24T15:15:05.007663Z","iopub.status.idle":"2025-09-24T15:15:05.960667Z","shell.execute_reply.started":"2025-09-24T15:15:05.007632Z","shell.execute_reply":"2025-09-24T15:15:05.959211Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_size = 128  # sets height & width of the image\nbat_size = 32     # batch size that will be trained or fed into the iterator at a time \nchannel = 3       # Sets the number of color channels to 3 (for RGB images).","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:15:30.623774Z","iopub.execute_input":"2025-09-24T15:15:30.624254Z","iopub.status.idle":"2025-09-24T15:15:30.628761Z","shell.execute_reply.started":"2025-09-24T15:15:30.624220Z","shell.execute_reply":"2025-09-24T15:15:30.627841Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Imports the utility for data augmentation and efficient loading of images\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator \n\n# ImageDataGenerator ==> Initializes the generator for training data with augmentation.\n# Passing parameters for Iterator i.e. (ImageDataGenerator)\ntrain_datagen = ImageDataGenerator(\n            rotation_range=15,        # Randomly rotates images by up to 15 degrees.\n            width_shift_range=0.2,    # Randomly shifts images up to 20%\n            height_shift_range=0.2,   # Randomly shifts images up to 20%\n            zoom_range=0.2,           # Randomly zooms images by up to 20%.\n            channel_shift_range=0.2,  # Randomly shifts pixel intensity value in each channel up to 20%\n            fill_mode='nearest', \n            horizontal_flip=True,     # Randomly flips images horizontally.\n            rescale=1/255) \ntest_datagen = ImageDataGenerator(rescale=1./255) # Normalization: Scales pixel values from [0, 255] to [0, 1].\n\n\"\"\" When you apply geometric transformations to an image—such as rotation, \nshifting, or zooming—some pixels in the resulting transformed image will fall outside the boundaries of the original image, \nor their source location will be a fractional coordinate, leading to \"holes\" or undefined areas.\"\"\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:15:44.864102Z","iopub.execute_input":"2025-09-24T15:15:44.865209Z","iopub.status.idle":"2025-09-24T15:16:04.059888Z","shell.execute_reply.started":"2025-09-24T15:15:44.865163Z","shell.execute_reply":"2025-09-24T15:16:04.058362Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator = train_datagen.flow_from_dataframe(X_train,\n                                                    directory = 'train/',\n                                                    x_col= 'filename',\n                                                    y_col= 'label',\n                                                    batch_size = bat_size,\n                                                    target_size = (image_size,image_size)\n                                                   )\nval_generator = test_datagen.flow_from_dataframe(X_val, \n                                                 directory = 'train/',\n                                                 x_col= 'filename',\n                                                 y_col= 'label',\n                                                 batch_size = bat_size,\n                                                 target_size = (image_size,image_size),\n                                                 shuffle=False\n                                                )","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:16:23.841131Z","iopub.execute_input":"2025-09-24T15:16:23.842093Z","iopub.status.idle":"2025-09-24T15:16:24.070142Z","shell.execute_reply.started":"2025-09-24T15:16:23.842059Z","shell.execute_reply":"2025-09-24T15:16:24.069006Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dropout, BatchNormalization, Dense\nmodel = Sequential()\n\n# Input Layer\nmodel.add(Conv2D(32,(3,3),activation='relu',input_shape = (image_size,image_size,channel))) \nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.2))\n\n# Bloack 1 \nmodel.add(Conv2D(64,(3,3),activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.2))\n# Block 2\nmodel.add(Conv2D(128,(3,3),activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.2))\n# Block 3\nmodel.add(Conv2D(256,(3,3),activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2,2)))\nmodel.add(Dropout(0.2))\n\n# Fully Connected layers \nmodel.add(Flatten())\nmodel.add(Dense(512,activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.2))\n\n# Output layer\nmodel.add(Dense(2,activation='softmax'))\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:16:46.472336Z","iopub.execute_input":"2025-09-24T15:16:46.472674Z","iopub.status.idle":"2025-09-24T15:16:47.175814Z","shell.execute_reply.started":"2025-09-24T15:16:46.472647Z","shell.execute_reply":"2025-09-24T15:16:47.175001Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ReduceLROnPlateau, EarlyStopping\nlearning_rate_reduction = ReduceLROnPlateau(\n    monitor = 'val_accuracy',\n    patience = 2,\n    factor = 0.5,\n    min_lr = 0.0001,\n    verbose = 1\n)\nearly_stopping = EarlyStopping(monitor = 'val_loss', patience = 3, restore_best_weights = 'True', verbose = 0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:17:12.478992Z","iopub.execute_input":"2025-09-24T15:17:12.479333Z","iopub.status.idle":"2025-09-24T15:17:12.486933Z","shell.execute_reply.started":"2025-09-24T15:17:12.479310Z","shell.execute_reply":"2025-09-24T15:17:12.485860Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:17:26.990807Z","iopub.execute_input":"2025-09-24T15:17:26.991105Z","iopub.status.idle":"2025-09-24T15:17:27.007278Z","shell.execute_reply.started":"2025-09-24T15:17:26.991085Z","shell.execute_reply":"2025-09-24T15:17:27.006297Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cat_dog = model.fit(train_generator, validation_data = val_generator, \n                    callbacks = [early_stopping, learning_rate_reduction],\n                    epochs = 5)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T15:17:42.840070Z","iopub.execute_input":"2025-09-24T15:17:42.840419Z","iopub.status.idle":"2025-09-24T16:11:48.262926Z","shell.execute_reply.started":"2025-09-24T15:17:42.840393Z","shell.execute_reply":"2025-09-24T16:11:48.261448Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cat_dog.history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:17:02.206296Z","iopub.execute_input":"2025-09-24T16:17:02.206898Z","iopub.status.idle":"2025-09-24T16:17:02.217983Z","shell.execute_reply.started":"2025-09-24T16:17:02.206792Z","shell.execute_reply":"2025-09-24T16:17:02.216600Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import seaborn as sns\nerror = pd.DataFrame(cat_dog.history)\n\nplt.figure(figsize=(18,5),dpi=200)\nsns.set_style('darkgrid')\n\nplt.subplot(121)\nplt.title('Cross Entropy Loss',fontsize=15)\nplt.xlabel('Epochs',fontsize=12)\nplt.ylabel('Loss',fontsize=12)\nplt.plot(error['loss'])\nplt.plot(error['val_loss'])\n\nplt.subplot(122)\nplt.title('Classification Accuracy',fontsize=15)\nplt.xlabel('Epochs',fontsize=12)\nplt.ylabel('Accuracy',fontsize=12)\nplt.plot(error['accuracy'])\nplt.plot(error['val_accuracy'])\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:17:24.917111Z","iopub.execute_input":"2025-09-24T16:17:24.917458Z","iopub.status.idle":"2025-09-24T16:17:26.331211Z","shell.execute_reply.started":"2025-09-24T16:17:24.917432Z","shell.execute_reply":"2025-09-24T16:17:26.330091Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Image generator (only rescaling, no augmentation for test)\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntest_dir = \"/kaggle/working/test\"\nfilenames = os.listdir(test_dir)\n\n# Flow from directory (no labels since it's test data)\ntest_data = pd.DataFrame({\"filename\":filenames})\ntest_data['label'] = 'unknown'\n\ntest_generator = test_datagen.flow_from_dataframe(\n    test_data,\n    directory = \"test/\",         # parent dir\n    x_col = \"filename\",\n    y_col = \"label\",       # only the test folder\n    target_size=(image_size, image_size),      # use same size as training\n    batch_size=bat_size,\n    class_mode=None,             # no labels\n    shuffle=False                # IMPORTANT to keep order\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:17:31.724676Z","iopub.execute_input":"2025-09-24T16:17:31.725340Z","iopub.status.idle":"2025-09-24T16:17:31.840046Z","shell.execute_reply.started":"2025-09-24T16:17:31.725305Z","shell.execute_reply":"2025-09-24T16:17:31.839041Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_predict = model.predict(test_generator,verbose = 0)\ntest_predict_argmax = np.argmax(test_predict, axis=1)\ny_test_pred = test_predict_argmax\n\ntest_data['label'] = y_test_pred\n\n# mapping\nlabel_mapping = {0: 'cat', 1: 'dog'}\ntest_data['label'] = test_data['label'].map(label_mapping)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:17:35.238346Z","iopub.execute_input":"2025-09-24T16:17:35.238664Z","iopub.status.idle":"2025-09-24T16:18:54.535578Z","shell.execute_reply.started":"2025-09-24T16:17:35.238643Z","shell.execute_reply":"2025-09-24T16:18:54.534651Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:26:35.162522Z","iopub.execute_input":"2025-09-24T16:26:35.162882Z","iopub.status.idle":"2025-09-24T16:26:35.176600Z","shell.execute_reply.started":"2025-09-24T16:26:35.162858Z","shell.execute_reply":"2025-09-24T16:26:35.175372Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# csv file output for submission\n\n\nop = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv',index_col='id')\n\nop['label'] = y_test_pred\n\nop.to_csv('submission.csv',index=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-24T16:26:40.654830Z","iopub.execute_input":"2025-09-24T16:26:40.655131Z","iopub.status.idle":"2025-09-24T16:26:40.701120Z","shell.execute_reply.started":"2025-09-24T16:26:40.655108Z","shell.execute_reply":"2025-09-24T16:26:40.699912Z"}},"outputs":[],"execution_count":null}]}