前回で準備は整ったので、Recommendation Templateを元にカスタマイズしていこうと思ったのですが、いまいち仕組みがよくわからず、難航しているうちに挫折しました… 1
以下にRecommendation Templateをいじってわかったことをざっくりまとめておきますので、何かのお役にたてば幸いです。
(嘘書いてる可能性も高いので、参考程度にお願いいたします…)
0. DASE
以下を最初に軽く目を通しておくと理解しやすいと思います。
Engine Templateの実装としてはSkelton Templateが一番シンプルなのですが、Model学習部分などが省略されてしまっているのでわかりにくいかもしれません。
1. 学習用データ登録
- REST API経由
- SDK経由($ python data/import_eventserver.py ...)
どちらもデータ構造は同じで、これらはPredictonIOによって決められています。以下を参照してください。
Recommendation Templateの以下のデータを例にすると、「評価(rate)イベントが発生し、ユーザ(user=u0)が、映画(item=i0)に対して、評価点5(properties.rating=5)をつけた」という意味合いになります。3
{
"event" : "rate",
"entityType" : "user",
"entityId" : "u0",
"targetEntityType" : "item",
"targetEntityId" : "i0",
"properties" : {
"rating" : 5
}
"eventTime" : "2014-11-02T09:39:45.618-08:00"
}
PredictionIOに登録されたデータをEngine Templateから読み取るのは、以下のようなコードにより、DataSourceクラスで行います。2
ここでは登録されたデータを、Sparkのデータ型であるRDDに変換しています。
val eventsRDD: RDD[Event] = PEventStore.find(
appName = dsp.appName,
entityType = Some("user"),
eventNames = Some(List("rate", "buy")), // read "rate" and "buy" event
// targetEntityType is optional field of an event.
targetEntityType = Some(Some("item")))(sc)
2. 学習
基本的には以下の流れです。Recommendation Templateを例に説明します。
- engine.jsonで指定されている、Engine.RecommendationEngineが呼び出される
- 登録されている学習用データを読み取り、TrainingDataに格納する (DataSource.readTraining())
- TrainingDataに対して前処理4を行い、PreparedDataに格納する(Preparator.prepare())
- PreparedDataを入力として、機械学習モデルのトレーニングを行う(ALSAlgorithm.train())
- org.apache.spark.mllib.recommendation.MatrixFactorizationModelを拡張したALSModelを使い、org.apache.spark.mllib.recommendation.ALS.train()で学習し、結果をMatrixFactorizationModel.save()で永続化している
engine.jsonに記述してある各学習用パラメータが、ALSAlgorithm.ALSAlgorithmParamsに対応します。
3. レコメンデーション
- RESTAPI(POST http://localhost:8000/queries.json) で指定された問い合わせ内容が Engine.Query に格納される
-
ALSAlgorithm.predict()が呼び出される
- トレーニングしたALSModelと、指定されたQueryを使って、レコメンド結果を取得
- 結果をEngine.PredictedResultに格納して返却
4. Evalution
$ pio eval org.template.recommendation.RecommendationEvaluation org.template.recommendation.EngineParamsList
として実行した場合です。
-
RecommendationEvaluation中でEngine(RecommendationEngine)と各種評価関数(MetricEvaluator)を指定
- traitでEngineParamsListを使い挙動を上書き
- 登録されている学習用データを読み取り、TrainigDataに格納(DataSource.readEval())
- このあたりは学習時のreadTraining()の処理と対応していると思われる5
- training -> predictの流れを学習用パラメータを変更しながら、繰り返し実行
- 結果をMetricEvaluatorの評価関数を利用して判定、最も良かった学習用パラメータの組み合わせが返却される6
さいごに
PredictionIO、現時点では荒削り感がすごいのですが、触っていて面白く、アプローチとしては非常にわかりやすいと思うので、これをきっかけに人柱触ってみてくれる人が増えればいいなあと思いました。
何かしらのお役にたてば幸いです。
-
Engine Templateのお作法に従わなければいけない部分がだんだんしんどくなってきました… ↩
-
quickstartの一番下のリンクから飛べるのですが、最初気が付きませんでした。 ↩
-
Recommendation Templateには"buy"イベントはrating=4として扱うという、わかるようなわからないようなロジックも入っています。 ↩
-
Recommendation Templateでは特に何もしていませんが、たとえばデータ型を変換したり、学習用データと評価用データに分ける、などを想定しているんじゃないかと思います。 ↩
-
学習用データと評価用データを分けたりする作業をreadEval()内でやっているのは、Preparatorでやるとtrainとevalの両方で適用されてしまうから(train時はデータを評価用にわけずに全部使いたいから?)という理由ではないかと。 ↩
-
たぶんここはPredictionIO内でやってくれているんじゃないでしょうか。(自信ないです) ↩