{"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":3362,"databundleVersionId":31148,"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-08-19T16:27:59.031447Z","iopub.execute_input":"2025-08-19T16:27:59.031783Z","iopub.status.idle":"2025-08-19T16:27:59.040009Z","shell.execute_reply.started":"2025-08-19T16:27:59.031758Z","shell.execute_reply":"2025-08-19T16:27:59.039097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd \nfrom keras.preprocessing.image import load_img\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom keras.utils import to_categorical\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport random\nimport os\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:27:59.041421Z","iopub.execute_input":"2025-08-19T16:27:59.041775Z","iopub.status.idle":"2025-08-19T16:27:59.059102Z","shell.execute_reply.started":"2025-08-19T16:27:59.041748Z","shell.execute_reply":"2025-08-19T16:27:59.057874Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(np.__version__)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:27:59.060044Z","iopub.execute_input":"2025-08-19T16:27:59.06033Z","iopub.status.idle":"2025-08-19T16:27:59.078378Z","shell.execute_reply.started":"2025-08-19T16:27:59.060306Z","shell.execute_reply":"2025-08-19T16:27:59.077463Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Defining some constants\nFAST_RUN = False\nIMAGE_WIDTH = 128 #pxl\nIMAGE_HEIGHT = 128\nIMAGE_SIZE = (IMAGE_WIDTH, IMAGE_HEIGHT) #Many image-processing libraries (like TensorFlow, Keras, or OpenCV) expect the size in this format when resizing.\nIMAGE_CHANNELS = 3\n\n# Defines the number of color channels in each image.\n# Common values:\n# 1 → Grayscale (black & white images).\n# 3 → RGB (Red, Green, Blue → normal colored images).\n# 4 → RGBA (RGB + Alpha channel for transparency).\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:27:59.079921Z","iopub.execute_input":"2025-08-19T16:27:59.080198Z","iopub.status.idle":"2025-08-19T16:27:59.098016Z","shell.execute_reply.started":"2025-08-19T16:27:59.080176Z","shell.execute_reply":"2025-08-19T16:27:59.097002Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile\nimport os\n\n# Path to the zip file\nzip_path = \"/kaggle/input/dogs-vs-cats/train.zip\"\nextract_path = \"/kaggle/working/train\"  \n\n# Extract zip\nwith zipfile.ZipFile(zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n\n# Now list files\nfilenames = os.listdir(extract_path)\nprint(len(filenames), \"files extracted\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:27:59.098965Z","iopub.execute_input":"2025-08-19T16:27:59.099239Z","iopub.status.idle":"2025-08-19T16:28:10.177762Z","shell.execute_reply.started":"2025-08-19T16:27:59.099219Z","shell.execute_reply":"2025-08-19T16:28:10.176828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"zipfile.is_zipfile(\"/kaggle/input/dogs-vs-cats/train.zip\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:28:10.178712Z","iopub.execute_input":"2025-08-19T16:28:10.178954Z","iopub.status.idle":"2025-08-19T16:28:10.186905Z","shell.execute_reply.started":"2025-08-19T16:28:10.178935Z","shell.execute_reply":"2025-08-19T16:28:10.185795Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"categories = []\nfilenames = os.listdir(\"/kaggle/working/train/train\")\n\nfor filename in filenames:\n    category = filename.split('.')[0] \n    if category == 'dog':\n        categories.append(1)\n    else:\n        categories.append(0)\n\nimport pandas as pd\ndf = pd.DataFrame({\n    'filename': filenames,\n    'category': categories\n})\nprint(df.head())\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:28:10.18809Z","iopub.execute_input":"2025-08-19T16:28:10.188476Z","iopub.status.idle":"2025-08-19T16:28:10.263791Z","shell.execute_reply.started":"2025-08-19T16:28:10.188445Z","shell.execute_reply":"2025-08-19T16:28:10.262755Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(df[df['filename'] == 'dog.11754.jpg'])\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:28:10.264764Z","iopub.execute_input":"2025-08-19T16:28:10.265056Z","iopub.status.idle":"2025-08-19T16:28:10.280628Z","shell.execute_reply.started":"2025-08-19T16:28:10.265025Z","shell.execute_reply":"2025-08-19T16:28:10.279704Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:28:10.282985Z","iopub.execute_input":"2025-08-19T16:28:10.283218Z","iopub.status.idle":"2025-08-19T16:28:10.318425Z","shell.execute_reply.started":"2025-08-19T16:28:10.283201Z","shell.execute_reply":"2025-08-19T16:28:10.317467Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df['category'].value_counts().plot.bar(color = ['grey', 'brown'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:28:10.319897Z","iopub.execute_input":"2025-08-19T16:28:10.320331Z","iopub.status.idle":"2025-08-19T16:28:10.6899Z","shell.execute_reply.started":"2025-08-19T16:28:10.320284Z","shell.execute_reply":"2025-08-19T16:28:10.689131Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D, Dropout, Flatten, Dense, Activation, BatchNormalization","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:45:07.458244Z","iopub.execute_input":"2025-08-19T16:45:07.458557Z","iopub.status.idle":"2025-08-19T16:45:07.462822Z","shell.execute_reply.started":"2025-08-19T16:45:07.458534Z","shell.execute_reply":"2025-08-19T16:45:07.462029Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\nmodel = Sequential()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:52:20.900303Z","iopub.execute_input":"2025-08-19T16:52:20.900605Z","iopub.status.idle":"2025-08-19T16:52:20.905376Z","shell.execute_reply.started":"2025-08-19T16:52:20.900585Z","shell.execute_reply":"2025-08-19T16:52:20.9046Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.add(Conv2D(32, (3, 3), activation='relu', input_shape=(IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_CHANNELS)))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:52:24.960784Z","iopub.execute_input":"2025-08-19T16:52:24.961063Z","iopub.status.idle":"2025-08-19T16:52:25.307543Z","shell.execute_reply.started":"2025-08-19T16:52:24.961043Z","shell.execute_reply":"2025-08-19T16:52:25.306743Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.add(Conv2D(64, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:52:49.862202Z","iopub.execute_input":"2025-08-19T16:52:49.862517Z","iopub.status.idle":"2025-08-19T16:52:49.907882Z","shell.execute_reply.started":"2025-08-19T16:52:49.862493Z","shell.execute_reply":"2025-08-19T16:52:49.906925Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.add(Conv2D(128, (3, 3), activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(MaxPooling2D(pool_size=(2, 2)))\nmodel.add(Dropout(0.25))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:53:00.481318Z","iopub.execute_input":"2025-08-19T16:53:00.481651Z","iopub.status.idle":"2025-08-19T16:53:00.536754Z","shell.execute_reply.started":"2025-08-19T16:53:00.481627Z","shell.execute_reply":"2025-08-19T16:53:00.535848Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.add(Flatten())\nmodel.add(Dense(512, activation='relu'))\nmodel.add(BatchNormalization())\nmodel.add(Dropout(0.5))\nmodel.add(Dense(2, activation='softmax'))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:53:23.16122Z","iopub.execute_input":"2025-08-19T16:53:23.162016Z","iopub.status.idle":"2025-08-19T16:53:23.329654Z","shell.execute_reply.started":"2025-08-19T16:53:23.161988Z","shell.execute_reply":"2025-08-19T16:53:23.328939Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy'])\n\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:53:33.035146Z","iopub.execute_input":"2025-08-19T16:53:33.036023Z","iopub.status.idle":"2025-08-19T16:53:33.07021Z","shell.execute_reply.started":"2025-08-19T16:53:33.035994Z","shell.execute_reply":"2025-08-19T16:53:33.069367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from keras.callbacks import EarlyStopping, ReduceLROnPlateau\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:57:24.887479Z","iopub.execute_input":"2025-08-19T16:57:24.888198Z","iopub.status.idle":"2025-08-19T16:57:24.893655Z","shell.execute_reply.started":"2025-08-19T16:57:24.88817Z","shell.execute_reply":"2025-08-19T16:57:24.892734Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"earlystop = EarlyStopping(patience=10)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:57:35.273169Z","iopub.execute_input":"2025-08-19T16:57:35.273451Z","iopub.status.idle":"2025-08-19T16:57:35.277547Z","shell.execute_reply.started":"2025-08-19T16:57:35.273433Z","shell.execute_reply":"2025-08-19T16:57:35.276844Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', patience=2, verbose=1, factor=0.5, min_lr=0.00001)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:58:58.010851Z","iopub.execute_input":"2025-08-19T16:58:58.011172Z","iopub.status.idle":"2025-08-19T16:58:58.015838Z","shell.execute_reply.started":"2025-08-19T16:58:58.011147Z","shell.execute_reply":"2025-08-19T16:58:58.014851Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"callbacks = [earlystop, learning_rate_reduction]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T16:59:23.97876Z","iopub.execute_input":"2025-08-19T16:59:23.979046Z","iopub.status.idle":"2025-08-19T16:59:23.983462Z","shell.execute_reply.started":"2025-08-19T16:59:23.979027Z","shell.execute_reply":"2025-08-19T16:59:23.982477Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df[\"category\"] = df[\"category\"].replace({0: 'Cat', 1: 'Dog'}) ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:02:06.598184Z","iopub.execute_input":"2025-08-19T17:02:06.598722Z","iopub.status.idle":"2025-08-19T17:02:06.607388Z","shell.execute_reply.started":"2025-08-19T17:02:06.598695Z","shell.execute_reply":"2025-08-19T17:02:06.60647Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df, validate_df = train_test_split(df, test_size=0.20, random_state=42)\ntrain_df = train_df.reset_index(drop=True)\nvalidate_df = validate_df.reset_index(drop=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:02:08.076404Z","iopub.execute_input":"2025-08-19T17:02:08.076773Z","iopub.status.idle":"2025-08-19T17:02:08.088511Z","shell.execute_reply.started":"2025-08-19T17:02:08.076748Z","shell.execute_reply":"2025-08-19T17:02:08.08774Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_df['category'].value_counts().plot.bar(color = ['grey', 'brown'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:02:09.898016Z","iopub.execute_input":"2025-08-19T17:02:09.898689Z","iopub.status.idle":"2025-08-19T17:02:10.032377Z","shell.execute_reply.started":"2025-08-19T17:02:09.898644Z","shell.execute_reply":"2025-08-19T17:02:10.03155Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validate_df['category'].value_counts().plot.bar(color = ['grey', 'brown'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:02:45.007601Z","iopub.execute_input":"2025-08-19T17:02:45.008598Z","iopub.status.idle":"2025-08-19T17:02:45.138862Z","shell.execute_reply.started":"2025-08-19T17:02:45.008566Z","shell.execute_reply":"2025-08-19T17:02:45.137969Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"total_train = train_df.shape[0]\ntotal_validate = validate_df.shape[0]\nbatch_size=15","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:02:59.14048Z","iopub.execute_input":"2025-08-19T17:02:59.140822Z","iopub.status.idle":"2025-08-19T17:02:59.145641Z","shell.execute_reply.started":"2025-08-19T17:02:59.140797Z","shell.execute_reply":"2025-08-19T17:02:59.14494Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_datagen = ImageDataGenerator(\n    rotation_range=15,\n    rescale=1./255,\n    shear_range=0.1,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    width_shift_range=0.1,\n    height_shift_range=0.1\n)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df, \n    \"/kaggle/working/train/train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:03:38.656798Z","iopub.execute_input":"2025-08-19T17:03:38.657599Z","iopub.status.idle":"2025-08-19T17:03:38.84085Z","shell.execute_reply.started":"2025-08-19T17:03:38.65757Z","shell.execute_reply":"2025-08-19T17:03:38.840109Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"validation_datagen = ImageDataGenerator(rescale=1./255)\nvalidation_generator = validation_datagen.flow_from_dataframe(\n    validate_df, \n    \"/kaggle/working/train/train/\", \n    x_col='filename',\n    y_col='category',\n    target_size=IMAGE_SIZE,\n    class_mode='categorical',\n    batch_size=batch_size\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T17:07:14.898372Z","iopub.execute_input":"2025-08-19T17:07:14.898724Z","iopub.status.idle":"2025-08-19T17:07:14.954121Z","shell.execute_reply.started":"2025-08-19T17:07:14.898657Z","shell.execute_reply":"2025-08-19T17:07:14.953413Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"epochs = 3 if FAST_RUN else 6\n\nhistory = model.fit(\n    train_generator, \n    epochs=epochs,\n    validation_data=validation_generator,\n    validation_steps=total_validate // batch_size,\n    steps_per_epoch=total_train // batch_size,\n    callbacks=callbacks\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T18:10:02.325091Z","iopub.execute_input":"2025-08-19T18:10:02.325413Z","iopub.status.idle":"2025-08-19T18:40:46.206148Z","shell.execute_reply.started":"2025-08-19T18:10:02.32539Z","shell.execute_reply":"2025-08-19T18:40:46.205233Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"*I only ran 6 epochs because my internet was extremely slow. For now, I’m stopping here and will revisit it later. In the meantime, I’ll consider the results from just these 6 epochs.*\n","metadata":{}},{"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 12))\n\n# Plot Loss\nax1.plot(history.history['loss'], color='b', label=\"Training loss\")\nax1.plot(history.history['val_loss'], color='r', label=\"Validation loss\")\nax1.set_xticks(np.arange(1, epochs+1, 1))\nax1.set_yticks(np.arange(0, 1.1, 0.1))\nax1.set_title(\"Model Loss\")\nax1.legend()\n\n# Plot Accuracy\nax2.plot(history.history['accuracy'], color='b', label=\"Training accuracy\")\nax2.plot(history.history['val_accuracy'], color='r', label=\"Validation accuracy\")\nax2.set_xticks(np.arange(1, epochs+1, 1))\nax2.set_yticks(np.arange(0.7, 1.05, 0.05))  # adjust to your accuracy range\nax2.set_title(\"Model Accuracy\")\nax2.legend()\n\nplt.tight_layout()\nplt.show()\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-08-19T18:51:03.828398Z","iopub.execute_input":"2025-08-19T18:51:03.828764Z","iopub.status.idle":"2025-08-19T18:51:04.269485Z","shell.execute_reply.started":"2025-08-19T18:51:03.828738Z","shell.execute_reply":"2025-08-19T18:51:04.268482Z"}},"outputs":[],"execution_count":null}]}