科学しよう

量子計算のプログラミングの解説をメインに、データサイエンス・機械学習について勉強したことをご紹介します

MENU

kaggle体験記: Global Wheat Detection (物体検出による小麦の穂の検出)

8月4日まで開催されていたkaggleの「Global Wheat Detection」コンペの体験談と学んだことをまとめます。

このコンペは様々な地域で撮影された写真から小麦の穂を検出するという物体検出の課題でした。

なお、僕は物体検出はもちろん深層学習もほぼ初心者のため、このエントリーでは技術的に深い内容は書けていないと思います。
逆にこれからkaggle始める、深層学習を使い始める、物体検出を始める、という方に近い内容となっております。

初めてのエントリーでわかりにくいところもあるかと思います。
ご指摘いただけますと幸いです。

目次

1. コンペ概要

https://www.kaggle.com/c/global-wheat-detection

小麦は世界中の食卓に使われていて、植物学的にも農業的にも小麦の分布を知るということが重要らしい。
ただし、これまでの物体検出の取り組みでは地域によってことなる小麦を同じモデルでは検出できていなかった。
このコンペでは複数の地域の小麦の画像を混ぜたデータセットを用いて一つのモデルで小麦を検出できることを目指す。

ということから、地域によるバイアスがかからない柔軟なモデルを構築する必要があります。一昔前に問題になった人種バイアス・性別バイアスにも通じますね。

画像データサマリ

学習データ画像

  • 3422件

評価データ画像

  • 10件(公開データの件数、非公開なデータでは1000件)

評価方法

評価指標

ノートブックの規定

 このコンペはノートブックを提出する必要があります。
https://www.kaggle.com/c/global-wheat-detection/overview/code-requirements

  • CPUだけを使う場合は9時間以内に実行が終了すること
  • GPUを使う場合は6時間に実行が終了すること
  • TPUは使用不可
  • 提出するノートブックについてインターネットは使用不可
    →kaggle kernel標準でインストールされていないライブラリなどをインターネットからpipすることは不可(whlファイルなどをデータセットとしてアップロードしておくことや、gitレポジトリをあらかじめcloneしてデータセットとしてアップロードしておくことは可)
  • 学習済みモデルなど外部データを使うことは可
  • kaggle kernel内でライブラリを編集することは不可
  • 提出ファイル名は「submission.csv」であること

2. 参戦動機

scikit-learnやSQLを使った統計的機械学習はこれまでの業務で経験したり勉強してきましたが、深層学習はありませんでした。
画像処理や物体検出は将来アプリ開発をしてみたく、今のうちに経験しておこうという動機です。
具体的には下記となります。

  • PyTorchを使えるようになりたい
  • 深層学習の勉強をしたい
  • 物体検出の経験を積みたい
  • 画像処理の経験を積みたい
  • (将来的に)メダルが欲しい
    →今回上位50%にやっと入った程度なので、力不足でした、、

3. 結果として経験になったこと

  • PyTorchで学習済みモデルを使った再学習の標準的な流れ
  • FasterRCNNとYOLOv5の使い方
    →YOLOv5は使ってみたけど最終的にはライセンスの問題で使用不可となりました
  • 画像の前処理のライブラリ(albumentation, OpenCV)の使い方
  • 画像の代表的な前処理(DataAugumentation)
  • kaggle kernelの使い方
    ・datasetのアップロード方法
    ・internet使用不可の場合のライブラリ追加方法


4. EDA

小麦画像可視化

バウンディングボックスの位置・幅・高さは画像ごとに下記のようにCSVで与えられています。

f:id:sakumadaisuke32:20200817074841p:plain

小麦画像のバウンディングボックスCSV

"width", "height"列は画像自体のサイズで、1024px x 1024pxの画像ということです。
"x", "y" は各バウンディングボックスの左上の座標で、"w", "h"がその幅と高さです。
これらを基に下記のような画像を作ることでバウンディングボックスの形状や配置を理解することができます。

f:id:sakumadaisuke32:20200817072157p:plain

小麦画像とバウンディングボックス

異常な大きさのバウンディングボックス

バウンディングボックスのCSVから面積の分布を観察しました。

f:id:sakumadaisuke32:20200817075725p:plain

バウディングボックスの大きさの分布(実軸)

f:id:sakumadaisuke32:20200817075813p:plain

バウンディングボックスの大きさの分布(対数軸)

上のグラフからは面積50万平方pxということで、1024px四方にも関わらず700px x 700px程度の大きさもありうることが示唆され、また逆に下の図からは数平方pxの非常に小さいバウンディングボックスが存在することがわかります。
実際に対象の画像を可視化すると下記のようになっていました。

f:id:sakumadaisuke32:20200817080309p:plain

最大の面積のバウンディングボックスを持つ画像
(複数の小麦を含む大きなバウンディングボックス)

f:id:sakumadaisuke32:20200817080728p:plain

最小の面積のバウンディングボックスを持つ画像

最大面積のバウンディングボックスの方は見ての通りですが、最小面積の方は右下をよく見ると

f:id:sakumadaisuke32:20200817080938p:plain

最小面積のバウンディングボックス詳細

という点のようなバウンディングボックスがあります。

これらは教師データとしてはノイズとなるので、除外します。
具体的には面積をあらかじめ計算し、観察した結果から上限・下限を決め打ちし、範囲外のバウンディングボックスを除外します。

また、学習用のデータセットの画像はより大きな画像から切り出された画像であることが元の論文からわかるそうです。(僕は未着手です)
なんとかして切り貼りして元の画像を復元することで新しい画像を作り出すこともできたようです。
https://www.kaggle.com/c/global-wheat-detection/discussion/149805


5. 重要だった前処理

画像処理

用いたライブラリ

 

前処理の種類

アフィン変換

  • 回転
  • 拡大・縮小
  • 上下左右反転(マイナス倍の拡大縮小)
  • せん断(やってない)
  • 平行移動

https://imagingsolution.blog.fc2.com/blog-entry-284.html

の画像がわかりやすく、大きく4種類です。


クロッピング

画像の一部分を切り出すこと

 

HSV変換

画像データの表現方法の一つ、HSV(Hue-Sturation-Value=色相-彩度-明度)を調整すること

 

モザイク

ここでのモザイクは画像をぼかすことではなく、複数(今回は四枚)の画像を切り貼りして一つの画像とすることでした

 

cut-out

CNNの正則化手法の一つで、画像の一部を塗りつぶして欠落させること

これらを試した結果の前後が下図です。

f:id:sakumadaisuke32:20200817083002p:plain

前処理前

f:id:sakumadaisuke32:20200817083045p:plain

前処理後

画像処理後、範囲外やcut-outで画像が小麦がなくなった箇所のバウンディングボックスは削除や変形が必要です。
albumentationsを用いた場合には自動で処理してくれるメソッドもありますが、してくれないメソッドもあります。

なのでcut-outやモザイクは下記のノートブックのように自作関数で処理しています。

https://www.kaggle.com/nvnnghia/awesome-augmentation#Augmentation-functions

https://www.kaggle.com/kaushal2896/data-augmentation-tutorial-basic-cutout-mixup#Let's-define-new-augmentations

また、僕は今回適用する時間がなかったのですが下記のmix-upも有効だったようです。

mix-up

2つの画像を透過させる形で重ね合わせる手法です。
概要は下記の記事をご参照ください。
https://qiita.com/yu4u/items/70aa007346ec73b7ff05
https://www.kaggle.com/kaushal2896/data-augmentation-tutorial-basic-cutout-mixup#Let's-define-new-augmentations

Pseudo-labeling(擬似ラベリング) 

COCOなどで作成された事前学習モデルから今回の小麦データで再学習する前に、検証用のpublicの画像データにバウンディングボックスを推論し、検証用データも学習データに含めること。
データの水増しとエントロピー減少に役立つらしい。
ノートブック
https://www.kaggle.com/nvnnghia/fasterrcnn-pseudo-labeling
元論文
http://deeplearning.net/wp-content/uploads/2013/03/pseudo_label_final.pdf

 

6. よく利用されていたアルゴリズム

Faster-RCNN

https://qiita.com/mshinoda88/items/9770ee671ea27f2c81a9#2-5-faster-r-cnn

EfficientDet

https://www.kaggle.com/shonenkov/training-efficientdet

YOLOv5(ライセンスの問題で使用不可) 

https://github.com/ultralytics/yolov5

7. 苦労したこと

データ拡張のハイパーパラメータ調整

上記の前処理ではHSV・回転角・平行移動の距離などを元の画像からどれだけ変調するかというのがパラメータでした。
またここで紹介した以外にもコントラスト・ブライトネスの調整した方がいいのかなど、public scoreを見てみないとわかりませんでしたので、試したものを全て記録・比較しました。

f:id:sakumadaisuke32:20200817092652p:plain

前処理結果の比較

実行した結果がどのノートブックかわかるように「ver」で管理していました。

albumentationsでのデータ拡張とそれ以外のデータ拡張を組み合わせること

top kernelの方々を参考にしつつ上記の要領で前処理を試しては追加しました。
この時の実行順やデータ型が適切でなくてエラーになったり、バウンディングボックスの座標が崩れました。

特に順番に決まりはないと思いますが、自作関数で前処理を追加した前後ではバウンディングボックスの数・位置・サイズを確認し、削除されるべきものが削除されているかなど確認しました。

dataloderのreturnではtorch.Tensorになっているようにしました。

YOLOv5など外部レポジトリを用いてモデル作成するときのバージョン管理

特にYOLOv5が日々アップデートされていたからですが、後から追いつこうとした場合に採用しているpytorchなどのバージョンが異なっていて、あるべきメソッドがなかったり、CUDAがうまく使えなかったです。

discussionやノートブックが共有されたら早めにキャッチアップしましょう。

8. 反省・これから頑張りたいこと

  • PyTorchのお作法を学ぶ
    ・入力データのTensorのndimやshapeがどうあるべきか
    ・DatasetやDataloaderの挙動を理解する
    ・学習済みモデルの重みのセーブ・ロードの方法に何パターンかあり、状況に応じて使い分けられるようになる
  • (既存の手法を組み合わせるとしても)ゼロからスクリプトを書けるようになること
    ・今回はtop kernelのノートブックをforkしてそのまま使わせていただいたので、自分で必要と思う処理を探してきて、インターフェースに気をつけながら自分で組み合わせられるようになる
  • top kernelのノートブックを鮮度が新しいうちに真似すること
    ・時間が経つとノートブック内で参照されている外部レポジトリがアップデートされて、ノートブックだけforkしてもそのままでは実行できない状態になっている。その結果デバッグに無駄な時間を費やす(結果的に勉強にはなるのだけど、コンペ向きではない)


9. 基礎知識

kaggleカーネル

  • データセット
    外部ファイルなどをノートブックで使えるようにするには、kernelの右側で「add data」でできます。

    f:id:sakumadaisuke32:20200817085947p:plain

  • pip
    インターネットが使えるコンペであればいつものこれです
    !pip install ライブラリ名
    手元で実行している分にはこれでいいですが、submitする場合にはこれではダメです。
    これはあらかじめwhlファイルを取得してkaggle datasetにアップロードしておくことで対処できます。
    https://www.kaggle.com/c/severstal-steel-defect-detection/discussion/113195
  • GitHub連携
    データセットアップロード画面にGitHubの項目があります。

    f:id:sakumadaisuke32:20200817090657p:plain



  • 読み取り・書き込み権限
    ・inputフォルダ:予めデータセットとしてデータを格納することが可能。
    しかし、後からファイル保存や書き込みは不可。
    ・outputフォルダ:予めデータを格納することは不可。
    しかし、後からファイル保存や書き込みは可能。
    使用するレポジトリの都合でファイルが作成される場合などはこちらに出力するようにしておく必要がある。
  • ノートブックから「.py」ファイル中でCUDAを実行するための環境構築
    コンペ終了直前でPyTorchが1.6.0にアップデートされました。
    そのままYOLOv5などのスクリプトを実行しようとすると、CUDAが認識されませんでした。
    原因は不明ですが、下記のノートの通りに「torch==1.6.0+cu101」であれば実行可能でした。
    https://www.kaggle.com/okeaditya/what-s-new-in-pytorch-1-6

評価指標

  • MAP(Mean Average Precision):
    ・物体検出の評価指標の一つ
    ・検出された物体のうちラベルが正解だったものの割合がPrecision
    ・IoUの閾値を0~1で変化させた時の平均がAverage Precision
    ・全ての画像についてAverage Precisionを平均したのがMean Average Precision
  • IoU(Intersection of Union) :
    ・物体検出の評価指標の一つ
    ・教師データと推論したバウンディングボックスの重なりの正確さを示す
    ・(教師データと推論結果の領域の積集合) / (教師データと推論結果の領域の和集合)
    ・全く重なっている部分がなければ0、ぴったり重なっていれば1、一部分が重なっていたり領域が包含関係にある場合には0~1の間となる。