🏺【年内ラスト】Vesuvius Surface Detectionで“沼→0.467”まで駆け上がった話(そして次に0.47台を取りに行く設計図)
3日前、Public Scoreは 0.235。
「これ、何か根本からズレてない?」と疑いながらも、手を動かして、試して、壊して、戻して。
昨日、ようやく 0.467 まで到達しました。
年内最後の投稿なので、今回は「気合い」でまとめます。
何が効いたのか/なぜ効いたのか/次に何をするのかを、技術的に腹落ちする形で書き残します。
1. 0.235 → 0.467:一番効いたのは「encoder刷新」だった
結論から言うと、スコアが跳ねた最大要因はこれです。
encoder="resnet34" → "timm-efficientnet-b3" に変更
3日前に0.23台で迷走していたときは、改善の方向性が見えづらかった。
でもB3に変えた瞬間、景色が変わった。これは偶然じゃなくて、セグメンテーション(特に2.5D)の構造と相性がいい。
なぜ EfficientNet-B3 が効きやすいのか(技術的整理)
Vesuviusのsurfaceは、輪郭がくっきりしているわけじゃない。
薄いテクスチャ差、局所の濃淡、かすれ…そういう“微妙な違い”を拾いに行くタスクです。
UNet/UNet++は、encoderが吐き出す各stageの特徴(浅いエッジ〜深い文脈)をdecoderで再構成する。
つまり encoderの特徴品質がそのままスコアに乗る。
ResNet34でも動くけど、B3は
特徴表現がリッチになりやすい
同解像度帯で拾えるテクスチャ情報が増える
2.5D(複数スライスch)の統合が強く出やすい
結果として、土台が一段上がる。
今回のジャンプは、まさにそれだった。
2. 「突然スコアが落ちる」現象も体験した(0.467 → 0.452)
0.467まで来たあと、直近提出が 0.452 に落ちました。
この -0.015 は、モデルが弱いというより 推論パイプラインのどこかが壊れたサインになりやすい。
セグは特に、“盛った工夫”が逆に刺さって死ぬことがある。
典型的に落ちる原因(今回意識したチェックポイント)
閾値がズレた(0.50固定の罠)
後処理が強すぎる(MIN_SIZEやdilationで細いsurfaceが消える)
アンサンブルの平均方式ミス(logits平均↔︎prob平均、sigmoid二重)
TTAの入れ方(flip戻しミス/効果薄なのに時間だけ増える)
正規化やsliceの取り方がtrainとズレた
この段階で痛感したのはこれ。
スコアを上げる前に、まず“壊れてない推論”を固定するべき
3. 0.46台の戦い方:この帯は「0.003で順位が動く」
この順位帯、スコア密度が高い。
0.470(+0.003)、0.474(+0.007)、0.477(+0.010)…と、少しの改善で順位が動く。
だからここからは、アーキ刷新より
推論の再現性
閾値最適化
後処理の最適化
アンサンブルの安定化
が、最短で効く。
4. 推論を“壊さずに”伸ばす技術:まずは3手で切り分ける
セグは、いきなり全部盛るとどれが効いたかわからない。
提出枠も有限なので、「切り分けて当てる」のが速い。
Step 1:まず“素の推論”に戻す(安全確認)
TTA:OFF
後処理:OFF(MIN_SIZE=0 / DILATE=0)
閾値:0.50(仮)
アンサンブル:等重み(まず0.5/0.5)
目的はスコアUPじゃない。
パイプラインが壊れてないかを確認する。
Step 2:閾値をOOFで最適化(この帯の最強の拾い方)
0.50固定は損しやすい。
OOFで最適閾値を拾って固定すると、+0.003〜0.01が普通に出る。
Step 3:後処理は“弱く入れて”スイープ
まず MIN_SIZE のみ(0, 50, 100, 150, 200)
dilationは最後(入れるなら1から)
「見た目が綺麗」=「高スコア」ではない。
surfaceは細い構造になりやすいので、MIN_SIZE強すぎは普通にFNを増やす。
5. アンサンブルは “logits平均” が安定(ここ重要)
セグのアンサンブルで事故りやすいのが「平均の場所」。
prob平均でも動くけど、モデル間キャリブレーション差があると不利になりやすい。
経験上、最も安定するのは:
logitsを重み付き平均 → sigmoidは最後に1回
これは“壊れにくい”。
6. 次の予定:B3で堅く伸ばしつつ、B0を「役割」で使う
ここからの作戦は2軸。
軸A:現行EffB3でアンサンブルを詰めて0.47台へ
伸びやすい順にいくと:
foldモデルのlogits平均(等重み)
アンサンブル後に閾値をOOFで再最適化
seed違いを追加して 2→3→5本へ
checkpoint averaging(EMA/SWA等)でブレを減らす
この順で、スコアを落とさず上積みを狙う。
軸B:EffB0は「単体で勝つ」より“多様性枠”として使う
B0は軽い。だからこそできることがある。
img_size を 320/384 に上げる
num_slices を増やす(9/11など)
それでB3と違う予測傾向を作って、アンサンブルで得する
B0は「B3の下位互換」になりがちだけど、
設計を変えて予測のズレを作れれば強い味方になる。
7. タイムアウト回避の優先度(精度を落としにくい順)
時間制限は、このコンペの“現実”。
最優先:GPUを必ず使う(Accelerator Noneは詰み)
次:TTAは基本OFF(時間増が大きい割に効かないことがある)
次:BATCH_Z を上げる(精度影響ゼロの高速化)
最後:Z_INFER_STRIDE=2(速いが精度落ちやすいので最終手段)
まとめ:年内の結論は「土台を上げて、壊さずに詰める」
この数日で一番大きかった学びはこれです。
土台(encoder)が弱いと、詰めても伸びない
推論パイプラインが不安定だと、盛るほど死ぬ
0.46〜0.47台は、モデル刷新より 閾値・後処理・アンサンブルが効く
ResNet34→EffB3で土台が上がった。
ここからは、壊れない推論を固定して、堅く0.47台を取りに行く。
年内ラスト、ここまで積み上げた。
年明けは、アンサンブルを完成させてもう一段上へ。
もし同じ帯で沼っている人がいたら、まず言いたいのはこれ。
「盛る」より先に「壊れてない」推論を作る。
そして閾値をOOFで決める。
この2つだけで、たぶん世界が変わります。
スキ・フォローで応援いただけると励みになります!
他にも「AI×仕事術」の具体的な活用ノウハウを発信しています。
👉 Threads: @code.hachi
👉 Instagram: @code.hachi
