{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.12.12","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":126119,"databundleVersionId":14953781,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import os\nimport random\nfrom pathlib import Path\nimport pandas as pd\nimport numpy as np\nfrom PIL import Image\n\nimport matplotlib.pyplot as plt\n\nimport torch\n\nplt.rcParams[\"figure.figsize\"] = (6, 6)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:15:25.586315Z","iopub.execute_input":"2026-02-07T08:15:25.587586Z","iopub.status.idle":"2026-02-07T08:15:32.967772Z","shell.execute_reply.started":"2026-02-07T08:15:25.587530Z","shell.execute_reply":"2026-02-07T08:15:32.966518Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"DATA_ROOT = Path(\"/kaggle/input/beyond-visible-spectrum-ai-for-agriculture-2026\")\nDATASET_DIR = DATA_ROOT / \"Kaggle_Prepared\"\n\nTRAIN_DIR = DATASET_DIR / \"train\"\nVAL_DIR   = DATASET_DIR / \"val\"\n\nRGB_DIR = \"RGB\"\nMS_DIR  = \"MS\"\nHS_DIR  = \"HS\"","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:15:38.511526Z","iopub.execute_input":"2026-02-07T08:15:38.512784Z","iopub.status.idle":"2026-02-07T08:15:38.518817Z","shell.execute_reply.started":"2026-02-07T08:15:38.512733Z","shell.execute_reply":"2026-02-07T08:15:38.517508Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# reproducibility package\nSEED = 42\nrandom.seed(SEED)\nnp.random.seed(SEED)\ntorch.manual_seed(SEED)\ntorch.cuda.manual_seed(SEED)\ntorch.cuda.manual_seed_all(SEED)\n\ntorch.backends.cudnn.deterministic = True\ntorch.backends.cudnn.benchmark = False","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:15:40.331634Z","iopub.execute_input":"2026-02-07T08:15:40.331963Z","iopub.status.idle":"2026-02-07T08:15:40.345955Z","shell.execute_reply.started":"2026-02-07T08:15:40.331938Z","shell.execute_reply":"2026-02-07T08:15:40.344450Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# DataFrame ","metadata":{}},{"cell_type":"markdown","source":"## for train","metadata":{}},{"cell_type":"code","source":"def build_train_df(train_dir: Path) -> pd.DataFrame:\n    \"\"\"function for constructing a DataFrame based on train data\"\"\"\n    rows = []\n\n    rgb_path = train_dir / RGB_DIR\n\n    # Iterating through all files in the RGB folder\n    # os.listdir(rgb_path) returns file names, not paths\n    for fname in sorted(os.listdir(rgb_path)):\n        if not fname.endswith(\".png\"):\n            continue\n\n        sample_id = fname.replace(\".png\", \"\")\n        category = sample_id.split(\"_\")[0]  # Health / Rust / Other\n\n        rows.append({\n            \"Id\": sample_id,\n            \"Category\": category,\n            \"rgb_path\": train_dir / RGB_DIR / f\"{sample_id}.png\",\n            \"ms_path\":  train_dir / MS_DIR  / f\"{sample_id}.tif\",\n            \"hs_path\":  train_dir / HS_DIR  / f\"{sample_id}.tif\",\n        })\n\n    return pd.DataFrame(rows)\n\ntrain_df = build_train_df(TRAIN_DIR)\ntrain_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:18:15.512374Z","iopub.execute_input":"2026-02-07T08:18:15.512863Z","iopub.status.idle":"2026-02-07T08:18:15.542360Z","shell.execute_reply.started":"2026-02-07T08:18:15.512821Z","shell.execute_reply":"2026-02-07T08:18:15.540820Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train samples:\", len(train_df))\ntrain_df[\"Category\"].value_counts()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:15:44.969333Z","iopub.execute_input":"2026-02-07T08:15:44.969913Z","iopub.status.idle":"2026-02-07T08:15:44.991660Z","shell.execute_reply.started":"2026-02-07T08:15:44.969878Z","shell.execute_reply":"2026-02-07T08:15:44.990353Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def check_files_exist(df: pd.DataFrame):\n    for col in [\"rgb_path\", \"ms_path\", \"hs_path\"]:\n        missing = ~df[col].apply(lambda x: Path(x).exists())\n        print(f\"{col}: missing files =\", missing.sum())\n\ncheck_files_exist(train_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:15:46.697628Z","iopub.execute_input":"2026-02-07T08:15:46.699106Z","iopub.status.idle":"2026-02-07T08:15:51.753772Z","shell.execute_reply.started":"2026-02-07T08:15:46.699053Z","shell.execute_reply":"2026-02-07T08:15:51.752684Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## for validation","metadata":{}},{"cell_type":"code","source":"def build_val_df(val_dir: Path) -> pd.DataFrame:\n    \"\"\"function for constructing a DataFrame based on validation data\"\"\"\n    rows = []\n\n    rgb_path = val_dir / RGB_DIR\n\n    # Iterating through all files in the RGB folder\n    # os.listdir(rgb_path) returns file names, not paths\n    for fname in sorted(os.listdir(rgb_path)):\n        if not fname.endswith(\".png\"):\n            continue\n\n        sample_id = fname.replace(\".png\", \"\")\n\n        rows.append({\n            \"Id\": sample_id,\n            \"Category\": np.nan,    # target\n            \"rgb_path\": val_dir / RGB_DIR / f\"{sample_id}.png\",\n            \"ms_path\":  val_dir / MS_DIR  / f\"{sample_id}.tif\",\n            \"hs_path\":  val_dir / HS_DIR  / f\"{sample_id}.tif\",\n        })\n\n    return pd.DataFrame(rows)\n\nval_df = build_val_df(VAL_DIR)\nval_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:16:12.696352Z","iopub.execute_input":"2026-02-07T08:16:12.696795Z","iopub.status.idle":"2026-02-07T08:16:12.722755Z","shell.execute_reply.started":"2026-02-07T08:16:12.696766Z","shell.execute_reply":"2026-02-07T08:16:12.721284Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"check_files_exist(val_df)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:55:48.164362Z","iopub.execute_input":"2026-02-06T08:55:48.164846Z","iopub.status.idle":"2026-02-06T08:55:52.750881Z","shell.execute_reply.started":"2026-02-06T08:55:48.164806Z","shell.execute_reply":"2026-02-06T08:55:52.749676Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Visualization","metadata":{}},{"cell_type":"code","source":"sample = train_df.sample(1).iloc[0]\nsample","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:55:52.753907Z","iopub.execute_input":"2026-02-06T08:55:52.754804Z","iopub.status.idle":"2026-02-06T08:55:52.770940Z","shell.execute_reply.started":"2026-02-06T08:55:52.754764Z","shell.execute_reply":"2026-02-06T08:55:52.769555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_rgb = Image.open(sample[\"rgb_path\"])\nprint(\"RGB size:\", img_rgb.size)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:55:52.772347Z","iopub.execute_input":"2026-02-06T08:55:52.772699Z","iopub.status.idle":"2026-02-06T08:55:52.884084Z","shell.execute_reply.started":"2026-02-06T08:55:52.772668Z","shell.execute_reply":"2026-02-06T08:55:52.882870Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"plt.imshow(img_rgb)\nplt.title(f\"RGB | {sample['Category']}\")\nplt.axis(\"off\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:55:52.885418Z","iopub.execute_input":"2026-02-06T08:55:52.885882Z","iopub.status.idle":"2026-02-06T08:55:53.039299Z","shell.execute_reply.started":"2026-02-06T08:55:52.885850Z","shell.execute_reply":"2026-02-06T08:55:53.037286Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"try:\n    import rasterio\nexcept ModuleNotFoundError:\n    !pip install rasterio\n    import rasterio","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:55:53.040993Z","iopub.execute_input":"2026-02-06T08:55:53.041308Z","iopub.status.idle":"2026-02-06T08:56:03.348997Z","shell.execute_reply.started":"2026-02-06T08:55:53.041281Z","shell.execute_reply":"2026-02-06T08:56:03.347044Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import warnings\nfrom rasterio.errors import NotGeoreferencedWarning\n\nwarnings.filterwarnings(\n    \"ignore\",\n    category=NotGeoreferencedWarning\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.352430Z","iopub.execute_input":"2026-02-06T08:56:03.354099Z","iopub.status.idle":"2026-02-06T08:56:03.361118Z","shell.execute_reply.started":"2026-02-06T08:56:03.354036Z","shell.execute_reply":"2026-02-06T08:56:03.359626Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with rasterio.open(sample[\"ms_path\"]) as src:\n    ms = src.read()\n    print(\"MS shape:\", ms.shape)  # (C, H, W)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.363030Z","iopub.execute_input":"2026-02-06T08:56:03.363492Z","iopub.status.idle":"2026-02-06T08:56:03.420137Z","shell.execute_reply.started":"2026-02-06T08:56:03.363448Z","shell.execute_reply":"2026-02-06T08:56:03.418747Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# MS: B, G, R = 0,1,2\nms_rgb = np.stack([\n    ms[2],  # R\n    ms[1],  # G\n    ms[0],  # B\n], axis=-1)\n\nms_rgb = (ms_rgb - ms_rgb.min()) / (ms_rgb.max() - ms_rgb.min())\n\nplt.imshow(ms_rgb)\nplt.title(\"MS pseudo-RGB\")\nplt.axis(\"off\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.421545Z","iopub.execute_input":"2026-02-06T08:56:03.422012Z","iopub.status.idle":"2026-02-06T08:56:03.566664Z","shell.execute_reply.started":"2026-02-06T08:56:03.421978Z","shell.execute_reply":"2026-02-06T08:56:03.565705Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"with rasterio.open(sample[\"hs_path\"]) as src:\n    hs = src.read()\n    print(\"HS shape:\", hs.shape)  # (C, H, W)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.567938Z","iopub.execute_input":"2026-02-06T08:56:03.568606Z","iopub.status.idle":"2026-02-06T08:56:03.620678Z","shell.execute_reply.started":"2026-02-06T08:56:03.568562Z","shell.execute_reply":"2026-02-06T08:56:03.619601Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"hs_mean = hs.mean(axis=0)\n\nplt.imshow(hs_mean, cmap=\"gray\")\nplt.title(\"HS mean over spectrum\")\nplt.axis(\"off\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.622089Z","iopub.execute_input":"2026-02-06T08:56:03.622683Z","iopub.status.idle":"2026-02-06T08:56:03.768477Z","shell.execute_reply.started":"2026-02-06T08:56:03.622638Z","shell.execute_reply":"2026-02-06T08:56:03.767534Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"def find_constant_triplets(\n    df: pd.DataFrame,\n    eps: float = 1e-6,\n    show: int = 30,\n    check_cols=(\"rgb_path\", \"ms_path\", \"hs_path\"),\n) -> pd.DataFrame:\n    \"\"\"\n    One-pass check for constant (all-zero / constant) images across multiple modalities.\n    Returns a single DataFrame with stats per modality and flags.\n    Also prints intersection sizes incl. All three.\n    \"\"\"\n\n    def _read_stats(path) -> tuple[float, float, float]:\n        with rasterio.open(path) as src:\n            x = src.read().astype(np.float32)\n        return float(x.min()), float(x.max()), float(np.std(x))\n\n    rows = []\n    for idx, row in df.iterrows():\n        rec = {\"index\": idx, \"Id\": row[\"Id\"], \"Category\": row.get(\"Category\", np.nan)}\n\n        # compute stats per modality\n        flags = []\n        for col in check_cols:\n            mn, mx, sd = _read_stats(row[col])\n            rec[f\"{col}_min\"] = mn\n            rec[f\"{col}_max\"] = mx\n            rec[f\"{col}_std\"] = sd\n            is_const = (sd < eps)\n            rec[f\"{col}_const\"] = bool(is_const)\n            flags.append(is_const)\n\n        # aggregate flags\n        rec[\"any_const\"] = bool(np.any(flags))\n        rec[\"all_three_const\"] = bool(np.all(flags))\n\n        if rec[\"any_const\"]:\n            rows.append(rec)\n\n    out = pd.DataFrame(rows)\n\n    # summary sets\n    def _ids_where(col_flag: str) -> set:\n        if out.empty:\n            return set()\n        return set(out.loc[out[col_flag], \"Id\"].tolist())\n\n    rgb_ids = _ids_where(\"rgb_path_const\")\n    ms_ids  = _ids_where(\"ms_path_const\")\n    hs_ids  = _ids_where(\"hs_path_const\")\n\n    print(\"RGB ∩ MS:\", len(rgb_ids & ms_ids))\n    print(\"RGB ∩ HS:\", len(rgb_ids & hs_ids))\n    print(\"MS  ∩ HS:\", len(ms_ids & hs_ids))\n    print(\"All three:\", len(rgb_ids & ms_ids & hs_ids))\n\n    # show only all-three (since that's what you care about)\n    if not out.empty:\n        all_three_df = out[out[\"all_three_const\"]].copy()\n\n        print(\"\\nAll-three constant samples:\", len(all_three_df))\n        if len(all_three_df) > 0:\n            # compact view\n            cols_view = [\"index\", \"Id\", \"Category\",\n                         \"rgb_path_min\",\"rgb_path_max\",\"rgb_path_std\",\n                         \"ms_path_min\",\"ms_path_max\",\"ms_path_std\",\n                         \"hs_path_min\",\"hs_path_max\",\"hs_path_std\"]\n            display(all_three_df[cols_view].head(show))\n\n            print(\"\\nCategory counts (all three):\")\n            display(all_three_df[\"Category\"].value_counts(dropna=False))\n\n        return all_three_df\n\n    return out  # empty","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:03.769730Z","iopub.execute_input":"2026-02-06T08:56:03.770107Z","iopub.status.idle":"2026-02-06T08:56:03.790017Z","shell.execute_reply.started":"2026-02-06T08:56:03.770061Z","shell.execute_reply":"2026-02-06T08:56:03.788653Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bad_df = find_constant_triplets(train_df, eps=1e-6, show=50)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:06.014214Z","iopub.execute_input":"2026-02-06T08:56:06.015394Z","iopub.status.idle":"2026-02-06T08:56:46.019450Z","shell.execute_reply.started":"2026-02-06T08:56:06.015316Z","shell.execute_reply":"2026-02-06T08:56:46.018154Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"bad_val_df = find_constant_triplets(val_df, eps=1e-6, show=50)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:56:46.021866Z","iopub.execute_input":"2026-02-06T08:56:46.022317Z","iopub.status.idle":"2026-02-06T08:57:06.849004Z","shell.execute_reply.started":"2026-02-06T08:56:46.022269Z","shell.execute_reply":"2026-02-06T08:57:06.848055Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from collections import defaultdict\n\ndef check_channels(df, col_path):\n    has_category = \"Category\" in df.columns and df[\"Category\"].notna().any()\n\n    if has_category:\n        stats = defaultdict(set)\n\n        for _, row in df.iterrows():\n            with rasterio.open(row[col_path]) as src:\n                c = src.count\n            stats[row[\"Category\"]].add(c)\n\n        for cat, chans in stats.items():\n            print(f\"{col_path} | {cat}: channels = {chans}\")\n\n    else:\n        chans = set()\n        for _, row in df.iterrows():\n            with rasterio.open(row[col_path]) as src:\n                chans.add(src.count)\n\n        print(f\"{col_path} | ALL: channels = {chans}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:37:21.332086Z","iopub.execute_input":"2026-02-06T08:37:21.332541Z","iopub.status.idle":"2026-02-06T08:37:21.340860Z","shell.execute_reply.started":"2026-02-06T08:37:21.332513Z","shell.execute_reply":"2026-02-06T08:37:21.339540Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"check_channels(train_df, \"rgb_path\")\ncheck_channels(train_df, \"ms_path\")\ncheck_channels(train_df, \"hs_path\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:37:24.289411Z","iopub.execute_input":"2026-02-06T08:37:24.289713Z","iopub.status.idle":"2026-02-06T08:37:28.591196Z","shell.execute_reply.started":"2026-02-06T08:37:24.289688Z","shell.execute_reply":"2026-02-06T08:37:28.589912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"check_channels(val_df, \"rgb_path\")\ncheck_channels(val_df, \"ms_path\")\ncheck_channels(val_df, \"hs_path\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-06T08:37:31.237865Z","iopub.execute_input":"2026-02-06T08:37:31.238402Z","iopub.status.idle":"2026-02-06T08:37:33.305954Z","shell.execute_reply.started":"2026-02-06T08:37:31.238373Z","shell.execute_reply":"2026-02-06T08:37:33.304637Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Dataset Summary & Key Findings**\n\nDataset Overview\n- Training set: **600 samples**\n- Classes: **3** (`Health`, `Rust`, `Other`)\n- Class distribution: **balanced** (200 samples per class)\n- Validation set: provided **without labels**\n- Missing files: **none** (all modalities are available for all samples)\n\n---\n\n**Data Modalities & Spatial Resolution**\n- **RGB**: `(3, 64, 64)`\n- **Multispectral (MS)**: `(5, 64, 64)`\n- **Hyperspectral (HS)**: `(125 or 126, 32, 32)`\n\nRGB and MS share the same spatial resolution, while HS has a **lower spatial resolution** and a variable number of channels.\n\n---\n\n**Constant (All-Zero) Samples**\n- Training set: **23 samples**\n  - Categories: `Other` (14), `Health` (9), `Rust` (0)\n- Validation set: **11 samples**\n- For these samples:\n  - **All three modalities are fully constant**\n  - Pixel values are exactly `0.0`\n- This is a known dataset artifact and must be handled explicitly during training and inference.\n\n---\n\n**Channel Consistency**\n- RGB: always **3 channels**\n- MS: always **5 channels**\n- HS: **125 or 126 channels** across all classes (not class-dependent)\n\nTherefore, HS requires **explicit channel unification** (e.g. cropping to a fixed number of spectral bands) before modeling.\n\n---\n\n**Practical Implications**\n- The dataset is **clean, balanced, and small** → no class weighting is required.\n- RGB provides a limited disease signal at this spatial resolution.\n- HS contains rich spectral information but:\n  - has lower spatial resolution,\n  - high dimensionality,\n  - a variable channel count,\n  - and requires additional preprocessing.\n\n---\n\n**Baseline Strategy**\n\n**Multispectral (MS)** is the most suitable modality to start with:\n- includes **Red Edge and NIR** bands strongly linked to plant health,\n- preserves full spatial resolution (64×64),\n- has a fixed and compact channel count,\n- offers the best signal-to-complexity trade-off for an initial baseline.## Dataset Summary & Key Findings\n\n**Dataset Overview**\n- Training set: **600 samples**\n- Classes: **3** (`Health`, `Rust`, `Other`)\n- Class distribution: **balanced** (200 samples per class)\n- Validation set: provided **without labels**\n- Missing files: **none** (all modalities are available for all samples)\n\n---\n\n**Data Modalities & Spatial Resolution**\n- **RGB**: `(3, 64, 64)`\n- **Multispectral (MS)**: `(5, 64, 64)`\n- **Hyperspectral (HS)**: `(125 or 126, 32, 32)`\n\nRGB and MS share the same spatial resolution, while HS has a **lower spatial resolution** and a variable number of channels.\n\n---\n\n**Constant (All-Zero) Samples**\n- Training set: **23 samples**\n  - Categories: `Other` (14), `Health` (9), `Rust` (0)\n- Validation set: **11 samples**\n- For these samples:\n  - **All three modalities are fully constant**\n  - Pixel values are exactly `0.0`\n- This is a known dataset artifact and must be handled explicitly during training and inference.\n\n---\n\n**Channel Consistency**\n- RGB: always **3 channels**\n- MS: always **5 channels**\n- HS: **125 or 126 channels** across all classes (not class-dependent)\n\nTherefore, HS requires **explicit channel unification** (e.g. cropping to a fixed number of spectral bands) before modeling.\n\n---\n\n**Practical Implications**\n- The dataset is **clean, balanced, and small** → no class weighting is required.\n- RGB provides a limited disease signal at this spatial resolution.\n- HS contains rich spectral information but:\n  - has lower spatial resolution,\n  - high dimensionality,\n  - a variable channel count,\n  - and requires additional preprocessing.\n\n---\n\n**Baseline Strategy**\n\n**Multispectral (MS)** is the most suitable modality to start with:\n- includes **Red Edge and NIR** bands strongly linked to plant health,\n- preserves full spatial resolution (64×64),\n- has a fixed and compact channel count,\n- offers the best signal-to-complexity trade-off for an initial baseline.","metadata":{}},{"cell_type":"code","source":"train_df.to_csv('train_df.csv', index=False)\nval_df.to_csv('val_df.csv', index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-02-07T08:18:35.596565Z","iopub.execute_input":"2026-02-07T08:18:35.598218Z","iopub.status.idle":"2026-02-07T08:18:35.655864Z","shell.execute_reply.started":"2026-02-07T08:18:35.598171Z","shell.execute_reply":"2026-02-07T08:18:35.654718Z"}},"outputs":[],"execution_count":null}]}