Hatena::ブログ(Diary)

Secret Staircase on はてな

2012-02-01

ブログ引越しました

ちょっと前になるけど、引越しました。

新しいのはこちらです。

http://blog.physalis.net/

引き続きよろしくおねがいします。

2011-12-01

Scalala コンソール

Scalala (https://github.com/scalala/Scalala) をちょこっと使うのに便利なように scalala-console を用意しました。

https://github.com/akr4/scalala-console

sbt の initialCommands で import しているだけですw

たくさん import しないと使えないんですよね

利用例

% sbt console
[info] Set current project to default-435ec2 (in build file:/Users/akira/projects/scalala-console/)
[info] Starting scala interpreter...
[info] 
import scalala.scalar._
import scalala.tensor.$colon$colon
import scalala.tensor.mutable._
import scalala.tensor.dense._
import scalala.tensor.sparse._
import scalala.library.Library._
import scalala.library.LinearAlgebra._
import scalala.library.Statistics._
import scalala.library.Plotting._
import scalala.operators.Implicits._
Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_29).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val a = Matrix((1, 2), (3, 4))
a: scalala.tensor.dense.DenseMatrix[Int] = 
1  2  
3  4  

scala> val b = Matrix((1, 0), (2, 0))
b: scalala.tensor.dense.DenseMatrix[Int] = 
1  0  
2  0  

scala> a * b
res0: scalala.tensor.dense.DenseMatrix[Int] = 
5   0  
11  0  

2011-11-27

2.5 Evaluating the GroupLens data set

GroupLens (http://www.grouplens.org/) が提供しているデータセットを使ってみようの回。

映画のリコメンデーションサイト MovieLens のデータが様々なサイズで提供されています。http://www.grouplens.org/node/73

今回はこのうち MovieLens 100k を使います。

前回 (http://d.hatena.ne.jp/akr4/20111121/1321878009) のコード例の FileDataModel のパスを書き換えてやるだけ。FileDataModel は csv でも tsv でもうまく読んでくれるそうです。

val model = new FileDataModel(new File("data/ml-100k/ua.base"))

AverageAbsoluteDifferenceRecommenderEvaluator で試すと 0.98 でした。1-5 の preference だからこの結果はまずまずですかな?


続いて Recommender を SlopeOneRecommender に切り替えてみます。

  lazy val slopeOne = new RecommenderBuilder {
    def buildRecommender(model: DataModel) = new SlopeOneRecommender(model) 
  }

AverageAbsoluteDifferenceRecommenderEvaluator の結果は 0.74 と出ました。GenericUserBasedRecommender より良い結果ですが、データセットによって変わりますよとのこと。

これで 2 章おわり。

2011-11-21

2.3 Evaluating a recommender/2.4 Evaluating precision and recall

今回は 2.3 Evaluating a recommender と 2.4 Evaluating precision and recall です。

Recommender を評価するために Evaluator が用意されています。

ここで使うのは以下 3 種。

AverageAbsoluteDifferenceRecommenderEvaluator予測と実際の値の差 (絶対値) の平均
RMSRecommenderEvaluator予測と実際の値の差の RMS (2 乗平均平方根)
GenericRecommenderIRStatsEvaluatorprecision/recall など

2.3 Evaluating a recommender

まず差の平均を使う例

object EvaluatorIntro extends App {

  RandomUtils.useTestSeed()
  val model = new FileDataModel(new File("../MIA/src/main/java/mia/recommender/ch02/intro.csv"))
  val evaluator = new AverageAbsoluteDifferenceRecommenderEvaluator
  //val evaluator = new RMSRecommenderEvaluator

  val builder = new RecommenderBuilder {
    def buildRecommender(model: DataModel) = {
      val similarity = new PearsonCorrelationSimilarity(model)
      val neighborhood = new NearestNUserNeighborhood(2, similarity, model)
      new GenericUserBasedRecommender(model, neighborhood, similarity)
    }
  }

  val score = evaluator.evaluate(builder, null, model, 0.7, 1.0)
  println(score)
}

RecommenderEvaluator の evaluate メソッドの定義は以下の通り。

  double evaluate(RecommenderBuilder recommenderBuilder,
                  DataModelBuilder dataModelBuilder,
                  DataModel dataModel,
                  double trainingPercentage,
                  double evaluationPercentage) throws TasteException;

dataModelBuilder にはここでは null を渡しています。DataModel をカスタマイズしたい場合に指定するらしい。

trainingPercentage はトレーニングデータセットの割合を指定します。残りはテストデータセットとして使われます。

evaluationPercentage は全体のデータセットのうち評価で使う割合を指定します。上の例では 100% 全部使います。評価にかかる時間を短くしたい場合に調整するそうです。

2.4 Evaluating precision and recall

続いて GenericRecommenderIRStatsEvaluator を使って precision と recall を計算する例です。ちなみに IR は Information Retrieval の略です。Wikipedia が詳しいですね。http://en.wikipedia.org/wiki/Information_retrieval

この Evaluator により Precision, Recall を計算できます。

object IREvaluatorIntro extends App {

  RandomUtils.useTestSeed()
  val model = new FileDataModel(new File("../MIA/src/main/java/mia/recommender/ch02/intro.csv"))
  val evaluator = new GenericRecommenderIRStatsEvaluator

  val builder = new RecommenderBuilder {
    def buildRecommender(model: DataModel) = {
      val similarity = new PearsonCorrelationSimilarity(model)
      val neighborhood = new NearestNUserNeighborhood(2, similarity, model)
      new GenericUserBasedRecommender(model, neighborhood, similarity)
    }
  }

  val stats = evaluator.evaluate(
    builder, null, model, null, 2,
    GenericRecommenderIRStatsEvaluator.CHOOSE_THRESHOLD,
    1.0)
  println(stats)
}

GenericRecommenderIRStatsEvaluator は RecommenderIRStatsEvaluator インタフェースを実装していて、その evaluate メソッドの定義は以下の通りです。

  IRStatistics evaluate(RecommenderBuilder recommenderBuilder,
                        DataModelBuilder dataModelBuilder,
                        DataModel dataModel,
                        IDRescorer rescorer,
                        int at,
                        double relevanceThreshold,
                        double evaluationPercentage) throws TasteException;

なんか全体的に引数が多いですね。

relevanceThreshold は関連があるとみなす最低の preference 値、上の例のように CHOOSE_THRESHOLD とするとその人の preference 値の平均 + 標準偏差にしてくれるとのこと。

低い preference 値を付けると予測されているのに推薦しないように設定するそうです。

実行結果はこんなの

IRStatisticsImpl[precision:0.75,recall:1.0,fallOut:0.08333333333333333,nDCG:1.0]

precision, recall が計算できました。

今回はここまで。

コードはこちらにあります https://github.com/akr4/mia-study

2011-11-15

whitepaper-config: アプリケーション設定ツールキット

Scala アプリケーションの設定をサポートするツールキット whitepaper-config を作りました。

https://github.com/akr4/whitepaper/tree/develop/config


設定を Scala コードとして書いておくと、実行時に環境に応じた設定を選択します。

設定ファイルを外出しにする必要のない web アプリケーションなどに向いています。


環境の選択には

  1. JVM のシステムプロパティ
  2. ホスト名

を使います。

使い方

まず設定クラスを用意します。名前、型はなんでも構いません。

trait Config {
  val dbUser: String
  val dbPassword: String
}

次に環境ごとの設定を Environments に登録します。

val env = Environments("whitepaper",
    "dev" -> new Config {
      val dbUser = "dbUser_dev"
      val dbPassword = "dbPassword_dev"
    },
    "prod" -> new Config {
      val dbUser = "dbUser_prod"
      val dbPassword = "dbPassword_prod"
    }
  )

あとは Environments.current メソッドにより環境に応じた設定を取り出すことができます。

env.current.dbUser // dbUser_dev または dbUser_prod

システムプロパティで環境を指定するには Environments の第1引数 + ".env" を使って

java -Dwhitepaper.env=dev ....

とします。

システムプロパティの指定がなければホスト名に一致する環境の設定が取り出されます。

まとめ

Scala で書く点は Twitter の util-eval と似ていますが web アプリケーションの場合たいてい動的に eval する必要がないので環境切り替えにフォーカスして作りました。

実際たいしたことやってなくて、Environments のコードはとても短いです。

Scala は少しのコードでも強力なので、小さめの小道具を組み合わせてシステムを構築するスタイルが向いているんじゃないかなと思っています。(Unfiltered の受け売りですw)

Connection: close