Skip to content

kbsooo/CSIRO-Image2Biomass-Prediction

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

84 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

CSIRO - Image2Biomass Prediction

Competition: Kaggle CSIRO Biomass Task: ๋ชฉ์ดˆ์ง€(Pasture) top-view ์ด๋ฏธ์ง€๋กœ ๋ฐ”์ด์˜ค๋งค์Šค(๊ฑด์กฐ ์ค‘๋Ÿ‰) ์˜ˆ์ธก Metric: Globally Weighted Rยฒ (Dry_Total_g 50%, GDM_g 20%, ๋‚˜๋จธ์ง€ ๊ฐ 10%) Data: 357๊ฐœ ์ด๋ฏธ์ง€ (70cm ร— 30cm quadrat), 19๊ฐœ ํ˜ธ์ฃผ ์‚ฌ์ดํŠธ


๐Ÿ† ์ตœ์ข… ๊ฒฐ๊ณผ ์š”์•ฝ

๋ฒ„์ „ CV Score Public LB ํ•ต์‹ฌ ํŠน์ง•
v27 (5-model ensemble) ~0.80 โš ๏ธleakage 0.70 ํ˜„์žฌ ์ตœ๊ณ  Public
CV1 (honest CV) 0.6366 0.68 ์ •์งํ•œ CV ๊ธฐ์ค€์ 
CV3 (preprocessing) 0.5253 0.65 ์ „์ฒ˜๋ฆฌ๊ฐ€ ์—ญํšจ๊ณผ
1์œ„ ? 0.79 ๋ชฉํ‘œ

โš ๏ธ v27์˜ CV ~0.80์€ data leakage๊ฐ€ ์žˆ๋Š” ํ—ˆ์œ„ ์ˆ˜์น˜. Private LB์—์„œ ํ•˜๋ฝ ์œ„ํ—˜ ์žˆ์Œ.


๐Ÿ“ ํŒŒ์ผ ๊ตฌ์กฐ

notebooks/
โ”œโ”€โ”€ 01_eda.py                   # ์ดˆ๊ธฐ EDA
โ”œโ”€โ”€ 02~11_*.py                  # ์ดˆ๊ธฐ ์‹คํ—˜ (DINOv2 ๊ธฐ๋ฐ˜, LB ~0.50)
โ”œโ”€โ”€ 12~19_*.py                  # DINOv3 ์ „ํ™˜ (LB ~0.70 ๋‹ฌ์„ฑ)
โ”œโ”€โ”€ 20~27_*.py                  # v20 ๊ณ„์—ด (v27 ์ตœ๊ณ ์  0.70)
โ”œโ”€โ”€ cv1_train/infer.py          # ์ •์งํ•œ CV ๊ธฐ์ค€์  (LB 0.68)
โ”œโ”€โ”€ cv2_train/infer.py          # Weighted Loss + Frozen backbone (์‹คํŒจ)
โ”œโ”€โ”€ cv3_train/infer.py          # ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ ์‹คํ—˜ (์—ญํšจ๊ณผ)
โ”œโ”€โ”€ cv4_infer.py                # v27 + TTA + WA ํ›„์ฒ˜๋ฆฌ
โ”œโ”€โ”€ cv4a/cv4b_infer.py          # Kaggle timeout ๋Œ€์‘ ๊ฒฝ๋Ÿ‰ ๋ฒ„์ „
โ”œโ”€โ”€ cv5_train/infer.py          # ConvNeXt-Base ๋ฉ€ํ‹ฐ ๋ฐฑ๋ณธ
โ”œโ”€โ”€ cv5e_infer.py               # DINOv3 + ConvNeXt ์•™์ƒ๋ธ”
โ”œโ”€โ”€ cv6_train/infer.py          # ์ง์‚ฌ๊ฐํ˜• full-frame + SSF
โ”œโ”€โ”€ cv7_train/infer.py          # v26 OOF training
โ”œโ”€โ”€ cv7a_train.py               # EMA ์ ์šฉ
โ”œโ”€โ”€ cv7b_train.py               # EMA variant 2
โ””โ”€โ”€ cv8_train/infer.py          # LLRD (Layer-wise LR Decay)

data/
โ”œโ”€โ”€ EDA_Report_CSIRO_Biomass.md
โ”œโ”€โ”€ Full_Analysis_Report.md
โ”œโ”€โ”€ Breakthrough_Strategy_0.70_to_0.79.md
โ”œโ”€โ”€ CV3_Strategy_0.72_Target.md
โ”œโ”€โ”€ CSIRO_Competition_Strategy_DINOv2.md
โ””โ”€โ”€ Strategy_0.75_Execution_Plan.md

docs/
โ”œโ”€โ”€ DINOV3_GOLD_STRATEGY.md     # ํ•ต์‹ฌ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„ ๋ฌธ์„œ
โ”œโ”€โ”€ DIAGNOSTIC_ANALYSIS.md
โ””โ”€โ”€ HYBRID_APPROACH_DESIGN.md

๐Ÿ—บ๏ธ ์‹คํ—˜ ์—ฐ๋Œ€๊ธฐ

Phase 0: EDA & ๋ฐ์ดํ„ฐ ํŒŒ์•…

ํŒŒ์ผ: 01_eda.py ์ฃผ์š” ๋ฐœ๊ฒฌ:

  • Train: 357๊ฐœ ๊ณ ์œ  ์ด๋ฏธ์ง€, ๊ฐ ์ด๋ฏธ์ง€๋‹น 5๊ฐœ ์ƒ˜ํ”Œ (ํƒ€๊ฒŸ๋ณ„) โ†’ ์ด 1,785ํ–‰
  • Test: ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—†์Œ โ†’ ์ด๋ฏธ์ง€๋งŒ์œผ๋กœ ์˜ˆ์ธกํ•ด์•ผ ํ•จ
  • ํƒ€๊ฒŸ ๋ถ„ํฌ:
    • Dry_Clover_g: 37.8%๊ฐ€ 0 (์‹ฌํ•œ sparsity)
    • Dry_Total_g โ‰ˆ Dry_Green_g + Dry_Dead_g + Dry_Clover_g (๋ฌผ๋ฆฌ์  ๊ด€๊ณ„)
    • GDM_g โ‰ˆ Dry_Green_g + Dry_Clover_g
  • Height_Ave_cm๊ณผ Dry_Green_g ์ƒ๊ด€๊ณ„์ˆ˜ 0.648 (๊ฐ€์žฅ ๊ฐ•ํ•จ)
  • WA(Western Australia) 32๊ฐœ ์ƒ˜ํ”Œ ์ „๋ถ€ Dry_Dead_g = 0 (100% ํŒจํ„ด)

Phase 1: ์ดˆ๊ธฐ ์‹คํ—˜ โ€” DINOv2 ViT-Base ์‹œ๋Œ€ (v02~v11)

ํŒŒ์ผ: 02~11_*.py ์ ‘๊ทผ๋ฒ•: DINOv2 ViT-Base(86M) โ†’ Frozen backbone โ†’ ๋‹ค์–‘ํ•œ Head ์‹คํ—˜

์‹คํ—˜ ํŠน์ง•
02~06 ResNet/EfficientNet baseline, Kaggle/Colab ํ™˜๊ฒฝ ์„ค์ •
07 Physics-constrained head (GDM=G+C, Total=GDM+D)
08 Auxiliary task learning
09~10 Pseudo labeling
11 LUPI/Knowledge Distillation hybrid approach

๊ฒฐ๊ณผ: LB ~0.50์—์„œ ์ •์ฒด ์›์ธ ๋ถ„์„:

  • ViT-Base๋Š” feature ํ‘œํ˜„๋ ฅ์ด ๋ถ€์กฑ
  • Frozen backbone โ†’ ๋„๋ฉ”์ธ ์ ์‘ ๋ถˆ๊ฐ€
  • LUPI/KD๋Š” Teacher ceiling(0.62)์ด Student ์ƒํ•œ์„ ์ด ๋จ

Phase 2: DINOv3 ViT-Large ์ „ํ™˜ (v12~v19)

ํ•ต์‹ฌ ์ „ํ™˜: Public notebook 070.py ๋ถ„์„์œผ๋กœ ํ•ต์‹ฌ ๊ตฌ์กฐ ํŒŒ์•…

ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ:
1. DINOv3 ViT-Large (~300M) >> ViT-Base (86M)
2. ์ด๋ฏธ์ง€๋ฅผ Left/Right ์ ˆ๋ฐ˜์œผ๋กœ ๋ถ„ํ•  ํ›„ FiLM fusion
3. Physics constraints (GDM=G+C, Total=GDM+D)
4. 5-Fold Ensemble + TTA

์•„ํ‚คํ…์ฒ˜ (v12~ ์ดํ›„ ํ‘œ์ค€):

Input Image (70cm ร— 30cm)
        โ”‚
   โ”Œโ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”
   โ–ผ         โ–ผ
Left Half  Right Half (๊ฐ๊ฐ 512ร—512 resize)
   โ”‚         โ”‚
   โ””โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”˜
        โ”‚ DINOv3 ViT-Large (๊ณต์œ  backbone)
        โ”‚ output: 1024-dim
        โ–ผ
      FiLM Module (cross-region context sharing)
      ฮณ = Tanh(MLP(left+right)/2)
      ฮฒ = Tanh(MLP(left+right)/2)
      left_mod = left ร— (1+ฮณ) + ฮฒ
        โ”‚
   Concat(left_mod, right_mod) โ†’ 2048-dim
        โ”‚
   โ”Œโ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”
Head_Green  Head_Clover  Head_Dead
   โ”‚           โ”‚           โ”‚
   โ””โ”€โ”€โ”€โ”€โ”€Softplus (non-negative)
        โ”‚
   Physics Layer: GDM = G+C, Total = GDM+D
        โ”‚
   [Green, Dead, Clover, GDM, Total]

์‹คํ—˜ ํ๋ฆ„:

๋ฒ„์ „ ํ•ต์‹ฌ ๋ณ€๊ฒฝ ๊ฒฐ๊ณผ
v12 DINOv3 ViT-Large + FiLM ์ฒซ ๊ตฌํ˜„ ๊ธฐ์ค€์ 
v13 ์ตœ์ ํ™” (AMP, gradient clipping) -
v14 ๊ฐœ์„  -
v15 ๊ธฐ๋ณธ์œผ๋กœ ๋ณต๊ท€ -
v16 Optuna HPO ์ถ”๊ฐ€ -
v17 Optuna ์ตœ์ ํ™” ์ ์šฉ -
v17b CV-LB gap ๊ฐ์†Œ ์‹œ๋„ -
v18 Simple model tuning -
v19 Trial 22 vs 27 ๋น„๊ต -

Phase 3: v20 ๊ณ„์—ด โ€” ์ตœ๊ณ ์  ๋‹ฌ์„ฑ (v20~v27)

v20: ํ•ต์‹ฌ baseline ํ™•๋ฆฝ

ํŒŒ์ผ: 20_train.py ์ฃผ์š” ํŠน์ง•:

  • hidden_dim=512, num_layers=3, dropout=0.1
  • Sampling_Date ๊ธฐ๋ฐ˜ StratifiedGroupKFold โ† ์ดํ›„ ๋ฐœ๊ฒฌ์ ์œผ๋กœ ์ค‘์š”
  • AMP(์ž๋™ ํ˜ผํ•ฉ ์ •๋ฐ€๋„) ํ•™์Šต
  • Cosine scheduler with warmup

v21: LOGO (Leave-One-Group-Out)

ํŒŒ์ผ: 21_train.py ์•„์ด๋””์–ด: Location(Site) ๊ธฐ๋ฐ˜ leave-one-out CV๋กœ ๋” ์—„๊ฒฉํ•œ validation ๊ฒฐ๊ณผ: CV ํ•˜๋ฝ (๋ฐ์ดํ„ฐ๊ฐ€ ๋„ˆ๋ฌด ์ž‘์Œ)

v22: Frozen backbone + ๊ฐ•ํ•œ ์ •๊ทœํ™”

ํŒŒ์ผ: 22_train.py ํŠน์ง•: hidden_dim=256, num_layers=2, backbone ๊ณ ์ • ๊ฒฐ๊ณผ: CV ํ•˜๋ฝ - fine-tuning์ด ํ•„์š”ํ•จ์„ ํ™•์ธ

v23: ์ตœ์ ํ™”๋œ LOGO

ํŒŒ์ผ: 23_train.py ๊ฒฐ๊ณผ: ๊ฐœ์„  ์—†์Œ

v24: TENT (Test-Time Entropy minimization)

ํŒŒ์ผ: 24_infer_tent.py ์•„์ด๋””์–ด: Test ๋ฐ์ดํ„ฐ์˜ BN ํ†ต๊ณ„๋กœ ๋ชจ๋ธ adapt ๊ฒฐ๊ณผ: Hidden test set์—์„œ ์˜ค๋ฅ˜ ๋ฐœ์ƒ์œผ๋กœ ์‹คํŒจ

v25: Vegetation Index Late Fusion

ํŒŒ์ผ: 25_train.py ์•„์ด๋””์–ด: NDVI/Height ๋“ฑ tabular feature๋ฅผ ์ถ”๊ฐ€ ์ž…๋ ฅ์œผ๋กœ ๊ฒฐ๊ณผ: Test์— ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์—†์–ด ํšจ๊ณผ ์ œํ•œ์ 

v26: OOF (Out-of-Fold) ์ €์žฅ

ํŒŒ์ผ: 26_train_oof.py ๋ชฉ์ : ์•™์ƒ๋ธ” ๊ฐ€์ค‘์น˜ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•œ OOF ์˜ˆ์ธก ์ˆ˜์ง‘ ํŠน์ง•: v20 ๊ตฌ์กฐ ์œ ์ง€, OOF ํŒŒ์ผ ์ถ”๊ฐ€ ์ €์žฅ

v27: 5-๋ชจ๋ธ ์•™์ƒ๋ธ” โ€” ํ˜„์žฌ ์ตœ๊ณ ์  LB 0.70

ํŒŒ์ผ: 27_train.py, 27_infer.py

# v27์˜ 5๊ฐœ ๋ชจ๋ธ ์กฐํ•ฉ
MODELS = {
    'v20': (hidden_dim=512, layers=3),  # ๊ธฐ๋ณธ ๊ตฌ์กฐ
    'v22': (hidden_dim=256, layers=2),  # ์ž‘์€ Head, frozen backbone
    'v23': (hidden_dim=512, layers=3),  # v20๊ณผ ๋™์ผ, ๋‹ค๋ฅธ seed
    'v25': VegetationEncoder + FiLM,    # VegIdx late fusion
    'v26': (hidden_dim=512, layers=3),  # OOF ๋ฒ„์ „
}
# ์•™์ƒ๋ธ”: Simple average (5 ร— 5-fold = 25๊ฐœ ๋ชจ๋ธ)

์™œ 0.70์„ ๋‹ฌ์„ฑํ–ˆ๋‚˜:

  • ๋ชจ๋ธ ๋‹ค์–‘์„ฑ: 3๊ฐ€์ง€ ๊ตฌ์กฐ ร— ๋‹ค๋ฅธ seed โ†’ ์•™์ƒ๋ธ” ํšจ๊ณผ
  • 5๊ฐœ ๋ชจ๋ธ ร— 5-fold = 25๊ฐœ ์˜ˆ์ธก์˜ ํ‰๊ท 

์•ฝ์ :

  • CV leakage (image_id๋กœ grouping โ†’ ๊ฐ™์€ ๋‚ ์งœ ์ด๋ฏธ์ง€๋“ค์ด ์„ž์ž„)
  • CV ~0.80์€ ํ—ˆ์œ„ โ€” ๊ณผ์ ํ•ฉ๋œ ๊ฒƒ
  • TTA ์—†์Œ

Phase 4: CV ๊ฐœํ˜ โ€” ์ •์งํ•œ Cross-Validation

๋ฐฐ๊ฒฝ: Discussion 126 votes ์ธ์‚ฌ์ดํŠธ

"๋ฐ˜๋“œ์‹œ Sampling_Date๋กœ GroupKFold ํ•ด์•ผ ํ•จ. ๊ฐ™์€ ๋‚ ์งœ ์ด๋ฏธ์ง€๋“ค์€ ๋™์ผํ•œ ๋‚ ์”จ/์กฐ๋ช… ์กฐ๊ฑด ๊ณต์œ . image_id๋กœ ํ•˜๋ฉด ์‹ฌ๊ฐํ•œ data leakage."

CV1: ์ •์งํ•œ CV ๊ธฐ์ค€์  โ€” LB 0.68

ํŒŒ์ผ: cv1_train.py, cv1_infer.py ํ•ต์‹ฌ ๋ณ€๊ฒฝ:

# โŒ ์ด์ „ (leakage)
groups = df['image_id']

# โœ… CV1 (์ •์ง)
groups = df['Sampling_Date']  # ๋‚ ์งœ๋ณ„ ์™„์ „ ๋ถ„๋ฆฌ
sgkf = StratifiedGroupKFold(n_splits=5)
# + State_Month stratification key
๋ณ€๊ฒฝ์‚ฌํ•ญ:
- CV Split: image_id โ†’ Sampling_Date (data leakage ์ œ๊ฑฐ)
- ํ•ด์ƒ๋„: 512 โ†’ 560 (14์™€ 16 ๋ชจ๋‘์˜ ๋ฐฐ์ˆ˜)
- TTA: 4-fold (Original ร— HFlip ร— VFlip)
- Head: hidden_dim=256, num_layers=2, dropout=0.3

๊ฒฐ๊ณผ:

  • CV Score: 0.6366 (์ •์ง, fold๋ณ„ 0.71, 0.65, 0.64, 0.66, 0.63)
  • Public LB: 0.68
  • CV-LB gap: ~0.04 (์ด์ „ v27์˜ gap ~0.10๋ณด๋‹ค ํ›จ์”ฌ ์ž‘์Œ)

์˜๋ฏธ: ์ •์งํ•œ CV ํ™•๋ณด โ†’ ์ดํ›„ ์‹คํ—˜์˜ ์‹ ๋ขฐ ๊ฐ€๋Šฅํ•œ ๊ธฐ์ค€์ 


CV2: Weighted Loss + Frozen backbone

ํŒŒ์ผ: cv2_train.py ์‹คํ—˜ ๋ชฉ์ : ๋Œ€ํšŒ ํ‰๊ฐ€์ง€ํ‘œ(Weighted Rยฒ)์— ๋งž์ถ˜ loss function

# Competition weights: Total=0.5, GDM=0.2, ๋‚˜๋จธ์ง€=0.1
loss = weighted_mse(pred, target, weights=[0.1, 0.1, 0.1, 0.2, 0.5])
+ frozen backbone (fine-tuning ์—†์ด head๋งŒ ํ•™์Šต)

๊ฒฐ๊ณผ: CV 0.5966 โ†’ ์‹คํŒจ ์›์ธ:

  • Frozen backbone: 357๊ฐœ ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ์—์„œ ๋„๋ฉ”์ธ ๊ฐญ ํ•ด๊ฒฐ ๋ถˆ๊ฐ€
  • Weighted Loss: MSE ๋Œ€๋น„ ํ•™์Šต ๋ถˆ์•ˆ์ •

์„œ๋ธŒ ์‹คํ—˜: Optuna HPO (cv2_optuna.py)

  • ์ž‘์€ Head ํƒ์ƒ‰: hidden_dim=[64,128,256,512], num_layers=[1,2,3]
  • ๊ฒฐ๋ก : hidden_dim=256, num_layers=2๊ฐ€ ์ตœ์  (ํฐ head๋Š” 357๊ฐœ์— ๊ณผ์ ํ•ฉ)

CV3: ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ โ€” ์—ญํšจ๊ณผ

ํŒŒ์ผ: cv3_train.py, cv3_infer.py ์‹คํ—˜ ๋ชฉ์ : Discussion ๋ณด๊ณ  (0.60 โ†’ 0.62 ๊ฐœ์„ )

def clean_image(img):
    # 1. Bottom 10% crop (color chart, cardboard artifacts)
    img = img[0:int(h*0.90), :]

    # 2. Orange timestamp inpainting (HSV mask + cv2.inpaint)
    mask = cv2.inRange(hsv, [5,150,150], [25,255,255])
    img = cv2.inpaint(img, mask, 3, cv2.INPAINT_TELEA)

๊ฒฐ๊ณผ: CV 0.5253 โ†’ Public LB 0.65 โ†’ ์—ญํšจ๊ณผ

์›์ธ ๋ถ„์„:

0.60 ์ˆ˜์ค€: ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ โ†’ ์‹ ํ˜ธ ๋Œ€๋น„ ํ–ฅ์ƒ โ†’ ํšจ๊ณผ์ 
0.70 ์ˆ˜์ค€: ์ •๋ณด ์†์‹ค์ด ๋” ํผ โ†’ ์˜คํžˆ๋ ค ํ•ด๋กœ์›€
๊ฒฐ๋ก : ๊ณ ๋“์  ๊ตฌ๊ฐ„์—์„œ๋Š” "๋…ธ์ด์ฆˆ ์ œ๊ฑฐ"๋ณด๋‹ค "์ •๋ณด ๋ณด์กด"์ด ์ค‘์š”

๋ณ‘ํ–‰ ์‹คํ—˜: WA State Dead=0 ํ›„์ฒ˜๋ฆฌ ๊ฐœ๋ฐœ

# WA 32๊ฐœ ์ƒ˜ํ”Œ ๋ชจ๋‘ Dead=0 โ†’ 100% ํŒจํ„ด โ†’ ๊ฐ•์ œ ํ›„์ฒ˜๋ฆฌ
if state == 'WA':
    pred[dead_idx] = 0.0
    pred[gdm_idx] = green + clover
    pred[total_idx] = green + clover  # dead=0์ด๋ฏ€๋กœ

Phase 5: ์•™์ƒ๋ธ” ์ „๋žต ๊ฐ•ํ™”

CV4: v27 + TTA + WA ํ›„์ฒ˜๋ฆฌ

ํŒŒ์ผ: cv4_infer.py ๋ชฉํ‘œ: ๊ธฐ์กด v27 ์ฒดํฌํฌ์ธํŠธ ํ™œ์šฉ, ๋น ๋ฅธ ์ ์ˆ˜ ํ–ฅ์ƒ

v27 5๊ฐœ ๋ชจ๋ธ ร— 5-fold = 25 ์ฒดํฌํฌ์ธํŠธ
+ 4-fold TTA (Original, HFlip, VFlip, Both)
+ WA State Dead=0 ๊ฐ•์ œ ํ›„์ฒ˜๋ฆฌ
= ์ด 100๊ฐœ ์˜ˆ์ธก ํ‰๊ท 

ํŒŒ์ƒ ๋ฒ„์ „:

  • cv4a_infer.py: 2-fold TTA๋งŒ (Kaggle ์‹œ๊ฐ„ ์ œํ•œ ๋Œ€์‘)
  • cv4b_infer.py: v20/v22/v26 3๊ฐœ ๋ชจ๋ธ๋งŒ (timeout ๋ฌธ์ œ ํ•ด๊ฒฐ)

CV5: ConvNeXt-Base ๋ฉ€ํ‹ฐ ๋ฐฑ๋ณธ ์•™์ƒ๋ธ”

ํŒŒ์ผ: cv5_train.py, cv5_infer.py ์•„์ด๋””์–ด: Transformer + CNN์˜ ์ด์ค‘ ๊ด€์  ์•™์ƒ๋ธ”

DINOv3 ViT-Large: Global attention, long-range dependency
ConvNeXt-Base (ImageNet-22k): Local patterns, hierarchical features
โ†’ ์„œ๋กœ ๋‹ค๋ฅธ inductive bias โ†’ ์•™์ƒ๋ธ” ๋‹ค์–‘์„ฑ ๊ทน๋Œ€ํ™”
# cv5e (์•™์ƒ๋ธ” inference)
CV5E_WEIGHT = 0.3   # ConvNeXt: ๋‹ค์–‘์„ฑ ๋ชฉ์ 
V27_WEIGHT = 0.7    # DINOv3: ๋ฉ”์ธ ๋ชจ๋ธ

ํŠน์ง•:

  • ConvNeXt: convnext_base.fb_in22k_ft_in1k, feat_dim=1024
  • ์ด๋ฏธ์ง€ ํฌ๊ธฐ: 560ร—560 (DINOv3์™€ ๋™์ผ)
  • WandB ์‹คํ—˜ ์ถ”์ 

Phase 6: ์•„ํ‚คํ…์ฒ˜ ์‹คํ—˜ (CV6~CV8)

CV6: ์ง์‚ฌ๊ฐํ˜• full-frame + SSF Adapters

ํŒŒ์ผ: cv6_train.py, cv6_infer.py ํ•ต์‹ฌ ์•„์ด๋””์–ด: ์ด๋ฏธ์ง€๋ฅผ Left/Right๋กœ ์ž๋ฅด์ง€ ๋ง๊ณ , ์›๋ž˜ ๋น„์œจ ์œ ์ง€

๊ธฐ์กด: Left(512ร—512) + Right(512ร—512) โ†’ FiLM fusion
CV6:  Full-frame (784ร—336)           โ†’ ๋‹จ์ผ ์ž…๋ ฅ
     โ†‘ 70cmร—30cm ์›๋ž˜ ๋น„์œจ ๊ทผ์‚ฌ
class CFG:
    img_size = (336, 784)      # Height ร— Width (๋น„์œจ ์œ ์ง€)
    freeze_backbone = True     # Frozen + SSF๋งŒ ํ•™์Šต
    use_ssf = True             # Scale-Shift Feature adapters

# SSF: ๊ฐ Transformer block ์ถœ๋ ฅ์— ํ•™์Šต ๊ฐ€๋Šฅํ•œ scale/shift ์ ์šฉ
# ฮณ, ฮฒ๋งŒ ํ•™์Šต โ†’ Frozen backbone์—์„œ ๋„๋ฉ”์ธ ์ ์‘ ๊ฐ€๋Šฅ
class SSFAdapter(nn.Module):
    # scale: ฮพ * x + ฮณ (per-feature)

์ถ”๊ฐ€ ํŠน์ง•:

  • ZeroInflatedHead: Clover์˜ 37.8% zero ์ฒ˜๋ฆฌ (๋ถ„๋ฅ˜ + ํšŒ๊ท€ 2-stage)
  • CLS + Patch Mean pooling (richer aggregation)
  • ZeroInflatedLoss: BCE(zero/nonzero) + MSE(nonzero only)

๋ชฉํ‘œ: SSF๋กœ frozen backbone์˜ ํ•œ๊ณ„ ๊ทน๋ณตํ•˜๋ฉด์„œ overfitting ๋ฐฉ์ง€


CV7: OOF ๊ธฐ๋ฐ˜ ์žฌํ•™์Šต

ํŒŒ์ผ: cv7_train.py, cv7_infer.py ๊ธฐ๋ฐ˜: v26 ๊ตฌ์กฐ ๋ชฉ์ : ๋‹ค๋ฅธ ํ•ด์ƒ๋„/๋‚ ์งœ split ์„ค์ •์œผ๋กœ OOF ํ’ˆ์งˆ ๊ฐœ์„ 


CV7a: EMA (Exponential Moving Average)

ํŒŒ์ผ: cv7a_train.py ํ•ต์‹ฌ ์ถ”๊ฐ€:

class EMA:
    """Shadow weights: ฮธ_ema = decay * ฮธ_ema + (1-decay) * ฮธ"""
    # ํ•™์Šต ์ค‘ weight์˜ ์ง€์ˆ˜ ์ด๋™ ํ‰๊ท  ์œ ์ง€
    # Inference: EMA weights ์‚ฌ์šฉ โ†’ ์•ˆ์ •์ , ์ผ๋ฐ˜ํ™” ์šฐ์ˆ˜

class CFG:
    use_ema = True
    ema_decay = 0.999
    backbone_lr_mult = 0.084  # LLRD: backbone lr = lr ร— 0.084

์™œ EMA์ธ๊ฐ€: ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ(357๊ฐœ)์—์„œ weight ์ง„๋™ ์™„ํ™”, ๋” ๋ถ€๋“œ๋Ÿฌ์šด loss landscape


CV7b: EMA variant 2

ํŒŒ์ผ: cv7b_train.py EMA ์„ค์ • ๋ณ€ํ˜• ์‹คํ—˜


CV8: LLRD (Layer-wise Learning Rate Decay)

ํŒŒ์ผ: cv8_train.py ํ•ต์‹ฌ ์•„์ด๋””์–ด:

# Transformer ๋ ˆ์ด์–ด๋ณ„ LR ๊ฐ์‡  ์ ์šฉ
# ๊นŠ์€ ๋ ˆ์ด์–ด (ํ•˜์œ„ ๋ ˆ์ด์–ด): ์ž‘์€ LR โ†’ ์‚ฌ์ „ํ•™์Šต ๋ณด์กด
# ์ƒ์œ„ ๋ ˆ์ด์–ด + Head: ํฐ LR โ†’ ํƒœ์Šคํฌ ์ ์‘
layer_lr_decay = 0.9  # ๋ ˆ์ด์–ด๋‹น 10% ๊ฐ์‡ 
# Layer 0 lr = base_lr ร— decay^n_layers
# Layer n lr = base_lr ร— decay^0 = base_lr

๐Ÿ”‘ ํ•ต์‹ฌ ์ธ์‚ฌ์ดํŠธ ๋ฐ ๊ตํ›ˆ

1. CV ์ „๋žต์ด ๊ฐ€์žฅ ์ค‘์š”

image_id grouping โ†’ CV 0.80 (ํ—ˆ์œ„) โ†’ LB 0.70, CV-LB gap 0.10
Sampling_Date grouping โ†’ CV 0.64 (์ •์ง) โ†’ LB 0.68, CV-LB gap 0.04

โ†’ ์ •์งํ•œ CV ์—†์ด๋Š” ์•„๋ฌด๊ฒƒ๋„ ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋‹ค.

2. ์ด๋ฏธ์ง€ ์ „์ฒ˜๋ฆฌ์˜ ์—ญ์„ค

๋‚ฎ์€ ์ ์ˆ˜(0.60): ์ „์ฒ˜๋ฆฌ ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ โ†’ +0.02 ํšจ๊ณผ ์žˆ์Œ (Discussion ๋ณด๊ณ )
๋†’์€ ์ ์ˆ˜(0.70): ์ „์ฒ˜๋ฆฌ โ†’ ์˜คํžˆ๋ ค -0.05 (CV3)

โ†’ ์ •๋ณด ๋ณด์กด vs ๋…ธ์ด์ฆˆ ์ œ๊ฑฐ์˜ trade-off๋Š” ์ ์ˆ˜ ์ˆ˜์ค€์— ๋”ฐ๋ผ ๋‹ค๋ฆ„

3. ์•™์ƒ๋ธ” ๋‹ค์–‘์„ฑ > ๋‹จ์ˆœ ์ •ํ™•๋„

๋‹จ์ผ ๋ชจ๋ธ (CV1): LB 0.68
5-๋ชจ๋ธ ์•™์ƒ๋ธ” (v27): LB 0.70
์ฐจ์ด: +0.02 (๋ชจ๋ธ ๋‹ค์–‘์„ฑ๋งŒ์œผ๋กœ)

4. ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ + ๊ฐ•๋ ฅํ•œ Backbone

๋ฐ์ดํ„ฐ: 357๊ฐœ ์ด๋ฏธ์ง€ (๋งค์šฐ ์ž‘์Œ)
์ตœ์  Head: hidden_dim=128~256, num_layers=1~2, dropout=0.3~0.5
ํฐ Head(hidden_dim=512, layers=3) โ†’ ๊ณผ์ ํ•ฉ
DINOv3 ViT-Large๊ฐ€ ์ด๋ฏธ 1024-dim ํ’๋ถ€ํ•œ feature ์ œ๊ณต

5. Physics Constraints๋Š” ๋ฌด๋ฃŒ ์„ฑ๋Šฅ ํ–ฅ์ƒ

# ๋ชจ๋ธ์ด ๋ฌผ๋ฆฌ ๋ฒ•์น™์„ ์ž๋™์œผ๋กœ ๋งŒ์กฑํ•˜๋„๋ก ๊ฐ•์ œ
GDM = Green + Clover      # ๋ณ„๋„ ํ•™์Šต ๋ถˆํ•„์š”
Total = GDM + Dead        # ํ•ญ์ƒ consistent

๐Ÿ—๏ธ ํ•ต์‹ฌ ์•„ํ‚คํ…์ฒ˜ (ํ‘œ์ค€ v20 ๊ณ„์—ด)

class CSIROModel(nn.Module):
    backbone = timm.create_model(
        "vit_large_patch16_dinov3_qkvb.lvd1689m",
        pretrained=False  # ๋ณ„๋„ weights ๋กœ๋“œ
    )  # DINOv3 ViT-Large, 1024-dim output

    film = FiLM(feat_dim=1024)           # Cross-region modulation

    head_green  = MLP(2048 โ†’ 512 โ†’ 1)   # Dry_Green_g
    head_clover = MLP(2048 โ†’ 512 โ†’ 1)   # Dry_Clover_g
    head_dead   = MLP(2048 โ†’ 512 โ†’ 1)   # Dry_Dead_g

    # Physics: GDM = G+C, Total = GDM+D (computation, not learning)

ํ•™์Šต ์„ค์ •:

  • Optimizer: AdamW
  • LR: 1e-4 (head), 1e-5 (backbone, ร—0.1)
  • Scheduler: Cosine with warmup
  • Loss: MSE on [Green, Dead, Clover] (GDM, Total์€ ๊ณ„์‚ฐ์œผ๋กœ ์ž๋™)
  • Image size: 560ร—560 (14์™€ 16 ๋ชจ๋‘์˜ ๋ฐฐ์ˆ˜)
  • Augmentation: HFlip, VFlip, ColorJitter
  • AMP (Mixed Precision)

๐Ÿš€ ํ˜„์žฌ ๋„์ „ ๊ณผ์ œ ๋ฐ ๋‹ค์Œ ์ „๋žต

๋ฌธ์ œ: 0.70 โ†’ 0.79 gap (0.09)

์˜ˆ์ƒ ํšจ๊ณผ๋ณ„ ์ „๋žต:

์ „๋žต ์˜ˆ์ƒ ํ–ฅ์ƒ ์ƒํƒœ
CV ์ˆ˜์ • (Sampling_Date) +0.03~0.05 โœ… CV1์—์„œ ์™„๋ฃŒ
ํ•ด์ƒ๋„ 560 + TTA +0.02~0.03 โœ… CV1์—์„œ ์™„๋ฃŒ
Optuna HPO (์ž‘์€ Head) +0.02~0.03 ๐Ÿ”œ ์ง„ํ–‰ ์˜ˆ์ •
EMA (CV7a) +0.01~0.02 ๐Ÿ”œ ์‹คํ—˜ ์ค‘
LLRD (CV8) +0.01~0.02 ๐Ÿ”œ ์‹คํ—˜ ์ค‘
Multi-backbone (DINOv3+ConvNeXt) +0.02~0.03 ๐Ÿ”œ CV5E
Weighted Loss alignment +0.01~0.02 ์‹คํ—˜ ํ•„์š”
Multi-seed ensemble +0.01 ์‹คํ—˜ ํ•„์š”
OOF ๊ธฐ๋ฐ˜ ์•™์ƒ๋ธ” ์ตœ์ ํ™” +0.01 ์‹คํ—˜ ํ•„์š”

์ฃผ์˜: Private LB๋Š” ์ „์ฒด์˜ 47%. v27(leakage CV) ๊ธฐ๋ฐ˜ ์ œ์ถœ์€ Private์—์„œ ํ•˜๋ฝ ์œ„ํ—˜.


๐Ÿ› ๏ธ ํ™˜๊ฒฝ ์„ค์ •

# ์ฃผ์š” ์˜์กด์„ฑ
torch>=2.0  timm  albumentations  transformers  wandb  optuna

# DINOv3 weights (Kaggle dataset: pretrained-weights-biomass)
# /kaggle/input/pretrained-weights-biomass/dinov3_large/dinov3_large/dinov3_vitl16_qkvb.pth

ํ•™์Šต/์ถ”๋ก  ๋ถ„๋ฆฌ ์ „๋žต:

1. [ํ•™์Šต] cv*_train.py โ†’ Colab/Kaggle GPU์—์„œ ์‹คํ–‰ (~80๋ถ„)
                       โ†’ fold*.pth ์ €์žฅ โ†’ Google Drive ๋˜๋Š” Kaggle Dataset
2. [์ถ”๋ก ] cv*_infer.py โ†’ Kaggle ์ œ์ถœ ๋…ธํŠธ๋ถ (๊ฐ€์ค‘์น˜๋งŒ ๋กœ๋“œ, ~1๋ถ„)

๋งˆ์ง€๋ง‰ ์—…๋ฐ์ดํŠธ: 2026-02-26 ํ˜„์žฌ ์ตœ๊ณ  Public LB: 0.70 (v27) ์ •์งํ•œ CV ๊ธฐ์ค€์ : 0.68 (CV1)

About

[Kaggle] ๐Ÿฅˆ 181st/3802

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors