{"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":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31234,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# ===============================\n# Imports\n# ===============================\nimport os\nimport numpy as np\nimport pandas as pd\n\nfrom sklearn.model_selection import KFold\nfrom tensorflow.keras.preprocessing.image import ImageDataGenerator\nfrom tensorflow.keras.models import Sequential\nfrom tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense\nfrom tensorflow.keras.callbacks import EarlyStopping\n\n# ===============================\n# Paths & Parameters\n# ===============================\nBASE_DIR = \"/kaggle/input/csiro-biomass\"\n\nimg_size = (128, 128)\nbatch_size = 16\nepochs = 10\nn_splits = 5\n\ntargets = [\n    \"Dry_Green_g\",\n    \"Dry_Dead_g\",\n    \"Dry_Clover_g\",\n    \"GDM_g\",\n    \"Dry_Total_g\"\n]\n\n# ===============================\n# Load CSVs\n# ===============================\ndf_train_long = pd.read_csv(f\"{BASE_DIR}/train.csv\")\ndf_test_long  = pd.read_csv(f\"{BASE_DIR}/test.csv\")\n\n# ===============================\n# Pivot TRAIN: long ➜ wide\n# ===============================\ndf_train = (\n    df_train_long\n    .pivot(index=\"image_path\", columns=\"target_name\", values=\"target\")\n    .reset_index()\n)\n\n# ===============================\n# Test images (unique only)\n# ===============================\ndf_test = df_test_long[[\"image_path\"]].drop_duplicates().reset_index(drop=True)\n\n# ===============================\n# Image Generators\n# ===============================\ntrain_datagen = ImageDataGenerator(\n    rescale=1./255,\n    horizontal_flip=True,\n    vertical_flip=True\n)\n\nval_datagen = ImageDataGenerator(rescale=1./255)\ntest_datagen = ImageDataGenerator(rescale=1./255)\n\n# ===============================\n# K-Fold CV\n# ===============================\nkf = KFold(n_splits=n_splits, shuffle=True, random_state=42)\ntest_preds = np.zeros((len(df_test), len(targets)))\n\nfor fold, (train_idx, val_idx) in enumerate(kf.split(df_train)):\n    print(f\"\\n🚀 Fold {fold+1}/{n_splits}\")\n\n    train_df = df_train.iloc[train_idx]\n    val_df   = df_train.iloc[val_idx]\n\n    train_generator = train_datagen.flow_from_dataframe(\n        dataframe=train_df,\n        directory=BASE_DIR,        # 🔥 CRITICAL FIX\n        x_col=\"image_path\",\n        y_col=targets,\n        target_size=img_size,\n        batch_size=batch_size,\n        class_mode=\"raw\"\n    )\n\n    val_generator = val_datagen.flow_from_dataframe(\n        dataframe=val_df,\n        directory=BASE_DIR,        # 🔥 CRITICAL FIX\n        x_col=\"image_path\",\n        y_col=targets,\n        target_size=img_size,\n        batch_size=batch_size,\n        class_mode=\"raw\"\n    )\n\n    test_generator = test_datagen.flow_from_dataframe(\n        dataframe=df_test,\n        directory=BASE_DIR,        # 🔥 CRITICAL FIX\n        x_col=\"image_path\",\n        y_col=None,\n        target_size=img_size,\n        batch_size=1,\n        class_mode=None,\n        shuffle=False\n    )\n\n    # ===============================\n    # CNN Model\n    # ===============================\n    model = Sequential([\n        Conv2D(32, (3,3), activation=\"relu\", input_shape=(*img_size, 3)),\n        MaxPooling2D(2,2),\n        Conv2D(64, (3,3), activation=\"relu\"),\n        MaxPooling2D(2,2),\n        Flatten(),\n        Dense(128, activation=\"relu\"),\n        Dense(len(targets), activation=\"linear\")\n    ])\n\n    model.compile(optimizer=\"adam\", loss=\"mse\", metrics=[\"mae\"])\n\n    model.fit(\n        train_generator,\n        validation_data=val_generator,\n        epochs=epochs,\n        callbacks=[EarlyStopping(patience=3, restore_best_weights=True)],\n        verbose=1\n    )\n\n    test_preds += model.predict(test_generator) / n_splits\n\n# ===============================\n# Submission file\n# ===============================\nsubmission = []\n\nfor i, row in df_test.iterrows():\n    image_id = os.path.basename(row[\"image_path\"]).replace(\".jpg\", \"\")\n    for j, t in enumerate(targets):\n        submission.append({\n            \"sample_id\": f\"{image_id}__{t}\",\n            \"target\": float(test_preds[i][j])\n        })\n\npd.DataFrame(submission).to_csv(\"submission.csv\", index=False)\nprint(\"✅ submission.csv generated\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-12-27T11:16:35.118929Z","iopub.execute_input":"2025-12-27T11:16:35.119746Z","iopub.status.idle":"2025-12-27T11:33:10.807191Z","shell.execute_reply.started":"2025-12-27T11:16:35.119711Z","shell.execute_reply":"2025-12-27T11:33:10.805908Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}