Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
45
Help us understand the problem. What is going on with this article?
@hmdhmd

2020年、最もお世話になった解法を紹介します

はじめに

この記事は kaggle advent calendar 2020 、10日目の記事です。
前日は rinascimento741 さんの 【Kaggle挫折しそうな方向け】AtCoderのススメ
の記事でした。
明日は tume731 さんの wandb+Pytorch-lightning+hydraで書くNNプロジェクト です。

自己紹介

Kaggle Master です。
今年の Kaggle の成績は下記の通りです。

  • OpenVaccine: COVID-19 : 847/1636

「うわ、こいつの順位低すぎ。。」
と思った方、逆に考えてみてください。

こんな私が書く最もお世話になった解法、気になりませんか...?

解法

結論から言ってしまうと
「target の予測値(oof) を利用して特徴を生成する」
です。

普段から Kaggle に取り組んでいる方には見慣れた内容かもしれませんが、
私は今年こちらの解法を Kaggle ではないコンペで活用したので、本記事のテーマとしたいと思います。

どれぐらい使われているの?

私が参加していたコンペでは、下記が該当します。

どういう内容?

前述のリンク先の説明が、すでにわかりやすくまとまっているのですが、さらに例を上げると下記のようになります。

お題
とあるソーシャルゲームで、特定の日にユーザーがバトルイベントをプレイするか否かを予測する1

与えられたデータ

  • train
    • target が目的変数
userId registDate leagueRank power target
1 2017-08-07 S 103,131 1
2 2019-03-01 B 35,328 0
  • test
userId registDate leagueRank power target
3 2018-04-02 A 61,722 ?
  • login
    • ユーザーのログイン履歴
userId date gachaEvent holiday
1 2020-01-01 1 1
1 2020-01-03 1 1
1 2020-01-05 0 1
1 2020-01-10 1 0
2 2020-01-02 1 1
2 2020-01-03 1 1
2 2020-01-07 0 0
3 2020-01-04 1 1
3 2020-01-05 1 1
3 2020-01-07 0 0
3 2020-01-08 0 0

特徴量生成
1, login に対して train を merge して、target 列を付与する。
このとき、 userId=3 は target 不明なので、 null になります。

userId date gachaEvent holiday target
1 2020-01-01 1 1 1
1 2020-01-03 1 1 1
1 2020-01-05 0 1 1
1 2020-01-10 1 0 1
2 2020-01-02 1 1 0
2 2020-01-03 1 1 0
2 2020-01-07 0 0 0
3 2020-01-04 1 1
3 2020-01-05 1 1
3 2020-01-07 0 0
3 2020-01-08 0 0

2, login の target を予測するモデルを作る

target が存在する userId=1 or 2 のデータを学習データとして
Cross Validation を行い、モデルを作ります。

userId=1 or 2 のデータに対しては oof ( Out Of Fold ) の値を付与します。
userId=3 のデータに対しては、各 Fold で作成したモデルで predict した値の平均値を付与します。

userId date gachaEvent holiday target predictions
1 2020-01-01 1 1 1 0.22
1 2020-01-03 1 1 1 0.18
1 2020-01-05 0 1 1 0.14
1 2020-01-10 1 0 1 0.11
2 2020-01-02 1 1 0 0.05
2 2020-01-03 1 1 0 0.06
2 2020-01-07 0 0 0 0.08
3 2020-01-04 1 1 0.11
3 2020-01-05 1 1 0.12
3 2020-01-07 0 0 0.07
3 2020-01-08 0 0 0.05

3, 予測値の集約特徴を作り、元の train, test に戻す

例えば、最小値、平均値、最大値をとって特徴量とすることができます。

  • train
userId registDate leagueRank power target predictions_min predictions_mean predictions_max
1 2017-08-07 S 103,131 1 0.11 0.1625 0.22
2 2019-03-01 B 35,328 0 0.05 0.0633 0.08
  • test
userId registDate leagueRank power target predictions_min predictions_mean predictions_max
3 2018-04-02 A 61,722 ? 0.05 0.0875 0.12

なんで上手くいくの?

前述の例であれば、他の方法(例えば、単に login から集約特徴を生成)よりも、効率よく情報を取り出せるため、というのが所感です。
TargetEncoding にも近い感覚ですが、なんだかんだリークしたり上手くいかない場合もあるので、oof を利用するのは理にかなっているのではないでしょうか。

適用できる場面が少ないのでは?

ここまでは target の oof を見てきましたが、応用して、重要度の高い説明変数の oof を利用するというやり方もあります。(特に、重要度が高いが null が多い説明変数に効果的です)

  • Kaggle / PLAsTiCC Astronomical Classification

    • 2nd place solution
    • 5 で「hostgal_specz」という変数の oof を利用した旨が書かれています
  • Kaggle / Home Credit Default Risk

    • 3rd place solution
    • 「ext_sources」という変数を予測するモデルを作成した旨が書かれています
  • bitgrit / SwipeToSuccess

    • 3rd place solution(私)

まとめ

Kaggle で度々使われている「target の予測値(oof) を利用して特徴を生成する」方法とその応用についてご紹介しました。Kaggle ではないコンペですが、私が今年お世話になったやり方です。

最近は時系列テーブルコンペでも Transformer の勢いを感じますが、今回のような方法も機会があれば試してみてはいかがでしょうか。


  1. もちろんダミーデータです 

45
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
45
Help us understand the problem. What is going on with this article?