{"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":"gpu","dataSources":[{"sourceId":13836,"databundleVersionId":1718836,"isSourceIdPinned":false,"sourceType":"competition"},{"sourceId":655746,"sourceType":"modelInstanceVersion","isSourceIdPinned":false,"modelInstanceId":495617,"modelId":511017}],"dockerImageVersionId":31193,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nfrom sklearn.model_selection import train_test_split\nimport tensorflow as tf\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator, load_img, img_to_array\nfrom tensorflow.keras.layers import GlobalAveragePooling2D, Dense\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.applications import EfficientNetB0\nfrom tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau\nfrom tensorflow.keras.optimizers import Adam","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:52:43.471631Z","iopub.execute_input":"2025-11-21T13:52:43.471847Z","iopub.status.idle":"2025-11-21T13:53:01.466031Z","shell.execute_reply.started":"2025-11-21T13:52:43.47182Z","shell.execute_reply":"2025-11-21T13:53:01.465414Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Set random seed for reproducibility\ntf.random.set_seed(42)\nnp.random.seed(42)\n\nBATCH_SIZE = 16\nIMG_SIZE = (224, 224)  # EfficientNetB4 input size\nEPOCHS = 30","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:53:05.417126Z","iopub.execute_input":"2025-11-21T13:53:05.417982Z","iopub.status.idle":"2025-11-21T13:53:05.422116Z","shell.execute_reply.started":"2025-11-21T13:53:05.417953Z","shell.execute_reply":"2025-11-21T13:53:05.421197Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load the data\ntrain_df = pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv')\ntrain_df['label'] = train_df['label'].astype(str)\ntrain_df['image_path'] = '/kaggle/input/cassava-leaf-disease-classification/train_images/' + train_df['image_id']\n\n# Split into train and validation (80/20)\ntrain_df, val_df = train_test_split(train_df, test_size=0.2, stratify=train_df['label'], random_state=42)\n\nprint(f'Training samples: {len(train_df)}, Validation samples: {len(val_df)}')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:53:14.162483Z","iopub.execute_input":"2025-11-21T13:53:14.163168Z","iopub.status.idle":"2025-11-21T13:53:14.231505Z","shell.execute_reply.started":"2025-11-21T13:53:14.163142Z","shell.execute_reply":"2025-11-21T13:53:14.230885Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Class distribution\nplt.figure(figsize=(10, 6))\nsns.countplot(x='label', data=pd.read_csv('/kaggle/input/cassava-leaf-disease-classification/train.csv'))\nplt.title('Class Distribution')\nplt.xlabel('Class')\nplt.ylabel('Count')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:53:17.021989Z","iopub.execute_input":"2025-11-21T13:53:17.022683Z","iopub.status.idle":"2025-11-21T13:53:17.23717Z","shell.execute_reply.started":"2025-11-21T13:53:17.022655Z","shell.execute_reply":"2025-11-21T13:53:17.236423Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Display sample images for each class\nfig, axes = plt.subplots(1, 5, figsize=(20, 4))\nclass_names = ['CBB (0)', 'CBSD (1)', 'CGM (2)', 'CMD (3)', 'Healthy (4)']\n\nfor i, ax in enumerate(axes):\n    sample = train_df[train_df['label'] == str(i)].sample(1).iloc[0]\n    img = load_img(sample['image_path'])\n    ax.imshow(img)\n    ax.set_title(class_names[i])\n    ax.axis('off')\n\nplt.suptitle('Sample Images per Class')\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:53:20.754081Z","iopub.execute_input":"2025-11-21T13:53:20.754678Z","iopub.status.idle":"2025-11-21T13:53:21.603089Z","shell.execute_reply.started":"2025-11-21T13:53:20.754651Z","shell.execute_reply":"2025-11-21T13:53:21.602094Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Data generators with augmentations\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    width_shift_range=0.2,\n    height_shift_range=0.2,\n    shear_range=0.2,\n    zoom_range=0.2,\n    horizontal_flip=True,\n    vertical_flip=True,\n    fill_mode='nearest',\n    validation_split=0.0\n)\n\nval_datagen = ImageDataGenerator(rescale=1./255)\n\ntrain_generator = train_datagen.flow_from_dataframe(\n    train_df,\n    x_col='image_path',\n    y_col='label',\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    shuffle=True\n)\n\nval_generator = val_datagen.flow_from_dataframe(\n    val_df,\n    x_col='image_path',\n    y_col='label',\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode='categorical',\n    shuffle=False\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:53:25.285946Z","iopub.execute_input":"2025-11-21T13:53:25.286599Z","iopub.status.idle":"2025-11-21T13:54:08.018781Z","shell.execute_reply.started":"2025-11-21T13:53:25.286573Z","shell.execute_reply":"2025-11-21T13:54:08.018168Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Build the model with fine tuning\ndef build_model():\n    base_model = EfficientNetB0(weights=\n                                \"/kaggle/input/efficientnetb0-notop/tensorflow2/default/1/efficientnetb0_notop.h5\",\n                                include_top=False\n                               )\n    #base_model.trainable = False\n\n    model = Sequential([\n        tf.keras.layers.Input(shape=(*IMG_SIZE, 3)),\n        base_model,\n        GlobalAveragePooling2D(),\n        Dense(5, activation='softmax')\n    ])\n\n    model.compile(\n        optimizer=Adam(learning_rate=1e-3),\n        loss='categorical_crossentropy',\n        metrics=['accuracy']\n    )\n    return model\n\nmodel = build_model()\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:56:44.94361Z","iopub.execute_input":"2025-11-21T13:56:44.944136Z","iopub.status.idle":"2025-11-21T13:56:46.233795Z","shell.execute_reply.started":"2025-11-21T13:56:44.944107Z","shell.execute_reply":"2025-11-21T13:56:46.233008Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Callbacks\nearly_stopping = EarlyStopping(monitor='val_loss', patience=5, restore_best_weights=True,\n                               mode='min', min_delta=0.001)\ncheckpoint = ModelCheckpoint('best_model.keras', monitor='val_accuracy',\n                             save_best_only=True, mode='max')\nreduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.3, patience=2, min_delta=0.001, \n                              mode='min', verbose=1)\n\n\n# Train the model\nhistory = model.fit(\n    train_generator,\n    epochs=EPOCHS,\n    validation_data=val_generator,\n    callbacks=[early_stopping, checkpoint, reduce_lr]\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-21T13:56:50.786Z","iopub.execute_input":"2025-11-21T13:56:50.786597Z","iopub.status.idle":"2025-11-21T14:28:14.17287Z","shell.execute_reply.started":"2025-11-21T13:56:50.786571Z","shell.execute_reply":"2025-11-21T14:28:14.171966Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Load best model\nmodel.load_weights('best_model.keras')\n\n# Test data generator\ntest_datagen = ImageDataGenerator(rescale=1./255)\ntest_dir = '/kaggle/input/cassava-leaf-disease-classification/test_images/'\ntest_df = pd.DataFrame({'image_path': [os.path.join(test_dir, f) for f in os.listdir(test_dir)]})\ntest_df['image_id'] = test_df['image_path'].apply(lambda x: os.path.basename(x))\n\ntest_generator = test_datagen.flow_from_dataframe(\n    test_df,\n    x_col='image_path',\n    y_col=None,\n    target_size=IMG_SIZE,\n    batch_size=BATCH_SIZE,\n    class_mode=None,\n    shuffle=False\n)\n\n# Predict\npredictions = model.predict(test_generator)\npredicted_labels = np.argmax(predictions, axis=1)\n\n# Submission\nsubmission = pd.DataFrame({'image_id': test_df['image_id'], 'label': predicted_labels})\nsubmission.to_csv('submission.csv', index=False)\nprint('Submission file created!')","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}