Search on the blog

2015年8月4日火曜日

Kaggle参加記:Search Results Relevance

 KaggleのSearch Results Relevanceに参加しました。

About competition
このコンテストでは、検索クエリとそれに対する検索結果がデータとして与えられます。教師ありデータではクエリに対する検索結果のマッチ度を1-4で評価しています。テストデータではこのマッチ度を予測します。

What I did
特徴エンジニアリングに利用するデータがテキストなので、NLPまわりの知識が必要になります。知識ゼロベースからのスタートだったので、とりあえず論文やらチュートリアルやらライブラリの使い方やらを読み漁るところから始めました。

 TF-IDFベクトルのコサイン類似度、Okappi BM25あたりが検索ワード-検索結果のランキングアルゴリズムでよく使われることが分かったので、この2つをC++でカスタム実装してみました。特徴量抽出後はsklearnのランダムフォレストで識別。いい結果出ず。テキストの前処理が甘いと思い、大文字⇒小文字変換、Stop-words除去、stemmingなどを行うもスコアが思ったように伸びず。

 こういうときは、Forumだ!ということで、Forumに上がっているスレッドを全部読みました。starter scriptなるものがあり、それを実行すると自分が書いたものよりいい結果が出て凹む。
しかもそのスクリプトがTF-IDFを抽出した後、次元圧縮し、SVMで識別するだけというシンプルなモデルだったため余計に凹む。しかし何故こんなモデルでうまくいくのだと悩んでいると同じようなことを質問しているユーザがいたため、何か手がかりになるはずと考え理由を考えました。

 そして検索対象がマッチしやすいかそうでないオブジェクトに分けるとうまくいくのではという結論に達しました。実際にデータを見てみると同じ検索クエリが複数回使われていて、平均マッチ度が高いクエリと低いクエリが存在することが判明しました。もっと早めに気づけよという感じです。「特徴エンジニアリングする前にデータをよく知る」ということが出来ていなかったです。

 この知見をベースに、クエリ毎に識別器を作ったり、始めにクエリをk-meansでクラスタリングした後にクラスタ毎に識別器を作ったりして、スコアもまあまあ上がりました。cross validationでいい結果の出たモデルをいくつか選んでスタッキングしてサブミットで試合終了となりました。

What I didn't do but top kagglers did
コンテスト終了後にトップランカーたちがやっていたことを調べました。その中でこれは!というものを書いておきます。1.-4.はテクニック的な話、5.はそもそもの心構え的な話です。
  1. コサイン類似度以外にも複数の距離(編集距離、圧縮距離など)を特徴量として使う
  2. 検索結果=4のものをクエリに足し合わせて拡張クエリを作る(マッチ度が高い検索結果 = クエリをより詳細に記述したものであるはず)
  3. 識別問題ではなく、回帰問題として扱う(評価基準がkappa estimatorなので、ラベルは離散値だけど実測値からの誤差を最小化するとうまくいく)
  4. 回帰モデルの予測値をソートし、"1","2","3","4"のスコアを訓練データと同じ割合で付与する(単純に回帰モデルの予測値を整数化してもいい結果はでない)
  5. validation時にスコアの悪いものを1つ1つ確認し、なぜスコアが悪いか考えモデルを改良していく

My model after the competition
ということで、上の反省をふまえてモデリングをやり直し、一から実装しなおしました。
まあこんな感じのものです。

ソースコードはこちら
private score = 0.66830でした。これでも180位くらいなのでまだまだですね。


0 件のコメント:

コメントを投稿