{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","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":"nvidiaTeslaT4","dataSources":[{"sourceId":5441,"databundleVersionId":38425,"isSourceIdPinned":false,"sourceType":"competition"}],"dockerImageVersionId":31012,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd \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-14T12:17:15.535118Z","iopub.execute_input":"2025-09-14T12:17:15.535367Z","iopub.status.idle":"2025-09-14T12:17:15.794326Z","shell.execute_reply.started":"2025-09-14T12:17:15.535347Z","shell.execute_reply":"2025-09-14T12:17:15.793634Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile\ntrain_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/train.zip'\ntest_path = '/kaggle/input/dogs-vs-cats-redux-kernels-edition/test.zip'\nfile_path = '/kaggle/working/'\n\nwith zipfile.ZipFile(train_path, 'r') as zipp:\n    zipp.extractall(file_path)\n\n\nwith zipfile.ZipFile(test_path, 'r') as zipp:\n    zipp.extractall(file_path)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T12:17:15.795597Z","iopub.execute_input":"2025-09-14T12:17:15.795883Z","iopub.status.idle":"2025-09-14T12:17:29.732921Z","shell.execute_reply.started":"2025-09-14T12:17:15.795867Z","shell.execute_reply":"2025-09-14T12:17:29.732146Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimage_dir = '/kaggle/working/train'\nfilenames = os.listdir(image_dir)\nlabels = [x.split('.')[0] for x in filenames]\ndata = pd.DataFrame({'filename': filenames, 'label': labels})\n\ndata.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T12:17:29.733707Z","iopub.execute_input":"2025-09-14T12:17:29.733897Z","iopub.status.idle":"2025-09-14T12:17:29.775986Z","shell.execute_reply.started":"2025-09-14T12:17:29.733875Z","shell.execute_reply":"2025-09-14T12:17:29.775387Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport matplotlib.image as imread\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-14T12:17:29.777426Z","iopub.execute_input":"2025-09-14T12:17:29.777695Z","iopub.status.idle":"2025-09-14T12:17:30.697796Z","shell.execute_reply.started":"2025-09-14T12:17:29.777678Z","shell.execute_reply":"2025-09-14T12:17:30.697010Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.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-14T12:17:30.698574Z","iopub.execute_input":"2025-09-14T12:17:30.698798Z","iopub.status.idle":"2025-09-14T12:17:31.505633Z","shell.execute_reply.started":"2025-09-14T12:17:30.698781Z","shell.execute_reply":"2025-09-14T12:17:31.504942Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Split data into training data and validation data, use validation data to evaluate the model performance and optimize accordingly","metadata":{}},{"cell_type":"code","source":"from 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-14T12:17:31.506439Z","iopub.execute_input":"2025-09-14T12:17:31.506706Z","iopub.status.idle":"2025-09-14T12:17:32.139615Z","shell.execute_reply.started":"2025-09-14T12:17:31.506685Z","shell.execute_reply":"2025-09-14T12:17:32.138978Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"In the next step, generate new images from training data set, which allow the model to be trained with diverse set of data.","metadata":{}},{"cell_type":"code","source":"image_size = 128 #define size of new images\nbat_size = 32\nchannel = 3","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T12:17:32.140357Z","iopub.execute_input":"2025-09-14T12:17:32.140794Z","iopub.status.idle":"2025-09-14T12:17:32.144435Z","shell.execute_reply.started":"2025-09-14T12:17:32.140768Z","shell.execute_reply":"2025-09-14T12:17:32.143887Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator #Procedure to form new image based on training set\ntrain_datagen = ImageDataGenerator(\n            rotation_range=15,\n            width_shift_range=0.2,\n            height_shift_range=0.2,\n            zoom_range=0.2,\n            channel_shift_range=0.2,\n            fill_mode='nearest',\n            horizontal_flip=True,\n            rescale=1/255)\ntest_datagen = ImageDataGenerator(rescale=1./255)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T12:17:32.145129Z","iopub.execute_input":"2025-09-14T12:17:32.145369Z","iopub.status.idle":"2025-09-14T12:17:46.184425Z","shell.execute_reply.started":"2025-09-14T12:17:32.145342Z","shell.execute_reply":"2025-09-14T12:17:46.183681Z"}},"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-14T12:17:46.185429Z","iopub.execute_input":"2025-09-14T12:17:46.185914Z","iopub.status.idle":"2025-09-14T12:17:46.369093Z","shell.execute_reply.started":"2025-09-14T12:17:46.185886Z","shell.execute_reply":"2025-09-14T12:17:46.368524Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"\nNow, create a model to be trained","metadata":{}},{"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-14T12:17:46.371087Z","iopub.execute_input":"2025-09-14T12:17:46.371337Z","iopub.status.idle":"2025-09-14T12:17:49.389567Z","shell.execute_reply.started":"2025-09-14T12:17:46.371322Z","shell.execute_reply":"2025-09-14T12:17:49.388977Z"}},"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-14T12:17:49.390212Z","iopub.execute_input":"2025-09-14T12:17:49.390468Z","iopub.status.idle":"2025-09-14T12:17:49.401239Z","shell.execute_reply.started":"2025-09-14T12:17:49.390451Z","shell.execute_reply":"2025-09-14T12:17:49.400641Z"}},"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-14T12:17:49.401999Z","iopub.execute_input":"2025-09-14T12:17:49.402231Z","iopub.status.idle":"2025-09-14T12:17:49.561763Z","shell.execute_reply.started":"2025-09-14T12:17:49.402204Z","shell.execute_reply":"2025-09-14T12:17:49.561224Z"}},"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-14T12:17:49.562404Z","iopub.execute_input":"2025-09-14T12:17:49.562646Z","iopub.status.idle":"2025-09-14T12:26:05.256924Z","shell.execute_reply.started":"2025-09-14T12:17:49.562625Z","shell.execute_reply":"2025-09-14T12:26:05.256336Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"cat_dog.history","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T12:26:05.257725Z","iopub.execute_input":"2025-09-14T12:26:05.257978Z","iopub.status.idle":"2025-09-14T12:26:05.262805Z","shell.execute_reply.started":"2025-09-14T12:26:05.257963Z","shell.execute_reply":"2025-09-14T12:26:05.262237Z"}},"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-14T12:26:05.263466Z","iopub.execute_input":"2025-09-14T12:26:05.263709Z","iopub.status.idle":"2025-09-14T12:26:06.171876Z","shell.execute_reply.started":"2025-09-14T12:26:05.263690Z","shell.execute_reply":"2025-09-14T12:26:06.171073Z"}},"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)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T13:15:43.680399Z","iopub.execute_input":"2025-09-14T13:15:43.680715Z","iopub.status.idle":"2025-09-14T13:15:43.778185Z","shell.execute_reply.started":"2025-09-14T13:15:43.680695Z","shell.execute_reply":"2025-09-14T13:15:43.777657Z"}},"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)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T13:17:37.064813Z","iopub.execute_input":"2025-09-14T13:17:37.065467Z","iopub.status.idle":"2025-09-14T13:17:51.777678Z","shell.execute_reply.started":"2025-09-14T13:17:37.065447Z","shell.execute_reply":"2025-09-14T13:17:51.777126Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_data.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T13:18:04.872315Z","iopub.execute_input":"2025-09-14T13:18:04.872597Z","iopub.status.idle":"2025-09-14T13:18:04.879768Z","shell.execute_reply.started":"2025-09-14T13:18:04.872577Z","shell.execute_reply":"2025-09-14T13:18:04.879167Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# csv file output for submission\n\n\nsub = pd.read_csv('/kaggle/input/dogs-vs-cats-redux-kernels-edition/sample_submission.csv',index_col='id')\n\nsub['label'] = y_test_pred\n\nsub.to_csv('submission.csv',index=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-09-14T13:25:22.154920Z","iopub.execute_input":"2025-09-14T13:25:22.155432Z","iopub.status.idle":"2025-09-14T13:25:22.172214Z","shell.execute_reply.started":"2025-09-14T13:25:22.155411Z","shell.execute_reply":"2025-09-14T13:25:22.171522Z"}},"outputs":[],"execution_count":null}]}