一定期間更新がないため広告を表示しています
関口宏司のLuceneブログOSS検索ライブラリのLuceneおよびそのサブプロジェクト(Solr/Tika/Mahoutなど)について
2017.01.21 Saturday
Solr でランキング学習を体験する
最近俄に(?)脚光を浴びてきた「ランキング学習(Learning-to-Rank、以下LTRと略すこともある)」をSolrで試す方法を紹介しよう。 Solrでランキング学習というと、まもなくリリースされる Solr 6.4.0 に含まれる SOLR-8542 を思い浮かべる方もいるかもしれない。しかしここでは、「第19回 Lucene/Solr 勉強会」でシーマークの山本社長が発表したNLP4Lを使った方法を採り上げたい。以下の理由からSOLR-8542よりはるかに使い方が簡単だからだ。
また、NLP4Lはランキング学習の論文で紹介される一般的な特徴であるTF、IDF、TF*IDFなどが扱えるのに対し、SOLR-8542はこれらの特徴は扱えない(扱う予定もなさそう)。さらにSOLR-8542はモデルを利用する部分でSolrに依存するところが大きいが、NLP4Lでは大事な部分はLuceneレベルで行われ、LTRの主要な部分の実装がコンパクトである。したがってElasticsearch対応も比較的簡単である。もちろんSOLR-8542の方が優れている部分もあり、使用する特徴をSolrのクエリ式で書けるところはNLP4Lよりも柔軟で優位性があるといえる。 LTRの学習データについてLTRは教師あり学習を基本とする。教師データのイメージは、「あるクエリについてそれぞれの文書がどのくらい関連しているか」というラベル(NLP4Lではrelevance degreeと呼んでいる)がつけられている一連のレコードである。この形式のデータを学習するアルゴリズムはPointwiseアプローチと呼ばれる。他にも「あるクエリについて文書ペアがどちらがより関連度が高いか」というラベルがついたデータを扱うPairwise、「あるクエリについて文書集合が関連度順にどのようにリストされるか」というラベルがついたデータを扱うListwiseがある。 前述の3番目の「教師データの準備方法」について、NLP4Lでは付属の「アノテーションGUI」を使った方法と、「アクセスログ(aka クリックログ、NLP4Lでは特別に「インプレッションログ」と呼んで通常のアクセスログと区別している)からクリックモデルを計算して関連度を自動算出する」方法が用意されている。本記事では説明の簡略化のため前者の「アノテーションGUI」を使った方法を採り上げる。しかし本番システムで人手でアノテーションを行うのはなにかと大変だ。本記事を読んでランキング学習の手順を理解したら、ぜひ後者の「アクセスログからクリックモデルを計算して関連度を自動算出する」方法に挑戦していただきたい。 以下、NLP4Lでのランキング学習の手順の概要である。この順番で以降説明を進める。
前述の通り、NLP4Lには詳細なLTRのためのマニュアルが付属するのでここであらためて記事にする必要もないかもしれないが、本記事では対象文書セットとしてlivedoorニュースコーパスを用いることで、一連の操作方法をより具体的に説明している。興味のある方は、下記手順通りにインストールと設定を進めれば、Solrでランキング学習の実際を体験することができる。より詳細を知りたい場合にはNLP4Lのマニュアルをご覧いただきたい。 Solr 6.3.0 のインストール適当なディレクトリにてSolr 6.3.0(本記事執筆時の最新)をダウンロード、展開する。本記事では/opt/nlp4l/solr-6.3.0ディレクトリにSolrを展開するとして話を進める。 $ pwd /opt/nlp4l $ wget http://ftp.tsukuba.wide.ad.jp/software/apache/lucene/solr/6.3.0/solr-6.3.0.tgz $ tar xvzf solr-6.3.0.tgz Solrを起動し、collection1という名前のコアを作成する。 $ cd solr-6.3.0 $ ./bin/solr start $ ./bin/solr create_core -c collection1 -d sample_techproducts_configs LTRのためのSolrプラグインのビルドと設定適当なディレクトリにてgithubで公開されているNLP4L/solrプロジェクトをダウンロード、ビルド、Solrにデプロイする。 $ pwd /somewhere/NLP4L $ git clone https://github.com/NLP4L/solr.git $ cd solr $ mvn package $ cp target/nlp4l-solr-1.1-SNAPSHOT.jar /opt/nlp4l/solr-6.3.0/server/solr-webapp/webapp/WEB-INF/lib NLP4L/solrはtypesafe社のconfigライブラリが必要なので、以下のように入手、ビルド、Solrにデプロイする。 $ cd /somewhere $ wget https://github.com/typesafehub/config/archive/v1.3.1.tar.gz $ tar xvzf v1.3.1.tar.gz $ cd config-1.3.1 $ sbt package $ cp config/target/config-1.3.0-20170120T044439.jar /opt/nlp4l/solr-6.3.0/server/solr-webapp/webapp/WEB-INF/lib Solrに付属のJettyのwebapp設定を次のように行う。 $ cd /opt/nlp4l/solr-6.3.0 $ vi server/solr-webapp/webapp/WEB-INF/web.xml
また、選択可能な特徴を以下のようにJSON設定ファイルに用意する。 $ vi server/solr/collection1/conf/ltr_features.conf { "features": [ { "name": "TF in title", "class": "org.nlp4l.solr.ltr.FieldFeatureTFExtractorFactory", "params": { "field": "title" } }, { "name": "TF in body", "class": "org.nlp4l.solr.ltr.FieldFeatureTFExtractorFactory", "params": { "field": "body" } }, { "name": "IDF in title", "class": "org.nlp4l.solr.ltr.FieldFeatureIDFExtractorFactory", "params": { "field": "title" } }, { "name": "IDF in body", "class": "org.nlp4l.solr.ltr.FieldFeatureIDFExtractorFactory", "params": { "field": "body" } }, { "name": "TF*IDF in title", "class": "org.nlp4l.solr.ltr.FieldFeatureTFIDFExtractorFactory", "params": { "field": "title" } }, { "name": "TF*IDF in body", "class": "org.nlp4l.solr.ltr.FieldFeatureTFIDFExtractorFactory", "params": { "field": "body" } } ] } また、solrconfig.xmlを以下のように編集する。 $ vi server/solr/collection1/conf/solrconfig.xml 標準の /select リクエストハンドラのdefaultsパラメータに以下を追加する。
NLP4L-LTRからの特徴抽出リクエストに応答するためのリクエストハンドラを以下のように設定する。
最後に、PRankクエリを呼び出すPRankQParserPluginを次のように設定する(PRank以外にRankingSVMが選択可能)。
またSolrあるあるであるが、Elevation Component関連の設定もここで削除しておこう。 livedoor ニュースコーパスの登録livedoor ニュースコーパスをSolrに登録するために、まずスキーマを設定する(APIを通じてスキーマ変更するのが推奨だが、面倒なのでエディタで編集してしまう)。 $ vi server/solr/collection1/conf/managed-schema
されに不要なcopyField設定は取り除いておく。ここでSolr設定の変更を有効化するためにコアのリロードまたは再起動を行う。 そしてlivedoor ニュースコーパスを入手し、Solrに登録する。 $ cd /somewhere $ wget http://www.rondhuit.com/download/livedoor-news-data.tar.gz $ tar xvzf livedoor-news-data.tar.gz $ /opt/nlp4l/solr-6.3.0/bin/post *.xml NLP4Lのインストールと起動および設定NLP4L/nlp4l プロジェクトを github から以下のように入手し起動する。 $ cd /somewhere/NLP4L $ git clone https://github.com/NLP4L/nlp4l.git $ cd nlp4l $ cp conf/application.conf.sample conf/application.conf $ vi conf/application.conf $ ./activator run そしてWebブラウザから http://localhost:9000/ にアクセスする。NLP4L-LTRというメニューを選び、画面上部に表示されるメニューのConfigをクリックする。そして<<New>>リンクをクリックすると、新しいConfig設定をするように促される。次の表を参考に設定する。
[Save]ボタンをクリックして[Load]をクリックすると、画面上部にtestという名前のConfigがロードされたことが示され、Query、Annotation、Feature、Trainingというメニュー項目が現れる。 教師データの作成教師データを作成する場合はQueryまたはAnnotationメニューを使う。なお前述の通り、本記事ではアノテーションGUIを使った教師データの作成方法を説明する。アクセスログ(インプレッションログ)からクリックモデルを計算することで教師データを安価に用意したい場合は、Queryメニューの[Import]ボタンをクリックしてログファイルをロードする。 Queryメニューにはファイルを選択するボタンがあり、これをクリックするとクエリ一覧が記載されたテキストファイルを選べるようになる。このテキストファイルには1行1クエリを記載しておく。このファイルをロードすると、下図のようにクエリが表示される。
このクエリのリンクをクリックすると連携先のSolrにてクエリが実行され、Annotation画面に結果が表示される。この画面ではSearchテキストボックスに選択したクエリが表示されているが、Queryメニューから始めなくても、Annotationメニューを選んでこのSearchテキストボックスに直接クエリを入れても同じである。
Annotation画面にて各クエリと返された文書の関連度を考えながら、右側に表示されている星の数を適切に選んでいく。1画面分終わったら、[Save]ボタンで保存し、[Next]で次のクエリに進む。一通り終了したら次のステップである特徴抽出に進む。 特徴抽出Featureメニューを選択する。すると下図のようなプログレスバーが現れる。[Extract]で特徴抽出が開始するが、すでにプログレスバーが緑色になっているときは、まず[Clear]ボタンをクリックしてから[Extract]を行う。終了するとDONEと表示される。
ランキング学習Trainigメニューを選択し、左側にある<<New>>をクリックする。するとSolrに配置した設定ファイル(ltr_features.conf)にしたがって特徴を選ぶチェックボックスが現れる。このチェックボックスで適当に特徴を選んで[Start]をクリックする。ここでも学習の進行状況がプログレスバーで示され、終了すると下のようにモデルファイルの内容が表示される。ここではPRankを選択したので、各特徴に対する重みと、3つの閾値(星の数を最大3にしたことに由来)が返される。 { "model" : { "name" : "prank", "type" : "prank", "weights" : [ { "name" : "TF in title", "weight" : -113 }, { "name" : "TF in body", "weight" : -14 }, { "name" : "IDF in body", "weight" : -322.44384765625 } ], "bs" : [ -2818, -2374, 6450 ] } } モデルのデプロイランキング学習が終了すると[Deploy]ボタンが表示されるので、これをクリックすることで連携先のSolrにHTTPで転送される。
Solr側ではこの学習モデルを有効化するために、コアのリロードが必要である。Solrの管理画面からコアのリロードを行うのが簡単だ。 ランキング学習モデルを使ったリランキングの実際NLP4L-LTRはSOLR-8542とは異なり、Solr標準のリランクを使って呼び出すのでrq={!rerank …}パラメータを利用する。前述のsolrconfig.xmlに設定したprank queryParserを呼び出すには次のように検索を実行する。 http://localhost:8983/solr/collection1/select?indent=on&q=社会人 学生&rq={!rerank reRankQuery=$rqq}&rqq={!prank}社会人 学生&debugQuery=on Solr標準のリランクは、(前述のsolrconfig.xmlの設定にしたがい)最初に通常のedismaxクエリを実行し、次に上位の200クエリ(reRankDocsのデフォルト)についてランキング学習モデルに基づいた再ランキングを行う。デバッグ情報のスコア詳細欄を見ると最初の2行は次のようになっている。 14.37461 = combined first and second pass score using class org.apache.solr.search.ReRankQParserPlugin$ReRankQueryRescorer 10.37461 = first pass score 最初の行は2段階クエリのスコアの和が14.37461になっていることを示し、次の行は第1段階のクエリ(ここでは通常のedismax)のスコアが10.37461であることを示している。3行目以降はedismaxのスコア詳細なのでここではスキップしよう。 第2段階のクエリ、つまりPRankのクエリで計算したスコア合計は2.0であり、その詳細は下記のブロックで示されている。 2.0 = second pass score 2.0 = is the index of bs(-2818.0,-2374.0,6450.0) > -2338.074707 sum of: -113.0 = weight: -113.0 * feature: 1.0 sum of: 0.0 = no matching terms 0.0 = no matching terms 1.0 = freq: 1 -84.0 = weight: -14.0 * feature: 6.0 sum of: 2.0 = freq: 2 3.0 = freq: 3 1.0 = freq: 1 -2141.0747 = weight: -322.44385 * feature: 6.640147 sum of: 2.762864 = log(numDocs: 7368/docFreq: 465) 0.55211145 = log(numDocs: 7368/docFreq: 4242) 3.3251717 = log(numDocs: 7368/docFreq: 265) 2.0というスコアは2倍(reRankWeightのデフォルト)され4.0となり、最終スコア合計が14.37461となる。2.0というスコアはどうやって計算されたかというと、モデルで与えられた重みを使って計算した結果が-2338.074707となるが、これは境界値の[-2374.0,6450.0]の範囲内にあるため2.0となる。 まとめlivedoorニュースコーパスはフィールド数、文書数とも少ないので十分な教師データを作るのが難しいが、実運用されているフィールド数、文書数とも大きなデータにおいて、ランキング学習は通常のSimilarityが算出するスコアをより良く改善することが期待できる。ぜひ試していただきたい。 コメント
詳しい記事ありがとうございます。参考にさせていただきます。
SolrCloudの場合、コアのディレクトリ名がcollection1_shard2_replica1のように動的に生成されると思うのですが、これに対応したroot_pathの指定は可能でしょうか? また、Annotation画面はtitle, bodyというフィールド名を変更したり、画像を表示したりできるのでしょうか?
| sc | 2017/01/24 9:22 PM |
特徴を設定するファイルや生成したモデルファイルを無理にconfディレクトリに置こうとすると上記のような設定になりますが、これはQParserPluginがSolrのリソースローダーにアクセスできないことから来ています。これらのファイルを${SOLR}/server/resources/ に置くようにすればいいのではないでしょうか。
Annotation画面でのフィールド姪は、記事中表のtitleやbodyを、myTitleやmyBodyなどとご自身のフィールド名に合わせて設定できます。画像は表示できないです。タイトルと本文だけからアノテーションしてもらう必要があります。
| 関口 | 2017/01/25 7:34 AM |
ありがとうございます。
フィールド名、普通に設定できましたね。失礼しました。
| sc | 2017/02/06 4:33 PM |
コメントする
この記事のトラックバックURL
トラックバック機能は終了しました。
トラックバック
|
+ Solrによるブログ内検索
+ PROFILE
+ LINKS
+ Lucene&Solrデモ
+ ThinkIT記事
+ RECOMMEND
+ RECOMMEND
Lucene in Action (JUGEMレビュー »)
Erik Hatcher,Otis Gospodnetic,Mike McCandless FastVectorHighlighterについて解説記事を寄稿しました。
+ RECOMMEND
+ SELECTED ENTRIES
+ RECENT COMMENTS
+ RECENT TRACKBACK
+ CATEGORIES
+ ARCHIVES
+ MOBILE
+ SPONSORED LINKS
|
(C) 2024 ブログ JUGEM Some Rights Reserved.
|
PAGE TOP |