{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":3978,"databundleVersionId":32719,"sourceType":"competition"},{"sourceId":13937562,"sourceType":"datasetVersion","datasetId":8882336}],"dockerImageVersionId":31192,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"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},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================================================\n# COMPLETE EFFICIENTNETB0 TRAINING PIPELINE (ALL-IN-ONE)\n# =========================================================\n\n# 0. RESET WORKSPACE (Optional for Kaggle)\n!rm -rf /kaggle/working/train\n!rm -rf /kaggle/working/test\n!mkdir -p /kaggle/working/train\n!mkdir -p /kaggle/working/test\n\n# 1. IMPORTS\nimport os, zipfile, glob\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout, BatchNormalization, Input\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input\nfrom sklearn.metrics import confusion_matrix\n\nprint(\"TensorFlow Version:\", tf.__version__)\n\n# 2. UNZIP TRAIN & TEST ZIP FILES\nprint(\"Unzipping dataset...\")\ntrain_zip_path = \"/kaggle/input/datasciencebowl/train.zip\"\ntest_zip_path = \"/kaggle/input/datasciencebowl/test.zip\"\n\nwith zipfile.ZipFile(train_zip_path, 'r') as z:\n    z.extractall(\"/kaggle/working/train\")\n\nwith zipfile.ZipFile(test_zip_path, 'r') as z:\n    z.extractall(\"/kaggle/working/test\")\n\nprint(\"Extraction complete!\")\n\n# 3. PATHS & CONFIG\nTRAIN_DIR = \"/kaggle/working/train/train\"\nTEST_DIR = \"/kaggle/working/test/test\"\n\nIMG_SIZE = (224, 224)\nBATCH_SIZE = 16\nNUM_CLASSES = 121\nEPOCHS = 10\n\n# 4. DATA GENERATORS\nprint(\"\\nLoading data generators...\")\n\ntrain_datagen = ImageDataGenerator(\n    preprocessing_function=preprocess_input,\n    rotation_range=360,\n    width_shift_range=0.10,\n    height_shift_range=0.10,\n    horizontal_flip=True,\n    vertical_flip=True,\n    validation_split=0.20\n)\n\ntrain_gen = train_datagen.flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    subset=\"training\",\n    seed=42\n)\n\nval_gen = train_datagen.flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    subset=\"validation\",\n    seed=42\n)\n\neval_gen = ImageDataGenerator(\n    preprocessing_function=preprocess_input,\n    validation_split=0.20\n).flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    subset=\"validation\",\n    shuffle=False\n)\n\nclasses = list(train_gen.class_indices.keys())\nprint(\"Classes Loaded:\", len(classes))\n\n# 5. BUILD EFFICIENTNETB0 MODEL\ndef build_model():\n    base = EfficientNetB0(weights=\"imagenet\", include_top=False, input_shape=(224,224,3))\n    base.trainable = False\n    inputs = Input(shape=(224,224,3))\n    x = base(inputs, training=False)\n    x = GlobalAveragePooling2D()(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.4)(x)\n    outputs = Dense(NUM_CLASSES, activation=\"softmax\")(x)\n    model = Model(inputs, outputs)\n    model.compile(optimizer=\"adam\", loss=\"categorical_crossentropy\", metrics=[\"accuracy\"])\n    return model\n\nmodel = build_model()\nmodel.summary()\n\n# 6. TRAIN MODEL\nprint(\"\\nTraining EfficientNetB0...\")\nhistory = model.fit(train_gen, validation_data=val_gen, epochs=EPOCHS, verbose=1)\n\n# 7. PLOT TRAINING CURVES\nplt.figure(figsize=(14,5))\nplt.subplot(1,2,1)\nplt.plot(history.history[\"accuracy\"], label=\"Train Acc\")\nplt.plot(history.history[\"val_accuracy\"], label=\"Val Acc\")\nplt.title(\"Accuracy Over Epochs\")\nplt.legend()\n\nplt.subplot(1,2,2)\nplt.plot(history.history[\"loss\"], label=\"Train Loss\")\nplt.plot(history.history[\"val_loss\"], label=\"Val Loss\")\nplt.title(\"Loss Over Epochs\")\nplt.legend()\nplt.savefig(\"training_plots.png\")\nplt.show()\n\n# 8. CONFUSION MATRIX\nprint(\"\\nGenerating Confusion Matrix...\")\npred = model.predict(eval_gen)\ny_pred = np.argmax(pred, axis=1)\ny_true = eval_gen.classes\ncm = confusion_matrix(y_true, y_pred)\n\nplt.figure(figsize=(18,18))\nsns.heatmap(cm, cmap=\"viridis\", xticklabels=False, yticklabels=False)\nplt.title(\"Confusion Matrix (121 Classes)\")\nplt.savefig(\"confusion_matrix.png\")\nplt.show()\n\n# 9. TEST PREDICTION + SUBMISSION\nprint(\"\\nPreparing Submission...\")\ntest_images = glob.glob(os.path.join(TEST_DIR, \"*.jpg\"))\nsubmission_data = []\n\nfor img_path in test_images:\n    img = load_img(img_path, target_size=IMG_SIZE)\n    x = img_to_array(img)\n    x = preprocess_input(x)\n    x = np.expand_dims(x, axis=0)\n    preds = np.clip(model.predict(x, verbose=0)[0], 1e-15, 1-1e-15)\n    submission_data.append([os.path.basename(img_path)] + list(preds))\n\nsubmission_df = pd.DataFrame(submission_data, columns=[\"image\"] + classes)\nsubmission_df.to_csv(\"submission_final_efficientnet.csv\", index=False)\nprint(\"\\n🎉 DONE! Submission saved as submission_final_efficientnet.csv\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T19:46:57.395080Z","iopub.execute_input":"2025-11-30T19:46:57.395261Z","iopub.status.idle":"2025-11-30T21:20:22.927155Z","shell.execute_reply.started":"2025-11-30T19:46:57.395243Z","shell.execute_reply":"2025-11-30T21:20:22.925801Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Assuming 'model' is already trained in memory\n\n# Save only the weights\nmodel.save_weights(\"efficientnetb0_weights.h5\")\nprint(\"Weights saved as efficientnetb0_weights.h5\")\n\n# Save entire model\nmodel.save(\"efficientnetb0_full_model.keras\")\nprint(\"Full model saved as efficientnetb0_full_model.keras\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T21:20:30.233525Z","iopub.execute_input":"2025-11-30T21:20:30.234077Z","iopub.status.idle":"2025-11-30T21:20:30.250659Z","shell.execute_reply.started":"2025-11-30T21:20:30.234050Z","shell.execute_reply":"2025-11-30T21:20:30.249608Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================================================\n# OPTIMIZED EFFICIENTNETB0 TRAINING PIPELINE (NO TESTING)\n# =========================================================\n\n# 0. RESET WORKSPACE (Optional for Kaggle)\n!rm -rf /kaggle/working/train\n!mkdir -p /kaggle/working/train\n\n# 1. IMPORTS\nimport os, zipfile, glob\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\n\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense, Dropout, BatchNormalization, Input\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.applications.efficientnet import preprocess_input\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau\nfrom sklearn.metrics import confusion_matrix\n\nprint(\"TensorFlow Version:\", tf.__version__)\n\n# 2. UNZIP TRAIN ZIP FILE ONLY\nprint(\"Unzipping training dataset...\")\ntrain_zip_path = \"/kaggle/input/datasciencebowl/train.zip\"\n\nwith zipfile.ZipFile(train_zip_path, 'r') as z:\n    z.extractall(\"/kaggle/working/train\")\n\nprint(\"Extraction complete!\")\n\n# 3. PATHS & CONFIG\nTRAIN_DIR = \"/kaggle/working/train/train\"\n\nIMG_SIZE = (224, 224)\nBATCH_SIZE = 16\nNUM_CLASSES = 121\nEPOCHS = 15   # increased for higher accuracy\n\n# 4. DATA GENERATORS (more augmentation)\ntrain_datagen = ImageDataGenerator(\n    preprocessing_function=preprocess_input,\n    rotation_range=20,\n    width_shift_range=0.15,\n    height_shift_range=0.15,\n    zoom_range=0.2,\n    brightness_range=[0.8, 1.2],\n    horizontal_flip=True,\n    vertical_flip=True,\n    validation_split=0.20\n)\n\ntrain_gen = train_datagen.flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    subset=\"training\",\n    seed=42\n)\n\nval_gen = train_datagen.flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=\"categorical\",\n    subset=\"validation\",\n    seed=42\n)\n\nclasses = list(train_gen.class_indices.keys())\nprint(\"Classes Loaded:\", len(classes))\n\n# 5. BUILD IMPROVED MODEL (with fine-tuning)\ndef build_model():\n    base = EfficientNetB0(weights=\"imagenet\", include_top=False, input_shape=(224,224,3))\n\n    # UNFREEZE LAST 20 LAYERS FOR FINE-TUNING\n    for layer in base.layers[-20:]:\n        layer.trainable = True\n\n    inputs = Input(shape=(224,224,3))\n    x = base(inputs)\n    x = GlobalAveragePooling2D()(x)\n    x = BatchNormalization()(x)\n    x = Dropout(0.4)(x)\n    outputs = Dense(NUM_CLASSES, activation=\"softmax\")(x)\n\n    model = Model(inputs, outputs)\n\n    model.compile(\n        optimizer=tf.keras.optimizers.Adam(learning_rate=1e-4),\n        loss=\"categorical_crossentropy\",\n        metrics=[\"accuracy\"]\n    )\n    return model\n\nmodel = build_model()\nmodel.summary()\n\n# 6. CALLBACKS FOR HIGHER ACCURACY\ncallbacks = [\n    EarlyStopping(patience=5, restore_best_weights=True),\n    ReduceLROnPlateau(factor=0.2, patience=2)\n]\n\n# 7. TRAIN MODEL\nprint(\"\\nTraining Optimized EfficientNetB0...\")\nhistory = model.fit(\n    train_gen,\n    validation_data=val_gen,\n    epochs=EPOCHS,\n    callbacks=callbacks,\n    verbose=1\n)\n\n# =========================================================\n# SAVE MODEL WEIGHTS AFTER TRAINING\n# =========================================================\nmodel.save_weights(\"efficientnetb0_finetuned_weights.h5\")\nprint(\"Saved weights as efficientnetb0_finetuned_weights.h5\")\n\nmodel.save(\"efficientnetb0_finetuned_full_model.keras\")\nprint(\"Saved full model as efficientnetb0_finetuned_full_model.keras\")\n\n# 8. CONFUSION MATRIX (Optional but useful)\nprint(\"\\nGenerating Confusion Matrix...\")\neval_gen = ImageDataGenerator(preprocess_input, validation_split=0.20).flow_from_directory(\n    TRAIN_DIR, target_size=IMG_SIZE, batch_size=BATCH_SIZE, class_mode=\"categorical\",\n    subset=\"validation\", shuffle=False\n)\n\npred = model.predict(eval_gen)\ny_pred = np.argmax(pred, axis=1)\ny_true = eval_gen.classes\ncm = confusion_matrix(y_true, y_pred)\n\nplt.figure(figsize=(18,18))\nsns.heatmap(cm, cmap=\"viridis\", xticklabels=False, yticklabels=False)\nplt.title(\"Confusion Matrix (121 Classes)\")\nplt.savefig(\"confusion_matrix_finetuned.png\")\nplt.show()\n\nprint(\"\\n🎉 Training Complete! Weights saved successfully.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T21:22:40.070205Z","iopub.execute_input":"2025-11-30T21:22:40.070981Z","iopub.status.idle":"2025-11-30T22:56:11.651303Z","shell.execute_reply.started":"2025-11-30T21:22:40.070953Z","shell.execute_reply":"2025-11-30T22:56:11.649911Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================================================\n# SAVE TRAINED WEIGHTS + FULL MODEL (Corrected)\n# =========================================================\n\n# Save only weights (must end with .weights.h5)\nmodel.save_weights(\"efficientnetb0_finetuned.weights.h5\")\nprint(\"Saved weights as efficientnetb0_finetuned.weights.h5\")\n\n# Save full model (architecture + weights + optimizer)\nmodel.save(\"efficientnetb0_finetuned_model.keras\")\nprint(\"Saved full model as efficientnetb0_finetuned_model.keras\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T22:59:03.984181Z","iopub.execute_input":"2025-11-30T22:59:03.984842Z","iopub.status.idle":"2025-11-30T22:59:05.640818Z","shell.execute_reply.started":"2025-11-30T22:59:03.984818Z","shell.execute_reply":"2025-11-30T22:59:05.640020Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# =========================================================\n# HYBRID ENSEMBLE: BASE CNN (128x128) + EfficientNetB0 (224x224)\n# =========================================================\n\nimport os\nimport numpy as np\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.applications.efficientnet import preprocess_input\nfrom sklearn.metrics import accuracy_score\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.metrics import confusion_matrix\n\nprint(\"TensorFlow:\", tf.__version__)\n\n# ---------------------------------------------------------\n# 1) PATHS  (change only if your .keras files are elsewhere)\n# ---------------------------------------------------------\nTRAIN_DIR       = \"/kaggle/working/train/train\"\n\nBASE_MODEL_PATH = \"/kaggle/input/base-cnn-keras/base_cnn_model.keras\"\nEFF_MODEL_PATH  = \"/kaggle/working/efficientnetb0_finetuned_model.keras\"\n\n# for single-image demo\n# TEST_IMAGE_PATH = \"/kaggle/input/zxcvbnm/22613.jpg\"   # change if needed\n\nIMG_SIZE_BASE = (128, 128)\nIMG_SIZE_EFF  = (224, 224)\nBATCH_BASE = 32\nBATCH_EFF  = 16\nSEED = 42\n\n# ---------------------------------------------------------\n# 2) VALIDATION GENERATORS (NO SHUFFLE)\n#    one for Base CNN, one for EfficientNetB0\n# ---------------------------------------------------------\nprint(\"\\nPreparing validation generators...\")\n\neval_gen_base = ImageDataGenerator(\n    rescale=1./255.0,\n    validation_split=0.20\n).flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE_BASE,\n    batch_size=BATCH_BASE,\n    class_mode=\"categorical\",\n    subset=\"validation\",\n    shuffle=False,\n    seed=SEED\n)\n\neval_gen_eff = ImageDataGenerator(\n    preprocessing_function=preprocess_input,\n    validation_split=0.20\n).flow_from_directory(\n    TRAIN_DIR,\n    target_size=IMG_SIZE_EFF,\n    batch_size=BATCH_EFF,\n    class_mode=\"categorical\",\n    subset=\"validation\",\n    shuffle=False,\n    seed=SEED\n)\n\n# Sanity check – labels must match\nassert np.array_equal(eval_gen_base.classes, eval_gen_eff.classes), \"Label orders do not match!\"\ny_true = eval_gen_base.classes\nclass_names = list(eval_gen_base.class_indices.keys())\nprint(\"Validation samples:\", len(y_true))\nprint(\"Number of classes:\", len(class_names))\n\n# ---------------------------------------------------------\n# 3) LOAD TRAINED MODELS\n# ---------------------------------------------------------\nprint(\"\\nLoading saved models...\")\nbase_cnn = tf.keras.models.load_model(BASE_MODEL_PATH)\neffnet   = tf.keras.models.load_model(EFF_MODEL_PATH)\nprint(\"Models loaded ✅\")\n\n# ---------------------------------------------------------\n# 4) PREDICT ON VALIDATION SET\n# ---------------------------------------------------------\nprint(\"\\nPredicting with Base CNN...\")\np_base = base_cnn.predict(eval_gen_base, verbose=1)\n\nprint(\"Predicting with EfficientNetB0...\")\np_eff  = effnet.predict(eval_gen_eff, verbose=1)\n\ny_pred_base = np.argmax(p_base, axis=1)\ny_pred_eff  = np.argmax(p_eff,  axis=1)\n\nacc_base = accuracy_score(y_true, y_pred_base)\nacc_eff  = accuracy_score(y_true, y_pred_eff)\n\nprint(f\"\\nBase CNN   Val Accuracy : {acc_base:.4f}\")\nprint(f\"EfficientNet Val Accuracy : {acc_eff:.4f}\")\n\n# ---------------------------------------------------------\n# 5) HYBRID – SEARCH BEST WEIGHT\n# ---------------------------------------------------------\nprint(\"\\nSearching best hybrid weight...\")\n\nbest_acc = 0.0\nbest_w   = 0.0\n\nfor w in np.arange(0, 1.05, 0.05):\n    hybrid_probs = w * p_base + (1 - w) * p_eff\n    hybrid_preds = np.argmax(hybrid_probs, axis=1)\n    acc = accuracy_score(y_true, hybrid_preds)\n    print(f\"w_base={w:.2f}, w_eff={1-w:.2f} -> acc={acc:.4f}\")\n    if acc > best_acc:\n        best_acc = acc\n        best_w = w\n\nprint(\"\\n========================================\")\nprint(f\"Best weight: Base={best_w:.2f}, Eff={1-best_w:.2f}\")\nprint(f\"Hybrid Validation Accuracy: {best_acc:.4f}\")\nprint(\"========================================\")\n\n# ---------------------------------------------------------\n# 6) CONFUSION MATRIX FOR HYBRID (OPTIONAL)\n# ---------------------------------------------------------\nhybrid_probs = best_w * p_base + (1 - best_w) * p_eff\nhybrid_preds = np.argmax(hybrid_probs, axis=1)\ncm = confusion_matrix(y_true, hybrid_preds)\n\nplt.figure(figsize=(20,20))\nsns.heatmap(cm, cmap=\"viridis\", xticklabels=False, yticklabels=False)\nplt.title(\"Hybrid Ensemble Confusion Matrix (Validation)\")\nplt.xlabel(\"Predicted\")\nplt.ylabel(\"True\")\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-30T23:35:46.443997Z","iopub.execute_input":"2025-11-30T23:35:46.444980Z","iopub.status.idle":"2025-11-30T23:36:11.446776Z","shell.execute_reply.started":"2025-11-30T23:35:46.444952Z","shell.execute_reply":"2025-11-30T23:36:11.446098Z"}},"outputs":[],"execution_count":null}]}