{"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":"nvidiaTeslaT4","dataSources":[{"sourceId":112509,"databundleVersionId":14254895,"sourceType":"competition"}],"dockerImageVersionId":31154,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\nimport os\nfor dirname, _, filenames in os.walk('/kaggle/input'):\n    for filename in filenames:\n        print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-11-07T19:57:15.831195Z","iopub.execute_input":"2025-11-07T19:57:15.831443Z","iopub.status.idle":"2025-11-07T19:57:17.907503Z","shell.execute_reply.started":"2025-11-07T19:57:15.831420Z","shell.execute_reply":"2025-11-07T19:57:17.906728Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from pathlib import Path\nimport pandas as pd\n\nBASE_DIR = Path('/kaggle/input/csiro-biomass')\n\nTrain_DIR = BASE_DIR / 'test'\nTest_DIR = BASE_DIR / 'test'\n\ntrain_csv_path = BASE_DIR / 'train.csv'\ntest_csv_path = BASE_DIR / 'test.csv'\n\ndf = pd.read_csv(train_csv_path)\ndf_test = pd.read_csv(test_csv_path)    ","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T19:57:17.909220Z","iopub.execute_input":"2025-11-07T19:57:17.909809Z","iopub.status.idle":"2025-11-07T19:57:17.990837Z","shell.execute_reply.started":"2025-11-07T19:57:17.909788Z","shell.execute_reply":"2025-11-07T19:57:17.990042Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T19:57:17.991517Z","iopub.execute_input":"2025-11-07T19:57:17.991780Z","iopub.status.idle":"2025-11-07T19:57:18.016871Z","shell.execute_reply.started":"2025-11-07T19:57:17.991757Z","shell.execute_reply":"2025-11-07T19:57:18.016111Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print('Shape:', df.shape)\nprint('Size:', df.size)\nprint('No. of Nulls:', df.isnull().sum().sum())","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T19:57:18.017781Z","iopub.execute_input":"2025-11-07T19:57:18.018014Z","iopub.status.idle":"2025-11-07T19:57:18.024095Z","shell.execute_reply.started":"2025-11-07T19:57:18.017988Z","shell.execute_reply":"2025-11-07T19:57:18.023206Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport seaborn as sns\nimport warnings\n\nwarnings.filterwarnings('ignore')\nsns.set_theme(style='darkgrid')\n\ndf['Species_short'] = df['Species'].apply(lambda x: ' '.join(x.replace('_', ' ').split()[:3]))\n\nplt.figure(figsize=(18, 8))\n\nplt.subplot(1, 3, 1)\norder = df['Species_short'].value_counts().index\nsns.countplot(data=df, x='Species_short', order=order, palette='Set3')\nsns.despine()\nplt.xticks(rotation=45, ha='right')\nplt.title(\"Species Distribution\", fontsize=14)\n\nplt.subplot(1, 3, 2)\nsns.scatterplot(data=df, x='Height_Ave_cm', y='target', hue='State', palette='Set2')\nsns.despine()\nplt.title(\"Height vs Target by State\", fontsize=14)\n\nplt.subplot(1, 3, 3)\nsns.histplot(data=df, x='target', hue='State', kde=True, palette='Dark2')\nsns.despine()\nplt.title(\"Target Distribution by State\", fontsize=14)\n\nplt.tight_layout()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T19:57:18.024901Z","iopub.execute_input":"2025-11-07T19:57:18.025528Z","iopub.status.idle":"2025-11-07T19:57:20.337638Z","shell.execute_reply.started":"2025-11-07T19:57:18.025510Z","shell.execute_reply":"2025-11-07T19:57:20.336912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from sklearn.preprocessing import OneHotEncoder\nfrom PIL import Image\nimport numpy as np\n\ndef img_to_array(paths, shape):\n    return np.array([\n        np.array(Image.open(BASE_DIR / path).resize(shape))\n        for path in paths])\n\ndef log_transform(target):\n    target = np.array(target)\n    return np.where(target >= 0, np.log(target), -1)\n\ndef inverse_transform(log_target):\n    log_target = np.array(log_target)\n    return np.where(log_target >= 0, np.exp(log_target), -1)\n\nencoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')\nspecies_reshaped = df['Species'].values.reshape(-1, 1)\n\n\nimage_arrays = img_to_array(df['image_path'], (384, 384))\none_hot_species = encoder.fit_transform(species_reshaped)\ntarget = log_transform(df['target'])","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T20:07:45.523282Z","iopub.execute_input":"2025-11-07T20:07:45.523864Z","iopub.status.idle":"2025-11-07T20:09:39.167069Z","shell.execute_reply.started":"2025-11-07T20:07:45.523825Z","shell.execute_reply":"2025-11-07T20:09:39.166009Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import tensorflow as tf\nfrom tensorflow.keras import layers, models\nfrom tensorflow.keras.applications import EfficientNetV2S\nfrom tensorflow.keras import layers, models, regularizers\nfrom tensorflow.keras.applications.efficientnet_v2 import preprocess_input\nimport os\nfrom tensorflow.keras import layers\n\npreprocess_layer = tf.keras.Sequential([\n    layers.Resizing(384, 384),\n    layers.Rescaling(1./255),\n    layers.Normalization(mean=[0.485, 0.456, 0.406],\n                         variance=[0.229**2, 0.224**2, 0.225**2])\n])\n\n\n\ndef preprocess_image(img):\n    img = tf.image.convert_image_dtype(img, tf.float32)  \n    img = tf.image.resize(img, (384, 384))\n    img = tf.keras.applications.efficientnet_v2.preprocess_input(img)\n    return img\n\ndef make_dataset(image_arrays, one_hot_species, targets, batch_size=32, shuffle=True, buffer_size=None):\n \n    image_arrays = tf.convert_to_tensor(image_arrays, dtype=tf.float32)\n    one_hot_species = tf.convert_to_tensor(one_hot_species, dtype=tf.float32)\n    targets = tf.convert_to_tensor(targets, dtype=tf.float32)\n\n    ds = tf.data.Dataset.from_tensor_slices((image_arrays, one_hot_species, targets))\n\n    def _process(img, sp, y):\n        img = preprocess_image(img)\n        return ({\"image_input\": img, \"species_input\": sp}, y)\n\n    \n    if shuffle:\n        if buffer_size is None:\n            buffer_size = tf.shape(image_arrays)[0]  # dynamic shape\n        ds = ds.shuffle(buffer_size=buffer_size, reshuffle_each_iteration=True)\n\n    ds = ds.map(_process, num_parallel_calls=tf.data.AUTOTUNE)\n    ds = ds.batch(batch_size).prefetch(tf.data.AUTOTUNE)\n    return ds\n\n\nnum_samples = len(image_arrays)\nif num_samples == 0:\n    raise ValueError(\"image_arrays is empty. please check your dataset loading.\")\n\nsplit = int(num_samples * 0.8)\n\ntrain_ds = make_dataset(\n    image_arrays[:split],\n    one_hot_species[:split],\n    target[:split],\n    batch_size=32,\n    shuffle=True,\n    buffer_size=min(1000, split)  \n)\n\nval_ds = make_dataset(\n    image_arrays[split:],\n    one_hot_species[split:],\n    target[split:],\n    batch_size=32,\n    shuffle=False\n)\n\n\ndef build_efficientnet_regressor(species_dim, fine_tune_at=400):\n    \n    backbone = EfficientNetV2S(include_top=False, weights='imagenet', pooling='avg')\n\n\n    backbone.trainable = True\n    for layer in backbone.layers[:fine_tune_at]:\n        layer.trainable = False\n\n    img_input = layers.Input(shape=(384, 384, 3), name=\"image_input\")\n    sp_input = layers.Input(shape=(species_dim,), name=\"species_input\")\n\n    x_img = tf.keras.applications.efficientnet_v2.preprocess_input(img_input)\n    x_img = backbone(x_img)\n\n    \n    x_sp = layers.BatchNormalization()(sp_input)\n\n    \n    x = layers.Concatenate()([x_img, x_sp])\n    x = layers.Dense(512, activation='relu', kernel_regularizer=regularizers.l2(1e-4))(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.4)(x)\n\n    x = layers.Dense(256, activation='relu', kernel_regularizer=regularizers.l2(1e-4))(x)\n    x = layers.BatchNormalization()(x)\n    x = layers.Dropout(0.3)(x)\n\n    output = layers.Dense(1)(x)\n\n    model = models.Model(inputs=[img_input, sp_input], outputs=output)\n    return model\n\n\ncheckpoint_dir = \"checkpoints\"\nos.makedirs(checkpoint_dir, exist_ok=True)\n\ncallbacks = [\n    tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=3, restore_best_weights=True),\n    tf.keras.callbacks.ModelCheckpoint(filepath=os.path.join(checkpoint_dir, 'best_model.keras'),\n                                       monitor='val_loss', save_best_only=True),\n    tf.keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.5, patience=3, verbose=1),\n    tf.keras.callbacks.TensorBoard(log_dir='logs')\n]\n\nspecies_dim = one_hot_species.shape[1]\nmodel = build_efficientnet_regressor(species_dim, fine_tune_at=400)\nmodel.compile(\n    optimizer=tf.keras.optimizers.Adam(learning_rate=1e-5),\n    loss='mse',\n    metrics=[tf.keras.metrics.RootMeanSquaredError(name='rmse')]\n)\n\nhistory = model.fit(\n    train_ds,\n    validation_data=val_ds,\n    epochs=100,\n    callbacks=callbacks\n)\n\nval_loss, val_rmse = model.evaluate(val_ds)\nprint(f\"Validation RMSE: {val_rmse:.4f}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T20:25:32.561787Z","iopub.execute_input":"2025-11-07T20:25:32.562627Z","iopub.status.idle":"2025-11-07T20:29:01.072567Z","shell.execute_reply.started":"2025-11-07T20:25:32.562591Z","shell.execute_reply":"2025-11-07T20:29:01.071961Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"image_arrays.shape","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-11-07T20:09:46.691063Z","iopub.execute_input":"2025-11-07T20:09:46.691617Z","iopub.status.idle":"2025-11-07T20:09:46.696228Z","shell.execute_reply.started":"2025-11-07T20:09:46.691593Z","shell.execute_reply":"2025-11-07T20:09:46.695605Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"test_species = df_test['Species'].values.reshape(-1, 1)\ntest_one_hot_species = encoder.transform(test_species)  \ntest_image_arrays = img_to_array(df_test['image_path'], (384, 384))\n\n\npreds_log = model.predict(test_ds).flatten()\n\npreds = inverse_transform(preds_log)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"submission = pd.DataFrame({\n    \"id\": df_test.index,\n    \"target\": preds\n})\nsubmission.to_csv(\"submission.csv\", index=False)\n\nprint(\"Submission file saved as submission.csv\")","metadata":{"trusted":true},"outputs":[],"execution_count":null}]}