tacoriceの日記

間違い等あれば指摘して頂けたら嬉しいです。

メラノーマコンペ ソリューション概要

 

 

こんにちは、tacorice です。

 先日終了したkaggleのメラノーマコンペ SIIM-ISIC Melanoma Classification に参加しました。とても幸いなことに ゴールドメダルを獲得できました。Discussionの中で、私のアンサンブル手法等をブログに残してはどうかという提案を頂いたこともあり、自分の Solution 概要や取り組みについて残しておこうと思います。

f:id:pino080:20200831181504p:plain

 

 
1. コンペについて

概要
 皮膚の画像からメラノーマ(悪性黒色腫である確率を 0.0から1.0の間で予測するコンペです。


データ
 本コンペは データとして train 33126, test 10982 の画像データとテーブルデータを利用できます。データサイズはなんと108Gもあります!

 外部データとして、2017 ~ 2019 年のデータが利用できました。また、PubricスコアトップのChris 氏が画像のサイズごとに (128, 192, 384, 512, 768, 1024) データセットを公開してくれていました。(thanks to @cdeotte)(こういった貢献の文化があるkaggleは素晴らしい情報共有と勉強の場であると感じます)

 

評価指標
ROC-AUC score


2. 参加の動機

・丁度長期休暇中であったので、全力コミットできる時間があった
・医療機器メーカーの一員として医療分野の最先端のAI技術開発に参加してみたかった
・知人に臨床検査技師の勉強をしている方がおり、臨床検査の視点から色々と相談できると思った(コンペを通してAI技術について医療側の意見等も聞きたかった)

 

3. 戦略

 休暇といっても使える時間があまりなかったので、解法が分かりやすいカーネルを参考にモデルを作成し、とりあえずLBの上位を目指しました。
 適当なハイパーパラメータを探すためKaggleのTPUをがん回して色々試行しました。あとは、解法との類似点が少ない(相関が小さい)公開カーネルの予測とアンサンブルを実施。
 また、アンサンブル時は、何か指標が欲しかったので、以下のような処理を実装しました。

github.com

 

 シンプルな手法ですが、効率的に(少ないアンサンブルとsubmit回数で)スコア伸ばすことができました。個人的には、難解な手法を試すより、分かりやすい手法を使ってみる方がPDCAの回転が速く効果的であると思います。シンプルイズベストです。

 やっていることとしては、最高スコアモデルのスコアアップに寄与したモデルを基準として、あるモデルとのアンサンブルと最高スコアモデルのアンサンブルの差分が最小になる割り合いで、アンサンブルするというものです。要は、もっといいモデルでアンサンブルしようという試みです。また、差分が極端に悪いものは除外することで効率よくスコアを上げることができたと思います。
 ただこのような手法は、必然的にpublicデータにfitしていってしまうため、privateで高得点を狙う場合は、差分だけでなく、R2スコアが0.5~0.7(相関が小さい)くらいでかつ、publicスコアが上がるものを見つける方が賢明でしょう。(コンペ後に、privateスコアが高いモデルのR2は0.6くらいでした。逆にprivateスコアが低かったモデルではR2が0.9以上ありました。)
 この辺で、銅圏(上位10%)でスコアが上がらなくなってしまったのでdisucussionをあさりまくりました。異なる画像サイズで学習を行うと、それぞれの画像サイズのモデルがそれぞれ異なった特徴を学習できるため、アンサンブルすると汎化性能の良いモデルができるという主張を発見しました。 また、CVを信用した方が良いという議論が頻繁に行われていたため、CVを重視しつつ、128,192,256,384,512の画像サイズでのモデルを作成。Foldはリソースの問題で2~3しか設定できませんでした。(もっと大きいFoldや画像サイズ(712,1024)を試せていればさらに高い得点がでたかもしれません)

 

 しかしながら、先に説明したアンサンブル手法を実施した時に、アンサンブル後との差分をとった際、上記の複数画像サイズのモデルとの差が大きくなってしまいました。原因を探るべく、複数画像サイズのモデルの予測結果とベストスコアのモデルの予測結果を一つずつ比較して確認したところ、ベストスコアのモデルでは陽性率が低く予測されているものに対して複数画像サイズのモデルでは一部高く予測しているものがあることを発見しました。さらに、公開されている多くのカーネルでも同様に確認したところ、陽性率が低く予測されていました。
私はこれが多くのモデルでは偽陰性を示してしまっている可能性を考えました。臨床検査の勉強している知人にモデルの精度について相談した際に、偽陰性を示してしまう感度が悪いモデルはあってはならないという話を聞いていたこともあり、このモデルの割合を高めにしてブレンドに用いました。(画像サイズ別にみていったところ、384*384のモデルが特に偽陰性を示す割合が低かったため、最終的に384*384のモデルのみ使用しました。)

 

 最終的に次のモデルを提出しました。
①ベストスコア
②ベストスコアと偽陰性の割合が低いと思われるモデルのアンサンブル
③オーバーフィットの危険から、ベストスコア以外のモデル*と偽陰性の割合が低いと思われるモデルのアンサンブル 
*ベストスコア以外のモデルにはPak Lau9氏のMinMax ensembringモデルを使用しました(thanks to@Pak Lau9)

 結果としては、モデル③がprivate 4thの結果となりました。また、①がもっとも悪く、②がぎりぎり銅圏でした。この結果から次のことが導かれます。


・多くのカーネルの予測モデル同様、ベストスコアモデルもまた偽陰性と判定してしまう可能性が高い、感度が悪いモデルであったこと
・ベストスコアモデルがpublicデータにオーバーフィットしていたこと

 

 これらの結果から、精度の高いモデルを作成するためには、次のことが有効であると考えます。
・コンペ終了前後で多くの議論がなされていたようにtrust CV
・CVを信頼したモデルと相関が小さい多くのモデルの結果を比較し、傾向を観察すること

・あと、ドメイン有識者から話を聞くことも気づきがあって大事だと思います


4. Solution

AjayKumar氏の notebook をベースに作成しました。 (thanks to @ajaykumar7778)


Dataset:image only

External data : (2019,2018,2017)

Cross-validation : STRATIFIED KFOLD (k=3)

Augmentation :
・random_flip_left_right
・random_Saturation
・random_Contrast
・random_brightness

EfficientNet : B6

Pretrain : imagenet

Image size : 384*384

Loss : binary_crossentropy

Optimizer : Adam

Seed : 42

TTA : 15

Model building
from efficientnet import tfkeras as efn
base=efn.EfficientNetB6(input_shape=(384,384,3),weights='imagenet', include_top=False)
x = base(keras.layers.Input(shape=(384,384,3)))
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dropout(0.3)(x)
x = keras.layers.Dense(1024)(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Dense(512)(x)
x = keras.layers.Dropout(0.4)(x)
x = keras.layers.Dense(256)(x)
x = keras.layers.Dropout(0.3)(x)
x = keras.layers.Dense(128)(x)
x = keras.layers.Dense(1)(x)
x = keras.layers.Activation('sigmoid', dtype='float32')(x)

1024のような大きい全結合層を入れているカーネルは本コンペではほとんど見られませんでしたが、私のモデルでは若干向上しました。(実務などで使う場合は計算コストの観点から追加しない方が良いと思います)


 今回やり残したことを下記にまとめておきます。
・さらに大きいFoldや画像サイズ(768*768,1024*1024)でのモデル作成
・EfficientNet以外のモデルの利用(ResNetやDenceNet)
・Psuedo labeling


5. 良かった点・悪かった点

 医療関係者からROC曲線や感度の大切さとかいろいろ話を聞けたこと。
これにより、病気であるのに病気でないと診断してしまうような偽陰性を示すことはあってはならないという信念の下、最終のアンサンブルを行う際に、モデル間で偽陰性を示してるものがないかを比較して重点的に確認できたことで、オーバーフィッティングの危険性に気付くことができました。

 一方で、kaerururuさんの記事を参考にテーブルデータを用いたLightGBMモデルをブレンドしたところ3位タイのスコアでした。テーブルデータはできる限り使用した方がよいでしょう。(LightGBMモデルが効くということはdiscussionで議論されていたようです。もう少し、discussion見てればなあ。)


6. まとめ

・医療系コンペに参加することで、医療分野へのAI技術の可能性がひしひしと感じられました。
・たとえ、モデルのスコアが低かったとしても、医療の分野では偽陰性を示してしまうモデルはあってはならないと思います。trust CVは偽陰性を高めないためにも重要な手法であると感じました。
・コンペであっても実務であっても、ドメイン有識者に話しを聞いておくことで、後戻りがなく後悔のないモデルができると思います。

 

7.今後

 コンペの復習と本コンペのモデルをマイコンに組み込み、簡易診断キットを作成してみたいです。