{"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":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31259,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# CSIRO – Image2Biomass Prediction\n\n## Objective\nPredict pasture biomass components from images and NDVI data\nto support better grazing and pasture management decisions.\n\n## Targets\n- Dry_Green_g\n- Dry_Dead_g\n- Dry_Clover_g\n- GDM_g\n- Dry_Total_g\n\n## Evaluation\nGlobally weighted R² score across all image–target pairs.","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os\n\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import r2_score","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.320206Z","iopub.execute_input":"2026-01-29T05:15:58.320873Z","iopub.status.idle":"2026-01-29T05:15:58.325344Z","shell.execute_reply.started":"2026-01-29T05:15:58.320838Z","shell.execute_reply":"2026-01-29T05:15:58.324430Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# List all datasets available\nos.listdir(\"/kaggle/input\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.327035Z","iopub.execute_input":"2026-01-29T05:15:58.327375Z","iopub.status.idle":"2026-01-29T05:15:58.348358Z","shell.execute_reply.started":"2026-01-29T05:15:58.327348Z","shell.execute_reply":"2026-01-29T05:15:58.347401Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import os\n\nDATA_PATH = \"/kaggle/input/csiro-biomass\"\n\nos.listdir(DATA_PATH)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.349439Z","iopub.execute_input":"2026-01-29T05:15:58.349794Z","iopub.status.idle":"2026-01-29T05:15:58.365362Z","shell.execute_reply.started":"2026-01-29T05:15:58.349757Z","shell.execute_reply":"2026-01-29T05:15:58.363510Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\n\ntrain_df = pd.read_csv(f\"{DATA_PATH}/train.csv\")\ntest_df  = pd.read_csv(f\"{DATA_PATH}/test.csv\")\n\nprint(\"Train shape:\", train_df.shape)\nprint(\"Test shape :\", test_df.shape)\n\ntrain_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.367625Z","iopub.execute_input":"2026-01-29T05:15:58.368515Z","iopub.status.idle":"2026-01-29T05:15:58.441969Z","shell.execute_reply.started":"2026-01-29T05:15:58.368484Z","shell.execute_reply":"2026-01-29T05:15:58.441240Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"TARGET_WEIGHTS = {\n    \"Dry_Green_g\": 0.1,\n    \"Dry_Dead_g\": 0.1,\n    \"Dry_Clover_g\": 0.1,\n    \"GDM_g\": 0.2,\n    \"Dry_Total_g\": 0.5\n}\n\ntrain_df[\"weight\"] = train_df[\"target_name\"].map(TARGET_WEIGHTS)\ntrain_df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.443161Z","iopub.execute_input":"2026-01-29T05:15:58.443566Z","iopub.status.idle":"2026-01-29T05:15:58.468705Z","shell.execute_reply.started":"2026-01-29T05:15:58.443527Z","shell.execute_reply":"2026-01-29T05:15:58.467837Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import LabelEncoder\n\ncat_cols = [\"State\", \"Species\", \"target_name\"]\n\nencoders = {}\n\nfor col in cat_cols:\n    le = LabelEncoder()\n    train_df[col] = le.fit_transform(train_df[col])\n    encoders[col] = le\n\ntrain_df[cat_cols].head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.469810Z","iopub.execute_input":"2026-01-29T05:15:58.470611Z","iopub.status.idle":"2026-01-29T05:15:58.492824Z","shell.execute_reply.started":"2026-01-29T05:15:58.470567Z","shell.execute_reply":"2026-01-29T05:15:58.491901Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"FEATURES = [\n    \"Pre_GSHH_NDVI\",\n    \"Height_Ave_cm\",\n    \"State\",\n    \"Species\",\n    \"target_name\"\n]\n\nFEATURES","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.494040Z","iopub.execute_input":"2026-01-29T05:15:58.494328Z","iopub.status.idle":"2026-01-29T05:15:58.508159Z","shell.execute_reply.started":"2026-01-29T05:15:58.494302Z","shell.execute_reply":"2026-01-29T05:15:58.507300Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X = train_df[FEATURES]\ny = train_df[\"target\"]\nweights = train_df[\"weight\"]\n\nprint(\"X shape:\", X.shape)\nprint(\"y shape:\", y.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.509153Z","iopub.execute_input":"2026-01-29T05:15:58.509416Z","iopub.status.idle":"2026-01-29T05:15:58.524742Z","shell.execute_reply.started":"2026-01-29T05:15:58.509384Z","shell.execute_reply":"2026-01-29T05:15:58.523773Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\nX_train, X_val, y_train, y_val, w_train, w_val = train_test_split(\n    X,\n    y,\n    weights,\n    test_size=0.20,\n    random_state=42\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.527176Z","iopub.execute_input":"2026-01-29T05:15:58.527471Z","iopub.status.idle":"2026-01-29T05:15:58.543272Z","shell.execute_reply.started":"2026-01-29T05:15:58.527445Z","shell.execute_reply":"2026-01-29T05:15:58.542466Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(\"Train size:\", X_train.shape)\nprint(\"Validation size:\", X_val.shape)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.544598Z","iopub.execute_input":"2026-01-29T05:15:58.545053Z","iopub.status.idle":"2026-01-29T05:15:58.550392Z","shell.execute_reply.started":"2026-01-29T05:15:58.545015Z","shell.execute_reply":"2026-01-29T05:15:58.549653Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestRegressor\n\n# RandomForest Regression model\nmodel = RandomForestRegressor(\n    n_estimators=300,   # number of trees\n    random_state=42,    # reproducibility\n    n_jobs=-1           # use all cores\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:58.551394Z","iopub.execute_input":"2026-01-29T05:15:58.551723Z","iopub.status.idle":"2026-01-29T05:15:59.051771Z","shell.execute_reply.started":"2026-01-29T05:15:58.551688Z","shell.execute_reply":"2026-01-29T05:15:59.051049Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Train model on training data\nmodel.fit(X_train, y_train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:59.052913Z","iopub.execute_input":"2026-01-29T05:15:59.053404Z","iopub.status.idle":"2026-01-29T05:15:59.796542Z","shell.execute_reply.started":"2026-01-29T05:15:59.053374Z","shell.execute_reply":"2026-01-29T05:15:59.795790Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"y_pred_sample = model.predict(X_val[:5])\nprint(\"Sample predictions:\", y_pred_sample)\nprint(\"Sample actuals    :\", y_val[:5].values)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:59.797529Z","iopub.execute_input":"2026-01-29T05:15:59.797829Z","iopub.status.idle":"2026-01-29T05:15:59.886839Z","shell.execute_reply.started":"2026-01-29T05:15:59.797796Z","shell.execute_reply":"2026-01-29T05:15:59.886051Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Predict on validation set\ny_val_pred = model.predict(X_val)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:59.887829Z","iopub.execute_input":"2026-01-29T05:15:59.888151Z","iopub.status.idle":"2026-01-29T05:15:59.992520Z","shell.execute_reply.started":"2026-01-29T05:15:59.888117Z","shell.execute_reply":"2026-01-29T05:15:59.991759Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import numpy as np\n\n# Weighted mean of ground truth\ny_bar = np.average(y_val, weights=w_val)\n\n# Residual Sum of Squares (RSS)\nrss = np.sum(w_val * (y_val - y_val_pred) ** 2)\n\n# Total Sum of Squares (TSS)\ntss = np.sum(w_val * (y_val - y_bar) ** 2)\n\n# Weighted R²\nweighted_r2 = 1 - (rss / tss)\n\nweighted_r2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:15:59.993595Z","iopub.execute_input":"2026-01-29T05:15:59.994101Z","iopub.status.idle":"2026-01-29T05:16:00.003095Z","shell.execute_reply.started":"2026-01-29T05:15:59.994062Z","shell.execute_reply":"2026-01-29T05:16:00.002271Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_df.columns","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.004036Z","iopub.execute_input":"2026-01-29T05:16:00.004302Z","iopub.status.idle":"2026-01-29T05:16:00.017908Z","shell.execute_reply.started":"2026-01-29T05:16:00.004268Z","shell.execute_reply":"2026-01-29T05:16:00.016959Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"FEATURES = [\"target_name\"]\nFEATURES","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.019096Z","iopub.execute_input":"2026-01-29T05:16:00.019470Z","iopub.status.idle":"2026-01-29T05:16:00.035216Z","shell.execute_reply.started":"2026-01-29T05:16:00.019432Z","shell.execute_reply":"2026-01-29T05:16:00.034318Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"target_map = {\n    \"Dry_Green_g\": 0,\n    \"Dry_Dead_g\": 1,\n    \"Dry_Clover_g\": 2,\n    \"GDM_g\": 3,\n    \"Dry_Total_g\": 4\n}","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.036509Z","iopub.execute_input":"2026-01-29T05:16:00.036953Z","iopub.status.idle":"2026-01-29T05:16:00.050373Z","shell.execute_reply.started":"2026-01-29T05:16:00.036915Z","shell.execute_reply":"2026-01-29T05:16:00.049495Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Apply mapping\ntrain_df[\"target_name_enc\"] = train_df[\"target_name\"].map(target_map)\ntest_df[\"target_name_enc\"]  = test_df[\"target_name\"].map(target_map)\n\ntrain_df[[\"target_name\", \"target_name_enc\"]].head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.051631Z","iopub.execute_input":"2026-01-29T05:16:00.052017Z","iopub.status.idle":"2026-01-29T05:16:00.073036Z","shell.execute_reply.started":"2026-01-29T05:16:00.051959Z","shell.execute_reply":"2026-01-29T05:16:00.072191Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.ensemble import RandomForestRegressor\n\nX_simple = train_df[[\"target_name_enc\"]]\ny_simple = train_df[\"target\"]\n\nsimple_model = RandomForestRegressor(\n    n_estimators=300,\n    random_state=42\n)\n\nsimple_model.fit(X_simple, y_simple)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.074212Z","iopub.execute_input":"2026-01-29T05:16:00.074564Z","iopub.status.idle":"2026-01-29T05:16:00.436698Z","shell.execute_reply.started":"2026-01-29T05:16:00.074527Z","shell.execute_reply":"2026-01-29T05:16:00.435902Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"X_test = test_df[[\"target_name_enc\"]]\ntest_predictions = simple_model.predict(X_test)\n\ntest_predictions","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.439380Z","iopub.execute_input":"2026-01-29T05:16:00.439736Z","iopub.status.idle":"2026-01-29T05:16:00.492244Z","shell.execute_reply.started":"2026-01-29T05:16:00.439710Z","shell.execute_reply":"2026-01-29T05:16:00.491097Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"sample_id\": test_df[\"sample_id\"],\n    \"target\": test_predictions\n})\n\nsubmission.to_csv(\"submission.csv\", index=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2026-01-29T05:16:00.493531Z","iopub.execute_input":"2026-01-29T05:16:00.493892Z","iopub.status.idle":"2026-01-29T05:16:00.513301Z","shell.execute_reply.started":"2026-01-29T05:16:00.493856Z","shell.execute_reply":"2026-01-29T05:16:00.512435Z"}},"outputs":[],"execution_count":null}]}