少し遅くなってしまいましたが、Covid-19コンペに参戦したので、やったことなどを記載しておきます。
コンペ概要
OpenVaccine: COVID-19 mRNA Vaccine Degradation Prediction
https://www.kaggle.com/c/stanford-covid-vaccine
COVID-19のワクチンの筆頭候補として、mRNAというワクチンがあります。
このワクチンの問題として、今考えられているワクチンの構造だと不安定すぎて冷蔵保存だと壊れてしまいます。
そうすると世界に輸出することができず、非常に困ります。
ということで、安定したmRNAを設計するため、データセットであるRNA分子の各塩基ごとの分解率を予測するというコンペです。
また、データセットの特徴として、testの中でpublicとprivateのものがどれかすでに判明しています。
以下、表の項目の説明。
RNAnum:RNA分子の数。
RNAlen:RNA分子に含まれる塩基の数。
scored:実際にkaggle上でscoringの対象となる塩基。
つまり、trainであれば1つのRNAの中の1~68個目の塩基の分解率はscoreの対象になるが、それ以降は無視されます。
RNAnum | RNAlen | scored | |
---|---|---|---|
train | 2400 | 107 | 68 |
test(pub) | 629 | 107 | 68 |
test(pri) | 3005 | 130 | 91 |
やったこと
モデルについて
前半は、以下のkernelを参考に(というかほぼコピペで)GRU+LSTMモデルを構築しました。
https://www.kaggle.com/its7171/gru-lstm-with-feature-engineering-and-augmentation
そして後半は、以下のkernelを参考に(というかh(ry)AE pretrain + GNN + Attn + CNNモデルを構築しました。
正直、このkernelで構築しているモデルはほぼ理解していないまま使っていたので、後の勉強項目です。
https://www.kaggle.com/mrkmakr/covid-ae-pretrain-gnn-attn-cnn
フィルタリングについて
コンペ初期は、trainとtest(pub)だけノイズとなる結果を運営がフィルタリングしていました。(フィルタリングしたものだけをscoringに使用する)
しかし、test(pri)だけフィルタリングしない状態だと、フィルタリングしたものに過学習したモデルを使うことでtest(pri)だと精度が落ちる可能性があるため、
途中で急遽test(pri)もフィルタリングする、と運営から発表がありました。
これを受けて、フィルタリングについては色々試しました。
・trainとvalidどちらもフィルタリング実施する
・validのみフィルタリングする
・trainとvalidに、ノイズ成分を同じ割合ずつ含ませる
普通に考えると、trainもtest(pub)もフィルタリングしているため、学習時もフィルタリングしたほうが精度は良くなると思いましたが…
publicLBはそこまで変わらずでした。
データ増幅について
「モデルについて」の1つ目のkernelでは、データの増幅を実施していました。
arnieというライブラリを用いると、1つの塩基の配列から複数の塩基の構造を作り出せます。
1つ目のkernelでは、データの増幅量を2倍だけにしていたので、以下の神kernelを参考に出せるだけ出して増幅しました。
約3倍位に増えていたはず。
これはCVがめちゃくちゃ上がりましたが、LBはそこまで上がらずでした。
(ちなみに、このデータ増幅を実施するには私の8GBメモリUbuntuマシンではメモリエラー。すぐにヨドバシで16GBメモリ×2を購入してきて気合の実行しました。)
https://www.kaggle.com/its7171/gru-lstm-with-feature-engineering-and-augmentation
データ増幅したものを含めた、cvとLBのグラフがこちら。
(2倍増幅を2x aug, 2倍より少し増幅したものを2.5x aug, できるだけ増幅したものをfull augと記載してます)
2倍にしたものはcvとLBは相関していましたが、それより増幅量を増やすとcvは低くなるがLBがあまり良くない傾向にありました。
やはり増幅したものと実際のtestのデータセットだとなにか違ったのか?arnieの中身を理解しようとしてもドキュメントどこにも落ちていなかったので理解が進まず…。
このkernel作ってくれた方すごいと思います。さすがGM。
かつ、bppsファイルという、どの塩基がくっついているかを配列で示すファイルも1つのRNAごとに提供されていましたが、
これも上記の増幅kernelで同じく作り出せるようでした。
ですが、「モデルについて」の1つ目のkernelではbppsは増幅せず既存のものを使いまわしていたので、追加でbppsも作ってinputとしました。
…が、cvもpublicLBもあまり上がらず。なぜだ…。
アンサンブルについて
いつも通り、ここを一番頑張りました。
最終的に作ったアンサンブル結果は70個以上。
-データの増幅量の違い
-フィルタリングの有無
-seed違い
とココらへんを混ぜまくりました。
最終的には、
[2x_augと2.5x_augのseedアンサンブル(10個)]*0.45 + [full_augのアンサンブル(3個)]*0.55
という黒魔術式でsubmitしました。これが銅メダル。
2x_aug&2.5x_augとfull_augでそれぞれ分けているのは、full_augは単体のcvが良すぎて、全てをアンサンブルで混ぜるとfull_augのみを混ぜるのが一番良いです!という結果になってしまうため。
結果
139/1636で銅メダル獲得でした。
このコンペ、結果発表でも2つほど波乱がありましたね。
1つ目:もうすぐ終了だし早めにスコア再計算しときますかw事件
〜コンペ終了の12時間前〜
運営「コンペ終わってないけど一応スコア計算し直しますわwwその間LBぐっちゃぐちゃになるけどサーセンwww」
kaggler「は????今からラストのsubしようと思ってたんだが???」
運営「大丈夫!すぐ計算終わるからさ!」
〜コンペ終了の9時間前〜
運営「リスコアに問題が発生したため、コンペ終了を24時間伸ばします(キリッ」
kaggler「はああああああああああああ???????」
2つ目:フィルタリング忘れてたてへぺろ事件
〜コンペ終了〜
kaggler「お疲れ様でしたー!めっちゃshakeしてるwww」
とあるGM「これフィルタリング有効化されてなくね??」
運営「フィルタリングが正しくアップデートされてませんでした。スコア変わります。」
まさかのPrivateLBのスコアが更新。ランキングが大きく入れ替わる。
kaggler「はあああああああああああああ?????????」
色々合ったコンペでしたが、とりあえず銅メダルゲットできたのでよし。
ただ、もう少しNNのモデルの部分を勉強しないといけない。
おわりに
今回は(も?)kernelで良さそうなものを使って、他のkernelの要素を組み込んでいき、最後はアンサンブルというパターンで乗り切りました。
他の方のsolutionをまだあまり読めていないので、そこを早く読まないといけない。