「衛星画像×機械学習で船を見つける！ViTとResNet50の性能比較」

---

## 衛星画像×機械学習：船舶検出モデルの選定と評価

### 背景と目的

衛星画像を用いた船舶検出は、海上交通監視や密漁防止、防災計画など、さまざまな分野で重要な役割を果たします。本記事では、Kaggleから公開されているデータセット（[Ships in Satellite Imagery](https://www.kaggle.com/datasets/rhammell/ships-in-satellite-imagery)）を用いて、「船が写っている（1）」か「船が写っていない（0）」の2値分類タスクを実施しました。

このタスクにおける主な目的は以下の通りです：
- 複数のモデルを比較し、分類性能を評価。
- 誤分類の原因を分析し、モデル改善のヒントを得る。

---

### 元データについて
本記事で使用したデータセットは、Robert Hammell氏が提供する以下のデータセットです：
- **データ名**: [Ships in Satellite Imagery](https://www.kaggle.com/datasets/rhammell/ships-in-satellite-imagery)  
- **提供者**: Robert Hammell  
- **DOI**: [10.34740/kaggle/dsv/61115](https://doi.org/10.34740/kaggle/dsv/61115)  
- **ライセンス**: CC BY-SA 4.0

```
@misc{robert_hammell_2018,
	title={Ships in Satellite Imagery},
	url={https://www.kaggle.com/dsv/61115},
	DOI={10.34740/KAGGLE/DSV/61115},
	publisher={Kaggle},
	author={Robert Hammell},
	year={2018}
}
```

---

## データ準備と拡張

### データセットの概要

- 総画像数: 4000枚（80x80ピクセルのカラー画像）
- クラス分布: 船あり(1000枚)、船なし(3000枚)
- 提供形式: JSONファイル形式（画像データ、ラベル、位置情報）(shipsnet.json (343.9 MB))
以下の画像はデータセットの一部です。

#### 港の全体画像

![sfbay_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/8d6e8d9e-f7d1-9b3b-3ec9-a011e6e68c61.png)


#### 船ありの画像例
![1__20180714_182155_1051__-122.34193815177993_37.71791845851837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/cd23b4ef-8312-d793-9feb-10651d47b079.png)

#### 船なしの画像例
![0__20150830_000650_0b07__-122.40480193174041_37.757000251300894.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/4cbb6a9c-ca19-e7b2-5034-f4ec1d6a4a6e.png)
![0__20150830_000650_0b07__-122.37967271362145_37.76049394246638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/5f10e8ec-009a-f647-a24c-3c7ed6e4817f.png)

### データの分割
データは以下の割合で分割しました：
- 訓練データ (60%)
- 検証データ (20%)
- テストデータ (20%)

### データ拡張
以下の手法を用いて訓練データを拡張し、モデルの汎化性能を向上させました：
- 水平反転
- ランダム回転
- ランダムクロップ

---

## モデルの選定と評価

### 使用したモデル一覧

以下の8つのモデルを選定し、性能を比較しました（記事の下部に詳細）：

1. **ViT (Vision Transformer)**  
   - **特長**: Transformerベースのアーキテクチャで、画像分類タスクに特化。ImageNetで事前学習済みモデルをファインチューニングした。  
   - **データ前処理**: 入力データ（80x80ピクセル）をモデル仕様に合わせて **224x224** にリサイズ。  
     ```python
     transforms.Resize((224, 224)),  # モデルに合わせてリサイズ
     ```

2. **ResNet50**  
   - **特長**: CNN（畳み込みニューラルネットワーク）の代表的なアーキテクチャであり、深い層構造を持つ。

3. **Simple CNN**  
   - **特長**: 軽量で高速なアーキテクチャ。小規模データセットに適した設計。

4. **EfficientNetB0**  
   - **特長**: パラメータ効率が高く、性能と計算コストのバランスが良い。

5. **EfficientNet-like (カスタム)**  
   - **特長**: EfficientNetを参考にしたカスタムアーキテクチャ。

6. **Custom ResNet**  
   - **特長**: ResNet50をベースに一部カスタマイズされたモデル。

7. **MobileNet-like (カスタム)**  
   - **特長**: 軽量なアーキテクチャで、リソース制約のある環境に適合。

8. **MobileNetV2**  
   - **特長**: MobileNetの改良版で、高効率なモデル設計。

9. **VGG16**  
   - **特長**: 初期の深層CNNアーキテクチャ。層が非常に深い一方で、パラメータ数が多い。

---

### モデル学習設定

- **環境**: Google Colab (NVIDIA T4 GPU)  
- **バッチサイズ**: 32  
- **エポック数**: ViTは10、それ以外は20  
- **オプティマイザ**: ViTはAdamW、それ以外はAdam  
- **ロス関数**: バイナリクロスエントロピー  

学習時間は、30分の学習で十分完了しました。

---
### 評価プロセス

1. **AUCスコアによる全モデルの評価**  
   - 各モデルについて、しきい値を固定（0.5）してAUCスコアを算出し、分類性能を比較。

2. **F1スコアを用いた最適なしきい値の探索**  
   - AUCスコア上位3モデルについて、F1スコアを最大化する最適なしきい値を決定。

### 評価結果

#### AUCスコアによる結果

| モデル名              | AUCスコア | 誤分類サンプル数 |
| ----------------- | ------ | -------- |
| ViT               | 1.0000 | 3        |
| ResNet50          | 0.9996 | 8        |
| Simple CNN        | 0.9982 | 13       |
| EfficientNetB0    | 0.9934 | 26       |
| EfficientNet-like | 0.9781 | 57       |
| Custom ResNet     | 0.9732 | 71       |
| MobileNet-like    | 0.9212 | 140      |
| MobileNetV2       | 0.5942 | 200      |
| VGG16             | 0.5000 | 200      |

---

### 上位3モデルの詳細

今回の評価で上位に選ばれた3モデルは以下の通りです。

---

#### 1. **ViT (Vision Transformer)**

- **ライブラリ**: [PyTorch](https://pytorch.org/) + [timm](https://github.com/huggingface/pytorch-image-models)  
  - **timm** は多数の事前学習済みモデルが公開されており、Apache-2.0 licenseで無料利用できます。  
- **モデル構築のポイント**:
  ```python
  import timm

  model_name = "vit_base_patch16_224"
  model = timm.create_model(
      model_name,
      pretrained=True,   # 事前学習済み重み
      num_classes=2      # 2クラス分類
  )
  ```
  - `vit_base_patch16_224` は ImageNetを使って事前学習されており、小規模データセットでも高性能が期待できます。
- **しきい値調整**: 0.95  
- **F1スコア**: 0.9975  
- **誤分類数**: 1
　以下は閾値0.5の時の誤分類例です。閾値を0.95にしたとき一番右のみが誤分類となります。右と左は船に見えますが、ラベルは「船でない」になっています。（ラベルミス？）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/4e2dae22-bb41-e916-2e51-a6bde8a8cdf2.png)


---

#### 2. **ResNet50**

- **モデルファイル**: `resnet50_model.keras`  
- **ライブラリ**: [Keras/TensorFlow](https://www.tensorflow.org/) または [PyTorch](https://pytorch.org/)  
  - 本記事ではKeras実装を使用。TensorFlow/KerasはApache License 2.0で無料利用可能です。  
- **モデル構築のポイント**:
  - 50層という深い構造を持つため、高い表現力を発揮。
  - 転移学習によりImageNetの事前学習済み重みを活用。
- **しきい値調整**: 0.61  
- **F1スコア**: 0.9826  
- **誤分類数**: 7
　以下は閾値0.5の時の誤分類例です。「船」を「船でない」に分類しているように見える例（上左から1番目）や、「船でない」を「船」に分類しているように見える例（上左から5番目）もあります。ラベルミスっぽいものもあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3973173/12162ddb-075a-155a-eea6-0cc0f6f2cf09.png)

---

#### 3. **Simple CNN**

- **モデルファイル**: `simple_cnn.keras`  
- **ライブラリ**: [Keras/TensorFlow](https://www.tensorflow.org/)  
- **モデル構築のポイント**:
  - 畳み込み層とプーリング層を基本としたごくシンプルな構成。
  - パラメータ数が少なく、計算コストを抑えられる。
- **しきい値調整**: 0.58  
- **F1スコア**: 0.9751  
- **誤分類数**: 10

---

### F1スコアを用いた結果（上位3モデル）

| モデル名              | AUCスコア | 最適なしきい値 | F1スコア  | 誤分類サンプル数 |
| ----------------- | ------ | ------- | ------ | -------- |
| ViT               | 1.0000 | 0.95    | 0.9975 | 1        |
| ResNet50          | 0.9996 | 0.61    | 0.9826 | 7        |
| Simple CNN        | 0.9982 | 0.58    | 0.9751 | 10       |

---
## 結論と提案

本記事では、衛星画像を用いた船舶検出タスクにおける複数モデルの性能を比較し、以下の知見を得ました：

### 主な知見
1. **ViTの卓越した性能**  
   - AUCスコア1.0000、F1スコア0.9975で、誤分類を1件に抑える優れた性能を発揮。  
   - 一方で計算コストが高く、リソース制約のある環境では注意が必要です。

2. **ResNet50のバランスの良さ**  
   - 高いAUCスコア（0.9996）と適度な計算コストを両立。  
   - しきい値調整（0.61）により、誤分類数を7件に削減可能。

3. **Simple CNNの効率性**  
   - 軽量モデルながらAUCスコア0.9982、F1スコア0.9751を達成。  
   - リソース制約のある環境や高速処理が求められる場面に適しています。

4. **その他のモデル**  
   - MobileNetV2やVGG16は学習に失敗の可能性があり、再検証が必要。  
   - EfficientNet系モデルは中程度の性能で、特定の制約下での利用が検討されます。

### 今後の課題と提案
1. **誤分類の原因分析**  
   - 一部ラベルミスが疑われる画像を再確認し、データ品質を向上させる。  
   - 船や波、背景の類似ケースを対象にデータ拡張やアンサンブルモデルを活用。

2. **計算効率の最適化**  
   - Simple CNNのさらなる軽量化や最適化を進めることで、運用効率を向上。  
   - 高性能モデル（ViTやResNet50）は、特定用途での実運用テストを実施。

今回の結果から、**衛星画像を用いた船検出タスク**ではViTやResNet50が非常に高い性能を示しました。一方で、Simple CNNのように軽量なモデルも、計算コストを抑えながら一定の精度を確保できます。運用環境やリソースに応じてモデルを選定し、さらなる改善（データ拡張やアンサンブルなど）を検討するとよいでしょう。


この記事の分析結果が、衛星画像解析プロジェクトやモデル選定の一助となれば幸いです。

---

## （おまけ）衛星画像分類タスクで使用したモデル

以下は、衛星画像を用いた船検出タスクで使用したモデルの一覧と、各モデルの構築に使用したライブラリ・アーキテクチャの概要です。これらのライブラリはすべて**無料で利用可能**であり、学習環境には**PyTorchやKeras、timmなどのオープンソースライブラリ**を使用しています。

| モデル名              | 特徴                                       | 使用ライブラリ              | 構築方法の概要                                                                                                 |
| ----------------- | -------------------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------- |
| **ViT**               | Transformerベースの画像分類モデル                | PyTorch + timm       | `create_model("vit_base_patch16_224", pretrained=False)`                                                    |
| **ResNet50**          | 深い層を持つCNNモデル（ResNetシリーズの50層バージョン） | TensorFlow/Keras     | `ResNet50(weights=None, include_top=False)` + GlobalAveragePooling2D + Dense(1, activation='sigmoid')       |
| **Simple CNN**        | 軽量でシンプルなCNNモデル                       | TensorFlow/Keras     | Conv2D + MaxPooling2D + Flatten + Dense(1, activation='sigmoid')                                           |
| **EfficientNetB0**    | パラメータ効率の高いモデル                     | TensorFlow/Keras     | `EfficientNetB0(weights=None, include_top=False)` + GlobalAveragePooling2D + Dense(1, activation='sigmoid') |
| **EfficientNet-like** | EfficientNetを参考に設計したカスタムモデル         | TensorFlow/Keras     | Conv2D + DepthwiseConv2D + GlobalAveragePooling2D + Dense(1, activation='sigmoid')                         |
| **Custom ResNet**     | ResNetアーキテクチャをカスタマイズ              | TensorFlow/Keras     | Conv2D + ResidualBlock + GlobalAveragePooling2D + Dense(1, activation='sigmoid')                           |
| **MobileNet-like**    | MobileNetを参考に軽量化を目指したカスタムモデル    | TensorFlow/Keras     | Conv2D + DepthwiseConv2D + GlobalAveragePooling2D + Dense(1, activation='sigmoid')                         |
| **MobileNetV2**       | MobileNetシリーズの進化版                     | TensorFlow/Keras     | `MobileNetV2(weights=None, include_top=False)` + GlobalAveragePooling2D + Dense(1, activation='sigmoid')    |
| **VGG16**             | 初期の深層CNNアーキテクチャ                    | TensorFlow/Keras     | `VGG16(weights=None, include_top=False)` + Flatten + Dense(1, activation='sigmoid')                        |



---