【R】recosystemでレコメンデーション
2020年10月9日
1. はじめに
まだ、よくわかってないのですが、推薦システム(のベース)をR
でやってみることに。これを実現するパッケージはすでに多くあるようなのですが、今回は、Yu-Chin Juan, Wei-Sheng Chin, Yong Zhuang, Bo-Wen Yuan, Meng-Yuan Yang, and Chih-Jen LinによるLIMBF
ライブラリーのWrapperであるrecosystem
というパッケージを使ってみます。
LIMBF
は、C++でかかれた高パフォーマンスのライブラリーで並列処理により効率よく大規模データを処理できます。また、CPUのみならずGPUにも対応しています。
推薦システムは、ECサイトなどで関連商品をレコメンドするものです。何らかのユーザー行動やアイテム情報などから、ユーザーが関心がありそうなアイテムを提示することが目的です。ユーザーが大量の商品から好みの商品を見つけやすくしたり、自分でも気づかなかった意外な商品を気に入るなどの意外性もあったりします。
2. インストール
CRANからインストールします。
install.packages("recosystem")
3. つかってみる
サンプルにあるデータを使ってみます。まずは、データの読み込み。
library(recosystem) set.seed(123) # This is a randomized algorithm train_set = data_file(system.file("dat", "smalltrain.txt", package = "recosystem")) test_set = data_file(system.file("dat", "smalltest.txt", package = "recosystem"))
Reco()
関数により、オブジェクトを作ります。
r = Reco()
$tune
メソッドにより最適なパラメータを選択します。
opts = r$tune(train_set, opts = list(dim = c(10, 20, 30), lrate = c(0.1, 0.2), costp_l1 = 0, costq_l1 = 0, nthread = 1, niter = 10)) opts
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
> opts
$min
$min$dim
[1] 10
$min$costp_l1
[1] 0
$min$costp_l2
[1] 0.1
$min$costq_l1
[1] 0
$min$costq_l2
[1] 0.1
$min$lrate
[1] 0.1
$min$loss_fun
[1] 0.9743264
$res
dim costp_l1 costp_l2 costq_l1 costq_l2 lrate loss_fun
1 10 0 0.01 0 0.01 0.1 1.0158789
2 20 0 0.01 0 0.01 0.1 0.9981966
3 30 0 0.01 0 0.01 0.1 0.9991761
4 10 0 0.10 0 0.01 0.1 1.0056670
5 20 0 0.10 0 0.01 0.1 0.9851703
6 30 0 0.10 0 0.01 0.1 0.9838365
7 10 0 0.01 0 0.10 0.1 0.9908790
8 20 0 0.01 0 0.10 0.1 0.9978197
9 30 0 0.01 0 0.10 0.1 0.9831165
10 10 0 0.10 0 0.10 0.1 0.9743264
11 20 0 0.10 0 0.10 0.1 0.9878893
12 30 0 0.10 0 0.10 0.1 0.9887035
13 10 0 0.01 0 0.01 0.2 1.0945747
14 20 0 0.01 0 0.01 0.2 1.0289115
15 30 0 0.01 0 0.01 0.2 1.0166264
16 10 0 0.10 0 0.01 0.2 1.0657177
17 20 0 0.10 0 0.01 0.2 1.0316208
18 30 0 0.10 0 0.01 0.2 1.0082243
19 10 0 0.01 0 0.10 0.2 1.0782190
20 20 0 0.01 0 0.10 0.2 1.0268844
21 30 0 0.01 0 0.10 0.2 1.0054406
22 10 0 0.10 0 0.10 0.2 1.0599895
23 20 0 0.10 0 0.10 0.2 1.0323456
24 30 0 0.10 0 0.10 0.2 1.0064500
$tune
の結果得られたパラメータを使って、$train
により学習します。
r$train(train_set, opts = c(opts$min, nthread = 1, niter = 20))
> r$train(train_set, opts = c(opts$min, nthread = 1, niter = 20))
iter tr_rmse obj
0 2.1027 4.8998e+04
1 0.9744 1.5287e+04
2 0.8348 1.2881e+04
3 0.8047 1.2434e+04
4 0.7883 1.2222e+04
5 0.7736 1.2030e+04
6 0.7592 1.1861e+04
7 0.7431 1.1673e+04
8 0.7263 1.1504e+04
9 0.7073 1.1305e+04
10 0.6891 1.1140e+04
11 0.6692 1.0943e+04
12 0.6519 1.0786e+04
13 0.6362 1.0654e+04
14 0.6214 1.0531e+04
15 0.6081 1.0420e+04
16 0.5967 1.0334e+04
17 0.5855 1.0241e+04
18 0.5761 1.0168e+04
19 0.5682 1.0117e+04
次にモデルで予測してみます。ファイルに保存する場合には、以下のようにします。
pred_file = tempfile() r$predict(test_set, out_file(pred_file)) print(scan(pred_file, n = 10))
メモリ上で行うには、次のようにします。
pred_rvec = r$predict(test_set, out_memory()) head(pred_rvec, 10)
> head(pred_rvec, 10)
[1] 3.851235 3.435712 2.890148 3.185432 2.307347 3.497945 2.890176 3.001640 1.998869
[10] 3.327145
モデルの性能を学習データを使ってみてみます。
library(caret) pred_rvec = r$predict(train_set, out_memory()) dat <- read.csv("smalltrain.txt", sep=" ", header = FALSE) MAE(round(pred_rvec,0), dat[,3]) RMSE(round(pred_rvec,0), dat[,3]) R2(round(pred_rvec,0), dat[,3], form = "traditional")
> MAE(round(pred_rvec,0), dat[,3])
[1] 0.3471
> RMSE(round(pred_rvec,0), dat[,3])
[1] 0.5990826
> R2(round(pred_rvec,0), dat[,3], form = "traditional")
[1] 0.4890019
どうなんでしょう?あまりよくないような。。。
4. さいごに
まだまだよくわからないので、これから勉強します。