【Object Detection】物体検出AIを学習させるコツ

# 目次
[1. はじめに](#1-はじめに)
[2. 物体検出AIとは](#2-物体検出aiとは)
[3. 物体検出AIは使えるのか](#3-物体検出aiは使えるのか)
[4. データ収集](#4-データ収集)
[5. アノテーション](#5-アノテーション)
[6. モデル選定](#6-モデル選定)
[7. 評価指標](#7-評価指標)
[8. 学習](#8-学習)
[9. おわりに](#9-おわりに)

# 1. はじめに
本記事では、深層学習に基づく物体検出AIを使用する場合のコツについて経験で得た知見をまとめました。

物体検出で最も広く知られているであろう参考文献はyolov3のwikiにある[Tips for Best Training Results](https://github.com/ultralytics/yolov3/wiki/Tips-for-Best-Training-Results)だと思います。このガイドラインに沿って、筆者の知見も合わせて解説します。


# 2. 物体検出AIとは

物体検出(Object Detection AI) は、画像やビデオ中の物体を検出し、それらの物体の位置を示す技術のことです。この技術は、画像分類とは異なり、単に画像内に含まれる物体の種類を判別するのではなく、物体の具体的な位置も同時に検出することができます。

基本的には単一の物体を矩形で囲むように物体を検出します。したがってAIの入力は画像、出力は左上と右上の座標です。

<img width=800 src="https://github.com/Megvii-BaseDetection/YOLOX/blob/main/assets/demo.png?raw=true">

[画像引用元](https://github.com/Megvii-BaseDetection/YOLOX/blob/main/assets/demo.png)

物体検出AIは、様々な産業分野で使われています。主な使用場面としては以下のようなものがあります。

- 画像/ビデオ編集： 物体を検出して切り取ったり、合成することができます。
- 自動運転： 車載カメラから取得されたカメラ映像から周囲の物体を検出し、安全な運行を支援することができます。
- 動画監視： ビデオ監視システムから取得された映像から異常な物体や行動を検出することができます。
- 画像検索： 画像内の物体を検出して、画像内容に基づいた検索結果を提供することができます。
- 商業分析：店舗内の様々な物品の販売や消費者行動の分析などに利用されます。

これらは一例であり、物体検出AIが使われる分野はますます拡がっています。

物体検出には、複数の手法がありますが、主に次の2つのタイプの手法が使われています。

1. 深層学習 (Deep Learning)
この手法では、画像内の物体を検出するために、Convolutional Neural Network (CNN) などの深層学習を使用します。この手法は高い精度を実現することができますが、学習に必要なデータセットが大量に必要であるという欠点もあります。

2. 基本的なアルゴリズム
この手法では、画像内の物体を検出するために、特徴量抽出、画像セグメンテーションなどの基本的なアルゴリズムを使用します。この手法は簡単で理解しやすいが、深層学習に比べて精度が劣るという欠点もあります。

近年は、深層学習に基づく手法が主流となっており、高い精度が求められる場合には、深層学習が適用されることが多いです。


# 3. 物体検出AIは使えるのか

## データの重要性

では私達のビジネスに物体検出AIを活用できるのでしょうか。

近年、画像認識技術の大幅な進歩とともに、物体検出アルゴリズムのアプリケーションも多様化しています。物体検出AIは、画像や動画に含まれる物体を正確に検出することができるため、画像処理、動画処理、セキュリティ、産業、健康などの多様な分野で実用的に利用されています。

一方で、**物体検出AIをうまく構築出来ないケースも見られます**。物体検出AIがうまく動かない場合には、以下のような原因が考えられます。

- **学習データ不足**：　学習データが不十分な場合、モデルは適切に学習することができず、不正確な予測結果を生成する可能性があります。
- 学習データのバイアス： 学習データにバイアスがある場合、モデルは不適切な予測結果を生成する可能性があります。
- **入力データの品質**： 入力データの品質が悪い場合、モデルは正確な予測結果を生成することができない可能性があります。
- モデルの問題： モデルの設定（例えば、モデルのサイズ、学習率、正則化など）が不適切な場合、過学習や学習不足の問題が生じ、正確な予測結果を生成することができない可能性があります。

これらの原因を把握して、適切な対策を講じることが重要です。特に学習データの量と品質に問題が生じることが多いです。

物体検出AIは、様々な対象に使用されていますが、頻繁に使用されている検出対象は、以下のものです。

- 人物： ビデオや写真に含まれる人物の検出。
- 車両： 道路や駐車場などに含まれる車両の検出。
- 物品： スーパーやストアなどでの商品の検出。
- 動物： 野生動物や家畜などの動物の検出。
- 建物： 街路や町の街並みなどの建物の検出。

これらの共通点は、**データが取得しやすいということと応用先が多い**ということです。それだけデータセットが入手しやすく、大量のデータでモデルを学習させることが出来ます。

一方で、自社のみが所持している物品、自社のみが製造している工業製品といったものは量が少なく、一から画像を取得しなければなりません。したがって、自社用のAIを開発するにはお金と時間がかかります。この**投資**[^99]が不十分な場合、目標とする精度を達成できず、プロジェクトが失敗します。

[^99]: AI導入は不確実で本当に効果が出るか分からないことが多い。また、導入にかかる費用も大きいため、効果が出て費用を回収するまでには時間がかかることが多い。つまり、AI導入は大きな「投資」であることを認識したほうが良い。

## 少量データ学習の限界とタスクの見直し

最先端の研究ではFew-Shot Object Detectionと呼ばれる手法が研究されています。Few-Shot Object Detectionは、物体検出のタスクにおいて、限られた数の学習データを使用して、物体検出することを目的とする手法です。
Few-Shot Object Detectionを使用すれば、数枚の教師画像で物体検出ができる可能性がありますが、**未だ発展途上で実用的ではありません**。

**学習データの量が確保できない場合はタスクを見直すことをおすすめします**。分類タスクであれば、少量データでもファインチューニングで高い精度を出すことが出来る可能性があります。AIを活用するプロセスを見直し、精度が必要な場合は分類タスクを、補助的な位置づけで物体検出を活用するとよいです。

学習データが少ない場合でも物体検出モデルを構築する方法を次章で解説しますが、**80%や90%といった精度が安安と出るとは思わないほうが良いです**。


# 4. データ収集
物体検出の学習に必要なデータセットの規模は、学習する物体の種類や数、アルゴリズムなどによって異なります。一般的に、**深層学習に基づく手法の場合は、大量の学習データが必要です**。

受託分析の最初の打ち合わせで、必ずと言っていいほど「どれくらいデータがあれば良いんですか？」と質問されます。開発してる側としては、やってみなければ分からないというのが正直なところですが、ある程度の当たりを付けていないとデータ収集の計画も立てられません。そこで、どれくらいのデータがあればよいかの知見を紹介します。

## 理想的なデータ収集

### 物体画像のバリエーション
>- **クラスごとの画像: 1,500枚以上。**
>- **クラスごとのインスタンス: 10,000インスタンス。**
>- インスタンスの多様性: **本番環境に近い見た目であること**。実際のユースケースでは、異なる時間帯、異なる季節、異なる天候、異なる照明、異なる角度、異なるソース（オンラインスクレイピング、ローカル収集、異なるカメラ）などからの画像を推奨。
> 
> 引用元: Tips for Best Training Results

インスタンスは画像中の物体のことです。**インスタンス数の確保の方が重要**であり、インスタンスの多様性を確保するために画像の枚数を必要とします。

画像1500枚で10,000インスタンスだと、画像1枚あたりにインスタンスが平均6~7個写っていることになります。物体の種類によっては平均6~7個は密に感じる（例えば空を飛んでいる飛行機は画像1枚に複数映る可能性は小さい）ので、**実際は1,500枚よりも多くなる場合があります**。

本番環境が異なる天候、異なるカメラ角度といった、物体の見た目のバリエーションが多くなる場合は、画像の枚数（つまり撮影パターンのバリエーション）を確保します。したがって、**場合によっては、画像枚数は1,500枚よりも多くなる場合があります**。また、見た目のバリエーションがあまりに多くなる場合は、10,000インスタンス以上必要になる場合があります。

[COCOデータセット](https://cocodataset.org/#home)では、**80クラス中73のクラスでインスタンスを10,000以上確保しています**。上記基準の状況に近いので、学習の設定に迷ったときはCOCOデータセットを使った実験を参考にすると良いです。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/d0364c6d-f407-52c3-6f55-ee0ab7061101.png">

[画像引用元](https://github.com/ultralytics/yolov5/wiki/Tips-for-Best-Training-Results)

### 背景画像

>- 背景画像: 背景画像とは、FP（False Positives）を減らすためにデータセットに追加される、物体のない画像のことです。**FPを減らすために0～10%程度の背景画像を推奨しています**（COCOでは参考までに全体の1%である1000枚の背景画像を用意しています）。背景画像にラベルは必要ありません。
> 
> 引用元: Tips for Best Training Results

背景画像も本番環境に近い画像を用意することで、FPを少なくすることができます。また、物体検出AIのフレームワークによっては、インスタンスがない画像は学習から取り除く設定などもあるので、仕様を確認するようにしてください。


### 画像の解像度

画像の解像度ですが、大きい画像サイズを使用する手法で$H=1333,W=800$というものがあるので、これ以上の解像度であれば十分です。

**最近の手法は正方形の画像を入力としていることが多いです**。アスペクト比が1:1でない画像は1:1になるようにグレー等でパディングします。アスペクト比が大きいと余白が大きくなってしまうので、最近のモデルに合わせるならば正方形画像や、4:3のアスペクト比を使用すると良いと思います。


## 実際のデータ収集

Tips for Best Training Results に従ったデータ収集が出来るのが理想ですが、実際の案件で数千~数万枚の画像を確保することは困難な事が多いです。立ち上がったばかりのプロジェクトでは各クラス100枚程度の画像を用意できれば良い方ではないでしょうか。

**数百枚程度の画像では精度を期待できないことが多いですが、物体の見た目のバリエーションを限定することで、少量の画像でも精度を確保できる可能性があります**。例えば車の検出であれば、型はセダンのみ、側面からの見た目、定点カメラにして背景・画角、物体の向きは同一、RGB画像ではなくグレースケール化[^4]、晴れ以外の天気や夜の精度は諦める、といったように状況を限定し、本番の状況を制限することで少量の画像でも精度を確保できる可能性があります。

[^4]: 十分な数のRGB画像を集められない場合はグレースケール化する。ファインチューニングはRGBのweightを使用可能。

このようなサービスの例として、富士フイルムの「[ひびみっけ](https://www.fujifilm.com/jp/ja/business/inspection/infraservice/hibimikke)」があります。このサービスはコンクリート画像からひびを検出するものです。撮影ガイドを準備し、ユーザーが特定の仕様、一定の品質で撮影できるようにしています。また、本番時の撮影品質を確保し、AIの検出率を高めるために、ひびみっけ「マイスター」という撮影ごと請け負うビジネスも展開しています。

<img width=800 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/9338610b-c2e0-d77e-0161-e432bdcab21d.png">

[画像引用元](https://www.fujifilm.com/jp/ja/business/inspection/infraservice/hibimikke/features)


また、大量の画像を用意できる場合でも、物体の見た目のバリエーションがどの程度あるのか把握しておくことは重要です。物体の見た目のバリエーションには次のような要素が影響します。

- 物体の色
- 物体の形
- 物体の素材（透明・反射）
- 物体の大きさ
- 物体の近さ
- 物体の向き
- 背景
- 時間帯・太陽の位置
- 季節
- 天候
- 照明の位置・角度・数
- カメラの角度
- カメラ・レンズの種類
- カメラのブレ（モーションブラー）
- カメラのパラメータ設定
- 白飛び
- フォーカス
- 逆光
- ノイズ
- レンズの汚れ
- 遮蔽物の発生
- 見切れの発生
- 画像の解像度
- 画像の明るさ・コントラスト
- 画像のアスペクト比
- 画像のフォーマット（JPEG、PNG、ほか）
- RGB or グレースケール

これらの要素を本番状況に合わせたデータ収集を行うとよいでしょう。


# 5. アノテーション

物体検出の学習データには、各画像に対する物体の位置情報が含まれている必要があります。この情報を「アノテーション」と呼びます。

アノテーションは、人手で画像内の物体を指定する必要があります。具体的には、画像内の物体を囲む長方形(バウンディングボックス)などの形状を描き、その形状内に含まれる物体を特定の種類にラベル付けすることが必要です。

アノテーションは非常に手間がかかる作業であり、物体検出モデルのトレーニングに最も時間がかかる部分となります。しかし、**高品質なアノテーションデータが用意されている場合、トレーニングされたモデルの精度が大幅に向上する可能性があります**。

## アノテーションの基本

### ラベルの品質

>- ラベルの無矛盾性: すべての画像に含まれるすべてのクラスのインスタンスにラベルを付ける必要があります。部分的なラベル付けはうまくいきません。
>- ラベルの正確性: ラベルは各オブジェクトを密接に囲む必要があります。オブジェクトとそのバウンディングボックスの間に空間があってはなりません。ラベルがないオブジェクトはありません。
> 
> 引用元: Tips for Best Training Results

ラベル（バウンディングボックス）の付け方は全データで一貫している必要があります。アノテーションの基準として、[VOC2011 Annotation Guidelines](http://host.robots.ox.ac.uk/pascal/VOC/voc2011/guidelines.html)が参考になります。重要な基準として、下記のようなものがあります。

- What to label: ラベルをつける全体方針。
- Bounding box: バウンディングボックスの付け方。
- Truncation: 画像からはみ出している物体に対する方針。
- Occlusion: 遮蔽されている物体に対する方針。

### アノテーションツール

手軽なアノテーションツールには以下のようなものがあります。

- [labelImg](https://github.com/heartexlabs/labelImg)
- [labelme](https://github.com/wkentaro/labelme)

構築が少し大変ですが、より便利なものもあります。

- [cvat](https://github.com/opencv/cvat)
- [VoTT](https://github.com/microsoft/VoTT)

**個人的にはcvatがおすすめです**。オートセーブ機能やユーザー管理機能（心許ないが）があり、さらに学習済みモデルを利用したAPIを導入して自動アノテーションも出来ます。

<img src="https://github.com/opencv/cvat/blob/develop/site/content/en/images/cvat.jpg?raw=true">

[画像引用元](https://github.com/opencv/cvat/blob/develop/site/content/en/images/cvat.jpg)

### アノテーションフォーマット

多くの学習手法のリポジトリが、物体検出のベンチマークデータセットであるCOCOデータセットのCOCOフォーマットに対応しているので、基本的にはCOCOフォーマットを使用します。

参考: [COCO Formatの作り方](https://qiita.com/harmegiddo/items/da131ae5bcddbbbde41f)

しかし、COCOフォーマットは一つのjsonファイルにすべての情報が記載されており、また各辞書のデータが相互に参照し合っているため、後から画像を追加したり、二つのデータセットを結合したりすることが難しいです。一応、[datumaro](https://github.com/openvinotoolkit/datumaro)というライブラリが存在し、データセットの結合などが出来ますが、datumaroの学習コストがかかるのであまりおすすめしません。

そこでおすすめなのがYOLOフォーマットです。YOLOフォーマットでは、画像ファイル1つに対してテキストファイルを1つ用意します。テキストファイルはカラムが5つのCSVデータで、(class_id, x_centre,  y_centre,  width,  height)を記載します。ヘッダーはありません。YOLOフォーマットで管理することでアノテーションの追加や画像のtrain-test分割などが簡単になります。**長期的にはYOLOフォーマットでアノテーションを作成し、AIモデルを作成する段階でYOLOフォーマットのアノテーションをCOCOフォーマットに変換するといった管理がおすすめです。**

## アノテーション作業時間の見積り

アノテーションの作業時間は、画像の数や物体の数、アノテーションの詳細度などによって大きく異なります。

一般的に、単一の画像に対するアノテーションには数十秒から数分程度の時間がかかります。また、大量の画像をアノテーションする場合、数時間から数日以上かかることもあります。大量の画像をアノテーションする場合は、チームで作業することもあります。アノテーションの作業時間は、物体検出モデルの精度に大きく影響する要因となりますので、この作業を行うことは、重要な投資となる場合があります。

cvatを使用したバウンディングボックスのアノテーションの場合、画像中に30個のアノテーション対象物体が写っているとして、慣れている人で1枚あたり80秒程度かかります。辛い単純作業なので、長時間集中することは難しく、休憩を多く取り、一日の作業時間も多くしすぎないような配慮が必要になります。

アノテーションの品質を確保するために、レビューも必要になります。理想的には、アノテーター間で相互にレビューし、アノテーター毎の品質や作業時間にばらつきが出ないように相互レビューをします。アノテーター間のレビューが終了したら、深層学習に詳しい人によるレビューも実施します。手戻りがないよう、アノテーション基準の認識合わせを兼ねたレビューをアノテーション作業の初期になるべくはやく行いましょう。

相互レビューも考慮した場合、アノテーション時間は1.5倍になると想定し、バウンディングボックス1個あたりのアノテーション時間は4秒。

$$
80 \times 1.5 \div 30 = 4
$$

**拘束時間を4時間、1時間に10分休憩を2回取るとすると、アノテーター1人・1日で160分の作業時間があり、2400インスタンスのアノテーションができる計算です**。この数値が作業時間見積りの参考値になるでしょう。

他にもアノテーションを行う際には以下のようなことを考慮する必要があります。

- アノテーション基準の作成
- アノテーションフォーマット
- アノテーション体制
- アノテーションスケジュール
- アノテーション基準の教育
- アノテーション時間の計測
- アノテーション生産性の測定
- アノテーションのバックアップ

アノテーションは一見簡単に見えて専門的な作業ですので、アノテーションを請け負う企業に外注することも多いです。1バウンディングボックスで5~15円、5万バウンディングボックスで3週間が目安です。


# 6. モデル選定

物体検出に使用する深層学習モデルの選定基準は以下のようなものがあります。

- アプリケーションの要件： 物体検出のタスクに応じて、画像サイズや物体のサイズ、種類、数などに対応する必要があります。
- 精度： モデルの予測精度が必要なレベルに達する必要があります。
- 推論速度： モデルの推論速度が十分である必要があります。
- メモリ使用量： モデルが使用するメモリ量が、限られたリソースに収まる必要があります。
- 学習データ量： モデルが必要とする学習データ量が利用可能なデータ量に収まる必要があります。
- ライセンス: モデルを実装しているライブラリのライセンスが開発の要件を満たしている必要があります。

これらの選定基準を満たす適切なモデルを選定するためには、複数のモデルを比較・評価する必要があります。また、適切なモデルを選定するためには、専門家の知識や経験が求められることもあります。

## 精度
深層学習は一般的にはモデルの変数が多いほど精度が高くなります。したがって精度を高める場合は変数が多いモデルを利用しますが、モデルの推論速度・メモリ消費量とトレードオフの関係にあるので、慎重に選択する必要があります。

## 推論速度

推論速度を速くするには以下のような方法があります。

- 入力する画像サイズを小さくする。
- バッチサイズを小さくする。
- GPUを使用する。

GPUの有無で推論の速度が大きく変わってしまいます。また、GPUは高価なハードウェアなので、推論速度と費用対効果を考慮して、本番でGPUを使用するか決める必要があります。

他の発展的な方法として、量子化、枝刈り、ONNX runtimeの利用などがあります。

また、推論機能の呼び出しごとにweightをロードする場合は、ロード時間の考慮も必要です。weightのロードは数秒から数十秒かかる場合もあります。

## メモリ使用量

GPUメモリの容量にも注意が必要です。深層学習のモデルおよびデータはGPUメモリを多く消費するため、モデル選定の際に本番のリソースでも稼働することを確認しておきましょう。画像サイズやバッチサイズでGPUメモリの消費量が変わるため注意が必要です。

CPUで推論する場合はRAMを消費しますが、そこまで気にしなくても大丈夫と思われます。

## 学習データ量

変数が多いモデルを学習させるには大量のデータが必要になります。学習済みモデルのファインチューニングでは比較的少ないデータでも良く学習しますが、うまく行かない場合は変数が少ないモデルを選択する必要も出てくるでしょう。

## ライセンス

実装済みモデルのライブラリを利用する場合、適切なライセンスのモデルを選択する必要があります。

[Faster R-CNN のtorchvision実装](https://github.com/pytorch/vision/blob/main/torchvision/models/detection/faster_rcnn.py)はBSD-3-Clause license、[YOLOXの本家実装](https://github.com/Megvii-BaseDetection/YOLOX)はApache-2.0 license、[yolov8の本家実装](https://github.com/ultralytics/ultralytics)はGPL-3.0 licenseとなっています。

アプリケーションの開発要件に合わせて適切なライセンスのモデルを選択する必要があります。コピーレフトライセンスのモデルには気をつけましょう。


## TIPS

物体検出のモデルには多種多様なものがありますが、最初はFaster R-CNNを使用するのが良いかもしれません。深層学習フレームワークであるPyTorchなどに実装が用意されており手軽に試せて、論文でもベンチマークとして頻繁に利用されているためタスクの難しさの感覚を掴むのに役立ちます。

ライセンスを許容できれば、YOLOv8が精度も高く使いやすいです。コピーレフトライセンスを回避するならYOLOXが有力候補になります。

また、小さい物体や混み合った物体の検出にはアンカーフリーのモデルを使用すると精度が出やすいです。発展的な手法には[SAHI](https://github.com/obss/sahi)があります。


## 物体検出フレームワーク

複数の物体検出モデルをまとめて使えるようにしてある便利なフレームワークがあります。

- [MMDetection](https://github.com/open-mmlab/mmdetection)
- [Detectron2](https://github.com/facebookresearch/detectron2)

**速度やモデルの種類数の面でMMDetectionがおすすめです**。ただし、モデルをカスタマイズする場合は学習コストがすごく高いので、オリジナルのモデルのリポジトリを使用することをおすすめします。

# 7. 評価指標

物体検出においては、様々な評価指標が使用されます。一般的に使用される評価指標は以下のものです。

- Precision (適合率)： 正解と予測した物体のうち、実際に正解であったものの割合。
- Recall (再現率)： 実際の正解の物体のうち、正しく予測されたものの割合。
- F1 Score (F1 スコア)： Precision と Recall の調和平均値。
- Intersection over Union (IoU)： 予測した物体と正解の物体の交差領域の割合。
- mean Average Precision (mAP)： 各クラスでの Average Precision (AP) の平均値。AP は Precision-Recall 曲線の下面積に基づく指標。

これらの指標を組み合わせたり、適宜カスタマイズすることで、物体検出タスクの精度を評価することができます。

Precision / Recall / F1 Score を計算するためにはハイパーパラメータとして(iouThrs[^1]、maxDets[^2])のセット、もしくは(iouThrs[^1]、scoreThrs[^3])のセットを与える必要があります。精度を比較する際にしきい値に依存するのは好ましくないため、モデルの評価はmAPで行います。しかし、**評価値の解釈が難しいので、本番導入に向けた評価にはPrecision / Recall / F1 Scoreを利用したほうがよいでしょう**。しきい値を決定する問題が残るので、厳密にはしきい値決定用バリデーションデータを用意しておく必要があります。もしくは、アプリケーションのUIを工夫して、しきい値をユーザーに決定させると良いでしょう。

[^1]: 検出成功とみなすIoUのしきい値。
[^2]: 一枚の画像に対する予測ボックス数の上限。
[^3]: 予測ボックスのクラス確率に対して足切りするしきい値。

# 8. 学習

### ファインチューニング・Early stopping

学習済みのweightがある場合は、ファインチューニングにしたほうが精度が上がりやすいです。ベンチマークデータセットであるCOCOの学習済みweightがある場合が多いです。

分類手法とは異なり、モデルのFC層のみ再学習するといったことはせず、モデル全体を再学習します。従って、**分類モデルと比較して学習に時間がかかります**。

[**物体検出の分野ではEarly stoppingが使われることが少ない**](https://github.com/open-mmlab/mmdetection/issues/2062)ため、Early stoppingが実装されていないケースもあります。


### エポック数・バッチサイズ

>- エポック数: 300エポックからスタートします。早期にオーバーフィットする場合は、エポック数を減らすことができます。300エポックでオーバーフィットが発生しない場合は、600、1200エポックなど、より長い時間学習する。
>- バッチサイズ: **ハードウェアが許容する最大のバッチサイズを使用する**。バッチサイズが小さいと、バッチノルム統計が悪くなるので、避けるべきである。
> 
> 引用元: Tips for Best Training Results

**エポック数よりも重要なのはステップ数です**。ステップ数はweightパラメーターの更新回数のことで、1エポックあたり、(データ数)÷(バッチサイズ)回だけ更新されます。

COCOデータセットを基準に考えることが多いです。各クラス1500枚で、80クラスあるデータセットだと画像枚数は120,000枚です(COCOデータセットだと118,287枚)。ステップ数はバッチサイズとエポック数で決まります。バッチサイズは標準で16とします（GPUに2枚ずつ、8GPU使用するのが標準的です）。

backboneにImageNet pretrainedモデルを使用する場合、慣習では12エポックの学習を1xと表記し、学習の1単位とします。ステップで換算すると、$118,287\times 12/16 = 88715.25$で約88Kステップとなります。慣習では1x,2x,3xといったパターンで学習します。また、エポックではなくステップの方を基準にとって、90Kステップを1単位として学習させる場合もあります。

YOLOシリーズの場合、backboneにCSPDarkNetを使用し、COCOデータセットをスクラッチ学習させることが多いです。バッチサイズを64として、300エポック学習させます。ステップ数では、$118,287\times 300/64=554,470.3125$ステップとなります。

カスタムデータセットを使用してモデルをファインチューニングする場合、データ量がCOCOデータセットと異なるため、元の学習量だと不十分な場合があります。十分な学習を経て収束させるため、**ステップ数が90K以上になるようにバッチサイズとエポックを調整してみてください**。ステップ数が少ないと、学習初期の不安定な挙動を収束していると勘違いすることがあります。もっとステップ数を増やすと精度が向上するといった可能性を見逃すので、最初は過大なステップ数（180K,270K,...）を設定してみて、Validationの値からオーバーフィッティング、アンダーフィッティングをチェックしたほうが良いです。



### モデルへ入力する画像の解像度

>- 画像サイズ。COCOはネイティブ解像度である--img 640で学習しますが、データセットに小さなオブジェクトが多いため、--img 1280のような高い解像度で学習すると効果的です。小さなオブジェクトが多い場合、カスタムデータセットではネイティブ解像度かそれ以上の解像度で学習するのが効果的です。つまり、--img 1280で学習した場合、テストと検出も--img 1280で行う必要があります。
> 
> 引用元: Tips for Best Training Results

yoloシリーズの場合、画像サイズは基本的に640x640pxです。

経験的に、インスタンスサイズは最低40x40px程度はないと、うまく検出出来ないように感じます。

物体検出AIはバウンディングボックスを回帰問題として予測しているので、学習データに含まれないサイズのバウンディングボックスは予測しにくいです。したがって、　**学習データのインスタンスサイズも本番に近いバリエーションを用意することが望ましいです**。画像サイズはオーグメンテーションで変えることもできます。

### ハイパーパラメータ

>- ハイパーパラメータ: デフォルトのハイパーパラメータはhyp.scratch.yamlにあります．ハイパーパラメータの変更を考える前に、**まずデフォルトのハイパーパラメータで訓練することをお勧めします**。一般に，オーグメンテーションハイパーパラメータを増やすと，オーバーフィッティングが減少し遅延するので，より長い学習とより高い最終的なMAPが可能になります．hyp['obj']のような損失成分ゲインのハイパーパラメータを減らすと、それらの特定の損失成分におけるオーバーフィッティングを減らすのに役立ちます。これらのハイパーパラメータを自動的に最適化する方法については、ハイパーパラメータ進化チュートリアルを参照してください。
> 
> 引用元: Tips for Best Training Results

- 調整するハイパーパラメータで影響が大きいのは学習率とweight decayです。Fine tuningの場合は、スクラッチの学習率に対して$10^{-2}\sim 10^{-3}$倍します。

- **アンカーフリーモデルでは、同一箇所に複数のバウンディングボックスが出やすい**ので、NMSの値は試行錯誤でしっかり決める必要があります。

### オーグメンテーション

- オーグメンテーションのバリエーションを増やすとオーバーフィッティングが改善されますが、学習に必要なステップ数が増えます。
- 物体検出AIは複数の損失関数の線形結合で書かれますが、係数を小さくしたタスク（分類やバウンディングボックスロケーション等）のオーバーフィッティングを抑制できます。

- **回転やクロップはshapeの依存性を下げ、テクスチャの依存性を上げます**。物体の形状が強い手がかりになるようなクラスのオブジェクトを検出する場合は回転のオーグメンテーションを弱く、例えば角度を離散的にするなどの対策が考えられます。CNNを用いた物体検出AIは平行移動不変なので平行移動のオーグメンテーションは不要（のはず）です。

### クロスバリデーション

深層学習はモデルの学習に時間がかかるため、ホールドアウト検証であることが多いです。しかし、画像数が少なく、バリデーション画像を十分に確保できない（1クラス100未満）場合は、**たまたま精度が高く出るtrain-valid分割になっている可能性があります**。データが少ない場合こそクロスバリデーションを実施し、精度を確かめましょう。

# 9. おわりに
本記事では、深層学習に基づく物体検出AIを使用する場合のコツについて経験で得た知見をまとめました。
他にも皆さんがご存知のコツがあったらコメントで教えて下さい。

他の深層学習のチューニングに関する文献です。

- [A Recipe for Training Neural Networks](http://karpathy.github.io/2019/04/25/recipe/)
- [Deep Learning Tuning Playbook](https://github.com/google-research/tuning_playbook)