Day 1 衛星画像分類 技術レポート

L1数式ルールからL3ファインチューニングまでの精度・考察・実務示唆を統合したシングルページレポート

このレポートについて

目的: 衛星画像の土地被覆分類(Land Use / Land Cover Classification)において、手法の複雑さを段階的に上げたとき、分類精度がどう変わるかを検証する。

具体的には、数式ベースの単純なルール(L1)→ 学習済みモデルの特徴量利用(L2)→ モデル全体のファインチューニング(L3)という3段階で精度を比較し、各手法のコスト対効果実務への適用可能性を評価した。

データセット: EuroSAT

項目内容
データ名EuroSAT(Sentinel-2 衛星画像ベンチマーク)
画像数27,000枚(各クラス 2,000〜3,000枚)
画像サイズ64×64ピクセル(10m解像度、約640m×640m の地表をカバー)
バンド数13バンド(可視光〜短波赤外)。ただし今回はRGB 3バンドのみ使用
クラス数10クラス(AnnualCrop, Forest, HerbaceousVegetation, Highway, Industrial, Pasture, PermanentCrop, Residential, River, SeaLake)
データ分割Train 80% (21,600枚) / Test 20% (5,400枚)、random_state=42 で固定
地域ヨーロッパ各地(Sentinel-2 の公開データから切り出し)

実行環境

項目内容
実行環境Google Colab Pro(GPU: T4 / A100)
Python3.10
主要ライブラリPyTorch 2.x, torchvision, scikit-learn, numpy, matplotlib
事前学習モデルResNet50(ImageNet-1K で事前学習済み)、ViT-Tiny(同)

評価指標

  • Accuracy(精度): 正しく分類できた画像の割合。全体の性能を示す最も基本的な指標
  • 3クラス精度: 10クラスを Vegetation / Water / Built-up の3つに集約して評価(L1との公平な比較用)
  • 10クラス精度: 10クラスそれぞれを区別する精度(L2/L3の本来の評価)
  • 混同行列: どのクラスをどのクラスに間違えたかの詳細
  • F1スコア: Precision(適合率)とRecall(再現率)の調和平均。クラスごとの性能評価に使用

比較する3手法

手法概要計算コスト
L1: 数式ベースNDVI/NDWI/NDBI の閾値ルールで3クラス分類。AIモデルなし数秒、GPU不要
L2: 事前学習モデル特徴量ResNet50(凍結)で特徴抽出 → ロジスティック回帰で10クラス分類数分、GPU推奨
L3: ファインチューニングResNet50の全層を衛星画像で再学習して10クラス分類30分、GPU必須

結果サマリ

Day 1(Task 1-1〜1-5)の全結果を統合し、何をどのコードでやったか → どんな結果が出たか → なぜそうなるか → 実務への示唆を1画面で追える内部向けレポートにまとめた。

L1 (Index Threshold)

64.4%

3クラス

L2 (ResNet50 + LogReg)

95.7%

10クラス

L3 (ResNet50 Full FT)

98.5%

10クラス

衛星データの本質

  • Sentinel-2は「写真」を撮るカメラではなく、13バンドの反射率を計測するセンサー
  • 今回のL2/L3はRGB 3バンド(Band 4/3/2)のみ利用し、元データの23%(3/13)しか使っていない。
  • 残り10バンド(近赤外・短波赤外など)を使う余地があり、特に植生系のクラス分離で改善余地がある。

Day 1の5つの学び

学び 1

学習済みモデルを使うだけで L1→L2 で +31.3pt の最大ジャンプ。

学び 2

ファインチューニング(L2→L3)で +2.8pt。追加コストに対して着実な上積み。

学び 3

Head Only (92.4%) は L2 (95.7%) を下回る。凍結特徴 + LogReg の最適化効率が高い。

学び 4

EuroSATのようなきれいなデータでは学習データ50%でも -0.5pt。実務データでは差が拡大しやすい。

学び 5

実務のボトルネックは画像取得ではなくラベル作成コスト(セグメンテーション1枚30分〜1時間)。

Task 1-1: L1 Index Threshold

概要: NDVI/NDWI/NDBI の3指数と閾値ルールだけで 3クラス分類を実施。AIモデルなしのベースラインとして、どこまで分類できるかを確認した。

結果: 3クラス精度 64.4%(Vegetation 98.7%、Water 73.9%、Built-up 0.0%)

目的と手法(指数の意味)

  • NDVI = (NIR - Red) / (NIR + Red): 植生活性を強調
  • NDWI = (Green - NIR) / (Green + NIR): 水域を強調
  • NDBI = (SWIR - NIR) / (SWIR + NIR): 都市域を強調(理論上)

分類ロジック(優先順位):

  1. 全件を Vegetation と仮置き
  2. NDWI > -0.18 を Water に上書き
  3. 残りで NDBI > NDVI を Built-up に上書き

コードで何をやったか(要約)

展開する
python
# 1) データ読み込み
rgb, nir, swir = load_sentinel2_bands(...)

# 2) 指数計算
ndvi = (nir - red) / (nir + red + 1e-8)
ndwi = (green - nir) / (green + nir + 1e-8)
ndbi = (swir - nir) / (swir + nir + 1e-8)

# 3) 閾値探索(NDWI)
for th in np.arange(-0.20, 0.30, 0.02):
    pred = rule_based_predict(ndvi_mean, ndwi_mean, ndbi_mean, th)
    score = accuracy(pred, y_true_3)

# 4) 分類と評価
best_th = -0.18
pred = rule_based_predict(..., best_th)
report = confusion_matrix_and_class_accuracy(pred, y_true_3, y_true_10)

結果テーブル(3クラス)

クラス正解数 / 全数正解率
Vegetation13,331 / 13,50098.7%
Water4,064 / 5,50073.9%
Built-up2 / 8,0000.0%

結果テーブル(10クラス詳細)

元クラス統合先枚数正解率
ForestVegetation3000100.0%
PermanentCropVegetation250099.9%
PastureVegetation200099.8%
AnnualCropVegetation300098.8%
HerbaceousVegetationVegetation300095.8%
SeaLakeWater3000100.0%
RiverWater250042.6%
HighwayBuilt-up25000.0%
IndustrialBuilt-up25000.0%
ResidentialBuilt-up30000.1%

指数分布(index_distributions.png)

指数分布(index_distributions.png)

何を見るべきか: NDWIがWaterを比較的分ける一方、NDVI/NDBIでBuilt-upとVegetationが重なる点。

何がわかるか: 閾値分類でBuilt-upが難しいことを学習前に予見できる。

混同行列(L1_confusion_matrix.png)

混同行列(L1_confusion_matrix.png)

何を見るべきか: Built-up行がどこへ流れているか。

何がわかるか: Built-upの大半がVegetationに流れ、構造的な失敗が確認できる。

ピクセル分類マップ(L1_classification_maps.png)

ピクセル分類マップ(L1_classification_maps.png)

何を見るべきか: River画像で川と周辺植生がどう塗り分けられているか。

何がわかるか: Riverの平均値が植生側へ引っ張られる理由が見える。

3D散布図(L1_3d_scatter.png)

3D散布図(L1_3d_scatter.png)

何を見るべきか: Built-upとVegetationの点群重なり。

何がわかるか: 3指数を同時に使っても線形閾値では分離困難である。

10クラスRGBサンプル(eurosat_10classes_rgb.png)

10クラスRGBサンプル(eurosat_10classes_rgb.png)

何を見るべきか: 見た目が似るクラス(例: AnnualCropとResidential)。

何がわかるか: 人間目視でも曖昧なペアが誤分類源になる。

考察

  • Built-up 0.0%の主因: 都市パッチ内に緑地が多く混在し、画像平均では NDBI > NDVI がほぼ成立しない。
  • River 42.6%の主因: 河川が細く、640mパッチの大半を周辺植生が占めるため平均NDWIが下がる。
  • 閾値法は「明確に異なる物質(水 vs 植生)」には有効だが、混在・微差の識別には限界。

L2への接続

L1の限界は『平均値3次元の情報不足』。L2ではResNet50の2048次元特徴により、テクスチャ・形状・配置パターンを使った判別へ移行する。

Task 1-2: L2 Pretrained Model

概要: ImageNet事前学習済み ResNet50 を特徴抽出器として固定し、抽出された2048次元特徴にロジスティック回帰を学習。

結果: 10クラス 95.7%、3クラス 98.1%

バックボーン + 分類器の構造

段階内容
入力224×224×3 = 150,528個の数値
バックボーンResNet50(50層、約2,350万パラメータ)
特徴2,048次元特徴ベクトル
分類器LogReg(2,048×10+10 = 20,490パラメータ)
出力10クラス確率(softmax)
  • バックボーンは画像から「意味のある特徴」を圧縮抽出する装置。
  • 分類器は2048特徴に重みを掛け、10クラスへ振り分ける。
  • L2ではバックボーンを凍結し、分類器のみ学習(転移学習の最小構成)。

コードで何をやったか(要約)

展開する
python
# 1) ResNet50で特徴抽出(weights=ImageNet)
features_train = backbone(train_images)   # (21600, 2048)
features_test  = backbone(test_images)    # (5400, 2048)

# 2) ロジスティック回帰で10クラス分類
clf = LogisticRegression(max_iter=1000, multi_class='multinomial')
clf.fit(features_train, y_train)
y_pred = clf.predict(features_test)

# 3) 評価
acc10 = accuracy_score(y_test, y_pred)
acc3  = accuracy_score(y_test_3, y_pred_3)

10クラス精度

95.7%

3クラス精度

98.1%

L2_confusion_matrix

L2_confusion_matrix

何を見るべきか: 対角線の濃さと誤分類先の集中。

何がわかるか: L1で壊滅したBuilt-up系が90%超まで回復。

L2_tsne

L2_tsne

何を見るべきか: クラスごとのクラスタ分離と重なり領域。

何がわかるか: 3次元指数では見えない分離構造を2048次元特徴が形成している。

L2_per_class_accuracy

L2_per_class_accuracy

何を見るべきか: クラス間ばらつき(最低Pasture〜最高SeaLake)。

何がわかるか: 全クラス92%以上で大崩れがない。

L2_predictions

L2_predictions

何を見るべきか: 高確信度・低確信度の正解サンプル。

何がわかるか: 『当てたけど迷った画像』がどのタイプか把握できる。

L2_correct_vs_misclassified

L2_correct_vs_misclassified

何を見るべきか: 各クラスの正解例と誤分類例の差。

何がわかるか: 誤分類が似たクラス間で起きることを視覚確認できる。

L2_hard_samples

L2_hard_samples

何を見るべきか: 低確信度サンプルの見た目。

何がわかるか: モデル限界は境界サンプルに集中している。

L1→L2で +31%pt ジャンプした理由

  • L1: NDVI/NDWI/NDBI3次元平均値で判定
  • L2: ResNet50の 2048次元特徴で判定

この「3次元→2048次元」の表現力の跳躍により、平均値では消える空間パターン(道路の直線、住宅地の格子、河川の蛇行)を識別できるようになった。

Task 1-3: L3 Fine-tuning

概要: ResNet50の全層を衛星画像で再学習(ファインチューニング)し、L2の凍結特徴からドメイン適応へ移行。

結果: Full FT 10クラス 98.5%、3クラス 99.6%

L2との違い

項目L2(特徴抽出)L3(FT)
バックボーン凍結更新
学習対象分類器のみ全層(またはヘッド)
計算負荷
期待効果即効で高精度ドメイン最適化

3実験の詳細

実験学習対象10クラス精度
Head OnlyFC層のみ92.4%
Full FT全23.5Mパラメータ98.5%
50% Data FT全23.5M(データ半分)98.0%

学習設定の解説

  • エポック: 全学習データ1周。10エポック = 21,600枚を10周。
  • バッチサイズ64: 21,600枚を337バッチに分割。更新回数は 337×10=3,370
  • Adam: 勢いを考慮してパラメータ更新する最適化手法。
  • CosineAnnealing: 前半は大きく、後半は小さく学習率を下げる。
  • データ拡張: 回転・反転で擬似データを増やして汎化を改善。
  • 正規化: (値-平均)/標準偏差 でスケールを揃える(偏差値と同じ原理)。

GPUが必要な理由

CPUは少数コアの逐次処理、GPUは数千コアの並列処理。2350万パラメータ更新を3370回繰り返すFull FTはGPU前提。

インタラクティブ学習曲線(Test Accuracy)

結果テーブル + 分類レポート(Full FT)

手法3クラス精度10クラス精度
L164.4%N/A
L298.1%95.7%
L3 Full FT99.6%98.5%
クラスPrecisionRecallF1
AnnualCrop0.9670.9770.972
Forest1.0000.9900.995
HerbaceousVegetation0.9720.9850.978
Highway0.9860.9900.988
Industrial0.9860.9940.990
Pasture0.9870.9630.975
PermanentCrop0.9660.9700.968
Residential0.9980.9900.994
River0.9920.9880.990
SeaLake0.9920.9930.993

L3_learning_curves

L3_learning_curves

何を見るべきか: 収束速度の差

何がわかるか: Full FTは初期から高精度で飽和。

L3_confusion_matrix

L3_confusion_matrix

何を見るべきか: 対角線集中

何がわかるか: 全クラスで高い再現率。

L3_per_class_accuracy

L3_per_class_accuracy

何を見るべきか: Head vs Fullの差

何がわかるか: 全層更新の改善幅をクラス別に把握できる。

L3_confusion_diff

L3_confusion_diff

何を見るべきか: 差分ヒートマップ

何がわかるか: どの誤分類ペアが減ったかが見える。

L3_correct_vs_incorrect

L3_correct_vs_incorrect

何を見るべきか: 誤分類サンプルの質

何がわかるか: 残存エラーは人間にも難しい境界事例。

学習曲線の読み方

最初の1〜3エポックで急改善し、その後は緩やかに収束。典型的な収穫逓減パターン。

なぜ Head Only (92.4%) < L2 (95.7%) か

  • L2は全データを一括で使うロジスティック回帰最適化(大域的に解きやすい)。
  • Head Onlyは64枚ミニバッチ更新で局所的・反復的に最適化。
  • NN向け汎用オプティマイザは、2万パラメータの線形分類には過剰で非効率になることがある。

Task 1-4: L1 vs L2 vs L3 比較

概要: L1/L2/L3の結果を横並びで比較し、「どこで何がどれだけ改善したか」を定量・定性の両面で評価。

精度比較(5手法)

手法3クラス精度10クラス精度改善幅
L1: NDVI/NDWI/NDBI Threshold64.4%N/A-
L2: ResNet50 + LogReg98.1%95.7%+31.3pt (vs L1)
L3: FT Head Only-92.4%-3.3pt (vs L2)
L3: FT Full (100% data)99.6%98.5%+2.8pt (vs L2)
L3: FT Full (50% data)-98.0%+2.3pt (vs L2)

5つの主要な発見

  1. L1→L2 が最大のジャンプ(+31.3pt)。
  2. L2→L3 Full FT は +2.8pt の上積み。
  3. Head Only は L2未満で、凍結条件ならLogRegが強い。
  4. Full FTが最高精度(98.5%)。
  5. 学習データ50%でも98.0%(EuroSATのクリーンさを反映)。

L1_L2_L3_comparison_bar

L1_L2_L3_comparison_bar

何を見るべきか: L1→L2→L3の段差

何がわかるか: 最も効く改善ステップが一目でわかる。

effort_vs_accuracy

effort_vs_accuracy

何を見るべきか: 労力と精度の位置関係

何がわかるか: 実務での投資対効果判断に直結する。

L2_vs_L3_confusion

L2_vs_L3_confusion

何を見るべきか: 誤分類セルの減少

何がわかるか: FTでどの混同が減ったか確認できる。

L2_vs_L3_radar

L2_vs_L3_radar

何を見るべきか: L2とL3の面積差

何がわかるか: L3が全方向で上回る傾向を把握できる。

3class_comparison

3class_comparison

何を見るべきか: L1/L2/L3の3クラス混同行列差

何がわかるか: Built-up崩壊がL2/L3で解消したことが明確。

same_image_comparison

same_image_comparison

何を見るべきか: 同一画像の予測変化

何がわかるか: 手法進化に伴う予測改善を直感的に追える。

comparison_6samples_L1L2L3

comparison_6samples_L1L2L3

何を見るべきか: 6サンプル横並び

何がわかるか: クラス横断の改善傾向を確認できる。

comparison_improvement_map

comparison_improvement_map

何を見るべきか: クラス別改善量

何がわかるか: FTの恩恵が大きいクラスを特定できる。

comparison_L3_failures

comparison_L3_failures

何を見るべきか: L3でも誤る画像

何がわかるか: 残課題がデータ曖昧性にあるとわかる。

comparison_L3_error_rate

comparison_L3_error_rate

何を見るべきか: クラス別エラー率

何がわかるか: 次に改善すべきクラス優先度を決められる。

きれいなデータ vs 実務データの精度差

データ量EuroSAT実務データ
1,000枚約95%約78%
5,000枚約97%約86%
20,000枚98.5%約91%

ラベル作りのコスト

衛星画像自体は無料で取得可能だが、高品質ラベル作成(特にセグメンテーション)は1枚30分〜1時間の人手コストが支配的。

Task 1-5: All Models Comparison

概要: 古典ML〜DLまで全8手法を横並び比較し、モデル選定の実務判断に使える精度・コスト地図を作成。

古典ML vs DL の本質

  • 古典ML: 人間が特徴量を設計し、モデルは判定だけを担当。
  • DL: モデルが特徴抽出と判定を同時に学習。深い層で段階的に高次特徴を構築。

古典ML向け手作り特徴量(32次元)

特徴群次元合計
13バンド平均13
13バンド標準偏差13
NDVI/NDWI/NDBI平均3
NDVI/NDWI/NDBI標準偏差332

全8モデル概要

モデルカテゴリ精度
L1: Index ThresholdL164.4
Random ForestClassical ML90.2
SVM (RBF)Classical ML93.8
k-NN (k=5)Classical ML90.3
Simple CNNDeep Learning94.9
L2: ResNet50 + LogRegL295.7
L3: ResNet50 FTL398.5
ViT-Tiny FTDeep Learning98.5

精度ランキング(インタラクティブ)

all_models_results.npz の実測値
モデル精度タイプ
Random Forest90.22Classical
SVM (RBF)93.76Classical
k-NN (k=5)90.28Classical
Simple CNN94.89DL
ViT-Tiny FT98.46DL

all_models_comparison

all_models_comparison

何を見るべきか: カテゴリ別の精度階段

何がわかるか: L1→Classical→DL/FT で段階的に伸びる。

all_models_ranking

all_models_ranking

何を見るべきか: 順位の確定

何がわかるか: 最終候補モデルを短時間で絞り込める。

all_models_class_heatmap

all_models_class_heatmap

何を見るべきか: クラス別の苦手分布

何がわかるか: モデル選定時にクラス別リスクを評価できる。

all_models_cost_vs_accuracy

all_models_cost_vs_accuracy

何を見るべきか: 学習時間と精度の関係

何がわかるか: 精度だけでなくコスト制約下の最適点を選べる。

事前学習 + FT が強い理由

ImageNet 120万枚で得た視覚知識を初期値にすることで、EuroSAT 27,000枚だけでは学びきれないパターンを利用できるため。

実務でのモデル選定フロー

  1. まずResNet50/ViTをFTしてベースライン作成
  2. 要件を満たせば運用へ
  3. 不足する場合はデータ追加・ラベル改善・衛星専用モデルへ拡張