{"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":13836,"databundleVersionId":1718836,"sourceType":"competition"}],"dockerImageVersionId":31011,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import EfficientNetB4\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau, ModelCheckpoint\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport os","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:58:30.823635Z","iopub.execute_input":"2025-04-12T09:58:30.824272Z","iopub.status.idle":"2025-04-12T09:58:43.549981Z","shell.execute_reply.started":"2025-04-12T09:58:30.824247Z","shell.execute_reply":"2025-04-12T09:58:43.549426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATA_DIR = \"/kaggle/input/cassava-leaf-disease-classification\"\nTRAIN_DIR = os.path.join(DATA_DIR, \"train_images\")\nTEST_DIR = os.path.join(DATA_DIR, \"test_images\")\n\n# Load training labels\ndf_train = pd.read_csv(os.path.join(DATA_DIR, \"train.csv\"))\ndf_train['label'] = df_train['label'].astype('str')  # For flow_from_dataframe\n\n# Class names\nclass_names = {\n    '0': 'Cassava Bacterial Blight (CBB)',\n    '1': 'Cassava Brown Streak Disease (CBSD)',\n    '2': 'Cassava Green Mottle (CGM)',\n    '3': 'Cassava Mosaic Disease (CMD)',\n    '4': 'Healthy'\n}\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:58:43.551455Z","iopub.execute_input":"2025-04-12T09:58:43.551935Z","iopub.status.idle":"2025-04-12T09:58:43.590811Z","shell.execute_reply.started":"2025-04-12T09:58:43.551914Z","shell.execute_reply":"2025-04-12T09:58:43.590302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"IMG_SIZE = 380\nBATCH_SIZE = 16\n\ntrain_datagen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255,\n    rotation_range=40,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.3,\n    brightness_range=[0.8, 1.2],\n    horizontal_flip=True,\n    vertical_flip=True,\n    fill_mode='nearest',\n    validation_split=0.2\n)\n\nvalid_datagen = tf.keras.preprocessing.image.ImageDataGenerator(\n    rescale=1./255,\n    validation_split=0.2\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:58:43.591523Z","iopub.execute_input":"2025-04-12T09:58:43.591782Z","iopub.status.idle":"2025-04-12T09:58:43.596407Z","shell.execute_reply.started":"2025-04-12T09:58:43.591760Z","shell.execute_reply":"2025-04-12T09:58:43.595800Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_gen = train_datagen.flow_from_dataframe(\n    dataframe=df_train,\n    directory=TRAIN_DIR,\n    x_col=\"image_id\",\n    y_col=\"label\",\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    subset='training',\n    shuffle=True\n)\n\nvalid_gen = valid_datagen.flow_from_dataframe(\n    dataframe=df_train,\n    directory=TRAIN_DIR,\n    x_col=\"image_id\",\n    y_col=\"label\",\n    target_size=(IMG_SIZE, IMG_SIZE),\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    subset='validation',\n    shuffle=False\n)\n\n# Class weights\nclass_counts = df_train['label'].value_counts()\ntotal = sum(class_counts)\nclass_weights = {i: total/(len(class_counts)*count) for i, count in enumerate(class_counts)}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:58:43.597181Z","iopub.execute_input":"2025-04-12T09:58:43.597398Z","iopub.status.idle":"2025-04-12T09:59:38.469180Z","shell.execute_reply.started":"2025-04-12T09:58:43.597381Z","shell.execute_reply":"2025-04-12T09:59:38.468375Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ======================\n# 5. MODEL ARCHITECTURE (CORRECTED)\n# ======================\ndef build_model():\n    base_model = EfficientNetB4(\n        weights='imagenet',\n        include_top=False,\n        input_shape=(IMG_SIZE, IMG_SIZE, 3)  # Removed invalid parameter\n    )\n    \n    # Freeze first 150 layers\n    for layer in base_model.layers[:150]:\n        layer.trainable = False\n    \n    # Add custom dropout instead\n    model = models.Sequential([\n        base_model,\n        layers.GlobalAveragePooling2D(),\n        layers.Dropout(0.5),  # Explicit dropout layer\n        layers.Dense(512, activation='relu', kernel_regularizer=tf.keras.regularizers.l2(0.01)),\n        layers.BatchNormalization(),\n        layers.Dropout(0.3),  # Additional dropout\n        layers.Dense(5, activation='softmax')\n    ])\n    \n    return model\n\nmodel = build_model()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:59:38.471254Z","iopub.execute_input":"2025-04-12T09:59:38.471503Z","iopub.status.idle":"2025-04-12T09:59:44.342017Z","shell.execute_reply.started":"2025-04-12T09:59:38.471486Z","shell.execute_reply":"2025-04-12T09:59:44.341474Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"model.compile(\n    optimizer=Adam(learning_rate=1e-4),\n    loss='categorical_crossentropy',\n    metrics=['accuracy',\n             tf.keras.metrics.Precision(name='precision'),\n             tf.keras.metrics.Recall(name='recall')]\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:59:44.342819Z","iopub.execute_input":"2025-04-12T09:59:44.343067Z","iopub.status.idle":"2025-04-12T09:59:44.366549Z","shell.execute_reply.started":"2025-04-12T09:59:44.343047Z","shell.execute_reply":"2025-04-12T09:59:44.365710Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"callbacks = [\n    EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True),\n    ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, min_lr=1e-6),\n    ModelCheckpoint('best_model.keras', monitor='val_accuracy', save_best_only=True)\n]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:59:44.367385Z","iopub.execute_input":"2025-04-12T09:59:44.367607Z","iopub.status.idle":"2025-04-12T09:59:44.486731Z","shell.execute_reply.started":"2025-04-12T09:59:44.367582Z","shell.execute_reply":"2025-04-12T09:59:44.485828Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# ======================\nhistory = model.fit(\n    train_gen,\n    steps_per_epoch=train_gen.n//train_gen.batch_size,\n    validation_data=valid_gen,\n    validation_steps=valid_gen.n//valid_gen.batch_size,\n    epochs=30,\n    callbacks=callbacks,\n    class_weight=class_weights\n)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-04-12T09:59:44.487740Z","iopub.execute_input":"2025-04-12T09:59:44.488539Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def plot_history(history):\n    plt.figure(figsize=(12, 4))\n    \n    plt.subplot(1, 2, 1)\n    plt.plot(history.history['accuracy'], label='Train Accuracy')\n    plt.plot(history.history['val_accuracy'], label='Val Accuracy')\n    plt.title('Accuracy Curves')\n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.legend()\n    \n    plt.subplot(1, 2, 2)\n    plt.plot(history.history['loss'], label='Train Loss')\n    plt.plot(history.history['val_loss'], label='Val Loss')\n    plt.title('Loss Curves')\n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.legend()\n    \n    plt.tight_layout()\n    plt.show()\n\nplot_history(history)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.metrics import classification_report, confusion_matrix\nimport seaborn as sns\n\n# Predict on validation set\ny_pred = model.predict(valid_gen)\ny_pred_classes = np.argmax(y_pred, axis=1)\ny_true = valid_gen.classes\n\n# Classification report\nprint(classification_report(y_true, y_pred_classes, target_names=class_names.values()))\n\n# Confusion matrix\nplt.figure(figsize=(10, 8))\nsns.heatmap(confusion_matrix(y_true, y_pred_classes), \n            annot=True, fmt='d', cmap='Blues',\n            xticklabels=class_names.values(),\n            yticklabels=class_names.values())\nplt.title('Confusion Matrix')\nplt.xlabel('Predicted')\nplt.ylabel('True')\nplt.show()\n","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}