【自作パッケージ】BPMFというJuliaでbayesian probabilistic matrix factorizationができるパッケージを公開しました
概要
タイトルの通りjuliaでbayesian probabilistic matrix factorizationができるBPMFというパッケージを公開しました。
インターフェースはpythonのscikit-learn風でとても使いやすくできたかなと個人的には思います。
そこで今回はこのパッケージに関して紹介していきたいと思います。
アルゴリズムに関して
bayesian probabilistic matrix factorizationの実装には色々なアルゴリズムがあるのですが今回実装したのは2つです。
1. Gibbs sampling
Gibbs samplingはMCMCの手法の一つです。
具体的なアルゴリズムは、以下の論文に書かれている通りの内容です。
https://www.cs.toronto.edu/~amnih/papers/bpmf.pdf
2. Variational inference
Variational inferenceは日本語だと変分推論と呼ばれますが確率分布の近似手法です。
変分推論は最適化問題を解くことで未知の確率分布の近似的な表現を得ることを目標としている手法です*1。
具体的なアルゴリズムは、以下の論文に書かれている通りの内容です。
https://www.cs.uic.edu/~liub/KDD-cup-2007/proceedings/variational-Lim.pdf
ただし、現状ELBO(evidence lower bound)による計算の収束判定部分は実装せず、指定した回数分計算を繰り返すようにしています*2。
パッケージ使い方
ではパッケージ使い方を説明します。
まず以下のようにパッケージを読み込んでダミーのデータを生成します。
using BPMF #data R = [ 0 0 7; 0 1 6; 0 2 7; 0 3 4; 0 4 5; 0 5 4; 1 0 6; 1 1 7; 1 3 4; 1 4 3; 1 5 4; 2 1 3; 2 2 3; 2 3 1; 2 4 1; 3 0 1; 3 1 2; 3 2 2; 3 3 3; 3 4 3; 3 5 4; 4 0 1; 4 2 1; 4 3 2; 4 4 3; 4 5 3; ]
データは1列目にユーザーのID、2列目にアイテムのIDといったイメージで用意してください。
次に学習ですがGibbs sampingの場合は以下です。
β₀ = 2 μ₀ = 0 D = 3 ν₀ = D W₀ = one(zeros(D, D)) α = 2 T = 100 #number of iterations U = [] V = [] N = length(unique(R[:, 1])) M = length(unique(R[:, 2])) #learning gibbs_model = BPMF.GBPMFModel(R, N, M, D, T, U, V, α, β₀, μ₀, ν₀, W₀) BPMF.fit(gibbs_model) #predict new data BPMF.predict(gibbs_model, R, 10) #burn-inとして10個のサンプルは除去
このようにscikit-learn風なインターフェースで使うことができます。
最終行では学習データ自体を予測していますが、予測したいデータを学習データと同じフォーマットで入れればば予測可能です。
Variational inferenceの場合はパラメータの数が異なりますが、データのフォーマットは同様で以下のとおりです。
N = length(unique(R[:, 1])) M = length(unique(R[:, 2])) D = 3 τ² = 1 L = 10 #number of iterations U = [] V = [] σ² = [] ρ² = [] #learning variational_model = BPMF.VBPMFModel(R, N, M, D, L, U, V, τ², σ², ρ²) BPMF.fit(variational_model) #predict new data BPMF.predict(variational_model, R)
予測も同様ですがburn-inがないので若干引数が異なっていますので注意してください。
各種アルゴリズムの精度・速度比較
最後にGibbs samplingとVariational inferenceの精度(RMSE)と速度をMovieLens 100Kのデータセットを用いて比較したいと思います。
それではまず諸々の準備です。
using BPMF using DataFrames using CSV using Random using StatsModels using Statistics using Plots #設定を変えて繰り返し実行するために関数を準備 function gibbs(train_df, test_df, D, t) β₀ = 2 μ₀ = 0 ν₀ = D W₀ = one(zeros(D, D)) α = 2 N = user #ユーザー数 M = item #アイテム数 U = [] V = [] gibbgs_model = BPMF.GBPMFModel(train_df, N, M, D, t, U, V, α, β₀, μ₀, ν₀, W₀) BPMF.fit(gibbgs_model) return sqrt(mean((test_df[:, 3] - BPMF.predict(gibbgs_model, test_df, Int64(ceil(t / 10)))) .^2 )) #RMSE end function variational(train_df, test_df, D, t) N = user M = item τ² = 1 U = [] V = [] σ² = [] ρ² = [] #learning variational_model = BPMF.VBPMFModel(train_df, N, M, D, t, U, V, τ², σ², ρ²) BPMF.fit(variational_model) return sqrt(mean((test_df[:, 3] - BPMF.predict(variational_model, test_df)) .^2 )) #RMSE end
そしてデータの読み込みと学習・検証用にデータを分けます。
#データ読み込み df = CSV.read("../data/ml-100k/u.data", header = false, delim = '\t') #配列化 df = convert(Array{Int64}, df[:, 1:3]) #オフセット idの最小値を0にする df[:, 1, :] = df[:, 1, :] .- 1 df[:, 2, :] = df[:, 2, :] .- 1 #ユニークユーザー、ユニークアイテム user = length(unique(df[:, 1])) item = length(unique(df[:, 2])) #シャッフル df = df[shuffle(1:end), :] #学習データとテストデータ分割 N = size(df)[1] train_size = Int64(N * 0.8) train_df = df[1:train_size, :] test_df = df[train_size:N, :]
そして学習します、今回はiterationの設定を10~30にしたときの比較します。
#計測 x = zeros(1000) loss_gibbs = zeros(1000) loss_variational = zeros(1000) time_gibbs = zeros(1000) time_variational = zeros(1000) for t = 10:30 ind = t - 9 x[ind] = t loss_gibbs[ind], time_gibbs[ind] = @timed gibbs(train_df, test_df, 10, t) loss_variational[ind], time_variational[ind] = @timed variational(train_df, test_df, 10, t) end
精度は以下のグラフの結果になりました。
青がGibbs samplingで赤がVariational inferenceとなりますが、iterationが少ないときはVariational inferenceが精度が良いです。
一方でiterationが多くなるほどGibbs samplingのほうが精度がよくなっています*3。
一般に言われている結果が見られました。
計算にかかった時間は以下のグラフのとおりです。
Variational inferenceのほうがGibbs samplingに比べて同じiterationなら断然早くなっています。
こちらも一般的な結果だと思います。
したがってデータのサイズが大きく、計算時間をあまり取れないような状況であればVariational inferenceが良さそうですが、基本的にはGibbs samplingを使うのがいいのではないかなという個人的な印象です。
まとめ
今回はjuliaでbayesian probabilistic matrix factorizationできるパッケージを紹介しました。
まだまだ改善の余地はあるのですがぜひ使って見ていただき意見をもらえたら嬉しいです。
よろしくお願いします!