イナズマの日記

こんにちは。

SIGNATE Student Cup 2021参加記 (public 9th, private 7th)

こんにちは,SIGNATE Student Cup 2021に参加しました. 機械学習コンペはリアルタイムで参加したのは2回目なのですが,7位になれたのでSolutionや感想その他などをここに残そうと思います. ソースコードこちら

どんなコンペ?

この画像(SIGNATEより引用)の通り,いくつかの特徴から音楽のジャンルを推定します. いわゆるテーブルデータを扱うコンペでした. f:id:inazuma110:20210510160624p:plain

Solution

Feature Engineering

各音楽ごとの欠損値の数,tempoのmax-min,以外は特徴量は追加していません. あとは標準化,欠損値の-1埋め,RegionのOne hot化,特徴量の重み付けです. 特徴量の重み付けはフォーラム通りにやったのですが,Feature Engineeringにおいてはこれが一番効きました.

Prediction

まず,上述の通りの前処理をした説明変数をkNNで予測し,これで自己訓練をしました. 具体的には,予測結果のうちpredict_probaの最大値が0.7以上のもの(これは結果的にはすべて1になりました)を疑似ラベルとしてトレーニングデータに追加して,半教師あり学習をしました. これもスコアを上げるのにかなり貢献してくれました.

Ensemble

上述の自己訓練を,kNN,SVC,Random Forest, XGBoostで行い,それらをアンサンブル学習したものを最終提出としました. kNN, SVCのCVが0.7以上だったことに対して,Random ForestとXGBoostがCVが0.6程度だったのですが,CVとLBが大きく乖離していたので過学習を恐れてアンサンブルしました. しかし,結果的にはSVC単体がCV, Public LB, Private LBすべて最も高いスコアとなりました.(これを最終提出にできていれば2位相当のスコアでした…)

期間中の流れ

ここからはより具体的に,コンペ中の流れや考えなどを時系列に沿って書きます.

チーム作成

正直,それほど良い結果を残せるとは思っていなかったのでチームメイトはプログラミングや機械学習の経験すら問わずにサークルのDiscordで募りました. f:id:inazuma110:20210510161759p:plain 仮に経験が無くとも,サークル活動で教えつつのんびり進められれば良いなと思っていました.

しかし,実際には緊急事態宣言の発令に伴い,サークルの対面活動が禁止され,コミュニケーションを取れた回数が減ってしまいました. 結果,後輩たちの面倒をほとんど見ることができず,自分で勝手にどんどん進んでしまったことは反省です.

Baseline

テーブルデータではXGBoostやLightGBMが強いということを知っていたので,まずはXGBoostで学習したものをベースラインとして提出しました. そのままでは扱えない特徴量は,それぞれいい感じに変換しましたが,元のデータままだと思ってください. f:id:inazuma110:20210510162548p:plain 思っていたよりスコアが高く,ブロンズが見えたため結構嬉しかったです.

フォーラムのタイトルにkNNとあったので,それも試したり, ScikitLearnのチートシートを見てRandom Forestなども試していました.

探索的データ解析

探索的データ解析(EDA)をしました. pandas-profilingを用いると良いということだったのでそれを用いました. tempo_maxとtempo_minという特徴量があったのですが,これらの相関係数が非常に高い(それはそう)ことに気付いたのでこれらの平均を取ることにして,特徴量を1つ減らしました. また,不均衡データであることもわかりました. これについては後述します.

その他は特にわかることはありませんでした. というのも,pandas-profilingの使い方を解説しているサイトは山ほどあっても,そこからどういうことに着目すれば良いかを書いているサイトはほとんど見つけられなかったからです. なにかいいサイトがあれば教えてください!

網羅的特徴量の探索

特徴量を四則演算したものや,カテゴリーごとに統計を取った特徴量(Aggregation)したものがよく使われるとわかったので,featuretoolsというライブラリを用いて特徴量の網羅的探索をした後にXGBoostにかけてみました. feature importanceの上位50%だけ追加,のような工夫をするも結果的にはCVが下がってしまったので,なにも採用することなく終わりました.

特徴量の重み付け

この辺りでフォーラムを眺め始めます. フォーラムは長いコードが書き連ねられていてなんとなく避けていたのですが,Baseline以上のスコアが全く達成できなかったので読んで見ることにしました. このフォーラムに結構とんでもないことが書いてあって,要約するとRegionがかなり重要と書いてあります.RegionはXGBのFeature importanceは小さい値だったのでかなり驚きつつ,フォーラムを参考にregionのOnehot化や特徴量への重み付けをしてkNNを提出しました. 結果的にスコアはかなり上がったものの,ブロンズのボーダーも上がっていてブロンズ入りは果たせませんでした.

しかし,ここでチームメイトが特徴量の重みやハイパーパラメータを探索してブロンズ入りを果たしてくれました!! f:id:inazuma110:20210510171926p:plain この辺りでSVCもkNNと同等以上の精度が出ることに気付きました.

不均衡データに対する対処

EDAの際にも書きましたが,本コンペのデータはいわゆる不均衡データです. ジャンルごとにデータ数の偏りがかなりあるので,どうにかしないといけないと思ってUnder SamplingやOver Smaplingなるものを試しました. これらは,データを切り捨てたり水増ししたりして,データの偏りを無くすのですが,両手法ともデメリットがあります.

バギングなどもしつつ両手法を試したのですがうまく行かず,不均衡データの対処は一回Pendingとしました. 結局最後まで対処はできなかったのですが,今回のデータでは有効な対処が発見されなかったのか,良好な成績を残すことができました.

疑似ラベル

もう1個のフォーラムで疑似ラベルなるものを利用していたので実際に使ってみました. フォーラムが長くてあんまり真面目にコードまでは読めなかったのですが,とりあえずkNNのpredict_proba(予測の際の確信度みたいなイメージ)を用いて疑似ラベルを振ってみました. 本当はSVCも試したかったのですが,どうもSVCのpredict_probaは訳ありみたいだったので今回は見送りました. f:id:inazuma110:20210510173019p:plain 結果,LBは上がったのですが,CVがLBを大幅に上回ったのでとても不安でした. 一応,チームメイトやフォーラムでも同様のことをしてCVが壊れるという報告があったので目をつぶることにしました.

突然のゴールド入り

ハイパーパラメータ探索をOptunaで行っていたのですが,最適化する関数の戻り値をCVにしたら突然スコアが0.2ほど上がりました. OptunaのGitHubのexampleでCVした値を返していたのでこういう変更をしたのですが,ここまで変わるとは思いませんでした. ありがとうOptuna. f:id:inazuma110:20210510175420p:plain

ensemble

とは言え,CVとLBの乖離は解消していなかったので過学習がとても怖かったです. 過学習気味のモデルをアンサンブルすると良い感じになると聞いたので,kNN,SVC,Random Forest,XGBoostをアンサンブルしたモデルを最終提出としました. 実はそれぞれをRandom Seed Averageしたモデルをアンサンブルしたものが締切4分前に学習が終わったのでそれも提出したのですが,しないものの方がLBが0.01程度高かったので最終提出にはしませんでしたし,実際最終評価のスコアも高かったです. f:id:inazuma110:20210510175859p:plain

感想

最初の目標よりはるかに高い順位でとても嬉しかったです. とは言え,機械学習コンペは(少なくとも僕から見ると)良くも悪くも運ゲーに感じてしまいました. どのアルゴリズムが適切か,どんな特徴量を増やす・減らすと良いのか,スタッキング,バギング,アンサンブルをどのくらいやるべきか,その際の重みや特徴量の重みはどんな値が適切かなどは何回も試して特定していくしかないように感じました. もちろん機械学習アルゴリズムへの理解やドメイン知識があればある程度わかることなのかもしれませんが,それでも試行回数を稼いでいろいろ試さなきゃいけない部分はなくならないと思います. これらの試行がうまくハマれば高いスコアが出てくれるので,僕のような初学者でもワンチャン賞金の夢を見ることができるのはとても良いと思いましたし,実際とても楽しかったです. (例えばAtCoderなどの短期間のアルゴリズムコンテストでは今の僕では絶対に上位に行くことはできないため)

チームメイトの皆さんもありがとうございました!楽しかったです!! チームでコンペに出た経験はICPCくらいしかないため,貴重な経験にもなりました.