surpriseに基づく2つの推奨アルゴリズムの実現


surpriseはscikitシリーズの1つであり、簡単で使いやすく、基礎アルゴリズム、協同フィルタリングアルゴリズム、マトリクス分解(隠語義モデル)など、多くの推奨アルゴリズムをサポートしています.surpriseドキュメント:https://surprise.readthedocs.io/en/stable/getting_started.htmlデータセット:movielens-100 kデータセットデータセットダウンロードアドレス:http://files.grouplens.org/datasets/movielens
1.近傍ベースの方法(協同フィルタリング):user-based,item-based.
import os, io, collections
import pandas as pd
from surprise import Dataset, KNNBaseline, SVD, accuracy, Reader
from surprise.model_selection import cross_validate, train_test_split

#       

#   movielens-100k   ,              ,         。
data = Dataset.load_builtin('ml-100k')

#         #      path to dataset filefile_path = os.path.expanduser('~/.surprise_data/ml-100k/ml-100k/u.data')#   Reader      ,  line_format    (  ),  sep     reader = Reader(line_format='user item rating timestamp', sep='\t')#      data = Dataset.load_from_file(file_path, reader=reader)

data_df = pd.read_csv(file_path, sep='\t', header=None, names=['user','item','rating','timestamp'])
item_df = pd.read_csv(os.path.expanduser('~/.surprise_data/ml-100k/ml-100k/u.item'), sep='|', encoding='ISO-8859-1', header=None, names=['mid','mtitle']+[x for x in range(22)])
#            
data_df = data_df.astype(str)
item_df = item_df.astype(str)
#   id        
item_dict = { item_df.loc[x, 'mid']: item_df.loc[x, 'mtitle'] for x in range(len(item_df)) }

1.1ユーザーベースの共同フィルタリングアルゴリズム:
#                  
# user-based
user_based_sim_option = {'name': 'pearson_baseline', 'user_based': True}
# item-based
item_based_sim_option = {'name': 'pearson_baseline', 'user_based': False}

#      n   ,           ,   10         ,                 。
def get_similar_users_recommendations(uid, n=10):
    #      ,          
    trainset = data.build_full_trainset()
    #              
    algo = KNNBaseline(sim_option = user_based_sim_option)
    #      
    algo.fit(trainset)
    #    id     id
    inner_id = algo.trainset.to_inner_uid(uid)
    #   get_neighbors    10       
    neighbors = algo.get_neighbors(inner_id, k=10)
    neighbors_uid = ( algo.trainset.to_raw_uid(x) for x in neighbors )
    recommendations = set()
    #    5         
    for user in neighbors_uid:
        if len(recommendations) > n:
            break
        item = data_df[data_df['user']==user]
        item = item[item['rating']=='5']['item']
        for i in item:
            recommendations.add(item_dict[i])
    print('
recommendations for user %s:') for i, j in enumerate(list(recommendations)): if i >= 10: break print(j)

テスト、idが1のユーザーに10本の映画を推薦します:
get_similar_users_recommendations('1', 10)

出力結果は次のとおりです:基于surprise的两种推荐算法的实现_第1张图片
1.2物品に基づく協同フィルタリングアルゴリズム:
#           n   ,           。
def get_similar_items(iid, n = 10):
    trainset = data.build_full_trainset()
    algo = KNNBaseline(sim_option = item_based_sim_option)
    algo.fit(trainset)
    inner_id = algo.trainset.to_inner_iid(iid)
    #   get_neighbors    n       
    neighbors = algo.get_neighbors(inner_id, k=n)
    neighbors_iid = ( algo.trainset.to_raw_iid(x) for x in neighbors )
    recommendations = [ item_dict[x] for x in neighbors_iid ]
    print('
ten movies most similar to the %s:' % item_dict[iid]) for i in recommendations: print(i)

idが2の映画(GoldenEye(1995))に最も類似度の高い10本の映画を与えた.
get_similar_items('2')

推奨結果:基于surprise的两种推荐算法的实现_第2张图片
2.隠語的意味に基づく方法(行列分解):SVD.
# SVD  ,            ,          n       。
def get_recommendations_dict(n = 10):
    trainset = data.build_full_trainset()
    #    ,       
    testset = trainset.build_anti_testset()
    #   SVD  
    algo = SVD()
    algo.fit(trainset)
    #   
    predictions = algo.test(testset)
    #      
    print("RMSE: %s" % accuracy.rmse(predictions))

    #                  
    user_recommendations = collections.defaultdict(list)
    for uid, iid, r_ui, est, details in predictions:
        user_recommendations[uid].append((iid, est))
    for uid, user_ratings in user_recommendations.items():
        user_ratings.sort(key = lambda x: x[1], reverse=True)
        user_recommendations[uid] = user_ratings[:n]
    return user_recommendations

#            10   
user_recommendations = get_recommendations_dict(10)

#            
def rec_for_user(uid):
    print("recommendations for user %s:" % uid)
    #[ item_dict[x[0]] for x in user_recommendations[uid] ]
    for i in user_recommendations[uid]:
        print(item_dict[i[0]])

idが1のユーザーに10本の映画を推薦します.
rec_for_user('1') 

出力結果は次のとおりです:基于surprise的两种推荐算法的实现_第3张图片
補足:GridSearchCVの使用
from surprise import SVD
from surprise import Dataset
from surprise.model_selection import GridSearchCV

# Use movielens-100K
data = Dataset.load_builtin('ml-100k')

param_grid = {'n_epochs': [5, 10], 'lr_all': [0.002, 0.005],
              'reg_all': [0.4, 0.6]}
gs = GridSearchCV(SVD, param_grid, measures=['rmse', 'mae'], cv=3)

gs.fit(data)

# best RMSE score
print(gs.best_score['rmse'])

# combination of parameters that gave the best RMSE score
print(gs.best_params['rmse'])

出力結果0.961300130118{‘n_epochs’:10,‘lr_all’:0.005,‘reg_all’:0.4}