Ousia Engineering Blog

Studio Ousiaのエンジニアリングブログです。社内での技術的な取り組みを中心に紹介していきます。

Kaggle WSDM Music Recommendation Challenge参加記録

こんにちは、インターンの玉木です。

昨年9月まで電気通信大学修士課程で対話システムの研究をしながら、Studio Ousiaのインターンプログラムに参加していました。大学院の修士課程はすでに修了しましたが、現在もインターンを続けています。

先日までKaggleで開催されていたWSDM KKBox's Music Recommendation Challengeに参加していました。 結果は1081チーム中47位でした。本記事ではこのコンペティションと参加した感想を紹介したいと思います。

KKBox's Music Recommendation Challenge

今回のコンペティションではKKBOXという音楽配信サービスのデータを使い、各ユーザーが一度聴いた曲を再度聴くかどうかの2値分類の精度を競いました。評価指標はAUCです。 与えられたデータの説明は記事の最後にあります。

実際の流れ

モデル作成は以下のようなプロセスで行います。

  1. 特徴量抽出
  2. モデル作成
  3. モデル評価

Kaggleではkernelという他の参加者の分析結果や上記1~3を行った結果などが共有されている場があります。 自分はupvoteが多いkernelを参考にして始めることが多いです。今回はこのkernelに特徴量を追加していく形で作業を進めていました。Kaggleではほとんど1の特徴量抽出で差がでます。2, 3のプロセスはほとんどやることが変わらないためです。

検証データの準備

今回のコンペティションのデータは時系列データで、訓練データとテストデータは期間で分割されています。時系列データの予測モデルを評価する場合、同様に期間で分割して作られた検証データを作る必要があります*1 。 しかし、今回使用するデータには明示的にtimestampが与えられておらず、訓練データから期間で分割された検証データを作ることができませんでした。timestampが与えられていれば良い検証データを作成できるだけでなくそれを用いて新たな特徴量も作れるのですが、リークに繋がる可能性を考慮して削除されたようです*2

多くの参加者が良い検証データを作るのに苦戦している中、訓練データとテストデータがシャッフルされておらず、時系列順に並んでいることを発見した参加者がいました*3。 曲が録音された年度の代わりにユーザーがサービスに登録した日付(registration_init_time)をplotすると、時系列順に並んでいることだけでなく、細かい日付まで知ることができます。横軸にデータのインデックス、縦軸にユーザーがサービスに登録した日付をplotした図が以下の図です。青色の部分が訓練データ、緑色の部分がテストデータです。

f:id:tmjtmk:20180114131944p:plain

Kaggle主催者がわざわざリークを考慮して含まなかった特徴量をこんな簡単に見つけられてしまっていいのかというツッコミもありますが、これで訓練データから良い検証データを作成できるようになり、より良いモデルの評価ができるようになりました。これがなかったらLeaderboard上のpublicデータでしか評価ができず、かなり厳しかったように思えます(publicデータにオーバーフィットしてしまう可能性もあります)。

自分がやったこと

最初に各カテゴリカル変数の頻度を計算しました。カテゴリカル変数とはグループで分類されるような変数のことを指します。今回与えられたデータでは、ユーザーID、 曲のID等ほとんどがカテゴリカル変数です。曲の長さ等はカテゴリカル変数に含まれません。実はこれらの特徴量を用いるだけで一気に上位に入ることができます。特にユーザーの頻度情報が効きました。

次に各カテゴリカル変数における目的変数の平均値(期待値)を計算しました。例えば、曲に対する目的変数の平均を取ることで、その曲がどのくらい再度聴かれているかを表現することができます。target based encodingなどと呼ばれることがあるのですが、目的変数の情報を用いるためそのまま使うとリークしてしまいます。自分自身の情報を含まないようにデータを4分割して、その訓練データのアイテムが含まれない他の3つを使って特徴量抽出をしたのですがAUCはむしろ下がってしまいました。そのときは極端に頻度が少ないユーザーや曲が存在するためなのかなーと考えていましたが、実は違う方法で特徴量を計算すれば非常に有効な特徴量になりました。後述します。

次にtimestampを用いて特徴量の作成を試みました。しかしこれも同様の後述する理由で失敗してしまいます。

最終的に各カテゴリカル変数の頻度に加えて、各カテゴリカル変数を組み合わせた頻度、その他細かい特徴量を追加してLightGBM を用いたGradient Boosted Decision Trees (GBDT) のシングルモデルの予測結果をsubmitしました。

その他ニューラルネットワークやFactorization Machinesも試したのですがGBDTに劣り、それらの結果をアンサンブルしても、むしろAUCが下がってしまいました。

答え合わせ

Kaggleではコンペティションが終わったあとにdiscussionという場でsolutionが公開されることがあります。 3位の方のsolutionが分かりやすかったので、ここで比較をしてみたいと思います。*4 この手法では、以下の特徴量を抽出したそうです。

1) mean of target from history by categorical features (pairs and triples)

2) count – the number of observations in all data by categorical features (pairs and triples)

3) regression – linear regression target by categorical features (msno, msno + genre_ids, msno+composer and so on)

4) time_from_prev_heard – time from last heard by categorical features (msno, msno + genre_ids, msno+composer and so on)

5) time_to_next_heard – time to next heard by categorical features (pairs and triples which include msno)

6) last_time_diff – time to the last heard by categorical features

7) part_of_unique_song – the share of unique song of artist that the user heard on all unique song of artist

8) matrix_factorization – LightFM. I use as a user msno in different context (source_type) and the msno was the feature for user.

特徴量の構成は私がやったことと似ているような気がします。では、私のやったこととの主な差分はどこにあるのでしょうか? その差分は特徴量の作り方にあります。3位の方は学習には訓練データの直近のデータ35%を学習に使い、残りの65%のデータから特徴量を作成しています。テストデータの特徴量の抽出にはすべての訓練データから抽出しています。自分は各カテゴリカル変数の目的変数の平均値の計算をデータを4分割して行いましたが、それがよくなかったようです。また、上記4~6のような時系列の特徴量を作る際、私はデータを分割せずにそのまま特徴量抽出をおこなっていました。結果として直近の似たデータとの差分等をとることになってしまい、意味のある特徴量を抽出できなかったようです。

1位の方もsolutionを公開しています*5。1位の方はGBDTとニューラルネットワークのアンサンブルを用いています。GBDTだけではLeaderboardで3位のスコアだったそうですが、ニューラルネットワークと組み合わせることにより、より高いスコアを獲得しています。GBDTとニューラルネットワークでは違った特徴の捉え方をするためだと考えられます。

1位の方が作成したモデルの概略図がこちらです。かなり複雑です。

また、1位の方は次のようにも述べています。

Again I learn how powerful GBDT is. A simple GBDT can beat an ensemble of 30 carefully-designed NNs (of course GBDT is an ensemble model itself).

以前Kaggleであったinstacartのコンペの3位の方がニューラルネットワークのみを用いてモデルを作成し話題になりました。個人的な感想ですが、今回のようなタスクにおいてニューラルネットワークのモデルを作成するのはかなり難しそうです。

感想

いい勉強になりました。コンペ期間中にうまくいかなかった原因を突き止められなかったのは正直悔しいですが次に活かしたいと思います。

本気で上位を目指そうと思ったら熱意が足りませんでした。1位の方はsubmit数もダントツに多いです。

データ分析の知見を得るのにKaggleはとても良いと思います。今現在もおもしろそうなコンペがいくつもあるので興味のあるコンペに参加してみてはいかがでしょうか。

与えられたデータ

train/test.csv(targetはtrainのみ) 説明
msno ユーザーのID
song_id 曲のID
source_system_tab そのイベントが起こったときのタブ名。search, radio, mylibrary等
source_screen_name ユーザーが見ているレイアウト
source_type ユーザーが最初にその曲を聴いたときのエントリーポイント。album, online-playlist等
target target=1がその曲をユーザーがもう一度聴いたことを示し、target=0が聴かなかったことを示す


songs.csv 説明
song_id 曲のID
song_length 曲の長さ(ms)
genre_ids 曲のジャンルのID
artist_name アーティストの名前
composer 作曲家の名前
lyricist 作詞家の名前
language 曲の言語


members.csv 説明
msno ユーザーのID
city 住んでいる場所
bd 年齢
gender 性別
registered_via サービスの登録方法
registration_init_time サービスを開始した日付
expiration_date サービスが使用できる期限


song_extra_info.csv 説明
song_id 曲のID
song_name 曲の名前
isrc International Standard Recording Code。曲が録音された年等の情報が含まれる

開発した早押しクイズAIが人間のチームと対戦して勝利しました @ NIPS 2017

こんにちは、CTOの山田です。

現在、人工知能やニューラルネットに関する世界最高峰の国際会議の一つであるNIPS 2017に参加するために、カリフォルニアのロングビーチに来ています。 昨日、この会議で、弊社の開発した早押しクイズAIとクイズのエキスパート6人で構成される人間のチームの対戦が行われて、弊社のAIが人間のチームに二倍以上のスコアの差(465対200)をつけて勝利しました!

f:id:ikuyayamada:20171210092208j:plain
弊社AIと人間のクイズ対戦の様子

f:id:ikuyayamada:20171210135502j:plain
対戦の終盤のスコア表

この対戦は、NIPSのコンペティショントラックの一つとして開催されている「Human-Computer Question Answering Competition」の中で行われました。 このコンペティションでは、参加者はクイズボウルと呼ばれる、クイズ対戦ゲームを解くAIを開発することを求められます。 そして、提出したAIは、他の提出されたAIとの対戦をして性能を評価され、このAI同士の対戦で勝利したAIが最終的に人間のチームと対戦するということになっています。 今回の人間のチームは、クイズ番組「ジェパディ!」の優勝者で、テレビ番組「Who Wants to be a Millionaire)」で過去に25万ドル獲得したことのあるRaj Dhuwalia氏や、数学者で、過去にいくつかの米国のクイズコンペティションで優勝した経験を持つDavid Farris氏などの有力なクイズプレーヤーを含む六名で構成されています。 このコンペティションは、2016年に開催された第一回に続いて二度目の開催で、前回と同様にメリーランド大学、スタンフォード大学、Allen Institute for AI等に所属する該当分野で著名な研究者がオーガナイズしています。 弊社は、このコンペティションの第一回目にも出場し、AI間の対戦では優勝したのですが、人間チームとの対局では155対190で負けてしまったため、今年のコンペティションに再度挑戦することになりました。

クイズボウルは日本では馴染みが少ないですが、英語圏を中心に幅広く人気があります。 例えば、AIブームのきっかけとなったと言われる、クイズ番組「ジェパディ!」でのIBM Watsonと人間の対戦で、IBM Watsonに敗れたクイズ王Ken Jenningsは、クイズボウルでも活動していたことが知られています。 また、年間を通じてクイズボウルのトーナメントが開催されています。 そして最近では、質問の意味を解析する自然言語処理の手法を評価する方法として、研究でも良く使われています*1

クイズボウルの特徴の一つは、早押しで回答する必要がある点です。 質問文は、早い段階で答えるのは難しく、読み上げられていく毎に簡単に回答できるように書かれていて、質問の早い段階で正解した場合は15ポイント、そうでない場合は10ポイントがもらえるルールになっています。 このため、質問文のなるべく早い段階で回答することが重要になってきます。 また、一度間違えると同じプレーヤーは再度回答することが出来ないため、回答の精度を維持することも重要です*2。 例えば、下記の質問文の回答は「豊臣秀吉」ですが、回答について知っていたとしても、質問文の早い段階で回答するのは、難易度が高いことがお分かりいただけると思います。

He displaced one of his rivals by giving the Kanto domain to them, which precipitated that family's move away from the Chubu region. This man redefined class relationships based on kokudaka, or amount of agricultural production. He became so enraged at his nephew Hidetsugu that he killed thirty of Hidetsugu's female relatives, and he failed to get past Korea in an attempt to conquer China. In order to enforce an order that allowed only samurai to bear arms, this man started the Great Sword Hunt. For 10 points, name this successor of Oda Nobunaga who unified Japan before being succeeded by the namesake of a shogunate, Tokugawa Ieyasu.

今回のシステムでは、二つのディープラーニングのモデルと、複数の情報検索モデルから出力された複数の特徴を、アンサンブル学習 (gradient boosted regression trees (GBRT)) を用いて組み合わせる*3ことで、高精度化を実現しました。 また、中核となっているディープラーニングのモデルとしては、質問文に対して回答を予測する分類モデルを用いました。 具体的には、Deep Averaging Networksという比較的シンプルなディープラーニングのモデルに対して、質問文中に出現した単語とWikipediaエンティティ(固有名詞や専門用語など)を入力することで、質問の意味のモデルを構成し、回答を予測しています。 このモデルの新しい点としては、(1) 単語だけでなく、曖昧性の無いWikipediaエンティティも合わせてモデルに入力していること、(2) 単語とエンティティのベクトルを、弊社が昨年に提案した新しい分散表現モデル*4を使って初期化していることがあげられます。

今回のシステムは、弊社で開発している質問応答システムであるQA ENGINEの製品の開発の過程で得られたノウハウを元に開発されました。 開発には、Python、Cython(高速化)、PyTorch(ニューラルネット)、LightGBM(GBRT)、Hyperopt(ハイパーパラメータ探索)などのライブラリを用いました。 また、来年には、このNIPSコンペティションでの成果をまとめて書籍が出版されることになっており、そちらでさらに詳細なアプローチを解説する予定です。

発表スライド:

*1:例: A Neural Network for Factoid Question Answering over Paragraphs (Iyyer et al., 2014) や Deep Unordered Composition Rivals Syntactic Methods for Text Classification (Iyyer et al., 2015)、Opponent Modeling in Deep Reinforcement Learning (He et al., 2016) など

*2:今回の場合、人間チームは6人いるので最大で6回の回答ができるのに対し、AIは一回間違えたら再回答できません。

*3:ディープラーニングの出力をアンサンブル学習に特徴として組み込む際にはstackingを用いています。

*4:Joint Learning of the Embedding of Words and Entities for Named Entity Disambiguation (Yamada et al., 2016)