{
  "id": 670977,
  "title": "54th Place Solution: All I Need Is fastai, timm, and DINOv3",
  "url": "/competitions/csiro-biomass/writeups/54th-place-solution-all-i-need-is-fastai-timm-a",
  "author_name": "",
  "post_date": "2026-01-30T16:12:47.873Z",
  "votes": 5,
  "comment_count": 1,
  "views": 0,
  "content": "<p>I would like to thank the competition organizers and Kaggle for creating this interesting challenge.\nThis competition was exactly the kind of image regression competition I had been waiting for.\nThis is my first writeup. I learned a lot from this competition, so I decided to share my solution.\nI hope it will be helpful to everyone!</p>\n<h2>1. Summary</h2>\n<ul>\n<li>Final Results<ul>\n<li>Private LB Score: 0.63</li>\n<li>Rank: 54</li></ul></li>\n<li>Framework<ul>\n<li>fastai🩷</li>\n<li>timm🩷</li></ul></li>\n<li>Models Used<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m</li>\n<li>vit_large_patch16_dinov3.lvd1689m</li></ul></li>\n<li>StratifiedGroupKFold (3 folds)</li>\n</ul>\n<h2>2. Validation Strategy</h2>\n<p>My approach for this competition was inspired by the previously held \"PetFinder.my - Pawpularity Contest\".\nThe Pawpularity competition also required quantifying latent features that are not clearly discernible to the human eye, making it similar to this biomass estimation task where judgment from images alone is difficult.</p>\n<h3>2.1. Kaggle Notebook Environment</h3>\n<ul>\n<li><p>Due to different start times, the Kaggle Notebook environment varied, so standardization was necessary</p></li>\n<li><p>I confirmed that older versions of scikit-learn produced incorrect split results with StratifiedGroupKFold</p>\n<ul>\n<li><a href=\"https://github.com/scikit-learn/scikit-learn/issues/32478\" target=\"_blank\">https://github.com/scikit-learn/scikit-learn/issues/32478</a></li>\n<li><a href=\"https://github.com/scikit-learn/scikit-learn/pull/32540\" target=\"_blank\">https://github.com/scikit-learn/scikit-learn/pull/32540</a></li></ul></li>\n<li><p>2025-11-07 version</p>\n<ul>\n<li>fastai: 2.8.5</li>\n<li>scikit-learn: 1.2.2</li>\n<li>timm: 1.0.19</li>\n<li>torch: 2.6.0+cu124</li></ul></li>\n<li><p>2025-12-17 version</p>\n<ul>\n<li>fastai: 2.8.4</li>\n<li>scikit-learn: 1.6.1</li>\n<li>timm: 1.0.20</li>\n<li>torch: 2.8.0+cu126</li></ul></li>\n<li><p>Standardized environment</p>\n<ul>\n<li>fastai: 2.8.4</li>\n<li>scikit-learn: 1.8.0</li>\n<li>timm: 1.0.24</li>\n<li>torch: 2.8.0+cu126\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2Faa3fa0cabace8ae9537d05cba6fb9d81%2Fenv.jpg?generation=1769832873123173&amp;alt=media\" alt=\"\"></li></ul></li>\n</ul>\n<h3>2.2. Images</h3>\n<ul>\n<li><p>Removed the annotation issue (ID230058600) reported in the discussion</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190</a></li></ul></li>\n<li><p>Confirmed distribution bias in Fescue</p>\n<ul>\n<li>2015/10/6: 11 images</li>\n<li>2015/2/25: 9 images</li>\n<li>2015/5/7: 8 images</li></ul></li>\n<li><p>Confirmed distribution bias in Lucerne (alfalfa)</p>\n<ul>\n<li>2015/1/15: 7 images</li>\n<li>2015/4/1: 10 images</li>\n<li>2015/5/7: 5 images</li></ul></li>\n</ul>\n<h3>2.3. Split Strategy</h3>\n<p>Used 3-fold split to properly handle Fescue and Lucerne (alfalfa)</p>\n<ul>\n<li>CV Strategy<ul>\n<li>StratifiedGroupKFold (3 folds)</li>\n<li>stratify: <code>stratify_label</code></li>\n<li>groups: <code>Sampling_Date</code> + <code>State</code></li></ul></li>\n</ul>\n<pre><code># Create `stratify_label` from species\ndef get_stratify_label(species):\n    if 'Lucerne' in species:\n        return 'Lucerne'\n    elif 'Fescue' in species:\n        return 'Fescue'\n    elif 'Phalaris' in species:\n        return 'Phalaris'\n    elif 'Clover' in species:\n        return 'Clover'\n    else:\n        return 'Other'\n</code></pre>\n<ul>\n<li>Average <code>Dry_Total_g</code> distribution for each seed<ul>\n<li><code>SEEDS = [42, 1, 777, 2024]</code></li></ul></li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>stratify_label</th>\n<th>fold</th>\n<th>42</th>\n<th>1</th>\n<th>777</th>\n<th>2024</th>\n<th>std</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Clover</td>\n<td>0</td>\n<td>38.488704</td>\n<td>40.031428</td>\n<td>40.821862</td>\n<td>40.821862</td>\n<td>1.099880</td>\n</tr>\n<tr>\n<td>Clover</td>\n<td>1</td>\n<td>36.034956</td>\n<td>34.881416</td>\n<td>34.090982</td>\n<td>33.604583</td>\n<td>1.060977</td>\n</tr>\n<tr>\n<td>Clover</td>\n<td>2</td>\n<td>34.221660</td>\n<td>33.740706</td>\n<td>33.740706</td>\n<td>34.221660</td>\n<td>0.277679</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>0</td>\n<td>76.177778</td>\n<td>76.177778</td>\n<td>75.376471</td>\n<td>76.177778</td>\n<td>0.400654</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>1</td>\n<td>46.550000</td>\n<td>91.121053</td>\n<td>103.227273</td>\n<td>46.550000</td>\n<td>29.642796</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>2</td>\n<td>91.121053</td>\n<td>46.550000</td>\n<td>46.550000</td>\n<td>91.121053</td>\n<td>25.733109</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>0</td>\n<td>42.160000</td>\n<td>42.160000</td>\n<td>50.920000</td>\n<td>42.160000</td>\n<td>4.380000</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>1</td>\n<td>75.171429</td>\n<td>50.920000</td>\n<td>42.160000</td>\n<td>75.171429</td>\n<td>16.912791</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>2</td>\n<td>50.920000</td>\n<td>75.171429</td>\n<td>75.171429</td>\n<td>50.920000</td>\n<td>14.001569</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>0</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>0.000000</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>1</td>\n<td>40.413157</td>\n<td>31.913777</td>\n<td>31.913777</td>\n<td>40.413157</td>\n<td>4.907119</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>2</td>\n<td>27.551414</td>\n<td>36.985586</td>\n<td>36.985586</td>\n<td>27.551414</td>\n<td>5.446822</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>0</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>0.000000</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>1</td>\n<td>76.023600</td>\n<td>50.312000</td>\n<td>61.631600</td>\n<td>64.704000</td>\n<td>10.571392</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>2</td>\n<td>46.888000</td>\n<td>72.599600</td>\n<td>61.280000</td>\n<td>58.207600</td>\n<td>10.571392</td>\n</tr>\n</tbody>\n</table>\n<h3>2.4. CV and LB Correlation</h3>\n<ul>\n<li>There was a very good correlation between CV and LB. This allowed me to confidently trust the CV scores.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>LB</th>\n<th>CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]</th>\n<th>Seed</th>\n<th>Target</th>\n<th>DINOv3</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0.75</td>\n<td>0.764281, [0.68012, 0.510887, 0.752103, 0.675727, 0.724613]</td>\n<td>42</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.753265, [0.659145, 0.495417, 0.730635, 0.661692, 0.713109]</td>\n<td>42</td>\n<td>5 biomass + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.754347, [0.684125, 0.503932, 0.724692, 0.666095, 0.705388]</td>\n<td>42</td>\n<td>3 primary + Height (-Noise)</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.75</td>\n<td>0.756209, [0.662654, 0.512846, 0.741057, 0.665265, 0.712921]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.745794, [0.703269, 0.471936, 0.717405, 0.656409, 0.686196]</td>\n<td>777</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.75</td>\n<td>0.733871, [0.705841, 0.484615, 0.714099, 0.640872, 0.657992]</td>\n<td>1</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.744295, [0.718311, 0.469911, 0.729706, 0.652764, 0.680162]</td>\n<td>2024</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.756737, [0.697973, 0.494104, 0.738189, 0.669619, 0.702361]</td>\n<td>777</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.720886, [0.700602, 0.451035, 0.709695, 0.61784, 0.653728]</td>\n<td>1</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.74205, [0.724016, 0.455966, 0.725739, 0.647846, 0.68428]</td>\n<td>2024</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.758067, [0.723696, 0.538679, 0.725656, 0.672485, 0.69996]</td>\n<td>42</td>\n<td>3 primary + Height</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.779158, [0.698054, 0.547103, 0.735667, 0.705507, 0.728854]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.779295, [0.694276, 0.526245, 0.740259, 0.706725, 0.726529]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI (drop_rate=0.3, wd=0.01)</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.71</td>\n<td>0.767606, [0.618705, 0.479375, 0.741914, 0.684672, 0.734104]</td>\n<td>42</td>\n<td>5 biomass + Height + NDVI (drop_rate=0.3, wd=0.01)</td>\n<td>Large</td>\n</tr>\n</tbody>\n</table>\n<h2>3. Model Architecture</h2>\n<p>I adopted DINOv3 pre-trained models.\nImage sizes were determined considering A100 memory constraints.</p>\n<ul>\n<li><p>vit_huge_plus_patch16_dinov3.lvd1689m</p>\n<ul>\n<li>Input: 448×896×3</li>\n<li>Epochs: 50</li></ul></li>\n<li><p>vit_large_patch16_dinov3.lvd1689m</p>\n<ul>\n<li>Input: 512×1024×3</li>\n<li>Epochs: 40</li></ul></li>\n<li><p>Common settings</p>\n<ul>\n<li>Loss: RMSELossFlat</li>\n<li>Learning rate: 0.0015</li>\n<li>Batch size: 16</li>\n<li>Freeze epochs: 4</li>\n<li>Callbacks: SaveModelCallback, ReduceLROnPlateau (monitor='rmse')</li></ul></li>\n</ul>\n<h2>4. Training</h2>\n<h3>4.1. Multi-target Learning Strategy</h3>\n<p>To improve representation learning, I added auxiliary tasks in addition to the submission target variables.</p>\n<pre><code># Final configuration (7 targets)\ntargets = [\n    'Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g',  # Primary (for submission)\n    'Dry_Total_g', 'GDM_g',                       # Auxiliary biomass\n    'Height_Ave_cm', 'Pre_GSHH_NDVI'              # Auxiliary measurements\n]\n</code></pre>\n<ul>\n<li>Configurations tested:<ul>\n<li>3 primary + Height</li>\n<li>3 primary + Height + NDVI</li>\n<li>5 biomass + Height</li>\n<li>5 biomass + Height + NDVI</li></ul></li>\n</ul>\n<h3>4.2. Data Augmentation</h3>\n<p>I used the fastai pipeline.</p>\n<pre><code># Resize to target resolution\nitem_tfms = Resize(input_size, method='squish')\n\n# Training augmentations\nbatch_tfms = \\\n    setup_aug_tfms([\n        Brightness(max_lighting=0.1),\n        Contrast(max_lighting=0.1),\n        Saturation(max_lighting=0.1),\n        Hue(max_hue=0.02)\n    ]) + aug_transforms(do_flip=True, flip_vert=True)\n</code></pre>\n<h2>5. Ensemble &amp; Post-processing</h2>\n<h3>5.1. Multi-seed Training</h3>\n<p>I trained with multiple seeds to ensure ensemble diversity.</p>\n<ul>\n<li>24 models<ul>\n<li>vit_huge_plus_patch16_dinov3</li>\n<li>4 seeds</li>\n<li>3 folds</li>\n<li>2 targets (3 primary + Height, 3 primary + Height + NDVI)</li></ul></li>\n</ul>\n<pre><code>SEEDS = [42, 1, 777, 2024]\nfor seed in SEEDS:\n    sgkf = StratifiedGroupKFold(n_splits=3, random_state=seed, shuffle=True)\n    for fold, (train_index, valid_index) in enumerate(sgkf.split(df, df['stratify_label'], df['group_key'])):\n        # Train and save model\n        model = train_fold(train_index, valid_index, seed, fold)\n</code></pre>\n<h3>5.2. Final Ensemble</h3>\n<p>The final submission was a simple average of 42 models.</p>\n<ul>\n<li>Simple averaging of 24 models</li>\n<li>Additional 18 models<ul>\n<li>5 biomass + Height: 3 models</li>\n<li>3 primary + Height (-Noise): 3 models</li>\n<li>vit_large_patch16_dinov3: 3 models x 4 targets = 12 models</li></ul></li>\n</ul>\n<h3>5.3. Post-processing</h3>\n<p>Predictions were made only for ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g'], and Total and other values were calculated from these.</p>\n<ul>\n<li><code>['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g']</code><ul>\n<li><code>'Dry_Total_g' = 'Dry_Clover_g' + 'Dry_Dead_g' + 'Dry_Green_g'</code></li>\n<li><code>'GDM_g' = 'Dry_Clover_g' + 'Dry_Green_g'</code></li></ul></li>\n</ul>\n<h3>5.4. Submit LB and CV</h3>\n<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m<ul>\n<li>seed: 42 x 4 models</li>\n<li>seed: 777 x 2 models</li>\n<li>seed: 1 x 2 models</li>\n<li>seed: 2024 x 2 models</li></ul></li>\n<li>vit_large_patch16_dinov3.lvd1689m<ul>\n<li>seed: 42 x 4 models</li></ul></li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>LB</th>\n<th>CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]</th>\n<th>Ensemble models</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0.75</td>\n<td>0.773948, [0.718483, 0.532946, 0.747799, 0.694633, 0.722592]</td>\n<td>huge:[42x4, 777x2, 1x2, 2024x2] + large:[42x4]</td>\n</tr>\n</tbody>\n</table>\n<h2>6. What Didn't Work</h2>\n<ul>\n<li>Noise removal of \"red spots, date-time strings, cardboard\" mentioned in discussions had little effect<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233</a></li>\n<li>GradCAM visualization confirmed that the model does not focus much on these noise regions\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F280d194b24de1ce4f3bab15b53b31f82%2Fgradcam_date.jpg?generation=1769787341656918&amp;alt=media\" alt=\"\">\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F8f131b9a0c92491543d980fa54bca1db%2Fgradcam_red.jpg?generation=1769787355824332&amp;alt=media\" alt=\"\"></li></ul></li>\n<li>Splitting by Sampling_Date: Results were unstable and CV worsened.<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/615401\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/615401</a></li></ul></li>\n<li>TTA: CV worsened.<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/668066\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/668066</a></li></ul></li>\n<li>Tried various models but CV did not improve much<ul>\n<li>eva02_large_patch14_448</li>\n<li>eva02_base_patch14_448</li>\n<li>vit_so400m_patch14_siglip_378</li>\n<li>vit_so150m2_patch16_reg1_gap_44</li>\n<li>convnext_large_mlp</li>\n<li>caformer_b36</li>\n<li>naflexvit_base_patch16_par_gap</li>\n<li>vit_base_patch14_reg4_dinov2</li>\n<li>vit_7b_patch16_dinov3.sat493m</li></ul></li>\n<li>Other approaches that worsened CV:<ul>\n<li>SmoothL1Loss</li>\n<li>MixUp()</li>\n<li>CutMix()</li></ul></li>\n</ul>\n<h2>7. Hardware &amp; Environment</h2>\n<p>For early to mid-stage validation, I used lightweight models on Kaggle Notebook</p>\n<ul>\n<li>T4 x2: 15GB<ul>\n<li>vit_small_plus_patch16_dinov3.lvd1689m</li>\n<li>CV Avg: 0.69</li>\n<li>15min/fold</li></ul></li>\n</ul>\n<p>For later-stage training, I used Google Colab Pro (approximately $25 cost)</p>\n<ul>\n<li>A100: 80GB<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m</li>\n<li>45min/fold</li></ul></li>\n<li>A100: 40GB<ul>\n<li>vit_large_patch16_dinov3.lvd1689m</li>\n<li>25min/fold</li></ul></li>\n</ul>\n<h2>8. Conclusion &amp; Lessons Learned</h2>\n<h3>8.1. DINOv3 is Amazing!</h3>\n<p>I used DINOv3 for the first time in this competition and was amazed by its high learning accuracy.</p>\n<h3>8.2. Domain Knowledge</h3>\n<p>I happened to watch an anime that featured alfalfa, which made me pay attention to the distribution bias in the images. I recommend everyone to watch it!</p>\n<ul>\n<li>Hiromu Arakawa's \"The Noble Farmer\" (Hyakushō Kizoku, 百姓貴族) Episode 30 \"Pasture\"</li>\n<li><a href=\"https://www.youtube.com/watch?v=ohJgdhWS218\" target=\"_blank\">https://www.youtube.com/watch?v=ohJgdhWS218</a></li>\n</ul>\n<h3>8.3. AI and Community Participation</h3>\n<p>I was anxious about communicating in English and had not made any posts before.\nHowever, with the advancement of AI translation technology in recent years, I have been able to obtain information from many participants in the Kaggle community.\nI also realized that AI has been a great help not only technically but also in participating in international communities.\nI plan to actively participate in the community and share information in the future.</p>\n<p>Thank you, AI❗<br>\nEnjoy! Happy Kaggling!</p>",
  "messages": [
    {
      "id": "3399305",
      "postDate": "01/30/2026 16:00:15",
      "content": "<p>I would like to thank the competition organizers and Kaggle for creating this interesting challenge.\nThis competition was exactly the kind of image regression competition I had been waiting for.\nThis is my first writeup. I learned a lot from this competition, so I decided to share my solution.\nI hope it will be helpful to everyone!</p>\n<h2>1. Summary</h2>\n<ul>\n<li>Final Results<ul>\n<li>Private LB Score: 0.63</li>\n<li>Rank: 54</li></ul></li>\n<li>Framework<ul>\n<li>fastai🩷</li>\n<li>timm🩷</li></ul></li>\n<li>Models Used<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m</li>\n<li>vit_large_patch16_dinov3.lvd1689m</li></ul></li>\n<li>StratifiedGroupKFold (3 folds)</li>\n</ul>\n<h2>2. Validation Strategy</h2>\n<p>My approach for this competition was inspired by the previously held \"PetFinder.my - Pawpularity Contest\".\nThe Pawpularity competition also required quantifying latent features that are not clearly discernible to the human eye, making it similar to this biomass estimation task where judgment from images alone is difficult.</p>\n<h3>2.1. Kaggle Notebook Environment</h3>\n<ul>\n<li><p>Due to different start times, the Kaggle Notebook environment varied, so standardization was necessary</p></li>\n<li><p>I confirmed that older versions of scikit-learn produced incorrect split results with StratifiedGroupKFold</p>\n<ul>\n<li><a href=\"https://github.com/scikit-learn/scikit-learn/issues/32478\" target=\"_blank\">https://github.com/scikit-learn/scikit-learn/issues/32478</a></li>\n<li><a href=\"https://github.com/scikit-learn/scikit-learn/pull/32540\" target=\"_blank\">https://github.com/scikit-learn/scikit-learn/pull/32540</a></li></ul></li>\n<li><p>2025-11-07 version</p>\n<ul>\n<li>fastai: 2.8.5</li>\n<li>scikit-learn: 1.2.2</li>\n<li>timm: 1.0.19</li>\n<li>torch: 2.6.0+cu124</li></ul></li>\n<li><p>2025-12-17 version</p>\n<ul>\n<li>fastai: 2.8.4</li>\n<li>scikit-learn: 1.6.1</li>\n<li>timm: 1.0.20</li>\n<li>torch: 2.8.0+cu126</li></ul></li>\n<li><p>Standardized environment</p>\n<ul>\n<li>fastai: 2.8.4</li>\n<li>scikit-learn: 1.8.0</li>\n<li>timm: 1.0.24</li>\n<li>torch: 2.8.0+cu126\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2Faa3fa0cabace8ae9537d05cba6fb9d81%2Fenv.jpg?generation=1769832873123173&amp;alt=media\" alt=\"\"></li></ul></li>\n</ul>\n<h3>2.2. Images</h3>\n<ul>\n<li><p>Removed the annotation issue (ID230058600) reported in the discussion</p>\n<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190</a></li></ul></li>\n<li><p>Confirmed distribution bias in Fescue</p>\n<ul>\n<li>2015/10/6: 11 images</li>\n<li>2015/2/25: 9 images</li>\n<li>2015/5/7: 8 images</li></ul></li>\n<li><p>Confirmed distribution bias in Lucerne (alfalfa)</p>\n<ul>\n<li>2015/1/15: 7 images</li>\n<li>2015/4/1: 10 images</li>\n<li>2015/5/7: 5 images</li></ul></li>\n</ul>\n<h3>2.3. Split Strategy</h3>\n<p>Used 3-fold split to properly handle Fescue and Lucerne (alfalfa)</p>\n<ul>\n<li>CV Strategy<ul>\n<li>StratifiedGroupKFold (3 folds)</li>\n<li>stratify: <code>stratify_label</code></li>\n<li>groups: <code>Sampling_Date</code> + <code>State</code></li></ul></li>\n</ul>\n<pre><code># Create `stratify_label` from species\ndef get_stratify_label(species):\n    if 'Lucerne' in species:\n        return 'Lucerne'\n    elif 'Fescue' in species:\n        return 'Fescue'\n    elif 'Phalaris' in species:\n        return 'Phalaris'\n    elif 'Clover' in species:\n        return 'Clover'\n    else:\n        return 'Other'\n</code></pre>\n<ul>\n<li>Average <code>Dry_Total_g</code> distribution for each seed<ul>\n<li><code>SEEDS = [42, 1, 777, 2024]</code></li></ul></li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>stratify_label</th>\n<th>fold</th>\n<th>42</th>\n<th>1</th>\n<th>777</th>\n<th>2024</th>\n<th>std</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Clover</td>\n<td>0</td>\n<td>38.488704</td>\n<td>40.031428</td>\n<td>40.821862</td>\n<td>40.821862</td>\n<td>1.099880</td>\n</tr>\n<tr>\n<td>Clover</td>\n<td>1</td>\n<td>36.034956</td>\n<td>34.881416</td>\n<td>34.090982</td>\n<td>33.604583</td>\n<td>1.060977</td>\n</tr>\n<tr>\n<td>Clover</td>\n<td>2</td>\n<td>34.221660</td>\n<td>33.740706</td>\n<td>33.740706</td>\n<td>34.221660</td>\n<td>0.277679</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>0</td>\n<td>76.177778</td>\n<td>76.177778</td>\n<td>75.376471</td>\n<td>76.177778</td>\n<td>0.400654</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>1</td>\n<td>46.550000</td>\n<td>91.121053</td>\n<td>103.227273</td>\n<td>46.550000</td>\n<td>29.642796</td>\n</tr>\n<tr>\n<td>Fescue</td>\n<td>2</td>\n<td>91.121053</td>\n<td>46.550000</td>\n<td>46.550000</td>\n<td>91.121053</td>\n<td>25.733109</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>0</td>\n<td>42.160000</td>\n<td>42.160000</td>\n<td>50.920000</td>\n<td>42.160000</td>\n<td>4.380000</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>1</td>\n<td>75.171429</td>\n<td>50.920000</td>\n<td>42.160000</td>\n<td>75.171429</td>\n<td>16.912791</td>\n</tr>\n<tr>\n<td>Lucerne</td>\n<td>2</td>\n<td>50.920000</td>\n<td>75.171429</td>\n<td>75.171429</td>\n<td>50.920000</td>\n<td>14.001569</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>0</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>39.602041</td>\n<td>0.000000</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>1</td>\n<td>40.413157</td>\n<td>31.913777</td>\n<td>31.913777</td>\n<td>40.413157</td>\n<td>4.907119</td>\n</tr>\n<tr>\n<td>Other</td>\n<td>2</td>\n<td>27.551414</td>\n<td>36.985586</td>\n<td>36.985586</td>\n<td>27.551414</td>\n<td>5.446822</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>0</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>38.461538</td>\n<td>0.000000</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>1</td>\n<td>76.023600</td>\n<td>50.312000</td>\n<td>61.631600</td>\n<td>64.704000</td>\n<td>10.571392</td>\n</tr>\n<tr>\n<td>Phalaris</td>\n<td>2</td>\n<td>46.888000</td>\n<td>72.599600</td>\n<td>61.280000</td>\n<td>58.207600</td>\n<td>10.571392</td>\n</tr>\n</tbody>\n</table>\n<h3>2.4. CV and LB Correlation</h3>\n<ul>\n<li>There was a very good correlation between CV and LB. This allowed me to confidently trust the CV scores.</li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>LB</th>\n<th>CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]</th>\n<th>Seed</th>\n<th>Target</th>\n<th>DINOv3</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0.75</td>\n<td>0.764281, [0.68012, 0.510887, 0.752103, 0.675727, 0.724613]</td>\n<td>42</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.753265, [0.659145, 0.495417, 0.730635, 0.661692, 0.713109]</td>\n<td>42</td>\n<td>5 biomass + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.754347, [0.684125, 0.503932, 0.724692, 0.666095, 0.705388]</td>\n<td>42</td>\n<td>3 primary + Height (-Noise)</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.75</td>\n<td>0.756209, [0.662654, 0.512846, 0.741057, 0.665265, 0.712921]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.745794, [0.703269, 0.471936, 0.717405, 0.656409, 0.686196]</td>\n<td>777</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.75</td>\n<td>0.733871, [0.705841, 0.484615, 0.714099, 0.640872, 0.657992]</td>\n<td>1</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.744295, [0.718311, 0.469911, 0.729706, 0.652764, 0.680162]</td>\n<td>2024</td>\n<td>3 primary + Height + NDVI</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.756737, [0.697973, 0.494104, 0.738189, 0.669619, 0.702361]</td>\n<td>777</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.720886, [0.700602, 0.451035, 0.709695, 0.61784, 0.653728]</td>\n<td>1</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.74205, [0.724016, 0.455966, 0.725739, 0.647846, 0.68428]</td>\n<td>2024</td>\n<td>3 primary + Height</td>\n<td>Huge</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.758067, [0.723696, 0.538679, 0.725656, 0.672485, 0.69996]</td>\n<td>42</td>\n<td>3 primary + Height</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.779158, [0.698054, 0.547103, 0.735667, 0.705507, 0.728854]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.74</td>\n<td>0.779295, [0.694276, 0.526245, 0.740259, 0.706725, 0.726529]</td>\n<td>42</td>\n<td>3 primary + Height + NDVI (drop_rate=0.3, wd=0.01)</td>\n<td>Large</td>\n</tr>\n<tr>\n<td>0.71</td>\n<td>0.767606, [0.618705, 0.479375, 0.741914, 0.684672, 0.734104]</td>\n<td>42</td>\n<td>5 biomass + Height + NDVI (drop_rate=0.3, wd=0.01)</td>\n<td>Large</td>\n</tr>\n</tbody>\n</table>\n<h2>3. Model Architecture</h2>\n<p>I adopted DINOv3 pre-trained models.\nImage sizes were determined considering A100 memory constraints.</p>\n<ul>\n<li><p>vit_huge_plus_patch16_dinov3.lvd1689m</p>\n<ul>\n<li>Input: 448×896×3</li>\n<li>Epochs: 50</li></ul></li>\n<li><p>vit_large_patch16_dinov3.lvd1689m</p>\n<ul>\n<li>Input: 512×1024×3</li>\n<li>Epochs: 40</li></ul></li>\n<li><p>Common settings</p>\n<ul>\n<li>Loss: RMSELossFlat</li>\n<li>Learning rate: 0.0015</li>\n<li>Batch size: 16</li>\n<li>Freeze epochs: 4</li>\n<li>Callbacks: SaveModelCallback, ReduceLROnPlateau (monitor='rmse')</li></ul></li>\n</ul>\n<h2>4. Training</h2>\n<h3>4.1. Multi-target Learning Strategy</h3>\n<p>To improve representation learning, I added auxiliary tasks in addition to the submission target variables.</p>\n<pre><code># Final configuration (7 targets)\ntargets = [\n    'Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g',  # Primary (for submission)\n    'Dry_Total_g', 'GDM_g',                       # Auxiliary biomass\n    'Height_Ave_cm', 'Pre_GSHH_NDVI'              # Auxiliary measurements\n]\n</code></pre>\n<ul>\n<li>Configurations tested:<ul>\n<li>3 primary + Height</li>\n<li>3 primary + Height + NDVI</li>\n<li>5 biomass + Height</li>\n<li>5 biomass + Height + NDVI</li></ul></li>\n</ul>\n<h3>4.2. Data Augmentation</h3>\n<p>I used the fastai pipeline.</p>\n<pre><code># Resize to target resolution\nitem_tfms = Resize(input_size, method='squish')\n\n# Training augmentations\nbatch_tfms = \\\n    setup_aug_tfms([\n        Brightness(max_lighting=0.1),\n        Contrast(max_lighting=0.1),\n        Saturation(max_lighting=0.1),\n        Hue(max_hue=0.02)\n    ]) + aug_transforms(do_flip=True, flip_vert=True)\n</code></pre>\n<h2>5. Ensemble &amp; Post-processing</h2>\n<h3>5.1. Multi-seed Training</h3>\n<p>I trained with multiple seeds to ensure ensemble diversity.</p>\n<ul>\n<li>24 models<ul>\n<li>vit_huge_plus_patch16_dinov3</li>\n<li>4 seeds</li>\n<li>3 folds</li>\n<li>2 targets (3 primary + Height, 3 primary + Height + NDVI)</li></ul></li>\n</ul>\n<pre><code>SEEDS = [42, 1, 777, 2024]\nfor seed in SEEDS:\n    sgkf = StratifiedGroupKFold(n_splits=3, random_state=seed, shuffle=True)\n    for fold, (train_index, valid_index) in enumerate(sgkf.split(df, df['stratify_label'], df['group_key'])):\n        # Train and save model\n        model = train_fold(train_index, valid_index, seed, fold)\n</code></pre>\n<h3>5.2. Final Ensemble</h3>\n<p>The final submission was a simple average of 42 models.</p>\n<ul>\n<li>Simple averaging of 24 models</li>\n<li>Additional 18 models<ul>\n<li>5 biomass + Height: 3 models</li>\n<li>3 primary + Height (-Noise): 3 models</li>\n<li>vit_large_patch16_dinov3: 3 models x 4 targets = 12 models</li></ul></li>\n</ul>\n<h3>5.3. Post-processing</h3>\n<p>Predictions were made only for ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g'], and Total and other values were calculated from these.</p>\n<ul>\n<li><code>['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g']</code><ul>\n<li><code>'Dry_Total_g' = 'Dry_Clover_g' + 'Dry_Dead_g' + 'Dry_Green_g'</code></li>\n<li><code>'GDM_g' = 'Dry_Clover_g' + 'Dry_Green_g'</code></li></ul></li>\n</ul>\n<h3>5.4. Submit LB and CV</h3>\n<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m<ul>\n<li>seed: 42 x 4 models</li>\n<li>seed: 777 x 2 models</li>\n<li>seed: 1 x 2 models</li>\n<li>seed: 2024 x 2 models</li></ul></li>\n<li>vit_large_patch16_dinov3.lvd1689m<ul>\n<li>seed: 42 x 4 models</li></ul></li>\n</ul>\n<table>\n<thead>\n<tr>\n<th>LB</th>\n<th>CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]</th>\n<th>Ensemble models</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>0.75</td>\n<td>0.773948, [0.718483, 0.532946, 0.747799, 0.694633, 0.722592]</td>\n<td>huge:[42x4, 777x2, 1x2, 2024x2] + large:[42x4]</td>\n</tr>\n</tbody>\n</table>\n<h2>6. What Didn't Work</h2>\n<ul>\n<li>Noise removal of \"red spots, date-time strings, cardboard\" mentioned in discussions had little effect<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233</a></li>\n<li>GradCAM visualization confirmed that the model does not focus much on these noise regions\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F280d194b24de1ce4f3bab15b53b31f82%2Fgradcam_date.jpg?generation=1769787341656918&amp;alt=media\" alt=\"\">\n<img src=\"https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F8f131b9a0c92491543d980fa54bca1db%2Fgradcam_red.jpg?generation=1769787355824332&amp;alt=media\" alt=\"\"></li></ul></li>\n<li>Splitting by Sampling_Date: Results were unstable and CV worsened.<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/615401\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/615401</a></li></ul></li>\n<li>TTA: CV worsened.<ul>\n<li><a href=\"https://www.kaggle.com/competitions/csiro-biomass/discussion/668066\" target=\"_blank\">https://www.kaggle.com/competitions/csiro-biomass/discussion/668066</a></li></ul></li>\n<li>Tried various models but CV did not improve much<ul>\n<li>eva02_large_patch14_448</li>\n<li>eva02_base_patch14_448</li>\n<li>vit_so400m_patch14_siglip_378</li>\n<li>vit_so150m2_patch16_reg1_gap_44</li>\n<li>convnext_large_mlp</li>\n<li>caformer_b36</li>\n<li>naflexvit_base_patch16_par_gap</li>\n<li>vit_base_patch14_reg4_dinov2</li>\n<li>vit_7b_patch16_dinov3.sat493m</li></ul></li>\n<li>Other approaches that worsened CV:<ul>\n<li>SmoothL1Loss</li>\n<li>MixUp()</li>\n<li>CutMix()</li></ul></li>\n</ul>\n<h2>7. Hardware &amp; Environment</h2>\n<p>For early to mid-stage validation, I used lightweight models on Kaggle Notebook</p>\n<ul>\n<li>T4 x2: 15GB<ul>\n<li>vit_small_plus_patch16_dinov3.lvd1689m</li>\n<li>CV Avg: 0.69</li>\n<li>15min/fold</li></ul></li>\n</ul>\n<p>For later-stage training, I used Google Colab Pro (approximately $25 cost)</p>\n<ul>\n<li>A100: 80GB<ul>\n<li>vit_huge_plus_patch16_dinov3.lvd1689m</li>\n<li>45min/fold</li></ul></li>\n<li>A100: 40GB<ul>\n<li>vit_large_patch16_dinov3.lvd1689m</li>\n<li>25min/fold</li></ul></li>\n</ul>\n<h2>8. Conclusion &amp; Lessons Learned</h2>\n<h3>8.1. DINOv3 is Amazing!</h3>\n<p>I used DINOv3 for the first time in this competition and was amazed by its high learning accuracy.</p>\n<h3>8.2. Domain Knowledge</h3>\n<p>I happened to watch an anime that featured alfalfa, which made me pay attention to the distribution bias in the images. I recommend everyone to watch it!</p>\n<ul>\n<li>Hiromu Arakawa's \"The Noble Farmer\" (Hyakushō Kizoku, 百姓貴族) Episode 30 \"Pasture\"</li>\n<li><a href=\"https://www.youtube.com/watch?v=ohJgdhWS218\" target=\"_blank\">https://www.youtube.com/watch?v=ohJgdhWS218</a></li>\n</ul>\n<h3>8.3. AI and Community Participation</h3>\n<p>I was anxious about communicating in English and had not made any posts before.\nHowever, with the advancement of AI translation technology in recent years, I have been able to obtain information from many participants in the Kaggle community.\nI also realized that AI has been a great help not only technically but also in participating in international communities.\nI plan to actively participate in the community and share information in the future.</p>\n<p>Thank you, AI❗<br>\nEnjoy! Happy Kaggling!</p>",
      "rawMarkdown": "I would like to thank the competition organizers and Kaggle for creating this interesting challenge.\nThis competition was exactly the kind of image regression competition I had been waiting for.\nThis is my first writeup. I learned a lot from this competition, so I decided to share my solution.\nI hope it will be helpful to everyone!\n\n## 1. Summary\n\n- Final Results\n  - Private LB Score: 0.63\n  - Rank: 54\n- Framework\n  - fastai🩷\n  - timm🩷\n- Models Used\n  - vit_huge_plus_patch16_dinov3.lvd1689m\n  - vit_large_patch16_dinov3.lvd1689m\n- StratifiedGroupKFold (3 folds)\n\n## 2. Validation Strategy\n\nMy approach for this competition was inspired by the previously held \"PetFinder.my - Pawpularity Contest\".\nThe Pawpularity competition also required quantifying latent features that are not clearly discernible to the human eye, making it similar to this biomass estimation task where judgment from images alone is difficult.\n\n### 2.1. Kaggle Notebook Environment\n\n- Due to different start times, the Kaggle Notebook environment varied, so standardization was necessary\n- I confirmed that older versions of scikit-learn produced incorrect split results with StratifiedGroupKFold\n  - https://github.com/scikit-learn/scikit-learn/issues/32478\n  - https://github.com/scikit-learn/scikit-learn/pull/32540\n\n- 2025-11-07 version\n  - fastai: 2.8.5\n  - scikit-learn: 1.2.2\n  - timm: 1.0.19\n  - torch: 2.6.0+cu124\n\n- 2025-12-17 version\n  - fastai: 2.8.4\n  - scikit-learn: 1.6.1\n  - timm: 1.0.20\n  - torch: 2.8.0+cu126\n\n- Standardized environment\n  - fastai: 2.8.4\n  - scikit-learn: 1.8.0\n  - timm: 1.0.24\n  - torch: 2.8.0+cu126\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2Faa3fa0cabace8ae9537d05cba6fb9d81%2Fenv.jpg?generation=1769832873123173&alt=media)\n\n### 2.2. Images\n\n- Removed the annotation issue (ID230058600) reported in the discussion\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190\n\n- Confirmed distribution bias in Fescue\n  - 2015/10/6: 11 images\n  - 2015/2/25: 9 images\n  - 2015/5/7: 8 images\n\n- Confirmed distribution bias in Lucerne (alfalfa)\n  - 2015/1/15: 7 images\n  - 2015/4/1: 10 images\n  - 2015/5/7: 5 images\n\n### 2.3. Split Strategy\n\nUsed 3-fold split to properly handle Fescue and Lucerne (alfalfa)\n\n- CV Strategy\n  - StratifiedGroupKFold (3 folds)\n  - stratify: `stratify_label`\n  - groups: `Sampling_Date` + `State`\n\n```python\n# Create `stratify_label` from species\ndef get_stratify_label(species):\n    if 'Lucerne' in species:\n        return 'Lucerne'\n    elif 'Fescue' in species:\n        return 'Fescue'\n    elif 'Phalaris' in species:\n        return 'Phalaris'\n    elif 'Clover' in species:\n        return 'Clover'\n    else:\n        return 'Other'\n```\n\n- Average `Dry_Total_g` distribution for each seed\n  - `SEEDS = [42, 1, 777, 2024]`\n\n| stratify_label | fold | 42 | 1 | 777 | 2024 | std |\n|---|---|---|---|---|---|---|\n| Clover | 0 | 38.488704 | 40.031428 | 40.821862 | 40.821862 | 1.099880 |\n| Clover | 1 | 36.034956 | 34.881416 | 34.090982 | 33.604583 | 1.060977 |\n| Clover | 2 | 34.221660 | 33.740706 | 33.740706 | 34.221660 | 0.277679 |\n| Fescue | 0 | 76.177778 | 76.177778 | 75.376471 | 76.177778 | 0.400654 |\n| Fescue | 1 | 46.550000 | 91.121053 | 103.227273 | 46.550000 | 29.642796 |\n| Fescue | 2 | 91.121053 | 46.550000 | 46.550000 | 91.121053 | 25.733109 |\n| Lucerne | 0 | 42.160000 | 42.160000 | 50.920000 | 42.160000 | 4.380000 |\n| Lucerne | 1 | 75.171429 | 50.920000 | 42.160000 | 75.171429 | 16.912791 |\n| Lucerne | 2 | 50.920000 | 75.171429 | 75.171429 | 50.920000 | 14.001569 |\n| Other | 0 | 39.602041 | 39.602041 | 39.602041 | 39.602041 | 0.000000 |\n| Other | 1 | 40.413157 | 31.913777 | 31.913777 | 40.413157 | 4.907119 |\n| Other | 2 | 27.551414 | 36.985586 | 36.985586 | 27.551414 | 5.446822 |\n| Phalaris | 0 | 38.461538 | 38.461538 | 38.461538 | 38.461538 | 0.000000 |\n| Phalaris | 1 | 76.023600 | 50.312000 | 61.631600 | 64.704000 | 10.571392 |\n| Phalaris | 2 | 46.888000 | 72.599600 | 61.280000 | 58.207600 | 10.571392 |\n\n### 2.4. CV and LB Correlation\n\n- There was a very good correlation between CV and LB. This allowed me to confidently trust the CV scores.\n\n|LB|CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]|Seed|Target|DINOv3|\n|---|---|---|---|---|\n|0.75|0.764281, [0.68012, 0.510887, 0.752103, 0.675727, 0.724613]|42|3 primary + Height|Huge|\n|0.74|0.753265, [0.659145, 0.495417, 0.730635, 0.661692, 0.713109]|42|5 biomass + Height|Huge|\n|0.74|0.754347, [0.684125, 0.503932, 0.724692, 0.666095, 0.705388]|42|3 primary + Height (-Noise)|Huge|\n|0.75|0.756209, [0.662654, 0.512846, 0.741057, 0.665265, 0.712921]|42|3 primary + Height + NDVI|Huge|\n|0.74|0.745794, [0.703269, 0.471936, 0.717405, 0.656409, 0.686196]|777|3 primary + Height + NDVI|Huge|\n|0.75|0.733871, [0.705841, 0.484615, 0.714099, 0.640872, 0.657992]|1|3 primary + Height + NDVI|Huge|\n|0.74|0.744295, [0.718311, 0.469911, 0.729706, 0.652764, 0.680162]|2024|3 primary + Height + NDVI|Huge|\n|0.74|0.756737, [0.697973, 0.494104, 0.738189, 0.669619, 0.702361]|777|3 primary + Height|Huge|\n|0.74|0.720886, [0.700602, 0.451035, 0.709695, 0.61784, 0.653728]|1|3 primary + Height|Huge|\n|0.74|0.74205, [0.724016, 0.455966, 0.725739, 0.647846, 0.68428]|2024|3 primary + Height|Huge|\n|0.74|0.758067, [0.723696, 0.538679, 0.725656, 0.672485, 0.69996]|42|3 primary + Height|Large|\n|0.74|0.779158, [0.698054, 0.547103, 0.735667, 0.705507, 0.728854]|42|3 primary + Height + NDVI|Large|\n|0.74|0.779295, [0.694276, 0.526245, 0.740259, 0.706725, 0.726529]|42|3 primary + Height + NDVI (drop_rate=0.3, wd=0.01)|Large|\n|0.71|0.767606, [0.618705, 0.479375, 0.741914, 0.684672, 0.734104]|42|5 biomass + Height + NDVI (drop_rate=0.3, wd=0.01)|Large|\n\n## 3. Model Architecture\n\nI adopted DINOv3 pre-trained models.\nImage sizes were determined considering A100 memory constraints.\n\n- vit_huge_plus_patch16_dinov3.lvd1689m\n  - Input: 448×896×3\n  - Epochs: 50\n\n- vit_large_patch16_dinov3.lvd1689m\n  - Input: 512×1024×3\n  - Epochs: 40\n\n- Common settings\n  - Loss: RMSELossFlat\n  - Learning rate: 0.0015\n  - Batch size: 16\n  - Freeze epochs: 4\n  - Callbacks: SaveModelCallback, ReduceLROnPlateau (monitor='rmse')\n\n## 4. Training\n\n### 4.1. Multi-target Learning Strategy\n\nTo improve representation learning, I added auxiliary tasks in addition to the submission target variables.\n\n```python\n# Final configuration (7 targets)\ntargets = [\n    'Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g',  # Primary (for submission)\n    'Dry_Total_g', 'GDM_g',                       # Auxiliary biomass\n    'Height_Ave_cm', 'Pre_GSHH_NDVI'              # Auxiliary measurements\n]\n```\n- Configurations tested:\n  - 3 primary + Height\n  - 3 primary + Height + NDVI\n  - 5 biomass + Height\n  - 5 biomass + Height + NDVI\n\n### 4.2. Data Augmentation\n\nI used the fastai pipeline.\n\n```python\n# Resize to target resolution\nitem_tfms = Resize(input_size, method='squish')\n\n# Training augmentations\nbatch_tfms = \\\n    setup_aug_tfms([\n        Brightness(max_lighting=0.1),\n        Contrast(max_lighting=0.1),\n        Saturation(max_lighting=0.1),\n        Hue(max_hue=0.02)\n    ]) + aug_transforms(do_flip=True, flip_vert=True)\n```\n\n## 5. Ensemble & Post-processing\n\n### 5.1. Multi-seed Training\n\nI trained with multiple seeds to ensure ensemble diversity.\n\n- 24 models\n  - vit_huge_plus_patch16_dinov3\n  - 4 seeds\n  - 3 folds\n  - 2 targets (3 primary + Height, 3 primary + Height + NDVI)\n\n```python\nSEEDS = [42, 1, 777, 2024]\nfor seed in SEEDS:\n    sgkf = StratifiedGroupKFold(n_splits=3, random_state=seed, shuffle=True)\n    for fold, (train_index, valid_index) in enumerate(sgkf.split(df, df['stratify_label'], df['group_key'])):\n        # Train and save model\n        model = train_fold(train_index, valid_index, seed, fold)\n```\n\n### 5.2. Final Ensemble\n\nThe final submission was a simple average of 42 models.\n- Simple averaging of 24 models\n- Additional 18 models\n  - 5 biomass + Height: 3 models\n  - 3 primary + Height (-Noise): 3 models\n  - vit_large_patch16_dinov3: 3 models x 4 targets = 12 models\n\n### 5.3. Post-processing\n\nPredictions were made only for ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g'], and Total and other values were calculated from these.\n\n- `['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g']`\n  - `'Dry_Total_g' = 'Dry_Clover_g' + 'Dry_Dead_g' + 'Dry_Green_g'`\n  - `'GDM_g' = 'Dry_Clover_g' + 'Dry_Green_g'`\n\n### 5.4. Submit LB and CV\n\n- vit_huge_plus_patch16_dinov3.lvd1689m\n  - seed: 42 x 4 models\n  - seed: 777 x 2 models\n  - seed: 1 x 2 models\n  - seed: 2024 x 2 models\n- vit_large_patch16_dinov3.lvd1689m\n  - seed: 42 x 4 models\n\n|LB|CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]|Ensemble models|\n|---|---|---|\n|0.75|0.773948, [0.718483, 0.532946, 0.747799, 0.694633, 0.722592]|huge:[42x4, 777x2, 1x2, 2024x2] + large:[42x4]|\n\n## 6. What Didn't Work\n\n- Noise removal of \"red spots, date-time strings, cardboard\" mentioned in discussions had little effect\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233\n  - GradCAM visualization confirmed that the model does not focus much on these noise regions\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F280d194b24de1ce4f3bab15b53b31f82%2Fgradcam_date.jpg?generation=1769787341656918&alt=media)\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F8f131b9a0c92491543d980fa54bca1db%2Fgradcam_red.jpg?generation=1769787355824332&alt=media)\n- Splitting by Sampling_Date: Results were unstable and CV worsened.\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/615401\n- TTA: CV worsened.\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/668066\n- Tried various models but CV did not improve much\n  - eva02_large_patch14_448\n  - eva02_base_patch14_448\n  - vit_so400m_patch14_siglip_378\n  - vit_so150m2_patch16_reg1_gap_44\n  - convnext_large_mlp\n  - caformer_b36\n  - naflexvit_base_patch16_par_gap\n  - vit_base_patch14_reg4_dinov2\n  - vit_7b_patch16_dinov3.sat493m\n- Other approaches that worsened CV:\n  - SmoothL1Loss\n  - MixUp()\n  - CutMix()\n\n## 7. Hardware & Environment\n\nFor early to mid-stage validation, I used lightweight models on Kaggle Notebook\n- T4 x2: 15GB\n  - vit_small_plus_patch16_dinov3.lvd1689m\n  - CV Avg: 0.69\n  - 15min/fold\n\nFor later-stage training, I used Google Colab Pro (approximately $25 cost)\n- A100: 80GB\n  - vit_huge_plus_patch16_dinov3.lvd1689m\n  - 45min/fold\n- A100: 40GB\n  - vit_large_patch16_dinov3.lvd1689m\n  - 25min/fold\n\n## 8. Conclusion & Lessons Learned\n\n### 8.1. DINOv3 is Amazing!\nI used DINOv3 for the first time in this competition and was amazed by its high learning accuracy.\n\n### 8.2. Domain Knowledge\nI happened to watch an anime that featured alfalfa, which made me pay attention to the distribution bias in the images. I recommend everyone to watch it!\n- Hiromu Arakawa's \"The Noble Farmer\" (Hyakushō Kizoku, 百姓貴族) Episode 30 \"Pasture\"\n- https://www.youtube.com/watch?v=ohJgdhWS218\n\n### 8.3. AI and Community Participation\nI was anxious about communicating in English and had not made any posts before.\nHowever, with the advancement of AI translation technology in recent years, I have been able to obtain information from many participants in the Kaggle community.\nI also realized that AI has been a great help not only technically but also in participating in international communities.\nI plan to actively participate in the community and share information in the future.\n\nThank you, AI❗  \nEnjoy! Happy Kaggling!",
      "votes": null
    },
    {
      "id": "3399320",
      "postDate": "01/30/2026 16:23:46",
      "content": "<p>Nice and straightforward solution. Interesting note about the sklearn KFold bug, I did notice different results depending on the version but I stuck with the older one for consistency reasons. That's one more thing I'll have to check.</p>",
      "rawMarkdown": "Nice and straightforward solution. Interesting note about the sklearn KFold bug, I did notice different results depending on the version but I stuck with the older one for consistency reasons. That's one more thing I'll have to check.",
      "votes": null
    }
  ],
  "comments": [
    {
      "id": 3399320,
      "author_name": "tennogh",
      "author_url": "",
      "post_date": "01/30/2026 16:23:46",
      "content": "<p>Nice and straightforward solution. Interesting note about the sklearn KFold bug, I did notice different results depending on the version but I stuck with the older one for consistency reasons. That's one more thing I'll have to check.</p>",
      "votes": null,
      "replies": []
    }
  ],
  "raw_markdown_by_id": {
    "3399305": "I would like to thank the competition organizers and Kaggle for creating this interesting challenge.\nThis competition was exactly the kind of image regression competition I had been waiting for.\nThis is my first writeup. I learned a lot from this competition, so I decided to share my solution.\nI hope it will be helpful to everyone!\n\n## 1. Summary\n\n- Final Results\n  - Private LB Score: 0.63\n  - Rank: 54\n- Framework\n  - fastai🩷\n  - timm🩷\n- Models Used\n  - vit_huge_plus_patch16_dinov3.lvd1689m\n  - vit_large_patch16_dinov3.lvd1689m\n- StratifiedGroupKFold (3 folds)\n\n## 2. Validation Strategy\n\nMy approach for this competition was inspired by the previously held \"PetFinder.my - Pawpularity Contest\".\nThe Pawpularity competition also required quantifying latent features that are not clearly discernible to the human eye, making it similar to this biomass estimation task where judgment from images alone is difficult.\n\n### 2.1. Kaggle Notebook Environment\n\n- Due to different start times, the Kaggle Notebook environment varied, so standardization was necessary\n- I confirmed that older versions of scikit-learn produced incorrect split results with StratifiedGroupKFold\n  - https://github.com/scikit-learn/scikit-learn/issues/32478\n  - https://github.com/scikit-learn/scikit-learn/pull/32540\n\n- 2025-11-07 version\n  - fastai: 2.8.5\n  - scikit-learn: 1.2.2\n  - timm: 1.0.19\n  - torch: 2.6.0+cu124\n\n- 2025-12-17 version\n  - fastai: 2.8.4\n  - scikit-learn: 1.6.1\n  - timm: 1.0.20\n  - torch: 2.8.0+cu126\n\n- Standardized environment\n  - fastai: 2.8.4\n  - scikit-learn: 1.8.0\n  - timm: 1.0.24\n  - torch: 2.8.0+cu126\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2Faa3fa0cabace8ae9537d05cba6fb9d81%2Fenv.jpg?generation=1769832873123173&alt=media)\n\n### 2.2. Images\n\n- Removed the annotation issue (ID230058600) reported in the discussion\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/631335#3338190\n\n- Confirmed distribution bias in Fescue\n  - 2015/10/6: 11 images\n  - 2015/2/25: 9 images\n  - 2015/5/7: 8 images\n\n- Confirmed distribution bias in Lucerne (alfalfa)\n  - 2015/1/15: 7 images\n  - 2015/4/1: 10 images\n  - 2015/5/7: 5 images\n\n### 2.3. Split Strategy\n\nUsed 3-fold split to properly handle Fescue and Lucerne (alfalfa)\n\n- CV Strategy\n  - StratifiedGroupKFold (3 folds)\n  - stratify: `stratify_label`\n  - groups: `Sampling_Date` + `State`\n\n```python\n# Create `stratify_label` from species\ndef get_stratify_label(species):\n    if 'Lucerne' in species:\n        return 'Lucerne'\n    elif 'Fescue' in species:\n        return 'Fescue'\n    elif 'Phalaris' in species:\n        return 'Phalaris'\n    elif 'Clover' in species:\n        return 'Clover'\n    else:\n        return 'Other'\n```\n\n- Average `Dry_Total_g` distribution for each seed\n  - `SEEDS = [42, 1, 777, 2024]`\n\n| stratify_label | fold | 42 | 1 | 777 | 2024 | std |\n|---|---|---|---|---|---|---|\n| Clover | 0 | 38.488704 | 40.031428 | 40.821862 | 40.821862 | 1.099880 |\n| Clover | 1 | 36.034956 | 34.881416 | 34.090982 | 33.604583 | 1.060977 |\n| Clover | 2 | 34.221660 | 33.740706 | 33.740706 | 34.221660 | 0.277679 |\n| Fescue | 0 | 76.177778 | 76.177778 | 75.376471 | 76.177778 | 0.400654 |\n| Fescue | 1 | 46.550000 | 91.121053 | 103.227273 | 46.550000 | 29.642796 |\n| Fescue | 2 | 91.121053 | 46.550000 | 46.550000 | 91.121053 | 25.733109 |\n| Lucerne | 0 | 42.160000 | 42.160000 | 50.920000 | 42.160000 | 4.380000 |\n| Lucerne | 1 | 75.171429 | 50.920000 | 42.160000 | 75.171429 | 16.912791 |\n| Lucerne | 2 | 50.920000 | 75.171429 | 75.171429 | 50.920000 | 14.001569 |\n| Other | 0 | 39.602041 | 39.602041 | 39.602041 | 39.602041 | 0.000000 |\n| Other | 1 | 40.413157 | 31.913777 | 31.913777 | 40.413157 | 4.907119 |\n| Other | 2 | 27.551414 | 36.985586 | 36.985586 | 27.551414 | 5.446822 |\n| Phalaris | 0 | 38.461538 | 38.461538 | 38.461538 | 38.461538 | 0.000000 |\n| Phalaris | 1 | 76.023600 | 50.312000 | 61.631600 | 64.704000 | 10.571392 |\n| Phalaris | 2 | 46.888000 | 72.599600 | 61.280000 | 58.207600 | 10.571392 |\n\n### 2.4. CV and LB Correlation\n\n- There was a very good correlation between CV and LB. This allowed me to confidently trust the CV scores.\n\n|LB|CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]|Seed|Target|DINOv3|\n|---|---|---|---|---|\n|0.75|0.764281, [0.68012, 0.510887, 0.752103, 0.675727, 0.724613]|42|3 primary + Height|Huge|\n|0.74|0.753265, [0.659145, 0.495417, 0.730635, 0.661692, 0.713109]|42|5 biomass + Height|Huge|\n|0.74|0.754347, [0.684125, 0.503932, 0.724692, 0.666095, 0.705388]|42|3 primary + Height (-Noise)|Huge|\n|0.75|0.756209, [0.662654, 0.512846, 0.741057, 0.665265, 0.712921]|42|3 primary + Height + NDVI|Huge|\n|0.74|0.745794, [0.703269, 0.471936, 0.717405, 0.656409, 0.686196]|777|3 primary + Height + NDVI|Huge|\n|0.75|0.733871, [0.705841, 0.484615, 0.714099, 0.640872, 0.657992]|1|3 primary + Height + NDVI|Huge|\n|0.74|0.744295, [0.718311, 0.469911, 0.729706, 0.652764, 0.680162]|2024|3 primary + Height + NDVI|Huge|\n|0.74|0.756737, [0.697973, 0.494104, 0.738189, 0.669619, 0.702361]|777|3 primary + Height|Huge|\n|0.74|0.720886, [0.700602, 0.451035, 0.709695, 0.61784, 0.653728]|1|3 primary + Height|Huge|\n|0.74|0.74205, [0.724016, 0.455966, 0.725739, 0.647846, 0.68428]|2024|3 primary + Height|Huge|\n|0.74|0.758067, [0.723696, 0.538679, 0.725656, 0.672485, 0.69996]|42|3 primary + Height|Large|\n|0.74|0.779158, [0.698054, 0.547103, 0.735667, 0.705507, 0.728854]|42|3 primary + Height + NDVI|Large|\n|0.74|0.779295, [0.694276, 0.526245, 0.740259, 0.706725, 0.726529]|42|3 primary + Height + NDVI (drop_rate=0.3, wd=0.01)|Large|\n|0.71|0.767606, [0.618705, 0.479375, 0.741914, 0.684672, 0.734104]|42|5 biomass + Height + NDVI (drop_rate=0.3, wd=0.01)|Large|\n\n## 3. Model Architecture\n\nI adopted DINOv3 pre-trained models.\nImage sizes were determined considering A100 memory constraints.\n\n- vit_huge_plus_patch16_dinov3.lvd1689m\n  - Input: 448×896×3\n  - Epochs: 50\n\n- vit_large_patch16_dinov3.lvd1689m\n  - Input: 512×1024×3\n  - Epochs: 40\n\n- Common settings\n  - Loss: RMSELossFlat\n  - Learning rate: 0.0015\n  - Batch size: 16\n  - Freeze epochs: 4\n  - Callbacks: SaveModelCallback, ReduceLROnPlateau (monitor='rmse')\n\n## 4. Training\n\n### 4.1. Multi-target Learning Strategy\n\nTo improve representation learning, I added auxiliary tasks in addition to the submission target variables.\n\n```python\n# Final configuration (7 targets)\ntargets = [\n    'Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g',  # Primary (for submission)\n    'Dry_Total_g', 'GDM_g',                       # Auxiliary biomass\n    'Height_Ave_cm', 'Pre_GSHH_NDVI'              # Auxiliary measurements\n]\n```\n- Configurations tested:\n  - 3 primary + Height\n  - 3 primary + Height + NDVI\n  - 5 biomass + Height\n  - 5 biomass + Height + NDVI\n\n### 4.2. Data Augmentation\n\nI used the fastai pipeline.\n\n```python\n# Resize to target resolution\nitem_tfms = Resize(input_size, method='squish')\n\n# Training augmentations\nbatch_tfms = \\\n    setup_aug_tfms([\n        Brightness(max_lighting=0.1),\n        Contrast(max_lighting=0.1),\n        Saturation(max_lighting=0.1),\n        Hue(max_hue=0.02)\n    ]) + aug_transforms(do_flip=True, flip_vert=True)\n```\n\n## 5. Ensemble & Post-processing\n\n### 5.1. Multi-seed Training\n\nI trained with multiple seeds to ensure ensemble diversity.\n\n- 24 models\n  - vit_huge_plus_patch16_dinov3\n  - 4 seeds\n  - 3 folds\n  - 2 targets (3 primary + Height, 3 primary + Height + NDVI)\n\n```python\nSEEDS = [42, 1, 777, 2024]\nfor seed in SEEDS:\n    sgkf = StratifiedGroupKFold(n_splits=3, random_state=seed, shuffle=True)\n    for fold, (train_index, valid_index) in enumerate(sgkf.split(df, df['stratify_label'], df['group_key'])):\n        # Train and save model\n        model = train_fold(train_index, valid_index, seed, fold)\n```\n\n### 5.2. Final Ensemble\n\nThe final submission was a simple average of 42 models.\n- Simple averaging of 24 models\n- Additional 18 models\n  - 5 biomass + Height: 3 models\n  - 3 primary + Height (-Noise): 3 models\n  - vit_large_patch16_dinov3: 3 models x 4 targets = 12 models\n\n### 5.3. Post-processing\n\nPredictions were made only for ['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g'], and Total and other values were calculated from these.\n\n- `['Dry_Clover_g', 'Dry_Dead_g', 'Dry_Green_g']`\n  - `'Dry_Total_g' = 'Dry_Clover_g' + 'Dry_Dead_g' + 'Dry_Green_g'`\n  - `'GDM_g' = 'Dry_Clover_g' + 'Dry_Green_g'`\n\n### 5.4. Submit LB and CV\n\n- vit_huge_plus_patch16_dinov3.lvd1689m\n  - seed: 42 x 4 models\n  - seed: 777 x 2 models\n  - seed: 1 x 2 models\n  - seed: 2024 x 2 models\n- vit_large_patch16_dinov3.lvd1689m\n  - seed: 42 x 4 models\n\n|LB|CV<br>r2_weighted, [Clover, Dead, Green, Total, GDM]|Ensemble models|\n|---|---|---|\n|0.75|0.773948, [0.718483, 0.532946, 0.747799, 0.694633, 0.722592]|huge:[42x4, 777x2, 1x2, 2024x2] + large:[42x4]|\n\n## 6. What Didn't Work\n\n- Noise removal of \"red spots, date-time strings, cardboard\" mentioned in discussions had little effect\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/651525#3363233\n  - GradCAM visualization confirmed that the model does not focus much on these noise regions\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F280d194b24de1ce4f3bab15b53b31f82%2Fgradcam_date.jpg?generation=1769787341656918&alt=media)\n![](https://www.googleapis.com/download/storage/v1/b/kaggle-user-content/o/inbox%2F2377068%2F8f131b9a0c92491543d980fa54bca1db%2Fgradcam_red.jpg?generation=1769787355824332&alt=media)\n- Splitting by Sampling_Date: Results were unstable and CV worsened.\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/615401\n- TTA: CV worsened.\n  - https://www.kaggle.com/competitions/csiro-biomass/discussion/668066\n- Tried various models but CV did not improve much\n  - eva02_large_patch14_448\n  - eva02_base_patch14_448\n  - vit_so400m_patch14_siglip_378\n  - vit_so150m2_patch16_reg1_gap_44\n  - convnext_large_mlp\n  - caformer_b36\n  - naflexvit_base_patch16_par_gap\n  - vit_base_patch14_reg4_dinov2\n  - vit_7b_patch16_dinov3.sat493m\n- Other approaches that worsened CV:\n  - SmoothL1Loss\n  - MixUp()\n  - CutMix()\n\n## 7. Hardware & Environment\n\nFor early to mid-stage validation, I used lightweight models on Kaggle Notebook\n- T4 x2: 15GB\n  - vit_small_plus_patch16_dinov3.lvd1689m\n  - CV Avg: 0.69\n  - 15min/fold\n\nFor later-stage training, I used Google Colab Pro (approximately $25 cost)\n- A100: 80GB\n  - vit_huge_plus_patch16_dinov3.lvd1689m\n  - 45min/fold\n- A100: 40GB\n  - vit_large_patch16_dinov3.lvd1689m\n  - 25min/fold\n\n## 8. Conclusion & Lessons Learned\n\n### 8.1. DINOv3 is Amazing!\nI used DINOv3 for the first time in this competition and was amazed by its high learning accuracy.\n\n### 8.2. Domain Knowledge\nI happened to watch an anime that featured alfalfa, which made me pay attention to the distribution bias in the images. I recommend everyone to watch it!\n- Hiromu Arakawa's \"The Noble Farmer\" (Hyakushō Kizoku, 百姓貴族) Episode 30 \"Pasture\"\n- https://www.youtube.com/watch?v=ohJgdhWS218\n\n### 8.3. AI and Community Participation\nI was anxious about communicating in English and had not made any posts before.\nHowever, with the advancement of AI translation technology in recent years, I have been able to obtain information from many participants in the Kaggle community.\nI also realized that AI has been a great help not only technically but also in participating in international communities.\nI plan to actively participate in the community and share information in the future.\n\nThank you, AI❗  \nEnjoy! Happy Kaggling!",
    "3399320": "Nice and straightforward solution. Interesting note about the sklearn KFold bug, I did notice different results depending on the version but I stuck with the older one for consistency reasons. That's one more thing I'll have to check."
  },
  "source": "meta"
}