技術ブログ

Developers's blog

Kaggleコンペ 2019 Data Science Bowlの振り返り

2020.01.24 岡本 和斗
kaggle 回帰 機械学習
Kaggleコンペ 2019 Data Science Bowlの振り返り

はじめに

昨日まで開催されていたKaggleの2019 Data Science Bowlに参加しました。結果から言いますと、public scoreでは銅メダル圏内に位置していたにも関わらず、大きなshake downを起こし3947チーム中1193位でのフィニッシュとなりました。今回メダルを獲得できればCompetition Expertになれたので悔しい結果となりましたが、このshake downの経験を通して学ぶことは多くあったので反省点も踏まえて今回のコンペを振り返っていきたいと思います。


コンペ概要

幼児用教育アプリを使う子ども達の能力を予測するコンペです。具体的な予測は次のようになります。
アプリ内でプレイ可能なゲームがそれぞれAssessment、Game、Activity、Clipの4つの分野に分類されます。そのうちAssessmentに分類されるゲームをプレイした際の問題の正解率を過去のプレイ履歴を元に0、1、2、3の4段階で予測します。モデルの評価指標はQuadratic Weighted Kappa (QWK)が採用されており、これがこのコンペで大きなshakeを生む原因の1つだったと言えます。
実際に多くの人がshake upまたはshake downし、private leaderboardにおいて1000位以上順位が動いた人もたくさんいました。


取り組み

以下で私がこのコンペで行った取り組みを記述していきます。


EDA

コンペの序盤は公開してくれているNotebookを元にEDAを行いました。
中盤以降はゲームの細かいプレイ履歴を見るためにテーブルデータそのものを見て、データ中の項目が何を示しているか注意深く観察するようにしました。


特徴量作成

特徴量は公開Notebookをベースとしました。そこにEDAやDiscussionを元に特徴量を作成して、モデルの精度が向上するかどうかトライアンドエラーを繰り返しました。


データの前処理

testデータの各特徴量の平均値をtrainデータに合わせて変換しているNotebookを見つけ、自分のパイプラインに取り込んだところ精度が大きく向上したのでそれ以降ずっとこの手法を取り入れていました。
しかし、正直なところ過学習の原因になりかねない危ない処理だとも考えていました。


モデル

今回はLGBMとXGBoostを試しました。それぞれのモデル単体ではLGBMが良い性能を示し、アンサンブルで2つのモデルを用いても性能の向上が見られなかったため最終的にはLGBMのみ使いました。
LGBM1つの時に比べて、Local CVのスコアが高くなるランダムシードを5つ選びseed averagingを行ったモデルがpublic scoreで少し良い結果でした。今回のコンペでは評価指標のQWKが原因でpublic scoreが不安定であったので、アンサンブルをせず1つのモデルの結果を提出しているチームも多かったです。しかし、private scoreではやはりアンサンブルを用いた方が結果が良かったようです。


データの後処理

予測結果としては問題の正答率から0、1、2、3のラベルに分類するタスクでした。しかし、多くの参加者がregressionを使って連続値で予測した後に閾値を決めてそれぞれのラベルに分類する手法を取り入れていました。
この閾値を決定する方法が2つありました。1つはvalidationスコアからQWKが最適化されるように閾値を決定する方法。もう1つはラベルの割合がtrainデータと一致するように閾値を決定する方法です。
trainデータとtestデータの分布が似ていると仮定し私は後者を選びました。


結果

冒頭でも述べましたが最終日に銅メダル圏内に突入したものの、モデルがpublic leaderboardに対してひどい過学習を起こしておりprivate leaderboardでは900位近く順位が下がり3947チーム中1193位となりました。


反省

自分なりに大きなshake downの原因が何だったかいくつか要因を考えてみました。

まず第一にデータの前処理でtestデータの各特徴量の平均値をtrainデータの平均値に合わせたことです。 この処理はtrainデータとtestデータの分布の差を少なくするためのものでした。しかし、testデータがtrainデータと同じ分布に由来していた場合に、平均値を調整することでpublic scoreが上がるのはpublic leaderboardに過学習していると考えられます。
上位陣がこの前処理を行っていないことから、実際にこの処理がpublic leaderboardに過学習する原因になっていると言えます。

次にshake downの原因として考え得るのは、予測ラベルの割合をtrainデータに合わせにいったことです。この処理ではtestデータの正解ラベルの割合がtrainデータの割合と似ていると仮定していますが、public testデータが少ない状況でこの処理は危険であったと思います。
上位陣の解法でもこの手法は使わずに、validationデータに対してQWKを最適化して閾値を決めていました。

コンペ終了後に最終のsubmissionとして選ばなかったものを見ると、過学習を起こしうる処理を使う前のものではメダル圏内のscoreのものもありました。
このコンペを通してpublic scoreを改善することよりもロジカルに考えてパイプラインを構築することが大切だと実感しました。特に今回はtestデータが非常に少なく大きなshakeが起きる可能性が高いと自覚しながら、また過学習になりかねない処理だとも自覚しながら、public scoreを追ってしまったことは反省しなければならないところです。


まとめ

銅メダル圏内から900位近くshake downするという悔しい経験ではありましたが、そこから学ぶこと多くありました。やはりモデル構築の際は論理的に筋の通った処理をする必要があるなと感じました。今回の反省を活かし上位陣の解法から学べることは吸収して精進していきたいと思います。


Twitter・Facebookで定期的に情報発信しています!

お問い合わせはこちらから