Deep Karmaning

技術系の話から日常のことまで色々と書きます

【論文実装】Variational Bayesian Approach to Movie Rating PredictionをJuliaで実装

概要

個人的にBayesianなアプローチとMatrix Factorizationに最近興味を持っています。

そんなわけで今のところ以下のように色々と実験してきました。

rf00.hatenablog.com

rf00.hatenablog.com

rf00.hatenablog.com

その流れで今回はBayesianなMatrix Factorizationを変分推論で行うアルゴリズムをJulia*1で実装してみたいと思います。

変分推論でのアルゴリズムに関しては以下論文で導出されているものを使います。

https://www.cs.uic.edu/~liub/KDD-cup-2007/proceedings/variational-Lim.pdf

実験

実装の細かいところは見ていきませんが、今回の全体のコードは以下になります。

VariationalBayesianProbabilisticMatrixFactorization.ipynb · GitHub

データは毎度おなじみのMovie Lensを使います。

grouplens.org

まずはMovie Lensに入る前に適当なデータで試してみます。

データを生成して、

#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]

#ユニークユーザー、ユニークアイテム
n_user = length(unique(r[:, 1]))
n_item = length(unique(r[:, 2]))

学習データをそのまま予測してみると、

#predict
VBPMF = VariationalBayesianProbabilisticMatrixFactorization.VariationalBayesianProbabilisticMatrixFactorizationModel(r, n_user, n_item, 10, [], [], 1, [], [], 1)
VariationalBayesianProbabilisticMatrixFactorization.fit(VBPMF)
VariationalBayesianProbabilisticMatrixFactorization.predict(VBPMF, r)

こんな感じになり、

26-element Array{Float64,1}:
 6.692476057466172 
 6.1856309538003025
 6.6023995851109225
 3.843760930267997 
 4.368901630969246 
 3.8651527589913917
 5.379784014391833 
 6.080367423692413 
 3.8000648534494146
 3.570123259237677 
 4.132226272977147 
 2.432525435655192 
 2.2979338001075487
 1.385521188507398 
 1.3317745378407813
 1.4525667678497998
 2.3190717457234187
 1.82068120537136  
 2.3566533381545547
 2.4921900542852646
 3.168846326743875 
 1.1256917357867615
 1.288459642477627 
 1.8376837156781873
 2.0115436500847883
 2.458109288645016 

なんとなく学習・予測できてそうです。

次にMovie Lensをやってみます。

using DataFrames
using CSV

#データ読み込み
r = CSV.read("ml-100k/u.data", header = false, delim = '\t')

#配列化
r = convert(Array{Int64}, r[:, 1:3])

#オフセット idの最小値を0にする
r[:, 1, :] = r[:, 1, :] .- 1
r[:, 2, :] = r[:, 2, :] .- 1

#ユニークユーザー、ユニークアイテム
n_user = length(unique(r[:, 1]))
n_item = length(unique(r[:, 2]))

データの準備ができたので、速度計算のための準備をします。

function main()
    VBPMF = VariationalBayesianProbabilisticMatrixFactorization.VariationalBayesianProbabilisticMatrixFactorizationModel(r, n_user, n_item,10, [], [], 1, [], [], 10)
    VariationalBayesianProbabilisticMatrixFactorization.fit(VBPMF)
    sqrt(mean((r[:, 3] - VariationalBayesianProbabilisticMatrixFactorization.predict(VBPMF, r)) .^ 2))
end

速度を確認すると、

@time main()

結果としては、

 26.401632 seconds (148.09 M allocations: 23.299 GiB, 5.14% gc time)

となりなんとなく速い気がします*2

最後に学習データと検証データを分けて精度も確認します。

#学習データとテストデータ分割
N = size(r)[1]
train_size = Int64(N * 0.8)
train_df = r[1:train_size, :]
test_df = r[train_size:N, :]

#predict
VBPMF = VariationalBayesianProbabilisticMatrixFactorization.VariationalBayesianProbabilisticMatrixFactorizationModel(train_df, n_user, n_item,10, [], [], 1, [], [], 10)
VariationalBayesianProbabilisticMatrixFactorization.fit(VBPMF)
sqrt(mean((test_df[:, 3] - VariationalBayesianProbabilisticMatrixFactorization.predict(VBPMF, test_df)) .^ 2))

精度は、

0.9579913656751956

いい感じに学習できてそうです。

まとめ

Bayesian Matrix Factorizationを変分推論で行うアルゴリズムをJuliaで実装してみました。

変分推論で行うことで計算速度の速さはなんとなく実感することができました。

ただちゃんと他のアルゴリズムの場合と比較しないとわからない点も多いと思うので、今後は他のアルゴリズムであるGibbs Sampling等との精度比較や速度比較をできたらと思います。

それでは間違い等ありましたらご指摘お願いいたします。

*1:v1.0.0で実装しています

*2:今後きちんと他のアルゴリズムと比較したいです