{
  "id": 617680,
  "title": "[SOLVED] Why scoring stuck for ~8 hours?",
  "url": "/competitions/csiro-biomass/discussion/617680",
  "author_name": "",
  "post_date": "2025-11-11T14:56:51.138599100Z",
  "votes": 2,
  "comment_count": 17,
  "views": 0,
  "content": "<p>My latest submission has been in “Pending” status for about 8 hours. No error, no timeout, just no update. Has anyone else experienced prolonged hangs like this? Could it be an issue with the submission format, evaluation server, or backend queue? Any advice or host clarification would be appreciated 😁.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12877917%2F6da66fc4fab1e5072f059d557277c8c7%2FScreenshot%202025-11-11%20205138.png?generation=1762869108934710&amp;alt=media\" alt=\"\"></p>\n<p><strong><em>⁉️ Update:</em></strong></p>\n<blockquote>\n  <p>It turns out the issue isn’t from the notebook or the code itself, but likely from Kaggle’s backend. My workaround is to use GPU and reduce the model size when uploading.</p>\n  <p>It’s not a perfect fix, since I still have to wait about an hour for grading to complete, but it definitely runs faster and helps avoid long queue delays. You can also open your browser’s developer tools (F12) to monitor network activity and see what’s happening in real time.</p>\n</blockquote>",
  "messages": [
    {
      "id": "3319094",
      "postDate": "11/11/2025 14:56:51",
      "content": "<p>My latest submission has been in “Pending” status for about 8 hours. No error, no timeout, just no update. Has anyone else experienced prolonged hangs like this? Could it be an issue with the submission format, evaluation server, or backend queue? Any advice or host clarification would be appreciated 😁.</p>\n<p><img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12877917%2F6da66fc4fab1e5072f059d557277c8c7%2FScreenshot%202025-11-11%20205138.png?generation=1762869108934710&amp;alt=media\" alt=\"\"></p>\n<p><strong><em>⁉️ Update:</em></strong></p>\n<blockquote>\n  <p>It turns out the issue isn’t from the notebook or the code itself, but likely from Kaggle’s backend. My workaround is to use GPU and reduce the model size when uploading.</p>\n  <p>It’s not a perfect fix, since I still have to wait about an hour for grading to complete, but it definitely runs faster and helps avoid long queue delays. You can also open your browser’s developer tools (F12) to monitor network activity and see what’s happening in real time.</p>\n</blockquote>",
      "rawMarkdown": "My latest submission has been in “Pending” status for about 8 hours. No error, no timeout, just no update. Has anyone else experienced prolonged hangs like this? Could it be an issue with the submission format, evaluation server, or backend queue? Any advice or host clarification would be appreciated 😁.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12877917%2F6da66fc4fab1e5072f059d557277c8c7%2FScreenshot%202025-11-11%20205138.png?generation=1762869108934710&alt=media)\n\n***⁉️ Update:***\n> It turns out the issue isn’t from the notebook or the code itself, but likely from Kaggle’s backend. My workaround is to use GPU and reduce the model size when uploading.\n\n> It’s not a perfect fix, since I still have to wait about an hour for grading to complete, but it definitely runs faster and helps avoid long queue delays. You can also open your browser’s developer tools (F12) to monitor network activity and see what’s happening in real time.",
      "votes": null
    },
    {
      "id": "3319146",
      "postDate": "11/11/2025 15:31:40",
      "content": "<p>Is it were something wrong with evaluation format, you will get an error instead.\nI am not really sure what exactly you mean by 'evaluation server' and 'backend queue'.</p>\n<p>When you save the notebook, see the time it took to process 1 (given) test image. multiply that by ~700. </p>",
      "rawMarkdown": "Is it were something wrong with evaluation format, you will get an error instead.\nI am not really sure what exactly you mean by 'evaluation server' and 'backend queue'.\n\nWhen you save the notebook, see the time it took to process 1 (given) test image. multiply that by ~700.",
      "votes": null
    },
    {
      "id": "3319159",
      "postDate": "11/11/2025 15:35:40",
      "content": "<p>My submit time is like 5mins. Are you training your model in submission notebook?</p>",
      "rawMarkdown": "My submit time is like 5mins. Are you training your model in submission notebook?",
      "votes": null
    },
    {
      "id": "3319183",
      "postDate": "11/11/2025 15:45:25",
      "content": "<p>I trained locally on my PC and only made a Kaggle notebook for submission (with checkpoints from training, uploaded directly to Kaggle), so it’s not related to training at all </p>",
      "rawMarkdown": "I trained locally on my PC and only made a Kaggle notebook for submission (with checkpoints from training, uploaded directly to Kaggle), so it’s not related to training at all",
      "votes": null
    },
    {
      "id": "3319189",
      "postDate": "11/11/2025 15:48:22",
      "content": "<p>My notebook runtime was only ~5m 34s, but the submission stayed “running” until it timed out. No idea if it’s the checkpoint I uploaded, the way I load it, or something on Kaggle’s side.</p>",
      "rawMarkdown": "My notebook runtime was only ~5m 34s, but the submission stayed “running” until it timed out. No idea if it’s the checkpoint I uploaded, the way I load it, or something on Kaggle’s side.",
      "votes": null
    },
    {
      "id": "3319207",
      "postDate": "11/11/2025 16:01:02",
      "content": "<p>Suggest you add option in your code to predict on the train data rather than the test.  Run All on the notebook see how long it takes to predict on the 357 train images.  </p>\n<p>The image you shared indicated the notebook was running - not Pending.  If it was truly pending than probably a kaggle issue - i have that only once so far in this competition, but often over the years.</p>",
      "rawMarkdown": "Suggest you add option in your code to predict on the train data rather than the test.  Run All on the notebook see how long it takes to predict on the 357 train images.  \n\nThe image you shared indicated the notebook was running - not Pending.  If it was truly pending than probably a kaggle issue - i have that only once so far in this competition, but often over the years.",
      "votes": null
    },
    {
      "id": "3319702",
      "postDate": "11/12/2025 02:11:52",
      "content": "<p>Same….It is running for more than 3 hours even though the submission.csv was created a long time ago. I am adding my code herein</p>\n<h1>====================================================================================</h1>\n<h1>Complete Biomass Prediction Pipeline - All Models + Ensemble</h1>\n<h1>====================================================================================</h1>\n<p>import os, gc, warnings, json\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom pathlib import Path\nfrom tqdm import tqdm, tqdm_notebook\nfrom PIL import Image\nfrom dataclasses import dataclass, field</p>\n<p>import torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F</p>\n<p>from transformers import AutoImageProcessor, AutoModel\nimport timm\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2</p>\n<p>from sklearn.preprocessing import StandardScaler\nfrom sklearn.feature_selection import VarianceThreshold\nfrom sklearn.linear_model import ElasticNetCV, Ridge\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.pipeline import make_pipeline</p>\n<p>import lightgbm as lgb\nimport catboost</p>\n<p>warnings.filterwarnings(\"ignore\")\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\"\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")</p>\n<h1>====================================================================================</h1>\n<h1>MODEL 1: DINOv2-Giant + ElasticNetCV</h1>\n<h1>====================================================================================</h1>\n<p>def extract_dinov2_features(model, processor, img_paths, cache_name):\n    \"\"\"Extract DINOv2 embeddings with caching\"\"\"\n    if os.path.exists(cache_name):\n        print(f\"✅ Loaded cached features: {cache_name}\")\n        return np.load(cache_name)</p>\n<pre><code>feats = \nmodel()\nwith torch(), torch():\n       (img_paths, desc=):\n        with Image(path) as :\n            inputs = (images=, return_tensors=)(DEVICE)\n            outputs = (**inputs)\n            emb = outputs(dim=)()()\n            feats(emb)\nfeats = np(feats, axis=)\nnp(cache_name, feats)\nreturn feats\n</code></pre>\n<p>def run_model1_dinov2(root_path):\n    \"\"\"DINOv2-Giant + ElasticNetCV\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 1: DINOv2-Giant + ElasticNetCV\")\n    print(\"=\"</em>80)</p>\n<pre><code>processor = AutoImageProcessor.from_pretrained(f)\nmodel = AutoModel.from_pretrained(f).to(DEVICE)\n\ntrain_df = pd.read_csv(os.path.(root_path, ))\ntrain_df[] = train_df[].( x: x.()[])\ntarget_mapping = {\n    : , : , : ,\n    : , : \n}\n\nunique_imgs = train_df.drop_duplicates().reset_index(drop=True)\nimg_paths = [os.path.(root_path, p)  p  unique_imgs[]]\nfeats = extract_dinov2_features(model, processor, img_paths, )\n\ny_full = .zeros((len(unique_imgs), ))\n ,   train_df.iterrows():\n    idx = unique_imgs.index[unique_imgs[] == []][]\n    y_full[idx, target_mapping[[]]] = []\n\nkf = KFold(n_splits=, shuffle=True, random_state=)\noof = .zeros_like(y_full)\nregressors = [[]    ()]\n\n t  ():\n    y = y_full[:, t]\n     fold, (, va)  enumerate(kf.(feats)):\n        model_reg = make_pipeline(\n            StandardScaler(),\n            ElasticNetCV(l1_ratio=[, , , , ],\n                       alphas=.logspace(-, , ), =, n_jobs=-, max_iter=)\n        )\n        model_reg.fit(feats[], y[])\n        oof[va, t] = model_reg.predict(feats[va])\n        regressors[t].(model_reg)\n\noof_df = pd.DataFrame(oof, =target_mapping.keys())\noof_df[] = unique_imgs[]\noof_df.to_csv(, index=False)\n\n# Test inference\ntest_df = pd.read_csv(os.path.(root_path, ))\ntest_unique = test_df.drop_duplicates().reset_index(drop=True)\ntest_paths = [os.path.(root_path, p)  p  test_unique[]]\ntest_feats = extract_dinov2_features(model, processor, test_paths, )\n\npreds = .zeros((len(test_feats), ))\n t  ():\n    fold_preds = .column_stack([reg.predict(test_feats)  reg  regressors[t]])\n    preds[:, t] = fold_preds.(axis=)\n\npreds = .clip(preds, , None)\npreds_df = pd.DataFrame(preds, =target_mapping.keys())\npreds_df[] = test_unique[]\n\nsub = test_df.()\n   target_mapping.keys():\n    sub.loc[sub[] == , ] = \\\n        sub[].(preds_df.set_index()[])\nsub[[, ]].to_csv(, index=False)\n\n model, processor\ngc.collect()\ntorch.cuda.empty_cache()\n()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MODEL 2: ConvNeXt-Tiny</h1>\n<h1>====================================================================================</h1>\n<p><a href=\"https://www.kaggle.com/dataclass\" target=\"_blank\">@dataclass</a>\nclass ConvNextConfig:\n    base_path: Path = Path(\"/kaggle/input/csiro-biomass\")\n    model_dir: Path = Path(\"/kaggle/input/csiro-exp3/convnext_exp3\")\n    model_name: str = \"convnext_tiny\"\n    img_size: int = 1000\n    batch_size: int = 1\n    num_workers: int = 1\n    n_folds: int = 5\n    device: torch.device = field(default_factory=lambda: DEVICE)</p>\n<p>class BiomassDataset(Dataset):\n    def <strong>init</strong>(self, df, transform, image_dir):\n        self.df = df\n        self.image_paths = df[\"image_path\"].values\n        self.transform = transform\n        self.image_dir = image_dir</p>\n<pre><code> ():\n     (.df)\n\n ():\n    path = Path(.image_paths[idx])\n    full = .image_dir / path.name\n    img = cv2.imread((full))\n     img  :\n        img = np.zeros((, , ), np.uint8)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    h, w, _ = img.shape\n    mid = w // \n    l, r = img[:, :mid], img[:, mid:]\n     .transform(image=l)[], .transform(image=r)[]\n</code></pre>\n<p>class BiomassModel(nn.Module):\n    def <strong>init</strong>(self, model_name=\"convnext_tiny\"):\n        super().<strong>init</strong>()\n        self.backbone = timm.create_model(model_name, pretrained=False,\n                                        num_classes=0, global_pool=\"avg\")\n        nf = self.backbone.num_features\n        nc = nf * 2\n        def head():\n            return nn.Sequential(nn.Linear(nc, 768), nn.GELU(), nn.Linear(768, 1))\n        self.head_total = head()\n        self.head_gdm = head()\n        self.head_green = head()</p>\n<pre><code>def forward(, l, r):\n    fl, fr = .backbone(l), .backbone(r)\n     = torch.cat([fl, fr], )\n     .head_total(), .head_gdm(), .head_green()\n</code></pre>\n<p>def get_tta(img_size):\n    base = [A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2()]\n    return [\n        A.Compose([A.Resize(img_size, img_size), *base]),\n        A.Compose([A.HorizontalFlip(p=1), A.Resize(img_size, img_size), *base]),\n        A.Compose([A.VerticalFlip(p=1), A.Resize(img_size, img_size), *base]),\n    ]</p>\n<p>def run_model2_convnext():\n    \"\"\"ConvNeXt-Tiny ensemble inference\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 2: ConvNeXt-Tiny\")\n    print(\"=\"</em>80)</p>\n<pre><code>cfg = ConvNextConfig()\nmodels = []\n f  range(cfg.n_folds):\n    path = cfg.model_dir / f\n    model = BiomassModel(cfg.model_name)\n     = torch.(path, map_location=cfg.device)\n     = {k.replace(, ): v  k, v  .items()}\n    model.load_state_dict(, strict=False)\n    model.(cfg.device).eval()\n    models.append(model)\n\ndf_test = pd.read_csv(cfg.base_path / )\ndf_unique = df_test.drop_duplicates().reset_index(=True)\n\ntta = get_tta(cfg.img_size)\n = {: [], : [], : []}\n\n tr  tta:\n    dl = DataLoader(BiomassDataset(df_unique, tr, cfg.base_path / ),\n                   batch_size=cfg.batch_size, num_workers=cfg.num_workers)\n    part = {: [], : [], : []}\n\n    with torch.no_grad():\n         l, r  tqdm(dl, desc=):\n            l, r = l.(cfg.device), r.(cfg.device)\n            tmp = {: [], : [], : []}\n            with torch.cuda.amp.autocast():\n                 m  models:\n                    t, g, g2 = m(l, r)\n                    tmp[].append(t.cpu())\n                    tmp[].append(g.cpu())\n                    tmp[].append(g2.cpu())\n             k  tmp:\n                part[k].append(torch.mean(torch.stack(tmp[k]), ))\n\n     k  :\n        [k].append(torch.cat(part[k]).numpy().ravel())\n\npreds = {k: np.mean(v, )  k, v  .items()}\ntotal, gdm, green = preds[], preds[], preds[]\nclover = np.maximum(, gdm - green)\ndead = np.maximum(, total - gdm)\n\nwide = pd.DataFrame({\n    : df_unique[],\n    : green, : dead, : clover,\n    : gdm, : total\n})\n\nlong = wide.melt(id_vars=, var_name=, value_name=)\nsub = pd.merge(df_test[[, , ]],\n              long, =[, ], how=)\nsub[[, ]].to_csv(, index=False)\n\ndel models\ngc.collect()\ntorch.cuda.empty_cache()\nprint()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MODEL 3: SigLIP + Ensemble (ElasticNet + LightGBM + CatBoost)</h1>\n<h1>====================================================================================</h1>\n<p>LABELS = [\"Dry_Clover_g\", \"Dry_Dead_g\", \"Dry_Green_g\", \"Dry_Total_g\", \"GDM_g\"]\nWEIGHTS = {\"Dry_Green_g\": 0.1, \"Dry_Dead_g\": 0.1, \"Dry_Clover_g\": 0.1,\n          \"GDM_g\": 0.2, \"Dry_Total_g\": 0.5}</p>\n<p>def weighted_r2(y, t):\n    w = np.array([WEIGHTS[k] for k in LABELS])\n    ssr = np.average((y - t) ** 2, weights=w, axis=1).mean()\n    ym = np.average(y, weights=w, axis=1).mean()\n    sst = np.average((y - ym) ** 2, weights=w, axis=1).mean()\n    return 1 - ssr / sst</p>\n<p>def extract_siglip_features(paths, tag, data_path, model_path):\n    cache = Path(f\"siglip_{tag}.npy\")\n    if cache.exists():\n        return np.load(cache)</p>\n<pre><code>proc = AutoImageProcessor(model_path)\nmodel = AutoModel(model_path)(DEVICE)()\nfeats = \n\nwith torch(), torch():\n       ((, (paths), ), desc=f):\n        imgs = ]\n        inp = (images=imgs, return_tensors=)(DEVICE)\n        f = model(**inp)\n        f = F(f, dim=-)\n        feats(f()())\n\narr = np(feats, )\nnp(cache, arr)\nreturn arr\n</code></pre>\n<p>def run_model3_siglip(root_path):\n    \"\"\"SigLIP + Triple Ensemble\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 3: SigLIP + Ensemble\")\n    print(\"=\"</em>80)</p>\n<pre><code>data_path = Path(root_path)\nmodel_path = Path()\n\n\ndf = pl.read_csv(data_path / )\ndf = (df.with_columns([\n        pl.when(pl.col() == x).then(pl.col()).alias(x)\n         x  LABELS\n    ]).group_by().agg(\n        [pl.col(x).mean()  x  LABELS] +\n        [pl.concat_str([, ], =).alias(\"group\").first()]\n    ).sort())\n\nX = extract_siglip_features(df[].to_list(), , data_path, model_path)\ny = df.select(LABELS).to_numpy()\ng = df[].to_numpy()\n\nvt = VarianceThreshold(1e-6)\nX = vt.fit_transform(X)\n\n\ntest_df = pl.read_csv(data_path / )\ntest_unique = test_df.group_by().len().sort()\nXt = extract_siglip_features(test_unique[].to_list(), , data_path, model_path)\nXt = vt.transform(Xt)\n\n\ndef crossval(make_model, X, y, g, Xt):\n    gkf = GroupKFold(5)\n    o = np.zeros_like(y)\n    p = np.zeros((len(Xt), y.shape[1]))\n     i, (tr, va)  enumerate(gkf.split(X, y, =g)):\n        yp = np.zeros_like(y[va])\n         t  range(y.shape[1]):\n            m = make_model()\n            m.fit(X[tr], y[tr, t])\n            yp[:, t] = m.predict(X[va])\n            p[:, t] += m.predict(Xt) / 5\n        o[va] = yp\n    return o, p\n\n\ndef mk_elastic():\n    return make_pipeline(\n        StandardScaler(),\n        ElasticNetCV(l1_ratio=[.5, .7, .9, 1], =np.logspace(-4, 1, 20),\n                    =3, =5000))\no1, p1 = crossval(mk_elastic, X, y, g, Xt)\n\n\ndef mk_lgb():\n    return lgb.LGBMRegressor(=200, =.07, =48,\n                            =.8, =.8, =1,\n                            =.001, =10,\n                            =-1, =-1, =, =42)\no2, p2 = crossval(mk_lgb, X, y, g, Xt)\n\n\ndef mk_cat():\n    return catboost.CatBoostRegressor(=200, =.05, =6,\n                                     =2, =42, =,\n                                     =)\no3, p3 = crossval(mk_cat, X, y, g, Xt)\n\n\no = (o1 + o2 + o3) / 3\np = (p1 + p2 + p3) / 3\n(f)\n\n\no_df = df.select().to_pandas()\no_df[LABELS] = o\no_df.to_csv(, =)\n\n\npred_df = pl.DataFrame(p.clip(0), =LABELS)\npred_with_id = pl.concat([test_unique.select(), pred_df], =)\nsub = (test_df.join(pred_with_id, =)\n      .with_columns([pl.coalesce(*[\n          pl.when(pl.col() == x).then(pl.col(x))\n           x  LABELS\n      ]).alias()])\n      .select([, ]))\nsub.write_csv()\n()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>FINAL ENSEMBLE</h1>\n<h1>====================================================================================</h1>\n<p>def create_final_ensemble():\n    \"\"\"Dynamic weighted ensemble\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"FINAL ENSEMBLE\")\n    print(\"=\"</em>80)</p>\n<pre><code>files = {\n    : ,\n    : ,\n    : ,\n}\n\noof_files = {\n    : ,\n    : None,\n    : ,\n}\n\ndfs = {k: pd.read_csv(v).set_index()  k, v  files.items()}\nweights = np.array([0.25, 0.40, 0.35])\n\n\nvalid_oofs = {k: v  k, v  oof_files.items()  v  os.path.exists(v)}\n len(valid_oofs) &gt;= 2:\n    try:\n        oof_dfs = {k: pd.read_csv(v)  k, v  valid_oofs.items()}\n         df  oof_dfs.values():\n            df.drop(columns=[], =, =)\n\n        common_cols = set.intersection(*((df.columns)  df  oof_dfs.values()))\n        ref = next(iter(oof_dfs))\n        y_true = oof_dfs[ref][list(common_cols)].mean(=1).values\n\n        X = np.vstack([\n            oof_dfs[][list(common_cols)].mean(=1).values,\n            oof_dfs.(, oof_dfs[ref])[list(common_cols)].mean(=1).values,\n            oof_dfs[][list(common_cols)].mean(=1).values,\n        ]).T\n\n        ridge = Ridge(=, =42)\n        ridge.fit(X, y_true)\n        learned_w = ridge.coef_ / np.sum(ridge.coef_)\n\n          np.any(np.isnan(learned_w))  np.sum(learned_w) &gt; 0:\n            weights = learned_w\n            (f)\n    except Exception as e:\n        (f)\n\nfinal = (\n    weights[0] * dfs[] +\n    weights[1] * dfs[] +\n    weights[2] * dfs[]\n).clip(=0)\n\nfinal.to_csv()\n()\n(final.head())\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MAIN EXECUTION</h1>\n<h1>====================================================================================</h1>\n<p>def main():\n    ROOT = \"/kaggle/input/csiro-biomass\"</p>\n<pre><code>( + )\n()\n()\n\n\nrun_model1_dinov2(ROOT)\nrun_model2_convnext()\nrun_model3_siglip(ROOT)\n\n\ncreate_final_ensemble()\n\n( + )\n()\n()\n</code></pre>\n<p>if <strong>name</strong> == \"<strong>main</strong>\":\n    main()</p>",
      "rawMarkdown": "Same....It is running for more than 3 hours even though the submission.csv was created a long time ago. I am adding my code herein\n\n\n\n# ====================================================================================\n# Complete Biomass Prediction Pipeline - All Models + Ensemble\n# ====================================================================================\n\nimport os, gc, warnings, json\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom pathlib import Path\nfrom tqdm import tqdm, tqdm_notebook\nfrom PIL import Image\nfrom dataclasses import dataclass, field\n\nimport torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F\n\nfrom transformers import AutoImageProcessor, AutoModel\nimport timm\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.feature_selection import VarianceThreshold\nfrom sklearn.linear_model import ElasticNetCV, Ridge\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.pipeline import make_pipeline\n\nimport lightgbm as lgb\nimport catboost\n\nwarnings.filterwarnings(\"ignore\")\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\"\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# ====================================================================================\n# MODEL 1: DINOv2-Giant + ElasticNetCV\n# ====================================================================================\n\ndef extract_dinov2_features(model, processor, img_paths, cache_name):\n    \"\"\"Extract DINOv2 embeddings with caching\"\"\"\n    if os.path.exists(cache_name):\n        print(f\"✅ Loaded cached features: {cache_name}\")\n        return np.load(cache_name)\n    \n    feats = []\n    model.eval()\n    with torch.no_grad(), torch.cuda.amp.autocast():\n        for path in tqdm(img_paths, desc=\"Extracting DINOv2\"):\n            with Image.open(path) as img:\n                inputs = processor(images=img, return_tensors=\"pt\").to(DEVICE)\n                outputs = model(**inputs)\n                emb = outputs.last_hidden_state.mean(dim=1).cpu().numpy()\n                feats.append(emb)\n    feats = np.concatenate(feats, axis=0)\n    np.save(cache_name, feats)\n    return feats\n\ndef run_model1_dinov2(root_path):\n    \"\"\"DINOv2-Giant + ElasticNetCV\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 1: DINOv2-Giant + ElasticNetCV\")\n    print(\"=\"*80)\n    \n    processor = AutoImageProcessor.from_pretrained(f\"/kaggle/input/dinov2/pytorch/giant/1\")\n    model = AutoModel.from_pretrained(f\"/kaggle/input/dinov2/pytorch/giant/1\").to(DEVICE)\n    \n    train_df = pd.read_csv(os.path.join(root_path, \"train.csv\"))\n    train_df[\"target_name\"] = train_df[\"sample_id\"].apply(lambda x: x.split(\"__\")[1])\n    target_mapping = {\n        \"Dry_Clover_g\": 0, \"Dry_Dead_g\": 1, \"Dry_Green_g\": 2,\n        \"Dry_Total_g\": 3, \"GDM_g\": 4\n    }\n    \n    unique_imgs = train_df.drop_duplicates(\"image_path\").reset_index(drop=True)\n    img_paths = [os.path.join(root_path, p) for p in unique_imgs[\"image_path\"]]\n    feats = extract_dinov2_features(model, processor, img_paths, \"train_feats_dino.npy\")\n    \n    y_full = np.zeros((len(unique_imgs), 5))\n    for _, row in train_df.iterrows():\n        idx = unique_imgs.index[unique_imgs[\"image_path\"] == row[\"image_path\"]][0]\n        y_full[idx, target_mapping[row[\"target_name\"]]] = row[\"target\"]\n    \n    kf = KFold(n_splits=5, shuffle=True, random_state=42)\n    oof = np.zeros_like(y_full)\n    regressors = [[] for _ in range(5)]\n    \n    for t in range(5):\n        y = y_full[:, t]\n        for fold, (tr, va) in enumerate(kf.split(feats)):\n            model_reg = make_pipeline(\n                StandardScaler(),\n                ElasticNetCV(l1_ratio=[0.3, 0.5, 0.7, 0.9, 1.0],\n                           alphas=np.logspace(-4, 1, 30), cv=3, n_jobs=-1, max_iter=5000)\n            )\n            model_reg.fit(feats[tr], y[tr])\n            oof[va, t] = model_reg.predict(feats[va])\n            regressors[t].append(model_reg)\n    \n    oof_df = pd.DataFrame(oof, columns=target_mapping.keys())\n    oof_df[\"image_path\"] = unique_imgs[\"image_path\"]\n    oof_df.to_csv(\"oof_model_m1.csv\", index=False)\n    \n    # Test inference\n    test_df = pd.read_csv(os.path.join(root_path, \"test.csv\"))\n    test_unique = test_df.drop_duplicates(\"image_path\").reset_index(drop=True)\n    test_paths = [os.path.join(root_path, p) for p in test_unique[\"image_path\"]]\n    test_feats = extract_dinov2_features(model, processor, test_paths, \"test_feats_dino.npy\")\n    \n    preds = np.zeros((len(test_feats), 5))\n    for t in range(5):\n        fold_preds = np.column_stack([reg.predict(test_feats) for reg in regressors[t]])\n        preds[:, t] = fold_preds.mean(axis=1)\n    \n    preds = np.clip(preds, 0, None)\n    preds_df = pd.DataFrame(preds, columns=target_mapping.keys())\n    preds_df[\"image_path\"] = test_unique[\"image_path\"]\n    \n    sub = test_df.copy()\n    for col in target_mapping.keys():\n        sub.loc[sub[\"target_name\"] == col, \"target\"] = \\\n            sub[\"image_path\"].map(preds_df.set_index(\"image_path\")[col])\n    sub[[\"sample_id\", \"target\"]].to_csv(\"submission_dino_giant.csv\", index=False)\n    \n    del model, processor\n    gc.collect()\n    torch.cuda.empty_cache()\n    print(\"✅ Model 1 complete\")\n\n# ====================================================================================\n# MODEL 2: ConvNeXt-Tiny\n# ====================================================================================\n\n@dataclass\nclass ConvNextConfig:\n    base_path: Path = Path(\"/kaggle/input/csiro-biomass\")\n    model_dir: Path = Path(\"/kaggle/input/csiro-exp3/convnext_exp3\")\n    model_name: str = \"convnext_tiny\"\n    img_size: int = 1000\n    batch_size: int = 1\n    num_workers: int = 1\n    n_folds: int = 5\n    device: torch.device = field(default_factory=lambda: DEVICE)\n\nclass BiomassDataset(Dataset):\n    def __init__(self, df, transform, image_dir):\n        self.df = df\n        self.image_paths = df[\"image_path\"].values\n        self.transform = transform\n        self.image_dir = image_dir\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        path = Path(self.image_paths[idx])\n        full = self.image_dir / path.name\n        img = cv2.imread(str(full))\n        if img is None:\n            img = np.zeros((1000, 2000, 3), np.uint8)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        h, w, _ = img.shape\n        mid = w // 2\n        l, r = img[:, :mid], img[:, mid:]\n        return self.transform(image=l)[\"image\"], self.transform(image=r)[\"image\"]\n\nclass BiomassModel(nn.Module):\n    def __init__(self, model_name=\"convnext_tiny\"):\n        super().__init__()\n        self.backbone = timm.create_model(model_name, pretrained=False,\n                                        num_classes=0, global_pool=\"avg\")\n        nf = self.backbone.num_features\n        nc = nf * 2\n        def head():\n            return nn.Sequential(nn.Linear(nc, 768), nn.GELU(), nn.Linear(768, 1))\n        self.head_total = head()\n        self.head_gdm = head()\n        self.head_green = head()\n    \n    def forward(self, l, r):\n        fl, fr = self.backbone(l), self.backbone(r)\n        x = torch.cat([fl, fr], 1)\n        return self.head_total(x), self.head_gdm(x), self.head_green(x)\n\ndef get_tta(img_size):\n    base = [A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2()]\n    return [\n        A.Compose([A.Resize(img_size, img_size), *base]),\n        A.Compose([A.HorizontalFlip(p=1), A.Resize(img_size, img_size), *base]),\n        A.Compose([A.VerticalFlip(p=1), A.Resize(img_size, img_size), *base]),\n    ]\n\ndef run_model2_convnext():\n    \"\"\"ConvNeXt-Tiny ensemble inference\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 2: ConvNeXt-Tiny\")\n    print(\"=\"*80)\n    \n    cfg = ConvNextConfig()\n    models = []\n    for f in range(cfg.n_folds):\n        path = cfg.model_dir / f\"best_model_fold{f}.pth\"\n        model = BiomassModel(cfg.model_name)\n        state = torch.load(path, map_location=cfg.device)\n        state = {k.replace(\"module.\", \"\"): v for k, v in state.items()}\n        model.load_state_dict(state, strict=False)\n        model.to(cfg.device).eval()\n        models.append(model)\n    \n    df_test = pd.read_csv(cfg.base_path / \"test.csv\")\n    df_unique = df_test.drop_duplicates(\"image_path\").reset_index(drop=True)\n    \n    tta = get_tta(cfg.img_size)\n    out = {\"total\": [], \"gdm\": [], \"green\": []}\n    \n    for tr in tta:\n        dl = DataLoader(BiomassDataset(df_unique, tr, cfg.base_path / \"test\"),\n                       batch_size=cfg.batch_size, num_workers=cfg.num_workers)\n        part = {\"total\": [], \"gdm\": [], \"green\": []}\n        \n        with torch.no_grad():\n            for l, r in tqdm(dl, desc=\"Inference\"):\n                l, r = l.to(cfg.device), r.to(cfg.device)\n                tmp = {\"total\": [], \"gdm\": [], \"green\": []}\n                with torch.cuda.amp.autocast():\n                    for m in models:\n                        t, g, g2 = m(l, r)\n                        tmp[\"total\"].append(t.cpu())\n                        tmp[\"gdm\"].append(g.cpu())\n                        tmp[\"green\"].append(g2.cpu())\n                for k in tmp:\n                    part[k].append(torch.mean(torch.stack(tmp[k]), 0))\n        \n        for k in out:\n            out[k].append(torch.cat(part[k]).numpy().ravel())\n    \n    preds = {k: np.mean(v, 0) for k, v in out.items()}\n    total, gdm, green = preds[\"total\"], preds[\"gdm\"], preds[\"green\"]\n    clover = np.maximum(0, gdm - green)\n    dead = np.maximum(0, total - gdm)\n    \n    wide = pd.DataFrame({\n        \"image_path\": df_unique[\"image_path\"],\n        \"Dry_Green_g\": green, \"Dry_Dead_g\": dead, \"Dry_Clover_g\": clover,\n        \"GDM_g\": gdm, \"Dry_Total_g\": total\n    })\n    \n    long = wide.melt(id_vars=\"image_path\", var_name=\"target_name\", value_name=\"target\")\n    sub = pd.merge(df_test[[\"sample_id\", \"image_path\", \"target_name\"]],\n                  long, on=[\"image_path\", \"target_name\"], how=\"left\")\n    sub[[\"sample_id\", \"target\"]].to_csv(\"submission_ConvnextTiny.csv\", index=False)\n    \n    del models\n    gc.collect()\n    torch.cuda.empty_cache()\n    print(\"✅ Model 2 complete\")\n\n# ====================================================================================\n# MODEL 3: SigLIP + Ensemble (ElasticNet + LightGBM + CatBoost)\n# ====================================================================================\n\nLABELS = [\"Dry_Clover_g\", \"Dry_Dead_g\", \"Dry_Green_g\", \"Dry_Total_g\", \"GDM_g\"]\nWEIGHTS = {\"Dry_Green_g\": 0.1, \"Dry_Dead_g\": 0.1, \"Dry_Clover_g\": 0.1,\n          \"GDM_g\": 0.2, \"Dry_Total_g\": 0.5}\n\ndef weighted_r2(y, t):\n    w = np.array([WEIGHTS[k] for k in LABELS])\n    ssr = np.average((y - t) ** 2, weights=w, axis=1).mean()\n    ym = np.average(y, weights=w, axis=1).mean()\n    sst = np.average((y - ym) ** 2, weights=w, axis=1).mean()\n    return 1 - ssr / sst\n\ndef extract_siglip_features(paths, tag, data_path, model_path):\n    cache = Path(f\"siglip_{tag}.npy\")\n    if cache.exists():\n        return np.load(cache)\n    \n    proc = AutoImageProcessor.from_pretrained(model_path)\n    model = AutoModel.from_pretrained(model_path).to(DEVICE).eval()\n    feats = []\n    \n    with torch.no_grad(), torch.cuda.amp.autocast():\n        for i in tqdm(range(0, len(paths), 8), desc=f\"SigLIP {tag}\"):\n            imgs = [Image.open(data_path / p).convert(\"RGB\") for p in paths[i:i+8]]\n            inp = proc(images=imgs, return_tensors=\"pt\").to(DEVICE)\n            f = model.get_image_features(**inp)\n            f = F.normalize(f, dim=-1)\n            feats.append(f.cpu().numpy())\n    \n    arr = np.concatenate(feats, 0)\n    np.save(cache, arr)\n    return arr\n\ndef run_model3_siglip(root_path):\n    \"\"\"SigLIP + Triple Ensemble\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 3: SigLIP + Ensemble\")\n    print(\"=\"*80)\n    \n    data_path = Path(root_path)\n    model_path = Path(\"/kaggle/input/google-siglip-so400m-patch14-384/transformers/default/1\")\n    \n    # Train\n    df = pl.read_csv(data_path / \"train.csv\")\n    df = (df.with_columns([\n            pl.when(pl.col(\"target_name\") == x).then(pl.col(\"target\")).alias(x)\n            for x in LABELS\n        ]).group_by(\"image_path\").agg(\n            [pl.col(x).mean() for x in LABELS] +\n            [pl.concat_str([\"Sampling_Date\", \"State\"], separator=\"_\").alias(\"group\").first()]\n        ).sort(\"image_path\"))\n    \n    X = extract_siglip_features(df[\"image_path\"].to_list(), \"train\", data_path, model_path)\n    y = df.select(LABELS).to_numpy()\n    g = df[\"group\"].to_numpy()\n    \n    vt = VarianceThreshold(1e-6)\n    X = vt.fit_transform(X)\n    \n    # Test\n    test_df = pl.read_csv(data_path / \"test.csv\")\n    test_unique = test_df.group_by(\"image_path\").len().sort(\"image_path\")\n    Xt = extract_siglip_features(test_unique[\"image_path\"].to_list(), \"test\", data_path, model_path)\n    Xt = vt.transform(Xt)\n    \n    # Cross-validation function\n    def crossval(make_model, X, y, g, Xt):\n        gkf = GroupKFold(5)\n        o = np.zeros_like(y)\n        p = np.zeros((len(Xt), y.shape[1]))\n        for i, (tr, va) in enumerate(gkf.split(X, y, groups=g)):\n            yp = np.zeros_like(y[va])\n            for t in range(y.shape[1]):\n                m = make_model()\n                m.fit(X[tr], y[tr, t])\n                yp[:, t] = m.predict(X[va])\n                p[:, t] += m.predict(Xt) / 5\n            o[va] = yp\n        return o, p\n    \n    # ElasticNet\n    def mk_elastic():\n        return make_pipeline(\n            StandardScaler(),\n            ElasticNetCV(l1_ratio=[.5, .7, .9, 1], alphas=np.logspace(-4, 1, 20),\n                        cv=3, max_iter=5000))\n    o1, p1 = crossval(mk_elastic, X, y, g, Xt)\n    \n    # LightGBM\n    def mk_lgb():\n        return lgb.LGBMRegressor(n_estimators=200, learning_rate=.07, num_leaves=48,\n                                subsample=.8, colsample_bytree=.8, reg_lambda=1,\n                                min_gain_to_split=.001, min_data_in_leaf=10,\n                                n_jobs=-1, verbose=-1, force_col_wise=True, random_state=42)\n    o2, p2 = crossval(mk_lgb, X, y, g, Xt)\n    \n    # CatBoost\n    def mk_cat():\n        return catboost.CatBoostRegressor(iterations=200, learning_rate=.05, depth=6,\n                                         l2_leaf_reg=2, random_seed=42, verbose=False,\n                                         allow_writing_files=False)\n    o3, p3 = crossval(mk_cat, X, y, g, Xt)\n    \n    # Average ensemble\n    o = (o1 + o2 + o3) / 3\n    p = (p1 + p2 + p3) / 3\n    print(f\"Final Weighted R²: {weighted_r2(y, o):.4f}\")\n    \n    # Save OOF\n    o_df = df.select(\"image_path\").to_pandas()\n    o_df[LABELS] = o\n    o_df.to_csv(\"oof_model_m3.csv\", index=False)\n    \n    # Submission\n    pred_df = pl.DataFrame(p.clip(0), schema=LABELS)\n    pred_with_id = pl.concat([test_unique.select(\"image_path\"), pred_df], how=\"horizontal\")\n    sub = (test_df.join(pred_with_id, on=\"image_path\")\n          .with_columns([pl.coalesce(*[\n              pl.when(pl.col(\"target_name\") == x).then(pl.col(x))\n              for x in LABELS\n          ]).alias(\"target\")])\n          .select([\"sample_id\", \"target\"]))\n    sub.write_csv(\"submission_SigLIP.csv\")\n    print(\"✅ Model 3 complete\")\n\n# ====================================================================================\n# FINAL ENSEMBLE\n# ====================================================================================\n\ndef create_final_ensemble():\n    \"\"\"Dynamic weighted ensemble\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"FINAL ENSEMBLE\")\n    print(\"=\"*80)\n    \n    files = {\n        \"DINOv2\": \"submission_dino_giant.csv\",\n        \"ConvNeXt\": \"submission_ConvnextTiny.csv\",\n        \"SigLIP\": \"submission_SigLIP.csv\",\n    }\n    \n    oof_files = {\n        \"DINOv2\": \"oof_model_m1.csv\",\n        \"ConvNeXt\": None,\n        \"SigLIP\": \"oof_model_m3.csv\",\n    }\n    \n    dfs = {k: pd.read_csv(v).set_index(\"sample_id\") for k, v in files.items()}\n    weights = np.array([0.25, 0.40, 0.35])\n    \n    # Try learning weights from OOFs\n    valid_oofs = {k: v for k, v in oof_files.items() if v and os.path.exists(v)}\n    if len(valid_oofs) >= 2:\n        try:\n            oof_dfs = {k: pd.read_csv(v) for k, v in valid_oofs.items()}\n            for df in oof_dfs.values():\n                df.drop(columns=[\"image_path\"], inplace=True, errors=\"ignore\")\n            \n            common_cols = set.intersection(*(set(df.columns) for df in oof_dfs.values()))\n            ref = next(iter(oof_dfs))\n            y_true = oof_dfs[ref][list(common_cols)].mean(axis=1).values\n            \n            X = np.vstack([\n                oof_dfs[\"DINOv2\"][list(common_cols)].mean(axis=1).values,\n                oof_dfs.get(\"ConvNeXt\", oof_dfs[ref])[list(common_cols)].mean(axis=1).values,\n                oof_dfs[\"SigLIP\"][list(common_cols)].mean(axis=1).values,\n            ]).T\n            \n            ridge = Ridge(positive=True, random_state=42)\n            ridge.fit(X, y_true)\n            learned_w = ridge.coef_ / np.sum(ridge.coef_)\n            \n            if not np.any(np.isnan(learned_w)) and np.sum(learned_w) > 0:\n                weights = learned_w\n                print(f\"✅ Learned weights: {weights.round(3)}\")\n        except Exception as e:\n            print(f\"⚠️ Using default weights: {e}\")\n    \n    final = (\n        weights[0] * dfs[\"DINOv2\"] +\n        weights[1] * dfs[\"ConvNeXt\"] +\n        weights[2] * dfs[\"SigLIP\"]\n    ).clip(lower=0)\n    \n    final.to_csv(\"submission.csv\")\n    print(\"\\n🎯 Final submission created!\")\n    print(final.head())\n\n# ====================================================================================\n# MAIN EXECUTION\n# ====================================================================================\n\ndef main():\n    ROOT = \"/kaggle/input/csiro-biomass\"\n    \n    print(\"\\n\" + \"=\"*80)\n    print(\"BIOMASS PREDICTION - COMPLETE PIPELINE\")\n    print(\"=\"*80)\n    \n    # Run all models\n    run_model1_dinov2(ROOT)\n    run_model2_convnext()\n    run_model3_siglip(ROOT)\n    \n    # Create final ensemble\n    create_final_ensemble()\n    \n    print(\"\\n\" + \"=\"*80)\n    print(\"✨ PIPELINE COMPLETE!\")\n    print(\"=\"*80)\n\nif __name__ == \"__main__\":\n    main()",
      "votes": null
    },
    {
      "id": "3320604",
      "postDate": "11/12/2025 16:42:20",
      "content": "<p>Same, are you able to solve the problem?  My notebook created the .csv file nicely, but it got stuck showing \"error.\" </p>",
      "rawMarkdown": "Same, are you able to solve the problem?  My notebook created the .csv file nicely, but it got stuck showing \"error.\"",
      "votes": null
    },
    {
      "id": "3320649",
      "postDate": "11/12/2025 17:19:32",
      "content": "<p>I have total four submission instances where it ran for 9 hours and then timeout. I dnt understand why will it run for 9 hours even? Now i am loosing my motivation to try different approaches. you wait for 9 hours and then its timeout.</p>",
      "rawMarkdown": "I have total four submission instances where it ran for 9 hours and then timeout. I dnt understand why will it run for 9 hours even? Now i am loosing my motivation to try different approaches. you wait for 9 hours and then its timeout.",
      "votes": null
    },
    {
      "id": "3320778",
      "postDate": "11/12/2025 19:31:43",
      "content": "<p>Same, my notebook creates the csv perfectly but it refuses to submit</p>",
      "rawMarkdown": "Same, my notebook creates the csv perfectly but it refuses to submit",
      "votes": null
    },
    {
      "id": "3320784",
      "postDate": "11/12/2025 19:38:59",
      "content": "<p>Interestingly, when I switched to GPU, the runtime was much faster compared to using the CPU (which was the version I submitted earlier). The notebook finished running and produced the submission file, but it still took about an hour before the grading process completed. 🤣</p>",
      "rawMarkdown": "Interestingly, when I switched to GPU, the runtime was much faster compared to using the CPU (which was the version I submitted earlier). The notebook finished running and produced the submission file, but it still took about an hour before the grading process completed. 🤣",
      "votes": null
    },
    {
      "id": "3320786",
      "postDate": "11/12/2025 19:42:44",
      "content": "<p>My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete.</p>\n<p>The issue doesn’t seem to come from the notebook or the code itself, it’s likely on Kaggle’s backend. You can try using F12 to monitor the network activity and track what’s happening in real time.</p>",
      "rawMarkdown": "My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete.\n\nThe issue doesn’t seem to come from the notebook or the code itself, it’s likely on Kaggle’s backend. You can try using F12 to monitor the network activity and track what’s happening in real time.",
      "votes": null
    },
    {
      "id": "3320788",
      "postDate": "11/12/2025 19:43:49",
      "content": "<p>My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete, but hey, better than nothing, right?</p>\n<p>The issue doesn’t seem to come from the notebook or the code itself; it’s most likely on Kaggle’s backend. You can try using F12 to monitor the network activity and see what’s happening in real time.</p>",
      "rawMarkdown": "My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete, but hey, better than nothing, right?\n\nThe issue doesn’t seem to come from the notebook or the code itself; it’s most likely on Kaggle’s backend. You can try using F12 to monitor the network activity and see what’s happening in real time.",
      "votes": null
    },
    {
      "id": "3320791",
      "postDate": "11/12/2025 19:46:54",
      "content": "<p>Did your notebook get rejected immediately after submission with an error message, or did it run until hitting the competition timeout limit (around 9 hours)?</p>\n<p>If it’s the first case, check your submission format, predictions, and try running a smaller version of the code to identify any errors.</p>\n<p>If that’s not the issue, then it’s probably not related to your notebook or code, the problem is likely on Kaggle’s backend.\nMy own workaround is to use GPU and reduce the model size when uploading to Kaggle. It’s not a perfect fix, since I still have to wait about an hour for grading to finish, but hey, it’s better than nothing.</p>\n<p>You can also open the browser’s developer tools (F12) to monitor the network activity and see what’s going on in real time.</p>",
      "rawMarkdown": "Did your notebook get rejected immediately after submission with an error message, or did it run until hitting the competition timeout limit (around 9 hours)?\n\nIf it’s the first case, check your submission format, predictions, and try running a smaller version of the code to identify any errors.\n\nIf that’s not the issue, then it’s probably not related to your notebook or code, the problem is likely on Kaggle’s backend.\nMy own workaround is to use GPU and reduce the model size when uploading to Kaggle. It’s not a perfect fix, since I still have to wait about an hour for grading to finish, but hey, it’s better than nothing.\n\nYou can also open the browser’s developer tools (F12) to monitor the network activity and see what’s going on in real time.",
      "votes": null
    },
    {
      "id": "3383985",
      "postDate": "12/31/2025 08:54:36",
      "content": "<blockquote>\n  <p>My submit time is like 5mins. Are you training your model in submission notebook?</p>\n</blockquote>\n<p>Are you using GPU T4 or the TPU?</p>",
      "rawMarkdown": "> My submit time is like 5mins. Are you training your model in submission notebook?\n\nAre you using GPU T4 or the TPU?",
      "votes": null
    },
    {
      "id": "3384212",
      "postDate": "12/31/2025 18:09:23",
      "content": "<p>TPU not permitted for submissions in the competition.</p>",
      "rawMarkdown": "TPU not permitted for submissions in the competition.",
      "votes": null
    },
    {
      "id": "3384276",
      "postDate": "12/31/2025 21:10:48",
      "content": "<p><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/617680#3319159\" target=\"_blank\">Shanzhong8</a>\nWhat he has said it true, you need to make sure you are only performing inference in the submission notebook by setting train to False. This will make the notebook to run only in minutes until the complete scoring !!</p>",
      "rawMarkdown": "[Shanzhong8](https://www.kaggle.com/competitions/csiro-biomass/discussion/617680#3319159)\nWhat he has said it true, you need to make sure you are only performing inference in the submission notebook by setting train to False. This will make the notebook to run only in minutes until the complete scoring !!",
      "votes": null
    },
    {
      "id": "3384464",
      "postDate": "01/01/2026 09:59:21",
      "content": "<p>Oh, yeah. Got it.</p>",
      "rawMarkdown": "Oh, yeah. Got it.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 3319146,
      "author_name": "komilparmar",
      "author_url": "",
      "post_date": "11/11/2025 15:31:40",
      "content": "<p>Is it were something wrong with evaluation format, you will get an error instead.\nI am not really sure what exactly you mean by 'evaluation server' and 'backend queue'.</p>\n<p>When you save the notebook, see the time it took to process 1 (given) test image. multiply that by ~700. </p>",
      "votes": null,
      "replies": [
        {
          "id": 3319189,
          "author_name": "anmatngu",
          "author_url": "",
          "post_date": "11/11/2025 15:48:22",
          "content": "<p>My notebook runtime was only ~5m 34s, but the submission stayed “running” until it timed out. No idea if it’s the checkpoint I uploaded, the way I load it, or something on Kaggle’s side.</p>",
          "votes": null,
          "replies": [
            {
              "id": 3319207,
              "author_name": "pcjimmmy",
              "author_url": "",
              "post_date": "11/11/2025 16:01:02",
              "content": "<p>Suggest you add option in your code to predict on the train data rather than the test.  Run All on the notebook see how long it takes to predict on the 357 train images.  </p>\n<p>The image you shared indicated the notebook was running - not Pending.  If it was truly pending than probably a kaggle issue - i have that only once so far in this competition, but often over the years.</p>",
              "votes": null,
              "replies": [
                {
                  "id": 3320784,
                  "author_name": "anmatngu",
                  "author_url": "",
                  "post_date": "11/12/2025 19:38:59",
                  "content": "<p>Interestingly, when I switched to GPU, the runtime was much faster compared to using the CPU (which was the version I submitted earlier). The notebook finished running and produced the submission file, but it still took about an hour before the grading process completed. 🤣</p>",
                  "votes": null,
                  "replies": []
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "id": 3319159,
      "author_name": "shanzhong8",
      "author_url": "",
      "post_date": "11/11/2025 15:35:40",
      "content": "<p>My submit time is like 5mins. Are you training your model in submission notebook?</p>",
      "votes": null,
      "replies": [
        {
          "id": 3319183,
          "author_name": "anmatngu",
          "author_url": "",
          "post_date": "11/11/2025 15:45:25",
          "content": "<p>I trained locally on my PC and only made a Kaggle notebook for submission (with checkpoints from training, uploaded directly to Kaggle), so it’s not related to training at all </p>",
          "votes": null,
          "replies": []
        },
        {
          "id": 3383985,
          "author_name": "simonkosgei",
          "author_url": "",
          "post_date": "12/31/2025 08:54:36",
          "content": "<blockquote>\n  <p>My submit time is like 5mins. Are you training your model in submission notebook?</p>\n</blockquote>\n<p>Are you using GPU T4 or the TPU?</p>",
          "votes": null,
          "replies": [
            {
              "id": 3384212,
              "author_name": "pcjimmmy",
              "author_url": "",
              "post_date": "12/31/2025 18:09:23",
              "content": "<p>TPU not permitted for submissions in the competition.</p>",
              "votes": null,
              "replies": [
                {
                  "id": 3384464,
                  "author_name": "simonkosgei",
                  "author_url": "",
                  "post_date": "01/01/2026 09:59:21",
                  "content": "<p>Oh, yeah. Got it.</p>",
                  "votes": null,
                  "replies": []
                }
              ]
            }
          ]
        },
        {
          "id": 3384276,
          "author_name": "mugishapacifique",
          "author_url": "",
          "post_date": "12/31/2025 21:10:48",
          "content": "<p><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/617680#3319159\" target=\"_blank\">Shanzhong8</a>\nWhat he has said it true, you need to make sure you are only performing inference in the submission notebook by setting train to False. This will make the notebook to run only in minutes until the complete scoring !!</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3319702,
      "author_name": "jweariahoquenowrin",
      "author_url": "",
      "post_date": "11/12/2025 02:11:52",
      "content": "<p>Same….It is running for more than 3 hours even though the submission.csv was created a long time ago. I am adding my code herein</p>\n<h1>====================================================================================</h1>\n<h1>Complete Biomass Prediction Pipeline - All Models + Ensemble</h1>\n<h1>====================================================================================</h1>\n<p>import os, gc, warnings, json\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom pathlib import Path\nfrom tqdm import tqdm, tqdm_notebook\nfrom PIL import Image\nfrom dataclasses import dataclass, field</p>\n<p>import torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F</p>\n<p>from transformers import AutoImageProcessor, AutoModel\nimport timm\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2</p>\n<p>from sklearn.preprocessing import StandardScaler\nfrom sklearn.feature_selection import VarianceThreshold\nfrom sklearn.linear_model import ElasticNetCV, Ridge\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.pipeline import make_pipeline</p>\n<p>import lightgbm as lgb\nimport catboost</p>\n<p>warnings.filterwarnings(\"ignore\")\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\"\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")</p>\n<h1>====================================================================================</h1>\n<h1>MODEL 1: DINOv2-Giant + ElasticNetCV</h1>\n<h1>====================================================================================</h1>\n<p>def extract_dinov2_features(model, processor, img_paths, cache_name):\n    \"\"\"Extract DINOv2 embeddings with caching\"\"\"\n    if os.path.exists(cache_name):\n        print(f\"✅ Loaded cached features: {cache_name}\")\n        return np.load(cache_name)</p>\n<pre><code>feats = \nmodel()\nwith torch(), torch():\n       (img_paths, desc=):\n        with Image(path) as :\n            inputs = (images=, return_tensors=)(DEVICE)\n            outputs = (**inputs)\n            emb = outputs(dim=)()()\n            feats(emb)\nfeats = np(feats, axis=)\nnp(cache_name, feats)\nreturn feats\n</code></pre>\n<p>def run_model1_dinov2(root_path):\n    \"\"\"DINOv2-Giant + ElasticNetCV\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 1: DINOv2-Giant + ElasticNetCV\")\n    print(\"=\"</em>80)</p>\n<pre><code>processor = AutoImageProcessor.from_pretrained(f)\nmodel = AutoModel.from_pretrained(f).to(DEVICE)\n\ntrain_df = pd.read_csv(os.path.(root_path, ))\ntrain_df[] = train_df[].( x: x.()[])\ntarget_mapping = {\n    : , : , : ,\n    : , : \n}\n\nunique_imgs = train_df.drop_duplicates().reset_index(drop=True)\nimg_paths = [os.path.(root_path, p)  p  unique_imgs[]]\nfeats = extract_dinov2_features(model, processor, img_paths, )\n\ny_full = .zeros((len(unique_imgs), ))\n ,   train_df.iterrows():\n    idx = unique_imgs.index[unique_imgs[] == []][]\n    y_full[idx, target_mapping[[]]] = []\n\nkf = KFold(n_splits=, shuffle=True, random_state=)\noof = .zeros_like(y_full)\nregressors = [[]    ()]\n\n t  ():\n    y = y_full[:, t]\n     fold, (, va)  enumerate(kf.(feats)):\n        model_reg = make_pipeline(\n            StandardScaler(),\n            ElasticNetCV(l1_ratio=[, , , , ],\n                       alphas=.logspace(-, , ), =, n_jobs=-, max_iter=)\n        )\n        model_reg.fit(feats[], y[])\n        oof[va, t] = model_reg.predict(feats[va])\n        regressors[t].(model_reg)\n\noof_df = pd.DataFrame(oof, =target_mapping.keys())\noof_df[] = unique_imgs[]\noof_df.to_csv(, index=False)\n\n# Test inference\ntest_df = pd.read_csv(os.path.(root_path, ))\ntest_unique = test_df.drop_duplicates().reset_index(drop=True)\ntest_paths = [os.path.(root_path, p)  p  test_unique[]]\ntest_feats = extract_dinov2_features(model, processor, test_paths, )\n\npreds = .zeros((len(test_feats), ))\n t  ():\n    fold_preds = .column_stack([reg.predict(test_feats)  reg  regressors[t]])\n    preds[:, t] = fold_preds.(axis=)\n\npreds = .clip(preds, , None)\npreds_df = pd.DataFrame(preds, =target_mapping.keys())\npreds_df[] = test_unique[]\n\nsub = test_df.()\n   target_mapping.keys():\n    sub.loc[sub[] == , ] = \\\n        sub[].(preds_df.set_index()[])\nsub[[, ]].to_csv(, index=False)\n\n model, processor\ngc.collect()\ntorch.cuda.empty_cache()\n()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MODEL 2: ConvNeXt-Tiny</h1>\n<h1>====================================================================================</h1>\n<p><a href=\"https://www.kaggle.com/dataclass\" target=\"_blank\">@dataclass</a>\nclass ConvNextConfig:\n    base_path: Path = Path(\"/kaggle/input/csiro-biomass\")\n    model_dir: Path = Path(\"/kaggle/input/csiro-exp3/convnext_exp3\")\n    model_name: str = \"convnext_tiny\"\n    img_size: int = 1000\n    batch_size: int = 1\n    num_workers: int = 1\n    n_folds: int = 5\n    device: torch.device = field(default_factory=lambda: DEVICE)</p>\n<p>class BiomassDataset(Dataset):\n    def <strong>init</strong>(self, df, transform, image_dir):\n        self.df = df\n        self.image_paths = df[\"image_path\"].values\n        self.transform = transform\n        self.image_dir = image_dir</p>\n<pre><code> ():\n     (.df)\n\n ():\n    path = Path(.image_paths[idx])\n    full = .image_dir / path.name\n    img = cv2.imread((full))\n     img  :\n        img = np.zeros((, , ), np.uint8)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    h, w, _ = img.shape\n    mid = w // \n    l, r = img[:, :mid], img[:, mid:]\n     .transform(image=l)[], .transform(image=r)[]\n</code></pre>\n<p>class BiomassModel(nn.Module):\n    def <strong>init</strong>(self, model_name=\"convnext_tiny\"):\n        super().<strong>init</strong>()\n        self.backbone = timm.create_model(model_name, pretrained=False,\n                                        num_classes=0, global_pool=\"avg\")\n        nf = self.backbone.num_features\n        nc = nf * 2\n        def head():\n            return nn.Sequential(nn.Linear(nc, 768), nn.GELU(), nn.Linear(768, 1))\n        self.head_total = head()\n        self.head_gdm = head()\n        self.head_green = head()</p>\n<pre><code>def forward(, l, r):\n    fl, fr = .backbone(l), .backbone(r)\n     = torch.cat([fl, fr], )\n     .head_total(), .head_gdm(), .head_green()\n</code></pre>\n<p>def get_tta(img_size):\n    base = [A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2()]\n    return [\n        A.Compose([A.Resize(img_size, img_size), *base]),\n        A.Compose([A.HorizontalFlip(p=1), A.Resize(img_size, img_size), *base]),\n        A.Compose([A.VerticalFlip(p=1), A.Resize(img_size, img_size), *base]),\n    ]</p>\n<p>def run_model2_convnext():\n    \"\"\"ConvNeXt-Tiny ensemble inference\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 2: ConvNeXt-Tiny\")\n    print(\"=\"</em>80)</p>\n<pre><code>cfg = ConvNextConfig()\nmodels = []\n f  range(cfg.n_folds):\n    path = cfg.model_dir / f\n    model = BiomassModel(cfg.model_name)\n     = torch.(path, map_location=cfg.device)\n     = {k.replace(, ): v  k, v  .items()}\n    model.load_state_dict(, strict=False)\n    model.(cfg.device).eval()\n    models.append(model)\n\ndf_test = pd.read_csv(cfg.base_path / )\ndf_unique = df_test.drop_duplicates().reset_index(=True)\n\ntta = get_tta(cfg.img_size)\n = {: [], : [], : []}\n\n tr  tta:\n    dl = DataLoader(BiomassDataset(df_unique, tr, cfg.base_path / ),\n                   batch_size=cfg.batch_size, num_workers=cfg.num_workers)\n    part = {: [], : [], : []}\n\n    with torch.no_grad():\n         l, r  tqdm(dl, desc=):\n            l, r = l.(cfg.device), r.(cfg.device)\n            tmp = {: [], : [], : []}\n            with torch.cuda.amp.autocast():\n                 m  models:\n                    t, g, g2 = m(l, r)\n                    tmp[].append(t.cpu())\n                    tmp[].append(g.cpu())\n                    tmp[].append(g2.cpu())\n             k  tmp:\n                part[k].append(torch.mean(torch.stack(tmp[k]), ))\n\n     k  :\n        [k].append(torch.cat(part[k]).numpy().ravel())\n\npreds = {k: np.mean(v, )  k, v  .items()}\ntotal, gdm, green = preds[], preds[], preds[]\nclover = np.maximum(, gdm - green)\ndead = np.maximum(, total - gdm)\n\nwide = pd.DataFrame({\n    : df_unique[],\n    : green, : dead, : clover,\n    : gdm, : total\n})\n\nlong = wide.melt(id_vars=, var_name=, value_name=)\nsub = pd.merge(df_test[[, , ]],\n              long, =[, ], how=)\nsub[[, ]].to_csv(, index=False)\n\ndel models\ngc.collect()\ntorch.cuda.empty_cache()\nprint()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MODEL 3: SigLIP + Ensemble (ElasticNet + LightGBM + CatBoost)</h1>\n<h1>====================================================================================</h1>\n<p>LABELS = [\"Dry_Clover_g\", \"Dry_Dead_g\", \"Dry_Green_g\", \"Dry_Total_g\", \"GDM_g\"]\nWEIGHTS = {\"Dry_Green_g\": 0.1, \"Dry_Dead_g\": 0.1, \"Dry_Clover_g\": 0.1,\n          \"GDM_g\": 0.2, \"Dry_Total_g\": 0.5}</p>\n<p>def weighted_r2(y, t):\n    w = np.array([WEIGHTS[k] for k in LABELS])\n    ssr = np.average((y - t) ** 2, weights=w, axis=1).mean()\n    ym = np.average(y, weights=w, axis=1).mean()\n    sst = np.average((y - ym) ** 2, weights=w, axis=1).mean()\n    return 1 - ssr / sst</p>\n<p>def extract_siglip_features(paths, tag, data_path, model_path):\n    cache = Path(f\"siglip_{tag}.npy\")\n    if cache.exists():\n        return np.load(cache)</p>\n<pre><code>proc = AutoImageProcessor(model_path)\nmodel = AutoModel(model_path)(DEVICE)()\nfeats = \n\nwith torch(), torch():\n       ((, (paths), ), desc=f):\n        imgs = ]\n        inp = (images=imgs, return_tensors=)(DEVICE)\n        f = model(**inp)\n        f = F(f, dim=-)\n        feats(f()())\n\narr = np(feats, )\nnp(cache, arr)\nreturn arr\n</code></pre>\n<p>def run_model3_siglip(root_path):\n    \"\"\"SigLIP + Triple Ensemble\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"MODEL 3: SigLIP + Ensemble\")\n    print(\"=\"</em>80)</p>\n<pre><code>data_path = Path(root_path)\nmodel_path = Path()\n\n\ndf = pl.read_csv(data_path / )\ndf = (df.with_columns([\n        pl.when(pl.col() == x).then(pl.col()).alias(x)\n         x  LABELS\n    ]).group_by().agg(\n        [pl.col(x).mean()  x  LABELS] +\n        [pl.concat_str([, ], =).alias(\"group\").first()]\n    ).sort())\n\nX = extract_siglip_features(df[].to_list(), , data_path, model_path)\ny = df.select(LABELS).to_numpy()\ng = df[].to_numpy()\n\nvt = VarianceThreshold(1e-6)\nX = vt.fit_transform(X)\n\n\ntest_df = pl.read_csv(data_path / )\ntest_unique = test_df.group_by().len().sort()\nXt = extract_siglip_features(test_unique[].to_list(), , data_path, model_path)\nXt = vt.transform(Xt)\n\n\ndef crossval(make_model, X, y, g, Xt):\n    gkf = GroupKFold(5)\n    o = np.zeros_like(y)\n    p = np.zeros((len(Xt), y.shape[1]))\n     i, (tr, va)  enumerate(gkf.split(X, y, =g)):\n        yp = np.zeros_like(y[va])\n         t  range(y.shape[1]):\n            m = make_model()\n            m.fit(X[tr], y[tr, t])\n            yp[:, t] = m.predict(X[va])\n            p[:, t] += m.predict(Xt) / 5\n        o[va] = yp\n    return o, p\n\n\ndef mk_elastic():\n    return make_pipeline(\n        StandardScaler(),\n        ElasticNetCV(l1_ratio=[.5, .7, .9, 1], =np.logspace(-4, 1, 20),\n                    =3, =5000))\no1, p1 = crossval(mk_elastic, X, y, g, Xt)\n\n\ndef mk_lgb():\n    return lgb.LGBMRegressor(=200, =.07, =48,\n                            =.8, =.8, =1,\n                            =.001, =10,\n                            =-1, =-1, =, =42)\no2, p2 = crossval(mk_lgb, X, y, g, Xt)\n\n\ndef mk_cat():\n    return catboost.CatBoostRegressor(=200, =.05, =6,\n                                     =2, =42, =,\n                                     =)\no3, p3 = crossval(mk_cat, X, y, g, Xt)\n\n\no = (o1 + o2 + o3) / 3\np = (p1 + p2 + p3) / 3\n(f)\n\n\no_df = df.select().to_pandas()\no_df[LABELS] = o\no_df.to_csv(, =)\n\n\npred_df = pl.DataFrame(p.clip(0), =LABELS)\npred_with_id = pl.concat([test_unique.select(), pred_df], =)\nsub = (test_df.join(pred_with_id, =)\n      .with_columns([pl.coalesce(*[\n          pl.when(pl.col() == x).then(pl.col(x))\n           x  LABELS\n      ]).alias()])\n      .select([, ]))\nsub.write_csv()\n()\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>FINAL ENSEMBLE</h1>\n<h1>====================================================================================</h1>\n<p>def create_final_ensemble():\n    \"\"\"Dynamic weighted ensemble\"\"\"\n    print(\"\\n\" + \"=\"<em>80)\n    print(\"FINAL ENSEMBLE\")\n    print(\"=\"</em>80)</p>\n<pre><code>files = {\n    : ,\n    : ,\n    : ,\n}\n\noof_files = {\n    : ,\n    : None,\n    : ,\n}\n\ndfs = {k: pd.read_csv(v).set_index()  k, v  files.items()}\nweights = np.array([0.25, 0.40, 0.35])\n\n\nvalid_oofs = {k: v  k, v  oof_files.items()  v  os.path.exists(v)}\n len(valid_oofs) &gt;= 2:\n    try:\n        oof_dfs = {k: pd.read_csv(v)  k, v  valid_oofs.items()}\n         df  oof_dfs.values():\n            df.drop(columns=[], =, =)\n\n        common_cols = set.intersection(*((df.columns)  df  oof_dfs.values()))\n        ref = next(iter(oof_dfs))\n        y_true = oof_dfs[ref][list(common_cols)].mean(=1).values\n\n        X = np.vstack([\n            oof_dfs[][list(common_cols)].mean(=1).values,\n            oof_dfs.(, oof_dfs[ref])[list(common_cols)].mean(=1).values,\n            oof_dfs[][list(common_cols)].mean(=1).values,\n        ]).T\n\n        ridge = Ridge(=, =42)\n        ridge.fit(X, y_true)\n        learned_w = ridge.coef_ / np.sum(ridge.coef_)\n\n          np.any(np.isnan(learned_w))  np.sum(learned_w) &gt; 0:\n            weights = learned_w\n            (f)\n    except Exception as e:\n        (f)\n\nfinal = (\n    weights[0] * dfs[] +\n    weights[1] * dfs[] +\n    weights[2] * dfs[]\n).clip(=0)\n\nfinal.to_csv()\n()\n(final.head())\n</code></pre>\n<h1>====================================================================================</h1>\n<h1>MAIN EXECUTION</h1>\n<h1>====================================================================================</h1>\n<p>def main():\n    ROOT = \"/kaggle/input/csiro-biomass\"</p>\n<pre><code>( + )\n()\n()\n\n\nrun_model1_dinov2(ROOT)\nrun_model2_convnext()\nrun_model3_siglip(ROOT)\n\n\ncreate_final_ensemble()\n\n( + )\n()\n()\n</code></pre>\n<p>if <strong>name</strong> == \"<strong>main</strong>\":\n    main()</p>",
      "votes": null,
      "replies": [
        {
          "id": 3320786,
          "author_name": "anmatngu",
          "author_url": "",
          "post_date": "11/12/2025 19:42:44",
          "content": "<p>My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete.</p>\n<p>The issue doesn’t seem to come from the notebook or the code itself, it’s likely on Kaggle’s backend. You can try using F12 to monitor the network activity and track what’s happening in real time.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3320604,
      "author_name": "habiburrahman15",
      "author_url": "",
      "post_date": "11/12/2025 16:42:20",
      "content": "<p>Same, are you able to solve the problem?  My notebook created the .csv file nicely, but it got stuck showing \"error.\" </p>",
      "votes": null,
      "replies": [
        {
          "id": 3320791,
          "author_name": "anmatngu",
          "author_url": "",
          "post_date": "11/12/2025 19:46:54",
          "content": "<p>Did your notebook get rejected immediately after submission with an error message, or did it run until hitting the competition timeout limit (around 9 hours)?</p>\n<p>If it’s the first case, check your submission format, predictions, and try running a smaller version of the code to identify any errors.</p>\n<p>If that’s not the issue, then it’s probably not related to your notebook or code, the problem is likely on Kaggle’s backend.\nMy own workaround is to use GPU and reduce the model size when uploading to Kaggle. It’s not a perfect fix, since I still have to wait about an hour for grading to finish, but hey, it’s better than nothing.</p>\n<p>You can also open the browser’s developer tools (F12) to monitor the network activity and see what’s going on in real time.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3320649,
      "author_name": "iravkr",
      "author_url": "",
      "post_date": "11/12/2025 17:19:32",
      "content": "<p>I have total four submission instances where it ran for 9 hours and then timeout. I dnt understand why will it run for 9 hours even? Now i am loosing my motivation to try different approaches. you wait for 9 hours and then its timeout.</p>",
      "votes": null,
      "replies": [
        {
          "id": 3320788,
          "author_name": "anmatngu",
          "author_url": "",
          "post_date": "11/12/2025 19:43:49",
          "content": "<p>My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete, but hey, better than nothing, right?</p>\n<p>The issue doesn’t seem to come from the notebook or the code itself; it’s most likely on Kaggle’s backend. You can try using F12 to monitor the network activity and see what’s happening in real time.</p>",
          "votes": null,
          "replies": []
        }
      ]
    },
    {
      "id": 3320778,
      "author_name": "mrpies",
      "author_url": "",
      "post_date": "11/12/2025 19:31:43",
      "content": "<p>Same, my notebook creates the csv perfectly but it refuses to submit</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3319094": "My latest submission has been in “Pending” status for about 8 hours. No error, no timeout, just no update. Has anyone else experienced prolonged hangs like this? Could it be an issue with the submission format, evaluation server, or backend queue? Any advice or host clarification would be appreciated 😁.\n\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-forum-message-attachments/o/inbox%2F12877917%2F6da66fc4fab1e5072f059d557277c8c7%2FScreenshot%202025-11-11%20205138.png?generation=1762869108934710&alt=media)\n\n***⁉️ Update:***\n> It turns out the issue isn’t from the notebook or the code itself, but likely from Kaggle’s backend. My workaround is to use GPU and reduce the model size when uploading.\n\n> It’s not a perfect fix, since I still have to wait about an hour for grading to complete, but it definitely runs faster and helps avoid long queue delays. You can also open your browser’s developer tools (F12) to monitor network activity and see what’s happening in real time.",
    "3319146": "Is it were something wrong with evaluation format, you will get an error instead.\nI am not really sure what exactly you mean by 'evaluation server' and 'backend queue'.\n\nWhen you save the notebook, see the time it took to process 1 (given) test image. multiply that by ~700.",
    "3319159": "My submit time is like 5mins. Are you training your model in submission notebook?",
    "3319183": "I trained locally on my PC and only made a Kaggle notebook for submission (with checkpoints from training, uploaded directly to Kaggle), so it’s not related to training at all",
    "3319189": "My notebook runtime was only ~5m 34s, but the submission stayed “running” until it timed out. No idea if it’s the checkpoint I uploaded, the way I load it, or something on Kaggle’s side.",
    "3319207": "Suggest you add option in your code to predict on the train data rather than the test.  Run All on the notebook see how long it takes to predict on the 357 train images.  \n\nThe image you shared indicated the notebook was running - not Pending.  If it was truly pending than probably a kaggle issue - i have that only once so far in this competition, but often over the years.",
    "3319702": "Same....It is running for more than 3 hours even though the submission.csv was created a long time ago. I am adding my code herein\n\n\n\n# ====================================================================================\n# Complete Biomass Prediction Pipeline - All Models + Ensemble\n# ====================================================================================\n\nimport os, gc, warnings, json\nimport numpy as np\nimport pandas as pd\nimport polars as pl\nfrom pathlib import Path\nfrom tqdm import tqdm, tqdm_notebook\nfrom PIL import Image\nfrom dataclasses import dataclass, field\n\nimport torch\nfrom torch import nn\nfrom torch.utils.data import Dataset, DataLoader\nimport torch.nn.functional as F\n\nfrom transformers import AutoImageProcessor, AutoModel\nimport timm\nimport cv2\nimport albumentations as A\nfrom albumentations.pytorch import ToTensorV2\n\nfrom sklearn.preprocessing import StandardScaler\nfrom sklearn.feature_selection import VarianceThreshold\nfrom sklearn.linear_model import ElasticNetCV, Ridge\nfrom sklearn.model_selection import KFold, GroupKFold\nfrom sklearn.pipeline import make_pipeline\n\nimport lightgbm as lgb\nimport catboost\n\nwarnings.filterwarnings(\"ignore\")\nos.environ[\"TF_CPP_MIN_LOG_LEVEL\"] = \"3\"\nDEVICE = torch.device(\"cuda\" if torch.cuda.is_available() else \"cpu\")\n\n# ====================================================================================\n# MODEL 1: DINOv2-Giant + ElasticNetCV\n# ====================================================================================\n\ndef extract_dinov2_features(model, processor, img_paths, cache_name):\n    \"\"\"Extract DINOv2 embeddings with caching\"\"\"\n    if os.path.exists(cache_name):\n        print(f\"✅ Loaded cached features: {cache_name}\")\n        return np.load(cache_name)\n    \n    feats = []\n    model.eval()\n    with torch.no_grad(), torch.cuda.amp.autocast():\n        for path in tqdm(img_paths, desc=\"Extracting DINOv2\"):\n            with Image.open(path) as img:\n                inputs = processor(images=img, return_tensors=\"pt\").to(DEVICE)\n                outputs = model(**inputs)\n                emb = outputs.last_hidden_state.mean(dim=1).cpu().numpy()\n                feats.append(emb)\n    feats = np.concatenate(feats, axis=0)\n    np.save(cache_name, feats)\n    return feats\n\ndef run_model1_dinov2(root_path):\n    \"\"\"DINOv2-Giant + ElasticNetCV\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 1: DINOv2-Giant + ElasticNetCV\")\n    print(\"=\"*80)\n    \n    processor = AutoImageProcessor.from_pretrained(f\"/kaggle/input/dinov2/pytorch/giant/1\")\n    model = AutoModel.from_pretrained(f\"/kaggle/input/dinov2/pytorch/giant/1\").to(DEVICE)\n    \n    train_df = pd.read_csv(os.path.join(root_path, \"train.csv\"))\n    train_df[\"target_name\"] = train_df[\"sample_id\"].apply(lambda x: x.split(\"__\")[1])\n    target_mapping = {\n        \"Dry_Clover_g\": 0, \"Dry_Dead_g\": 1, \"Dry_Green_g\": 2,\n        \"Dry_Total_g\": 3, \"GDM_g\": 4\n    }\n    \n    unique_imgs = train_df.drop_duplicates(\"image_path\").reset_index(drop=True)\n    img_paths = [os.path.join(root_path, p) for p in unique_imgs[\"image_path\"]]\n    feats = extract_dinov2_features(model, processor, img_paths, \"train_feats_dino.npy\")\n    \n    y_full = np.zeros((len(unique_imgs), 5))\n    for _, row in train_df.iterrows():\n        idx = unique_imgs.index[unique_imgs[\"image_path\"] == row[\"image_path\"]][0]\n        y_full[idx, target_mapping[row[\"target_name\"]]] = row[\"target\"]\n    \n    kf = KFold(n_splits=5, shuffle=True, random_state=42)\n    oof = np.zeros_like(y_full)\n    regressors = [[] for _ in range(5)]\n    \n    for t in range(5):\n        y = y_full[:, t]\n        for fold, (tr, va) in enumerate(kf.split(feats)):\n            model_reg = make_pipeline(\n                StandardScaler(),\n                ElasticNetCV(l1_ratio=[0.3, 0.5, 0.7, 0.9, 1.0],\n                           alphas=np.logspace(-4, 1, 30), cv=3, n_jobs=-1, max_iter=5000)\n            )\n            model_reg.fit(feats[tr], y[tr])\n            oof[va, t] = model_reg.predict(feats[va])\n            regressors[t].append(model_reg)\n    \n    oof_df = pd.DataFrame(oof, columns=target_mapping.keys())\n    oof_df[\"image_path\"] = unique_imgs[\"image_path\"]\n    oof_df.to_csv(\"oof_model_m1.csv\", index=False)\n    \n    # Test inference\n    test_df = pd.read_csv(os.path.join(root_path, \"test.csv\"))\n    test_unique = test_df.drop_duplicates(\"image_path\").reset_index(drop=True)\n    test_paths = [os.path.join(root_path, p) for p in test_unique[\"image_path\"]]\n    test_feats = extract_dinov2_features(model, processor, test_paths, \"test_feats_dino.npy\")\n    \n    preds = np.zeros((len(test_feats), 5))\n    for t in range(5):\n        fold_preds = np.column_stack([reg.predict(test_feats) for reg in regressors[t]])\n        preds[:, t] = fold_preds.mean(axis=1)\n    \n    preds = np.clip(preds, 0, None)\n    preds_df = pd.DataFrame(preds, columns=target_mapping.keys())\n    preds_df[\"image_path\"] = test_unique[\"image_path\"]\n    \n    sub = test_df.copy()\n    for col in target_mapping.keys():\n        sub.loc[sub[\"target_name\"] == col, \"target\"] = \\\n            sub[\"image_path\"].map(preds_df.set_index(\"image_path\")[col])\n    sub[[\"sample_id\", \"target\"]].to_csv(\"submission_dino_giant.csv\", index=False)\n    \n    del model, processor\n    gc.collect()\n    torch.cuda.empty_cache()\n    print(\"✅ Model 1 complete\")\n\n# ====================================================================================\n# MODEL 2: ConvNeXt-Tiny\n# ====================================================================================\n\n@dataclass\nclass ConvNextConfig:\n    base_path: Path = Path(\"/kaggle/input/csiro-biomass\")\n    model_dir: Path = Path(\"/kaggle/input/csiro-exp3/convnext_exp3\")\n    model_name: str = \"convnext_tiny\"\n    img_size: int = 1000\n    batch_size: int = 1\n    num_workers: int = 1\n    n_folds: int = 5\n    device: torch.device = field(default_factory=lambda: DEVICE)\n\nclass BiomassDataset(Dataset):\n    def __init__(self, df, transform, image_dir):\n        self.df = df\n        self.image_paths = df[\"image_path\"].values\n        self.transform = transform\n        self.image_dir = image_dir\n    \n    def __len__(self):\n        return len(self.df)\n    \n    def __getitem__(self, idx):\n        path = Path(self.image_paths[idx])\n        full = self.image_dir / path.name\n        img = cv2.imread(str(full))\n        if img is None:\n            img = np.zeros((1000, 2000, 3), np.uint8)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        h, w, _ = img.shape\n        mid = w // 2\n        l, r = img[:, :mid], img[:, mid:]\n        return self.transform(image=l)[\"image\"], self.transform(image=r)[\"image\"]\n\nclass BiomassModel(nn.Module):\n    def __init__(self, model_name=\"convnext_tiny\"):\n        super().__init__()\n        self.backbone = timm.create_model(model_name, pretrained=False,\n                                        num_classes=0, global_pool=\"avg\")\n        nf = self.backbone.num_features\n        nc = nf * 2\n        def head():\n            return nn.Sequential(nn.Linear(nc, 768), nn.GELU(), nn.Linear(768, 1))\n        self.head_total = head()\n        self.head_gdm = head()\n        self.head_green = head()\n    \n    def forward(self, l, r):\n        fl, fr = self.backbone(l), self.backbone(r)\n        x = torch.cat([fl, fr], 1)\n        return self.head_total(x), self.head_gdm(x), self.head_green(x)\n\ndef get_tta(img_size):\n    base = [A.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), ToTensorV2()]\n    return [\n        A.Compose([A.Resize(img_size, img_size), *base]),\n        A.Compose([A.HorizontalFlip(p=1), A.Resize(img_size, img_size), *base]),\n        A.Compose([A.VerticalFlip(p=1), A.Resize(img_size, img_size), *base]),\n    ]\n\ndef run_model2_convnext():\n    \"\"\"ConvNeXt-Tiny ensemble inference\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 2: ConvNeXt-Tiny\")\n    print(\"=\"*80)\n    \n    cfg = ConvNextConfig()\n    models = []\n    for f in range(cfg.n_folds):\n        path = cfg.model_dir / f\"best_model_fold{f}.pth\"\n        model = BiomassModel(cfg.model_name)\n        state = torch.load(path, map_location=cfg.device)\n        state = {k.replace(\"module.\", \"\"): v for k, v in state.items()}\n        model.load_state_dict(state, strict=False)\n        model.to(cfg.device).eval()\n        models.append(model)\n    \n    df_test = pd.read_csv(cfg.base_path / \"test.csv\")\n    df_unique = df_test.drop_duplicates(\"image_path\").reset_index(drop=True)\n    \n    tta = get_tta(cfg.img_size)\n    out = {\"total\": [], \"gdm\": [], \"green\": []}\n    \n    for tr in tta:\n        dl = DataLoader(BiomassDataset(df_unique, tr, cfg.base_path / \"test\"),\n                       batch_size=cfg.batch_size, num_workers=cfg.num_workers)\n        part = {\"total\": [], \"gdm\": [], \"green\": []}\n        \n        with torch.no_grad():\n            for l, r in tqdm(dl, desc=\"Inference\"):\n                l, r = l.to(cfg.device), r.to(cfg.device)\n                tmp = {\"total\": [], \"gdm\": [], \"green\": []}\n                with torch.cuda.amp.autocast():\n                    for m in models:\n                        t, g, g2 = m(l, r)\n                        tmp[\"total\"].append(t.cpu())\n                        tmp[\"gdm\"].append(g.cpu())\n                        tmp[\"green\"].append(g2.cpu())\n                for k in tmp:\n                    part[k].append(torch.mean(torch.stack(tmp[k]), 0))\n        \n        for k in out:\n            out[k].append(torch.cat(part[k]).numpy().ravel())\n    \n    preds = {k: np.mean(v, 0) for k, v in out.items()}\n    total, gdm, green = preds[\"total\"], preds[\"gdm\"], preds[\"green\"]\n    clover = np.maximum(0, gdm - green)\n    dead = np.maximum(0, total - gdm)\n    \n    wide = pd.DataFrame({\n        \"image_path\": df_unique[\"image_path\"],\n        \"Dry_Green_g\": green, \"Dry_Dead_g\": dead, \"Dry_Clover_g\": clover,\n        \"GDM_g\": gdm, \"Dry_Total_g\": total\n    })\n    \n    long = wide.melt(id_vars=\"image_path\", var_name=\"target_name\", value_name=\"target\")\n    sub = pd.merge(df_test[[\"sample_id\", \"image_path\", \"target_name\"]],\n                  long, on=[\"image_path\", \"target_name\"], how=\"left\")\n    sub[[\"sample_id\", \"target\"]].to_csv(\"submission_ConvnextTiny.csv\", index=False)\n    \n    del models\n    gc.collect()\n    torch.cuda.empty_cache()\n    print(\"✅ Model 2 complete\")\n\n# ====================================================================================\n# MODEL 3: SigLIP + Ensemble (ElasticNet + LightGBM + CatBoost)\n# ====================================================================================\n\nLABELS = [\"Dry_Clover_g\", \"Dry_Dead_g\", \"Dry_Green_g\", \"Dry_Total_g\", \"GDM_g\"]\nWEIGHTS = {\"Dry_Green_g\": 0.1, \"Dry_Dead_g\": 0.1, \"Dry_Clover_g\": 0.1,\n          \"GDM_g\": 0.2, \"Dry_Total_g\": 0.5}\n\ndef weighted_r2(y, t):\n    w = np.array([WEIGHTS[k] for k in LABELS])\n    ssr = np.average((y - t) ** 2, weights=w, axis=1).mean()\n    ym = np.average(y, weights=w, axis=1).mean()\n    sst = np.average((y - ym) ** 2, weights=w, axis=1).mean()\n    return 1 - ssr / sst\n\ndef extract_siglip_features(paths, tag, data_path, model_path):\n    cache = Path(f\"siglip_{tag}.npy\")\n    if cache.exists():\n        return np.load(cache)\n    \n    proc = AutoImageProcessor.from_pretrained(model_path)\n    model = AutoModel.from_pretrained(model_path).to(DEVICE).eval()\n    feats = []\n    \n    with torch.no_grad(), torch.cuda.amp.autocast():\n        for i in tqdm(range(0, len(paths), 8), desc=f\"SigLIP {tag}\"):\n            imgs = [Image.open(data_path / p).convert(\"RGB\") for p in paths[i:i+8]]\n            inp = proc(images=imgs, return_tensors=\"pt\").to(DEVICE)\n            f = model.get_image_features(**inp)\n            f = F.normalize(f, dim=-1)\n            feats.append(f.cpu().numpy())\n    \n    arr = np.concatenate(feats, 0)\n    np.save(cache, arr)\n    return arr\n\ndef run_model3_siglip(root_path):\n    \"\"\"SigLIP + Triple Ensemble\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"MODEL 3: SigLIP + Ensemble\")\n    print(\"=\"*80)\n    \n    data_path = Path(root_path)\n    model_path = Path(\"/kaggle/input/google-siglip-so400m-patch14-384/transformers/default/1\")\n    \n    # Train\n    df = pl.read_csv(data_path / \"train.csv\")\n    df = (df.with_columns([\n            pl.when(pl.col(\"target_name\") == x).then(pl.col(\"target\")).alias(x)\n            for x in LABELS\n        ]).group_by(\"image_path\").agg(\n            [pl.col(x).mean() for x in LABELS] +\n            [pl.concat_str([\"Sampling_Date\", \"State\"], separator=\"_\").alias(\"group\").first()]\n        ).sort(\"image_path\"))\n    \n    X = extract_siglip_features(df[\"image_path\"].to_list(), \"train\", data_path, model_path)\n    y = df.select(LABELS).to_numpy()\n    g = df[\"group\"].to_numpy()\n    \n    vt = VarianceThreshold(1e-6)\n    X = vt.fit_transform(X)\n    \n    # Test\n    test_df = pl.read_csv(data_path / \"test.csv\")\n    test_unique = test_df.group_by(\"image_path\").len().sort(\"image_path\")\n    Xt = extract_siglip_features(test_unique[\"image_path\"].to_list(), \"test\", data_path, model_path)\n    Xt = vt.transform(Xt)\n    \n    # Cross-validation function\n    def crossval(make_model, X, y, g, Xt):\n        gkf = GroupKFold(5)\n        o = np.zeros_like(y)\n        p = np.zeros((len(Xt), y.shape[1]))\n        for i, (tr, va) in enumerate(gkf.split(X, y, groups=g)):\n            yp = np.zeros_like(y[va])\n            for t in range(y.shape[1]):\n                m = make_model()\n                m.fit(X[tr], y[tr, t])\n                yp[:, t] = m.predict(X[va])\n                p[:, t] += m.predict(Xt) / 5\n            o[va] = yp\n        return o, p\n    \n    # ElasticNet\n    def mk_elastic():\n        return make_pipeline(\n            StandardScaler(),\n            ElasticNetCV(l1_ratio=[.5, .7, .9, 1], alphas=np.logspace(-4, 1, 20),\n                        cv=3, max_iter=5000))\n    o1, p1 = crossval(mk_elastic, X, y, g, Xt)\n    \n    # LightGBM\n    def mk_lgb():\n        return lgb.LGBMRegressor(n_estimators=200, learning_rate=.07, num_leaves=48,\n                                subsample=.8, colsample_bytree=.8, reg_lambda=1,\n                                min_gain_to_split=.001, min_data_in_leaf=10,\n                                n_jobs=-1, verbose=-1, force_col_wise=True, random_state=42)\n    o2, p2 = crossval(mk_lgb, X, y, g, Xt)\n    \n    # CatBoost\n    def mk_cat():\n        return catboost.CatBoostRegressor(iterations=200, learning_rate=.05, depth=6,\n                                         l2_leaf_reg=2, random_seed=42, verbose=False,\n                                         allow_writing_files=False)\n    o3, p3 = crossval(mk_cat, X, y, g, Xt)\n    \n    # Average ensemble\n    o = (o1 + o2 + o3) / 3\n    p = (p1 + p2 + p3) / 3\n    print(f\"Final Weighted R²: {weighted_r2(y, o):.4f}\")\n    \n    # Save OOF\n    o_df = df.select(\"image_path\").to_pandas()\n    o_df[LABELS] = o\n    o_df.to_csv(\"oof_model_m3.csv\", index=False)\n    \n    # Submission\n    pred_df = pl.DataFrame(p.clip(0), schema=LABELS)\n    pred_with_id = pl.concat([test_unique.select(\"image_path\"), pred_df], how=\"horizontal\")\n    sub = (test_df.join(pred_with_id, on=\"image_path\")\n          .with_columns([pl.coalesce(*[\n              pl.when(pl.col(\"target_name\") == x).then(pl.col(x))\n              for x in LABELS\n          ]).alias(\"target\")])\n          .select([\"sample_id\", \"target\"]))\n    sub.write_csv(\"submission_SigLIP.csv\")\n    print(\"✅ Model 3 complete\")\n\n# ====================================================================================\n# FINAL ENSEMBLE\n# ====================================================================================\n\ndef create_final_ensemble():\n    \"\"\"Dynamic weighted ensemble\"\"\"\n    print(\"\\n\" + \"=\"*80)\n    print(\"FINAL ENSEMBLE\")\n    print(\"=\"*80)\n    \n    files = {\n        \"DINOv2\": \"submission_dino_giant.csv\",\n        \"ConvNeXt\": \"submission_ConvnextTiny.csv\",\n        \"SigLIP\": \"submission_SigLIP.csv\",\n    }\n    \n    oof_files = {\n        \"DINOv2\": \"oof_model_m1.csv\",\n        \"ConvNeXt\": None,\n        \"SigLIP\": \"oof_model_m3.csv\",\n    }\n    \n    dfs = {k: pd.read_csv(v).set_index(\"sample_id\") for k, v in files.items()}\n    weights = np.array([0.25, 0.40, 0.35])\n    \n    # Try learning weights from OOFs\n    valid_oofs = {k: v for k, v in oof_files.items() if v and os.path.exists(v)}\n    if len(valid_oofs) >= 2:\n        try:\n            oof_dfs = {k: pd.read_csv(v) for k, v in valid_oofs.items()}\n            for df in oof_dfs.values():\n                df.drop(columns=[\"image_path\"], inplace=True, errors=\"ignore\")\n            \n            common_cols = set.intersection(*(set(df.columns) for df in oof_dfs.values()))\n            ref = next(iter(oof_dfs))\n            y_true = oof_dfs[ref][list(common_cols)].mean(axis=1).values\n            \n            X = np.vstack([\n                oof_dfs[\"DINOv2\"][list(common_cols)].mean(axis=1).values,\n                oof_dfs.get(\"ConvNeXt\", oof_dfs[ref])[list(common_cols)].mean(axis=1).values,\n                oof_dfs[\"SigLIP\"][list(common_cols)].mean(axis=1).values,\n            ]).T\n            \n            ridge = Ridge(positive=True, random_state=42)\n            ridge.fit(X, y_true)\n            learned_w = ridge.coef_ / np.sum(ridge.coef_)\n            \n            if not np.any(np.isnan(learned_w)) and np.sum(learned_w) > 0:\n                weights = learned_w\n                print(f\"✅ Learned weights: {weights.round(3)}\")\n        except Exception as e:\n            print(f\"⚠️ Using default weights: {e}\")\n    \n    final = (\n        weights[0] * dfs[\"DINOv2\"] +\n        weights[1] * dfs[\"ConvNeXt\"] +\n        weights[2] * dfs[\"SigLIP\"]\n    ).clip(lower=0)\n    \n    final.to_csv(\"submission.csv\")\n    print(\"\\n🎯 Final submission created!\")\n    print(final.head())\n\n# ====================================================================================\n# MAIN EXECUTION\n# ====================================================================================\n\ndef main():\n    ROOT = \"/kaggle/input/csiro-biomass\"\n    \n    print(\"\\n\" + \"=\"*80)\n    print(\"BIOMASS PREDICTION - COMPLETE PIPELINE\")\n    print(\"=\"*80)\n    \n    # Run all models\n    run_model1_dinov2(ROOT)\n    run_model2_convnext()\n    run_model3_siglip(ROOT)\n    \n    # Create final ensemble\n    create_final_ensemble()\n    \n    print(\"\\n\" + \"=\"*80)\n    print(\"✨ PIPELINE COMPLETE!\")\n    print(\"=\"*80)\n\nif __name__ == \"__main__\":\n    main()",
    "3320604": "Same, are you able to solve the problem?  My notebook created the .csv file nicely, but it got stuck showing \"error.\"",
    "3320649": "I have total four submission instances where it ran for 9 hours and then timeout. I dnt understand why will it run for 9 hours even? Now i am loosing my motivation to try different approaches. you wait for 9 hours and then its timeout.",
    "3320778": "Same, my notebook creates the csv perfectly but it refuses to submit",
    "3320784": "Interestingly, when I switched to GPU, the runtime was much faster compared to using the CPU (which was the version I submitted earlier). The notebook finished running and produced the submission file, but it still took about an hour before the grading process completed. 🤣",
    "3320786": "My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete.\n\nThe issue doesn’t seem to come from the notebook or the code itself, it’s likely on Kaggle’s backend. You can try using F12 to monitor the network activity and track what’s happening in real time.",
    "3320788": "My own solution is to use GPU and reduce the model size when uploading to Kaggle. It’s not really an optimal fix, since I still have to wait about an hour for the grading to complete, but hey, better than nothing, right?\n\nThe issue doesn’t seem to come from the notebook or the code itself; it’s most likely on Kaggle’s backend. You can try using F12 to monitor the network activity and see what’s happening in real time.",
    "3320791": "Did your notebook get rejected immediately after submission with an error message, or did it run until hitting the competition timeout limit (around 9 hours)?\n\nIf it’s the first case, check your submission format, predictions, and try running a smaller version of the code to identify any errors.\n\nIf that’s not the issue, then it’s probably not related to your notebook or code, the problem is likely on Kaggle’s backend.\nMy own workaround is to use GPU and reduce the model size when uploading to Kaggle. It’s not a perfect fix, since I still have to wait about an hour for grading to finish, but hey, it’s better than nothing.\n\nYou can also open the browser’s developer tools (F12) to monitor the network activity and see what’s going on in real time.",
    "3383985": "> My submit time is like 5mins. Are you training your model in submission notebook?\n\nAre you using GPU T4 or the TPU?",
    "3384212": "TPU not permitted for submissions in the competition.",
    "3384276": "[Shanzhong8](https://www.kaggle.com/competitions/csiro-biomass/discussion/617680#3319159)\nWhat he has said it true, you need to make sure you are only performing inference in the submission notebook by setting train to False. This will make the notebook to run only in minutes until the complete scoring !!",
    "3384464": "Oh, yeah. Got it."
  },
  "source": "meta"
}