JuliaでMatrix Factorizationを実装してPythonと計算速度の比較をしてみたらJuliaのほうが早かった
概要
以前以下の記事でPythonによるMatrix Factorizationを行いました。
これをJuliaでやってみようと言うのが、今回の記事の趣旨です。
そしてJuliaとPythonでMatrix Factorizationの計算速度も比較したところJuliaが早かったので、 その点も最後に示します。
実装
今回使ったJuliaコードとPythonコードは以下です。
データは毎度おなじみのMovie Lensを使います。
モデル部分
Juliaでのモデルは以下のようにmoduleで実装しました。
module MatrixFactorization mutable struct MatrixFactorizationModel K::Int64 alpha::Float64 beta::Float64 n_user::Int64 n_item::Int64 R::Array user_factors::Array item_factors::Array end #学習 function fit(model::MatrixFactorizationModel, n_iter::Int64) model.user_factors = rand(Float64, model.n_user, model.K) model.item_factors = rand(Float64, model.n_item, model.K) for i = 1:n_iter sgd(model) end end #確率的最急降下法 function sgd(model::MatrixFactorizationModel) samples = model.R[shuffle(1:end), :] for i in 1:size(samples)[1] user = samples[i, :][1] item = samples[i, :][2] err = samples[i, :][3] - dot(model.user_factors[user], model.item_factors[item]) model.user_factors[user] += model.alpha * (err * model.item_factors[item] - model.beta * model.user_factors[user]) model.item_factors[item] += model.alpha * (err * model.user_factors[user] - model.beta * model.item_factors[item]) end end #予測 function predict(model::MatrixFactorizationModel, X::Array) rate = zeros(size(X)[1]) for i = 1:size(X)[1] user = X[i, :][1] item = X[i, :][2] rate[i] = dot(model.user_factors[user], model.item_factors[item]) end return rate end end
Pythonでの実装とかなり似たようにしていて、scikit-learn的に使えるようにしています。
次に学習の実施までを見ていきます。
学習の実施
まずはMovie Lensのデータをmoduleに利用できる形まで持っていきます。
using DataFrames using CSV df = CSV.read("data/ml-100k/u.data", header = false, delim = '\t') #配列化 df = Array(df[:, 1:3]) #ユニークユーザー、ユニークアイテム 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, :]
これで学習データと検証データに分割して準備ができました。
以下で学習して、精度検証をします。
#学習 MF = MatrixFactorization.MatrixFactorizationModel(20, 0.01, 0.5, user, item, train_df, [], []) MatrixFactorization.fit(MF, 10) #精度 pred = MatrixFactorization.predict(MF, test_df) #rmse sqrt(mean((pred - test_df[:, 3]).^2))
精度が、
1.0777975155497033
でとりあえず学習はできていそうですね!
計算時間
計算時間は以下のように計測しました。
まずはJuliaは、
function main() MF = MatrixFactorization.MatrixFactorizationModel(20, 0.01, 0.5, user, item, train_df, [], []) MatrixFactorization.fit(MF, 50) end @time main()
となり、結果は、
7.633972 seconds (155.94 M allocations: 3.576 GiB, 32.54% gc time)
という結果になりました。
一方でPythonで独自の実装を行ったものと比較すると(詳しくは上で貼ったコードを見てください)、
import time start = time.time() #Matrix Factorization MF = MatrixFactorization(K = 20, alpha = 0.01, beta = 0.5) MF.fit(train_df, n_user, n_item, n_iter = 50) time.time() - start
で実行し、
75.14610314369202
でした。
Juliaのほうが10倍くらい早いです(すごい!)。
Juliaを真面目に使えるようになろうと思います。
まとめ
今回は、JuliaでMatrix Factorizationを実装して、Pythonで以前実装したものとスピードを比較するところまで行いました。
その結果かなりJuliaのほうが10倍程度早いことがわかりました。
これは個人的にはかなりJuliaを使うモチベーションになりましたので、今後積極的に勉強していこうと思います。
間違い等ありましたらご指摘お願いいたします。