{"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":31239,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\n%matplotlib inline \nimport cv2\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:53:39.819907Z","iopub.execute_input":"2025-12-21T11:53:39.820099Z","iopub.status.idle":"2025-12-21T11:53:42.368687Z","shell.execute_reply.started":"2025-12-21T11:53:39.820081Z","shell.execute_reply":"2025-12-21T11:53:42.367632Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"***Global Constants***","metadata":{}},{"cell_type":"code","source":"# Fixed for our Cats & Dogs classes\nNUM_CLASSES = 2\n\n# Fixed for Cats & Dogs color images\nCHANNELS = 3\n\nIMAGE_RESIZE = 224\nRESNET50_POOLING_AVERAGE = 'avg'\nDENSE_LAYER_ACTIVATION = 'softmax'\nOBJECTIVE_FUNCTION = 'categorical_crossentropy'\n\n# Common accuracy metric for all outputs, but can use different metrics for different output\nLOSS_METRICS = ['accuracy']\n\n# EARLY_STOP_PATIENCE must be < NUM_EPOCHS\nNUM_EPOCHS = 10\nEARLY_STOP_PATIENCE = 3\n\n# These steps value should be proper FACTOR of no.-of-images in train & valid folders respectively\n# Training images processed in each step would be no.-of-train-images / STEPS_PER_EPOCH_TRAINING\nSTEPS_PER_EPOCH_TRAINING = 10\nSTEPS_PER_EPOCH_VALIDATION = 10\n\n# These steps value should be proper FACTOR of no.-of-images in train & valid folders respectively\n# NOTE that these BATCH* are for Keras ImageDataGenerator batching to fill epoch step input\nBATCH_SIZE_TRAINING = 100\nBATCH_SIZE_VALIDATION = 100\n\n# Using 1 to easily manage mapping between test_generator & prediction for submission preparation\nBATCH_SIZE_TESTING = 1","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:53:42.370643Z","iopub.execute_input":"2025-12-21T11:53:42.371105Z","iopub.status.idle":"2025-12-21T11:53:42.383976Z","shell.execute_reply.started":"2025-12-21T11:53:42.371079Z","shell.execute_reply":"2025-12-21T11:53:42.382412Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.applications import ResNet50\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Dense\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:54:35.518531Z","iopub.execute_input":"2025-12-21T11:54:35.518916Z","iopub.status.idle":"2025-12-21T11:54:35.610255Z","shell.execute_reply.started":"2025-12-21T11:54:35.518888Z","shell.execute_reply":"2025-12-21T11:54:35.609359Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"resnet_weights_path = '../input/resnet50/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:54:41.173564Z","iopub.execute_input":"2025-12-21T11:54:41.174357Z","iopub.status.idle":"2025-12-21T11:54:41.178688Z","shell.execute_reply.started":"2025-12-21T11:54:41.174328Z","shell.execute_reply":"2025-12-21T11:54:41.177779Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"\n# 1st layer as the lumpsum weights from resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5\n# NOTE that this layer will be set below as NOT TRAINABLE, i.e., use it as is\nresnet_base = ResNet50(\n    include_top=False,\n    weights='imagenet',  # هنا نستخدم weights الجاهزة\n    pooling='avg',\n    input_shape=(224, 224, 3)\n)\nresnet_base.trainable = False\n#Still not talking about our train/test data or any pre-processing.\nmodel = Sequential()\n\n# 2nd layer as Dense for 2-class classification, i.e., dog or cat using SoftMax activation\nmodel.add(resnet_base)\nmodel.add(Dense(NUM_CLASSES, activation=DENSE_LAYER_ACTIVATION))\n\n# Say not to train first layer (ResNet) model as it is already trained\nmodel.layers[0].trainable = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:56:52.665282Z","iopub.execute_input":"2025-12-21T11:56:52.665630Z","iopub.status.idle":"2025-12-21T11:56:58.333485Z","shell.execute_reply.started":"2025-12-21T11:56:52.665610Z","shell.execute_reply":"2025-12-21T11:56:58.332367Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:57:11.688802Z","iopub.execute_input":"2025-12-21T11:57:11.689181Z","iopub.status.idle":"2025-12-21T11:57:11.711869Z","shell.execute_reply.started":"2025-12-21T11:57:11.689110Z","shell.execute_reply":"2025-12-21T11:57:11.711153Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"***Compile Our Transfer Learning Model***","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.optimizers import SGD\n\nsgd = SGD(\n    learning_rate=0.01,\n    momentum=0.9,\n    nesterov=True\n)\n\nmodel.compile(\n    optimizer=sgd,\n    loss=OBJECTIVE_FUNCTION,\n    metrics=LOSS_METRICS\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T11:58:35.526108Z","iopub.execute_input":"2025-12-21T11:58:35.526990Z","iopub.status.idle":"2025-12-21T11:58:35.543522Z","shell.execute_reply.started":"2025-12-21T11:58:35.526961Z","shell.execute_reply":"2025-12-21T11:58:35.542492Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nprint(os.listdir('../input'))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:01:45.176969Z","iopub.execute_input":"2025-12-21T12:01:45.178181Z","iopub.status.idle":"2025-12-21T12:01:45.183092Z","shell.execute_reply.started":"2025-12-21T12:01:45.178140Z","shell.execute_reply":"2025-12-21T12:01:45.182172Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import zipfile\nimport os\n\nzip_path = '../input/dogs-vs-cats-redux-kernels-edition/train.zip'\nextract_path = '/kaggle/working/train'\n\nwith zipfile.ZipFile(zip_path, 'r') as zip_ref:\n    zip_ref.extractall(extract_path)\n\nprint(os.listdir(extract_path))\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:04:48.837715Z","iopub.execute_input":"2025-12-21T12:04:48.838146Z","iopub.status.idle":"2025-12-21T12:05:00.833557Z","shell.execute_reply.started":"2025-12-21T12:04:48.838105Z","shell.execute_reply":"2025-12-21T12:05:00.832611Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\nimport pandas as pd\n\ntrain_dir = '/kaggle/working/train/train'\n\nfilenames = os.listdir(train_dir)\ncategories = []\n\nfor fname in filenames:\n    if fname.startswith('cat'):\n        categories.append('cat')\n    else:\n        categories.append('dog')\n\ndf = pd.DataFrame({\n    'filename': filenames,\n    'class': categories\n})\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:09:11.166237Z","iopub.execute_input":"2025-12-21T12:09:11.166542Z","iopub.status.idle":"2025-12-21T12:09:11.195491Z","shell.execute_reply.started":"2025-12-21T12:09:11.166524Z","shell.execute_reply":"2025-12-21T12:09:11.194447Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\ntrain_df, valid_df = train_test_split(\n    df,\n    test_size=0.2,\n    random_state=42\n)\n\ntrain_df = train_df.reset_index(drop=True)\nvalid_df = valid_df.reset_index(drop=True)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:09:14.021230Z","iopub.execute_input":"2025-12-21T12:09:14.022059Z","iopub.status.idle":"2025-12-21T12:09:14.034740Z","shell.execute_reply.started":"2025-12-21T12:09:14.022033Z","shell.execute_reply":"2025-12-21T12:09:14.033849Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.applications.resnet50 import preprocess_input\n\ndatagen = ImageDataGenerator(\n    preprocessing_function=preprocess_input\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:09:28.775736Z","iopub.execute_input":"2025-12-21T12:09:28.776066Z","iopub.status.idle":"2025-12-21T12:09:28.780792Z","shell.execute_reply.started":"2025-12-21T12:09:28.776044Z","shell.execute_reply":"2025-12-21T12:09:28.779697Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_generator = datagen.flow_from_dataframe(\n    train_df,\n    directory=train_dir,\n    x_col='filename',\n    y_col='class',\n    target_size=(IMAGE_RESIZE, IMAGE_RESIZE),\n    batch_size=BATCH_SIZE_TRAINING,\n    class_mode='categorical'\n)\n\nvalidation_generator = datagen.flow_from_dataframe(\n    valid_df,\n    directory=train_dir,\n    x_col='filename',\n    y_col='class',\n    target_size=(IMAGE_RESIZE, IMAGE_RESIZE),\n    batch_size=BATCH_SIZE_VALIDATION,\n    class_mode='categorical'\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:09:42.287825Z","iopub.execute_input":"2025-12-21T12:09:42.288583Z","iopub.status.idle":"2025-12-21T12:09:42.520814Z","shell.execute_reply.started":"2025-12-21T12:09:42.288556Z","shell.execute_reply":"2025-12-21T12:09:42.519811Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Max number of steps that these generator will have opportunity to process their source content\n# len(train_generator) should be 'no. of available train images / BATCH_SIZE_TRAINING'\n# len(valid_generator) should be 'no. of available train images / BATCH_SIZE_VALIDATION'\n(BATCH_SIZE_TRAINING, len(train_generator), BATCH_SIZE_VALIDATION, len(validation_generator))","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:09:54.237380Z","iopub.execute_input":"2025-12-21T12:09:54.237708Z","iopub.status.idle":"2025-12-21T12:09:54.243915Z","shell.execute_reply.started":"2025-12-21T12:09:54.237686Z","shell.execute_reply":"2025-12-21T12:09:54.243147Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"### Train Our Model With Cats & Dogs Train (splitted) Data Set","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping\n\ncb_checkpointer = ModelCheckpoint(\n    filepath='best_model.keras',   # الأفضل .keras\n    monitor='val_loss',\n    save_best_only=True,\n    verbose=1\n)\n\ncb_early_stopper = EarlyStopping(\n    monitor='val_loss',\n    patience=3,\n    restore_best_weights=True\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:17:36.255198Z","iopub.execute_input":"2025-12-21T12:17:36.255657Z","iopub.status.idle":"2025-12-21T12:17:36.261493Z","shell.execute_reply.started":"2025-12-21T12:17:36.255627Z","shell.execute_reply":"2025-12-21T12:17:36.260355Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Grid Search is an ideal candidate for distributed machine learning\n# Pseudo code for hyperparameters Grid Search\n\n'''\nfrom sklearn.grid_search import ParameterGrid\nparam_grid = {'epochs': [5, 10, 15], 'steps_per_epoch' : [10, 20, 50]}\n\ngrid = ParameterGrid(param_grid)\n\n# Accumulate history of all permutations (may be for viewing trend) and keep watching for lowest val_loss as final model\nfor params in grid:\n    print(params)\n'''","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:17:38.876262Z","iopub.execute_input":"2025-12-21T12:17:38.877264Z","iopub.status.idle":"2025-12-21T12:17:38.883228Z","shell.execute_reply.started":"2025-12-21T12:17:38.877228Z","shell.execute_reply":"2025-12-21T12:17:38.882357Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"fit_history = model.fit(\n    train_generator,\n    steps_per_epoch=STEPS_PER_EPOCH_TRAINING,\n    epochs=NUM_EPOCHS,\n    validation_data=validation_generator,\n    validation_steps=STEPS_PER_EPOCH_VALIDATION,\n    callbacks=[cb_checkpointer, cb_early_stopper]\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:17:41.431651Z","iopub.execute_input":"2025-12-21T12:17:41.432090Z","iopub.status.idle":"2025-12-21T12:33:30.394036Z","shell.execute_reply.started":"2025-12-21T12:17:41.432064Z","shell.execute_reply":"2025-12-21T12:33:30.393057Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(fit_history.history.keys())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:34:15.262207Z","iopub.execute_input":"2025-12-21T12:34:15.262555Z","iopub.status.idle":"2025-12-21T12:34:15.268016Z","shell.execute_reply.started":"2025-12-21T12:34:15.262535Z","shell.execute_reply":"2025-12-21T12:34:15.267185Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.figure(1, figsize=(15, 8))\n\nplt.subplot(221)\nplt.plot(fit_history.history['accuracy'])\nplt.plot(fit_history.history['val_accuracy'])\nplt.title('Model Accuracy')\nplt.ylabel('Accuracy')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'])\n\nplt.subplot(222)\nplt.plot(fit_history.history['loss'])\nplt.plot(fit_history.history['val_loss'])\nplt.title('Model Loss')\nplt.ylabel('Loss')\nplt.xlabel('Epoch')\nplt.legend(['Train', 'Validation'])\n\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-21T12:34:59.165557Z","iopub.execute_input":"2025-12-21T12:34:59.166426Z","iopub.status.idle":"2025-12-21T12:34:59.591517Z","shell.execute_reply.started":"2025-12-21T12:34:59.166395Z","shell.execute_reply":"2025-12-21T12:34:59.590356Z"}},"outputs":[],"execution_count":null}]}