🕌

surpriseにある全レコメンドモデルを試す

2022/07/26に公開

surpriseとは

surpriseとは明示的な評価データ(explicit feedback)を処理する推薦システムを構築/分析するためのPythonライブラリです。
※暗黙の評価(implicit feedback)やコンテンツベースの推薦をサポートしていません。

この記事では、surpriseライブラリを使って用意されている全てのレコメンドモデルを試します。この結果をもとに、どんなレコメンドモデルが優勢なのか、あるいは実運用しやすいのか理解が深まるのではないかと思います。

事前準備

本記事の実装は、Google Colaboratory上で行います。
まずはsurpriseライブラリをインストールします。

!pip install scikit-surprise

事前に必要なライブラリをインポートします。

import time
import pandas as pd
import numpy as np
from surprise import Dataset, Reader, accuracy
from surprise.model_selection import train_test_split
from surprise import (
    NormalPredictor, BaselineOnly, KNNBasic, KNNWithMeans, KNNWithZScore, 
    KNNBaseline, SVD, SVDpp, NMF, SlopeOne, CoClustering
)

datasetの用意

このdatasetモジュールは、Datasetデータセットの管理に使用されるクラスとその他のサブクラスを定義します。
組み込みでmovielens-100kとmovielens-1Mのデータセットが用意されているので、load_builtinメソッドを利用することで、簡単に読み込むことができます。

data_ml_100k = Dataset.load_builtin(name=u'ml-100k', prompt=False)
data_ml_1m = Dataset.load_builtin(name=u'ml-1m', prompt=False)

実運用を想定して公式サイトからmovielens-100kのデータセットをダウンロードし、カスタムデータとしてDatasetを作成します。
pandas.DataFrameからロードできるload_from_dfを利用します。またこのメソッドを利用するためには、あらかじめReaderクラスで評価スケール(rating_scale)を定義する必要があります。

ML100K_URL = 'http://files.grouplens.org/datasets/movielens/ml-100k/u.data'
df_custom = pd.read_csv(
    ML100K_URL, names=["userid", "itemid", "rating", "timestamp"], sep="\t"
)
reader = Reader(rating_scale=(1, 5))
data_custom = Dataset.load_from_df(
    df_custom[["userid", "itemid", "rating"]], reader
)

データの分割方法

学習データとテストデータを8:2に分割します。(本記事ではこちらのデータセットを使います。)

trainset, testset = train_test_split(data_custom, test_size=.2)

分割せずに学習とテストで同じデータセットを使うこともできます。

trainset_all = data_custom.build_full_trainset()
testset_all = trainset_all.build_testset()

SVDモデルを試す

SVDモデルを試します。fit関数で学習し、test関数で推論します。連結して1文で書くこともできます。最後に4つの指標(RMSE,MSE,MAE,FCP)で評価します。

algo = SVD()
algo.fit(trainset)
pred = algo.test(testset)
#pred = algo.fit(trainset_all).test(testset_all)
accuracy.rmse(pred),accuracy.mse(pred),accuracy.mae(pred),accuracy.fcp(pred)

出力結果:

RMSE: 0.9388
MSE: 0.8813
MAE:  0.7421
FCP:  0.6948

surpriseにある全てのレコメンドモデルを試す

アルゴリズムの解説

surpriseには11個のアルゴリズムが用意されています。簡単な解説を載せますが、詳しく知りたい方は各自でお調べください。

アルゴリズム 概要
NormalPredictor 正常なトレーニングセットの分布に基づいてランダムな評価を予測するアルゴリズム。
BaselineOnly 特定のユーザーとアイテムのベースライン見積もりを予測するアルゴリズム。
KNNBasic 基本的な協調フィルタリングアルゴリズム。
KNNWithMeans 各ユーザーの平均評価を考慮した、基本的な協調フィルタリングアルゴリズム。
KNNWithZScore 各ユーザーのZスコア(データ群の該当する数値から平均値を引いて、標準偏差で割る)の正規化を考慮した基本的な協調フィルタリングアルゴリズム。
KNNBaseline ベースライン評価を考慮した基本的な協調フィルタリングアルゴリズム。
SVD 特異値分解。
SVDpp SVD++アルゴリズム、SVDを拡張して暗黙の評価を考慮する。
NMF 非負行列因子分解に基づく協調フィルタリングアルゴリズム。
SlopeOne シンプルでありながら正確な協調フィルタリングアルゴリズム。
CoClustering 共同クラスタリングに基づく協調フィルタリングアルゴリズム。

評価方法

surpriseには、RMSE, MSE, MAE, FCPと4種類のオフライン評価手法が予め用意されています。(詳しく知りたい方は、以下略)

surpriseにある全レコメンドモデルを試すを実装する

algo_list = {
    "NormalPredictor" : NormalPredictor, 
    "BaselineOnly" : BaselineOnly, 
    "KNNBasic" : KNNBasic, 
    "KNNWithMeans" : KNNWithMeans, 
    "KNNWithZScore" : KNNWithZScore, 
    "KNNBaseline" : KNNBaseline, 
    "SVD" : SVD, 
    "SVDpp" : SVDpp, 
    "NMF" : NMF, 
    "SlopeOne" : SlopeOne, 
    "CoClustering" : CoClustering
}

11個のレコメンドモデルに対し、4種類のオフライン評価結果と実行時間を測定します。

df_result = pd.DataFrame(columns=["algo","rmse","mse","mae","fcp","time"])
for key, value in algo_list.items():
    start = time.time()
    algo = value()
    pred = algo.fit(trainset).test(testset)
    end = time.time() - start
    record = pd.Series(
        [key, accuracy.rmse(pred), accuracy.mse(pred), accuracy.mae(pred), 
        accuracy.fcp(pred), end], index=df_result.columns
    )
    df_result = df_result.append(record, ignore_index=True)

df_result

出力結果:

algo rmse mse mae fcp time
NormalPredictor 1.51978 2.30972 1.21849 0.49576 2.38026
BaselineOnly 0.92274 0.85146 0.73127 0.71898 1.12585
KNNBasic 0.77807 0.60539 0.60821 0.82728 19.30517
KNNWithMeans 0.77279 0.59720 0.60449 0.83454 20.06934
KNNWithZScore 0.76543 0.58589 0.59611 0.82940 21.54288
KNNBaseline 0.75132 0.56448 0.58576 0.82631 24.56300
SVD 0.67199 0.45156 0.53195 0.88548 6.83804
SVDpp 0.75998 0.57757 0.59878 0.82622 277.93482
NMF 0.81857 0.67006 0.64244 0.78013 7.11345
SlopeOne 0.85808 0.73631 0.67414 0.77514 12.66350
CoClustering 0.91066 0.82930 0.71226 0.73465 2.96320

SVDがスコアも良く、実行時間も短いという結果になりました。

フィシルコム

Discussion