iT邦幫忙

2026 iThome 鐵人賽

DAY 17
0
AI Engineering

Model with GIS系列 第 22 篇

[Day 22] Mixing Dataset

  • 分享至 

  • xImage
  •  

Day 21 我們用幾何合併把六個碎框縫成一條跑道,但留下一個沒解決的問題,合併框太胖。跑道實際寬度大概 60 px,我們縫出來的框寬 224.9 px,長寬比只有 2.52。今天要處理這件事,用的是 Day 20 就講過但一直沒做的混合資料集。

為什麼混合資料集應該work

先把 Day 20 那張交叉驗證表拿出來看:

模型 驗證集 mAP50
baseline(整圖訓練) 原始整圖 valid 0.495
baseline(整圖訓練) 切片 valid 0.000
tiled(切片訓練) 原始整圖 valid 0.099
tiled(切片訓練) 切片 valid 0.205

對角線高、反對角線低,兩個模型各自只在自己的領域裡work。整圖模型有全局視野但看不見半截跑道,切片模型看得見半截跑道但忘了全局視野。

那如果把兩份資料餵給同一個模型呢?直覺上它應該要同時看過「一整座機場」跟「一截柏油路」,兩種感受野都學到。

合併資料集不是把檔案倒在一起

最直覺的做法是把兩個資料夾複製到同一個地方,但這樣會出事,因為比例不對:

整圖 train: 18 張
切片 train: 96 張

1 比 5.33,切片會把整圖淹掉。模型看到的絕大多數樣本都是切片,訓練出來會很接近純切片模型。

那要不要複製整圖 5 份湊成 1:1?這裡有個更細的問題,該用什麼當分母。我先把標註實例數也數出來:

Find-airport-1      train  檔案  18  實例  21  空標註  0
find-airport-tiled  train  檔案  96  實例  93  空標註 11

張數比是 1:5.33,實例比卻是 1:4.43。差異來自切片資料集裡那 11 張純背景(Day 20 刻意保留的負樣本),它們有圖片但沒有任何標註。拿張數當分母會被背景切片灌水。

模型實際在學的是標註實例,所以我用實例數來算過取樣倍率:

_, whole_inst = count_instances(WHOLE_ROOT / "train" / "labels")   # 21
_, tiled_inst = count_instances(TILED_ROOT / "train" / "labels")   # 93
repeat = max(1, round(tiled_inst / max(whole_inst, 1)))            # 4

跑出來的結果:

train 實例數: 整圖 21 / 切片 93 -> 整圖過取樣 x4
[train] 整圖   72 + 切片   96 =  168 張 /  177 實例
[valid] 整圖    2 + 切片   12 =   14 張 /   18 實例
[test ] 整圖    2 + 切片   12 =   14 張 /   11 實例

實例數 84 對 93,接近 1:1。

為什麼驗證集不做過取樣

BALANCE_SPLIT = "train"   # 只有訓練集需要重取樣

過取樣是為了改變模型看到的資料分布,那是訓練階段的事。驗證集的職責是量測,把同一張圖重複四次只會讓指標失真,而且跟其他模型的驗證集不一致就沒得比了。

過取樣不等於變出更多資料

要講清楚一件事,把同一張圖複製四份不是把資料變成四倍。模型看到的還是那 18 張原圖,只是每個 epoch 會看到它們四次。真正讓四份副本長得不一樣的是 augmentation(fliplr / flipud / degrees=90),每次餵進去的翻轉角度都不同。

所以這是重新加權,不是資料增量。它解決的是「整圖樣本被切片淹掉」的問題,解決不了「原圖只有 18 張」的問題。

訓練

超參數刻意一個字都沒改,跟 Day 20 的 train_tiled.py 完全一樣:

model.train(
    data=str(project_root / "find-airport-mixed" / "data.yaml"),
    epochs=50, imgsz=640, batch=16, device="0",
    name="airport_obb_mixed",
    fliplr=0.5, flipud=0.5,
    degrees=90.0,   # 跟 train_tiled 對齊,把資料集之外的變因鎖住
)

這是刻意的實驗設計。三個模型如果連 augmentation 都不一樣,最後跑出差異也說不清楚是資料的功勞還是超參數的功勞。只讓一個變因動。

50 epochs 在 RTX 5070 Ti 上跑了 58 秒。

交叉驗證:從 2x2 變成 3x2

把 Day 20 的四格表擴成六格:

模型 驗證集 P R mAP50 mAP50-95
baseline 整圖 valid 0.853 0.500 0.495 0.346
baseline 切片 valid 0.000 0.000 0.000 0.000
tiled 整圖 valid 0.189 0.500 0.099 0.069
tiled 切片 valid 0.541 0.250 0.205 0.131
mixed 整圖 valid 0.677 0.500 0.495 0.198
mixed 切片 valid 0.661 0.250 0.245 0.111

混合模型兩邊都站穩了。整圖 mAP50 從切片模型的 0.099 拉回 0.495,切片 mAP50 從 0.205 拉到 0.245,precision 更是兩邊都比對應的專家模型高或接近(切片上 0.661 > tiled 的 0.541)。

Day 20 那個 0.000 的斷崖,被填平了。

但這張表要小心讀

有三個地方會騙人,得先講清楚:

  1. 驗證集小到會量化。整圖 valid 只有 2 張圖、2 個實例,所以 recall 只可能是 0、0.5、1.0 三個值,三個模型都是 0.500 不是因為它們一樣強,是因為都只抓到兩個裡的一個。切片 valid 的 16 個實例也一樣,0.250 就是抓到 4 個。
  2. mixed 跟 baseline 的整圖 mAP50 一模一樣是 0.495,這在 2 個實例的驗證集上是巧合,不是「證明兩者等價」。
  3. mAP50-95 退步了。整圖上 baseline 是 0.346,mixed 只有 0.198。mAP50-95 要求在 IoU 0.5 到 0.95 的各個門檻下都框得準,這個數字掉下來的意思是混合模型找得到,但框得沒 baseline 那麼貼。

第三點特別重要,因為今天的目標就是「把胖框瘦回去」,而驗證集的指標說框得更不準了。所以還是得回到真實衛星圖上看。

拉回真實衛星圖

同一張 GeoTIFF、同一套 CLAHE 前處理、同樣 0.25 門檻,全部都套上 Day 21 的幾何合併:

[tiled  slice320] 原始 6 框 -> 合併後 4 框
   members=[0, 2, 4]  conf=0.559  角度=145.6  長=566.0  寬=224.9  長寬比=2.52
   members=[1]        conf=0.354  角度= 56.2  長= 67.5  寬= 59.0  長寬比=1.14
   members=[3]        conf=0.316  角度=  2.0  長=154.1  寬=100.0  長寬比=1.54
   members=[5]        conf=0.273  角度= 30.1  長=182.2  寬= 87.7  長寬比=2.08

[mixed  slice320] 原始 2 框 -> 合併後 1 框
   members=[0, 1]     conf=0.507  角度=142.0  長=467.3  寬= 92.4  長寬比=5.05

[mixed  slice640] 原始 3 框 -> 合併後 2 框
   members=[0, 1]     conf=0.577  角度=143.4  長=369.5  寬=102.3  長寬比=3.61
   members=[2]        conf=0.327  角度= 50.4  長= 53.8  寬= 37.1  長寬比=1.45

day22 compare

中間那張是今天的成果,一個框、一條跑道、零誤判。

三個數字最有感:

  • 寬度 224.9 -> 92.4,胖框瘦掉 59%
  • 長寬比 2.52 -> 5.05,形狀終於像一條跑道而不是一個街區
  • 原始框 6 -> 2,模型根本沒產生那些壓在市區跟海岸線上的誤判,Day 21 那個共線性過濾器這次沒東西可過濾

左邊那三個橘色框(Day 21 得靠共線性檢查踢掉的離群碎片)在中間這張完全消失了。這代表誤判不是靠後處理擋掉的,是模型一開始就沒認錯。

順便回答一個問題:混合模型該切多大

右邊那張是同一個混合模型改切 640。結果是長寬比 3.61(比 320 差),而且多了一個 0.33 的誤判小框。

有點反直覺,因為混合模型明明看過整圖,理論上 640 應該更適合它。我的解讀是切 640 的時候,這張 1349x923 的圖只切出寥寥幾片,重疊區變少,SAHI 能拿來互相佐證的證據也變少了。切 320 雖然把跑道切得更碎,但碎片多、重疊多,反而讓 Day 21 的主軸擬合有足夠的點去對齊。

切片尺寸要配合的是推論時的資料密度,不只是訓練時的視野。

還沒解決的

寬度 92.4 px 對上目測 60 px 的跑道,還是胖了 50%。要再瘦下去大概不是資料混合能解決的,得回到標註本身,或者用 segmentation 的遮罩去修 OBB。

更根本的問題是原圖只有 18 張。今天做的所有事情(切片、混合、過取樣)都是在同一批 18 張圖上重新排列組合,這是資料工程不是資料增量。驗證集只有 2 張圖 2 個實例,任何指標都很吵,六格表裡真正有說服力的其實只有 baseline 那個 0.000,因為只有它大到不可能是雜訊。

小結

今天把整圖跟切片合成一個資料集,關鍵不是複製檔案,是用標註實例數而不是圖片張數來決定過取樣倍率,避開了純背景切片灌水的陷阱。

交叉驗證從 2x2 擴成 3x2,混合模型兩個領域都站穩,Day 20 那個 0.000 的斷崖被填平。回到真實衛星圖,合併框寬度從 224.9 瘦到 92.4、長寬比從 2.52 拉到 5.05,而且誤判框直接歸零。

但也得誠實說,驗證集小到指標會量化,mAP50-95 甚至退步了,真正撐住結論的是衛星圖上那張圖,不是那張表。

明天要把 Day 18 的 CLAHE 前處理、今天的混合模型、Day 21 的幾何合併串成一條完整的推論管線,讓這三天的成果變成一個函式吃 GeoTIFF 就能用,那我們明天見。


上一篇
[Day 21] NMS、NMM and GREEDYNMM
下一篇
[Day 23] String
系列文
Model with GIS 共 23 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言