APTOS 2019 Blindness Detection コンペ反省会

失明にいたる病気を眼の画像から判定する(5段階)コンペ。初めての画像コンペ。画像コンペでは大きくマシンリソースを使うというイメージで敬遠していたがそこまでもなかった。チームで挑み結果は804/2987。public から375もランクダウン。Shake up の原因と対策はあとでまとめる。

学び

PyTorch

コンペの途中で Keras が deterministic results を出してくれないことに悩み PyTorch にスイッチ。PyTorch 公式のチュートリアルを写経するだけで十分だった。以前から PyTorch カーネルを読み込んでいて一番気になったのが train 時に back prop の伝播の一部を明示的に書かないといけないこと。やってみたらそれほど気にならなかった。それよりも PyTorch API と画像コンペとの相性のよさが際立っていた。これまで Tensorflow -> Keras -> PyTorch と流れてきたが PyTorch がちょうどよい。Define by Run も気軽で良い

ただ気になっていたのが高 Score Kernel が fast.ai で書かれていたことだ。次の波が来ている?

Augmentation

CNN などでの画像分類において training data が少ない場合に argumentation が効く。という教科書的な知識はもちろん知っていたが。どう apply するのか全くわからず困惑した。rotation の角度の範囲は?horizontal/vertical flip が起こる確率はいくつが良いのか? augmentation は組み合わせるもの?単体で使うもの? training epochs への影響は?など分からないまま後半に突入してしまった。上位カーネルで勉強したいところ。

4th solution によれば

Augmentations We used a lot of augmentations, at least more than I ever used before :) All from the wonderful albumentations library: Blur, Flip, RandomBrightnessContrast, ShiftScaleRotate, ElasticTransform, Transpose, GridDistortion, HueSaturationValue, CLAHE, CoarseDropout. とのことだったので知識も手数も足りなかった模様。

Ensemble

Ensemble が手元でほとんど効かなくて困惑した。まだ原因がわかっていない。

チーム

チームでやってみて良かったのは、各人の「やって当たり前」の前提が違うこと。例えば D 氏はとりあえず論文をいくつか読んだから実装してみる。と言って僕を驚かせた。自分は Discussion 読んで Kernel を書いて手を動かしがちなのとは対象的だ。M氏はクラウドリソースを用意してくれて、それがいかに素晴らしいものか教えてくれた。何度作業効率の上がることか。あとチーム内で最高スコアのカーネルをぱっと出してくれたのも M 氏である。コミュニケーションはまだまだ課題があると思った。チーム doc を用意したが最低限しか機能してなかったように思う。

コミュニティへの貢献

このコンペは submission がコケたときにヒントが少なすぎるという問題があって多くの人がハマっていた。How to debug "Kernel Threw Exception" with binary search というトピックでデバッグ方法を書いたら評判が良く、コンペ運営側の目にもとまって紹介されたのは良かった。上位ランカーがどこかで書いていたが、コミュニティーに自分の学びを共有すると結果的に自分が成長するということがよくあるらしいのでがんばりたい(因果関係かどうかはわからないけど)

反省

いまだに自分の時間をどう配分するかに迷いがある。順位が振るわないので改善の余地があるのだと思う。自分の書いたカーネルにこだわりすぎたのは本当に良くない。public kernel を少し改造しただけのもののほうが Score が良かった。時間のなさを言い訳にしたくなるが Neuron Engineer 氏は3歳のお子さんがいるらしいので。

pseudo-labeling を学ぼう。

top solution からのメモ

  • pseudo labeling
  • Downsampling
  • (480, 600) など。各種データサイズを試している。

```` Compose([ BensCrop(img_size), #from 2015 solution RandomHorizontalFlip(), RandomVerticalFlip(), RandomRotation*1, ), ])

for EfficientNet B5 Compose([ Resize(img_size), HorizontalFlip(), VerticalFlip(), Rotate(), RandomContrast(0.5), IAAAdditiveGaussianNoise(p=0.25), ]) ````

train_transform = transforms.Compose([ transforms.ColorJitter(brightness=0.45, contrast=0.45), transforms.RandomAffine(degrees=360, scale=(1.0, 1.3)), transforms.RandomHorizontalFlip(), transforms.RandomVerticalFlip(), transforms.ToTensor(), transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])

*1:-120, 120