Kaggleの画像コンペに初心者だけでチーム組んで挑んでみたら銅メダル取れた話


 
#はじめに
表題そのまんまですが、深層学習を勉強し始めてすぐに無謀にもkaggleの画像コンペに挑戦し、コンペ終了時点で学習期間3か月ちょっとの初心者チームが、銅メダルを取る（116位/1324）に至るまでの記録を書いていきます。
初心者がどうやってコンペに取り組んだかの記録がメインの話で、これからkaggleに参戦してみようかと思ってる人やチームを組もうか迷っている人の背中を後押しすることを目指した記事としています。
手法的な部分で参考になるようなものは少ないと思いますので、予めご了承ください。

#どんなコンペに参加したか
[SIIM-FISABIO-RSNA COVID-19 Detection](https://www.kaggle.com/c/siim-covid19-detection/overview)という画像コンペに参加しました。コンペの開催期間は5月18日から8月10日まででした。
肺のレントゲン画像に対して、新型コロナ感染症の罹患状況を表すnegative、typical、indeterminate、atypicalの4種に分類する分類タスク(Study-level)と、肺レントゲン画像の中のどこに混濁（opacity）があるかを検出する検出タスク(Image-level)の二つに取り組むものでした。
評価指標は[ｍAP](https://qiita.com/cv_carnavi/items/08e11426e2fac8433fed)でした。ｍAPって物体検出の指標だと思うんですが、分類タスクの精度はどう測るんだろう…とコンペ初期からずっと疑問に思っていて、最終的にコンペ終了までよく分からないままでした（誰か教えてください…）。

#コンペに参加した時点での自分のスキルと状況
コンペに参加したのが5月下旬からで、その時点での自分のスキルと状況について書いていきます。

コンペに参加する少し前（4月頭）の時点では、LightGBMなどの機械学習手法（not 深層学習）については少し触れたことはありましたが、書籍を写経して動かしたことがある程度で、実装経験は全くありませんでした。[Kaggleで勝つデータ分析の技術](https://www.amazon.co.jp/Kaggle%E3%81%A7%E5%8B%9D%E3%81%A4%E3%83%87%E3%83%BC%E3%82%BF%E5%88%86%E6%9E%90%E3%81%AE%E6%8A%80%E8%A1%93-%E9%96%80%E8%84%87-%E5%A4%A7%E8%BC%94/dp/4297108437)を一読したことがあったため、アンサンブルやクロスバリデーションなどのコンペで使われる手法については、実装経験はないものの知識としては多少ありました。

4月中旬から深層学習について本気出して学んでみようと考えるようになり、それにあたってE資格の講座の受講を始めています。E資格の試験は8月下旬にあるため、コンペの参加期間中はずっとE資格の勉強も並行して行っていました。

4月から深層学習を勉強し始めて、8月までE資格の勉強とコンペに並行して取り組むのは、時間的にかなり無理のあるスケジュールに思われるかもしれないですが、コンペの参加期間中のほとんどが閑散期だった・IT業界に未経験転職したばかり・会社から機械学習の勉強をしておくよう奨励されていたため、業務時間中もある程度は深層学習の勉強に取り組める時間があったというアドバンテージがありました。

チームに参加した5月下旬頃には、E資格の講座は一通り受講し終え、それに加えて[ゼロから作るDeep Learning](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)と[PythonとKerasによるディープラーニング]
(https://www.amazon.co.jp/Python%E3%81%A8Keras%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0-Francois-Chollet/dp/4839964262/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=keras%E3%81%AB%E3%82%88%E3%82%8B&qid=1628596633&s=books&sr=1-5)を読み終えていたという状況でした。

#チームについて
5月下旬にこのコンペに参加しようか迷っていたところ、Twitterで既にチームを組んで取り組もうとしてる人を見つけたので、声をかけて3人目のメンバーとして参加させてもらいました。自分の後にもう一人加入したので、最終的に4人チームで取り組むことになりました。
メンバーの特徴として、自分以外は3人ともデータサイエンティスト志望で、なおかつ深層学習はほぼ全く触ったことのない状態でした。

チームとしての活動は、slackでのやり取りに加えて、コンペの中盤までは週に二回勉強会を開いて、コンペに役立ちそうな知識の共有や、進捗状況の共有、相談を受けたり、時にはkaggleとは関係ないような内容についても取り上げていました。
週2回というのは頻度としては結構高いものだったわけですが、学んだことをアウトプット出来る機会は中々無いので、自分は勉強会が開催される時は毎回何かしら発表することをひそかに目標にしていました。アウトプットした内容はコンペに取り組むにあたって非常に役に立ったため、多少無理してでも毎回発表を続けてよかったと思っています。

#勉強会で取り上げたこと
主に有用そうなWebページなどを要約して発表する形で行っていました。後述しますが、過去コンペでどんな解法を用いていたかをを研究するために取り上げたものが多いです。
一部抜粋して紹介します。

- [評価指標（ｍAP）について](https://qiita.com/cv_carnavi/items/08e11426e2fac8433fed)
- [Kaggle Advent Calendar 2020](https://qiita.com/advent-calendar/2020/kaggle)
<br>この中から面白そうなものを各自ピックアップして発表するといったことをしていました。
- [【Kaggle】2020年に開催された画像分類コンペの1位の解法を紹介します](https://qiita.com/inoichan/items/140cf018d31151d2701a)
- [Winning Solutions of Similar Past Kaggle Competitions](https://www.kaggle.com/c/siim-covid19-detection/discussion/239898)
- [Recap top solutions for Xray Medical Imaging comps](https://www.kaggle.com/c/siim-covid19-detection/discussion/239891)
<br>類似コンペの上位解法。コンペ期間の早い段階にYolov5、WBF、TTAといったよく使われるモデル・手法の名前だけでも知ることが出来たのはとても大きかったです。
- [Faster R-CNNにおけるRPNの世界一分かりやすい解説](https://medium.com/lsc-psd/faster-r-cnn%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8Brpn%E3%81%AE%E4%B8%96%E7%95%8C%E4%B8%80%E5%88%86%E3%81%8B%E3%82%8A%E3%82%84%E3%81%99%E3%81%84%E8%A7%A3%E8%AA%AC-dfc0c293cb69)
<br>ガチガチな理論についての記事ですが、発表するには難しすぎた…
- [Yolov5](https://github.com/ultralytics/yolov5)
<br>Yolov5が直近の類似コンペでよく使われていたのに加え、チュートリアル中のTest-Time Augmentation、Hyperparameter Evolution、Tips for Best Training Resultsについてのページは特に有用だと思ったため取り上げました。
- [Kaggle Wheatコンペからの学び 〜 物体検出コンペで当たり前に行われている（っぽい）こと](https://mhiro216.hatenablog.com/entry/2020/08/09/205640)
<br>検出タスクに取り組むにあたってとても有用でした。
- [[Kaggle]PANDAコンペ参加記](https://qiita.com/tachyon777/items/e1e4eac8cbaa3e308ff4)
- [[Kaggle]メラノーマコンペ参加記](https://qiita.com/tachyon777/items/05e7d35b7e0b53ef03dd)
<br>医療画像の分類コンペということで、分類タスクに取り組むにあたってとても有用でした。
- [画像データ拡張ライブラリ ~ albumentations ~](https://qiita.com/Takayoshi_Makabe/items/79c8a5ba692aa94043f7) 
- [Albumentationsのaugmentationをひたすら動かす](https://qiita.com/kurilab/items/b69e1be8d0224ae139ad)
- [pytorch-image-models](https://github.com/rwightman/pytorch-image-models)（TIMM）
 

#いかにコンペに取り組んだか

チームとしての取組みスケジュールとして、まず理論部分を抑えたうえで実践に移ろう、ということになりました。そのため、チーム全員で[ゼロから作るDeep Learning](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)（以下ゼロつく）を読んで理論を抑えてから（～6月中旬）、実践に挑む前の基礎として[キカガクの無料の講座](https://www.kikagaku.ai/)に取り組む（～6月下旬）方針としました。
ゼロつくは深層学習の理論について分かりやすく書かれていて、初期に取り組んで良かったと思いましたし、キカガクはPyTorchについて無料でここまで学べるかと思うほど内容が充実していて、基礎固めに非常に役立ちました。特にメディカルAI専門コースでは、医療画像の様々なタスクに対する取り組み方について学べました。
コンペ開始前に自分がKerasについての本を一冊読み終えていたので、当初チームとしてKerasをメインに扱う方針で考えていましたが、公開notebookにKerasを使って書かれたものが少なかったため、早々にKerasをメインで使うことは辞めてPytorchをメインに扱えるようになるべく勉強していこうということになりました。

チームとしての目標は最初からメダル獲得を掲げており、学習開始から3か月という短い期間でこの目標を達成するためには効率よく取り組むことが必須だと感じていました。そのためにどうするのがよいかを考えた結果、基礎固めと並行して情報収集を行ってきました。

なにぶん全員がkaggle初心者なので、当初メダルを獲得出来るレベル感が全く分かっていなかったのですが、[【Kaggle】2020年に開催された画像分類コンペの1位の解法を紹介します](https://qiita.com/inoichan/items/140cf018d31151d2701a)を早い段階で見つけて勉強会でも取り上げた結果、医療画像コンペの銅メダルであれば、独創的なテクニックをとりいれなくても過去の類似コンペで使われていた手法を真似て適用してみれば獲得できるかもしれない、との見通しを立てることができました。ここで立てた見通しは、それ以後の勉強会で過去コンペの情報を重点的に当たってみたことに繋がっていきます。
他にも、公開notebookやdiscussionには有用な情報が沢山あるため、可能な限り目を通していくことで情報収集をしてきました。

6月下旬からは実際にkaggleに取り組んていく時期になりました。この時点で分類タスクにEfficientnet、検出タスクにYolov5を用いてモデルの訓練からsubmitまで出来る精度の良い公開notebookがあったので、これをベースラインのnotebookとして少しずつ改良して取り組んでいくことにしました。

検出タスクからまず取り組み、類似コンペでの使用頻度が高かったYolov5をメインに色々と試行錯誤を行っていきました。
公開notebookに頼らず[WBF](https://github.com/ZFTurbo/Weighted-Boxes-Fusion)を自力で実装してアンサンブルしたり、Yolov5の機能として組み込まれているHyperparameter Evolutionを使ってみるなど色々と試行錯誤してみたら、やればやるほどスコアが上がっていった時期でした。
分類タスクはこの時点ではまだ取り組んでいなかったのに、一時的に最高で53位になれるまでスコアが伸ばすことができて、銀メダル圏まであと一歩というところまでこれたので、とても楽しく取り組めていた時期でした。

検出タスクでの精度向上が頭打ちとなってきた頃に、区切りをつけて分類タスクの方にとりかかっていきました。
ベースラインとなるnotebookではTensorflowを使っており、Pytorchをメインに勉強してきた自分達では内容を完全には理解できなかったため、pytorch-image-models（TIMM）を使って実装していく方針で取り組んでいきました。
過去コンペでよく使われていたEfficientnetや、方々で凄いという話を聞いていたViTを使って検証してみたり、[メラノーマコンペ参加記](https://qiita.com/tachyon777/items/05e7d35b7e0b53ef03dd)の記事からAugmentationを色々工夫してやってみるのが精度向上に繋がるのかもしれないと思い色々と試したりしてみましたが、検出タスクとは打って変わって分類タスクのほうはベースラインのnotebookよりも全く精度が上がらず辛い時期でした。その結果、7月中旬～下旬はモチベーションが下がっていきほとんどkaggle触らない時期となってしまいました。
一時期は銀メダル圏目前までいっていたスコアもどんどん抜かされていって銅メダル圏からも転落してしまったり、誰も進捗を出せずにチームの勉強会で発表できるネタもなくなりslackのログも閑散としてきて、メダル獲得も諦めムードになっていきました。

7月下旬のコンペ終盤に差し掛かった時期に、公開notebookでさらにスコアの良いものが複数公開され（コンペ終了が近い時期にはよくあることみたいです）、この一部を取り入れたところ、少しスコアが改善されたことでモチベーションが復活し、再び色々と試行錯誤をしていくことにしました。時間があまり残されていなかったので、コードの内容をあまり理解しないまま統合させていたりと、この時期の取り組み姿勢には反省するところが多々あります…
自力では精度が全く向上しなかった分類タスクも、最終的には複数の公開notebookで使われているモデルをアンサンブルしたりパラメータ等を変えてみたりすることで、公開notebookよりも良いスコアを出すことが出来てコンペ終了を迎えることが出来ました。

#反省点

コンペを通して深層学習の実装・英語力などのスキルが身につきましたし、コンペ初参加で銅メダルをとれたことで自信はつきましたが、反省点も多かったです。

- コンペの評価指標や、最終subに取り入れたコードなどによくわかっていないものが多々ある
- 分類タスクは色々と試行錯誤はしたものの結局は公開notebookを混ぜただけというのに近くなってしまい悔しい 
- 後半にモチベーションが下がった時期があった。前半に早いペースで頑張りすぎていたのも一因かもしれない
- 最新のモデル(Efficientnetv2など)や手法について、コンペ終盤になってから存在を知ったり、コンペ終了後に上位解法を読んでも聞いたことが無いモデル・手法が多かったりして、調査不足を感じた
- 最終的にいくつかのモデルをアンサンブルするため、幅広くモデルを取り入れることを想定した情報収集をしておけば良かった

#おわりに
初参加となるコンペに対して、チームを組んで参加したわけですが、チームで参加したことで感じられた一番のメリットはコンペにより楽しく取り組める点だと思います。一人だと途中で投げ出してたかもしれず、チームを組んでコンペに取り組んだことで最後まで食らいついていくことが出来たと思います。
途中でモチベーションが落ちてつらい時期がありましたが、それでも最終日までコンペに真剣に取り組み続けるのが、初心者がコンペでメダルを獲得するのに一番重要なことだと感じました。
またkaggleは参加者間の交流が盛んで、discussionで意見交換が出来たり公開notebookのコードを拝借して使えるのは良い点だと思いますが、それに頼りっぱなしだと、仕事で活用する際に自力で解決するスキルが身につかなくなる可能性があると感じました。
今後については、公開notebookからコードを拝借せずスクラッチで挑んでみたいです。