Python推荐系统库——Surprise

本文介绍Surprise库在推荐系统中的应用,包括加载数据集、算法选择、模型评估及调参等关键步骤,并通过电影和音乐数据集示例展示具体操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@ 2018-01-24

Surprise

在推荐系统的建模过程中,我们将用到python库 Surprise(Simple Python RecommendatIon System Engine),是scikit系列中的一个(很多同学用过scikit-learn和scikit-image等库)。Surprise的User Guide有详细的解释和说明

简单易用,同时支持多种推荐算法:

算法类名说明
random_pred.NormalPredictorAlgorithm predicting a random rating based on the distribution of the training set, which is assumed to be normal.
baseline_only.BaselineOnlyAlgorithm predicting the baseline estimate for given user and item.
knns.KNNBasicA basic collaborative filtering algorithm.
knns.KNNWithMeansA basic collaborative filtering algorithm, taking into account the mean ratings of each user.
knns.KNNBaselineA basic collaborative filtering algorithm taking into account a baseline rating.
matrix_factorization.SVDThe famous SVD algorithm, as popularized by Simon Funk during the Netflix Prize.
matrix_factorization.SVDppThe SVD++ algorithm, an extension of SVD taking into account implicit ratings.
matrix_factorization.NMFA collaborative filtering algorithm based on Non-negative Matrix Factorization.
slope_one.SlopeOneA simple yet accurate collaborative filtering algorithm.
co_clustering.CoClusteringA collaborative filtering algorithm based on co-clustering.

其中基于近邻的方法(协同过滤)可以设定不同的度量准则。

相似度度量标准度量标准说明
cosineCompute the cosine similarity between all pairs of users (or items).
msdCompute the Mean Squared Difference similarity between all pairs of users (or items).
pearsonCompute the Pearson correlation coefficient between all pairs of users (or items).
pearson_baselineCompute the (shrunk) Pearson correlation coefficient between all pairs of users (or items) using baselines for centering instead of means.

支持不同的评估准则

评估准则准则说明
rmseCompute RMSE (Root Mean Squared Error).
maeCompute MAE (Mean Absolute Error).
fcpCompute FCP (Fraction of Concordant Pairs).

使用示例

基本使用方法如下
# 可以使用上面提到的各种推荐系统算法
from surprise import SVD
from surprise import Dataset
from surprise import evaluate, print_perf

# 默认载入movielens数据集,会提示是否下载这个数据集,这是非常经典的公开推荐系统数据集——MovieLens数据集之一
data = Dataset.load_builtin('ml-100k')
# k折交叉验证(k=3)
data.split(n_folds=3)
# 试一把SVD矩阵分解
algo = SVD()
# 在数据集上测试一下效果
perf = evaluate(algo, data, measures=['RMSE', 'MAE'])
#输出结果
print_perf(perf)
载入自己的数据集方法
# 指定文件所在路径
file_path = os.path.expanduser('~/.surprise_data/ml-100k/ml-100k/u.data')
# 告诉文本阅读器,文本的格式是怎么样的
reader = Reader(line_format='user item rating timestamp', sep='\t')
# 加载数据
data = Dataset.load_from_file(file_path, reader=reader)
# 手动切分成5折(方便交叉验证)
data.split(n_folds=5)
算法调参(让推荐系统有更好的效果)

这里实现的算法用到的算法无外乎也是SGD等,因此也有一些超参数会影响最后的结果,我们同样可以用sklearn中常用到的网格搜索交叉验证(GridSearchCV)来选择最优的参数。简单的例子如下所示:

# 定义好需要优选的参数网格
param_grid = {'n_epochs': [5, 10], 'lr_all': [0.002, 0.005],
              'reg_all': [0.4, 0.6]}
# 使用网格搜索交叉验证
grid_search = GridSearch(SVD, param_grid, measures=['RMSE', 'FCP'])
# 在数据集上找到最好的参数
data = Dataset.load_builtin('ml-100k')
data.split(n_folds=3)
grid_search.evaluate(data)
# 输出调优的参数组 
# 输出最好的RMSE结果
print(grid_search.best_score['RMSE'])
# >>> 0.96117566386

# 输出对应最好的RMSE结果的参数
print(grid_search.best_params['RMSE'])
# >>> {'reg_all': 0.4, 'lr_all': 0.005, 'n_epochs': 10}

# 最好的FCP得分
print(grid_search.best_score['FCP'])
# >>> 0.702279736531

# 对应最高FCP得分的参数
print(grid_search.best_params['FCP'])
# >>> {'reg_all': 0.6, 'lr_all': 0.005, 'n_epochs': 10}

在自己的数据集上训练模型

首先载入数据

import os
from surprise import Reader, Dataset
# 指定文件路径
file_path = os.path.expanduser('./popular_music_suprise_format.txt')
# 指定文件格式
reader = Reader(line_format='user item rating timestamp', sep=',')
# 从文件读取数据
music_data = Dataset.load_from_file(file_path, reader=reader)
# 分成5折
music_data.split(n_folds=5)

使用不同的推荐系统算法进行建模比较

### 使用NormalPredictor
from surprise import NormalPredictor, evaluate
algo = NormalPredictor()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用BaselineOnly
from surprise import BaselineOnly, evaluate
algo = BaselineOnly()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用基础版协同过滤
from surprise import KNNBasic, evaluate
algo = KNNBasic()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用均值协同过滤
from surprise import KNNWithMeans, evaluate
algo = KNNWithMeans()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用协同过滤baseline
from surprise import KNNBaseline, evaluate
algo = KNNBaseline()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用SVD
from surprise import SVD, evaluate
algo = SVD()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用SVD++
from surprise import SVDpp, evaluate
algo = SVDpp()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])

### 使用NMF
from surprise import NMF
algo = NMF()
perf = evaluate(algo, music_data, measures=['RMSE', 'MAE'])
print_perf(perf)

建模和存储模型

1.用协同过滤构建模型并进行预测

1.1 movielens的例子
# 可以使用上面提到的各种推荐系统算法
from surprise import SVD
from surprise import Dataset
from surprise import evaluate, print_perf

# 默认载入movielens数据集
data = Dataset.load_builtin('ml-100k')
# k折交叉验证(k=3)
data.split(n_folds=3)
# 试一把SVD矩阵分解
algo = SVD()
# 在数据集上测试一下效果
perf = evaluate(algo, data, measures=['RMSE', 'MAE'])
#输出结果
print_perf(perf)

"""
以下的程序段告诉大家如何在协同过滤算法建模以后,根据一个item取回相似度最高的item,主要是用到algo.get_neighbors()这个函数
"""

from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
import os
import io

from surprise import KNNBaseline
from surprise import Dataset


def read_item_names():
    """
    获取电影名到电影id 和 电影id到电影名的映射
    """

    file_name = (os.path.expanduser('~') +
                 '/.surprise_data/ml-100k/ml-100k/u.item')
    rid_to_name = {}
    name_to_rid = {}
    with io.open(file_name, 'r', encoding='ISO-8859-1') as f:
        for line in f:
            line = line.split('|')
            rid_to_name[line[0]] = line[1]
            name_to_rid[line[1]] = line[0]

    return rid_to_name, name_to_rid


# 首先,用算法计算相互间的相似度
data = Dataset.load_builtin('ml-100k')
trainset = data.build_full_trainset()
sim_options = {'name': 'pearson_baseline', 'user_based': False}
algo = KNNBaseline(sim_options=sim_options)
algo.train(trainset)

# 获取电影名到电影id 和 电影id到电影名的映射
rid_to_name, name_to_rid = read_item_names()

# Retieve inner id of the movie Toy Story
toy_story_raw_id = name_to_rid['Toy Story (1995)']
toy_story_inner_id = algo.trainset.to_inner_iid(toy_story_raw_id)

# Retrieve inner ids of the nearest neighbors of Toy Story.
toy_story_neighbors = algo.get_neighbors(toy_story_inner_id, k=10)

# Convert inner ids of the neighbors into names.
toy_story_neighbors = (algo.trainset.to_raw_iid(inner_id)
                       for inner_id in toy_story_neighbors)
toy_story_neighbors = (rid_to_name[rid]
                       for rid in toy_story_neighbors)

print()
print('The 10 nearest neighbors of Toy Story are:')
for movie in toy_story_neighbors:
    print(movie)
1.2 音乐预测的例子
from __future__ import (absolute_import, division, print_function, unicode_literals)
import os
import io

from surprise import KNNBaseline
from surprise import Dataset

import cPickle as pickle
# 重建歌单id到歌单名的映射字典
id_name_dic = pickle.load(open("popular_playlist.pkl","rb"))
print("加载歌单id到歌单名的映射字典完成...")
# 重建歌单名到歌单id的映射字典
name_id_dic = {}
for playlist_id in id_name_dic:
    name_id_dic[id_name_dic[playlist_id]] = playlist_id
print("加载歌单名到歌单id的映射字典完成...")


file_path = os.path.expanduser('./popular_music_suprise_format.txt')
# 指定文件格式
reader = Reader(line_format='user item rating timestamp', sep=',')
# 从文件读取数据
music_data = Dataset.load_from_file(file_path, reader=reader)
# 计算歌曲和歌曲之间的相似度
print("构建数据集...")
trainset = music_data.build_full_trainset()
#sim_options = {'name': 'pearson_baseline', 'user_based': False}
  • current_playlist => 歌单名
  • playlist_id => 歌单id(网易给的歌单id)
  • playlist_inner_id => 内部id(对所有歌单id重新从1开始编码)
print("开始训练模型...")
#sim_options = {'user_based': False}
#algo = KNNBaseline(sim_options=sim_options)
algo = KNNBaseline()
algo.train(trainset)

current_playlist = name_id_dic.keys()[39]
print(current_playlist)

# 取出近邻
playlist_id = name_id_dic[current_playlist]
print(playlist_id)
playlist_inner_id = algo.trainset.to_inner_uid(playlist_id)
print(playlist_inner_id)

playlist_neighbors = algo.get_neighbors(playlist_inner_id, k=10)

# 把歌曲id转成歌曲名字
playlist_neighbors = (algo.trainset.to_raw_uid(inner_id)
                       for inner_id in playlist_neighbors)
playlist_neighbors = (id_name_dic[playlist_id]
                       for playlist_id in playlist_neighbors)

print()
print("和歌单 《", current_playlist, "》 最接近的10个歌单为:\n")
for playlist in playlist_neighbors:
    print(playlist)

2.用SVD矩阵分解进行预测

### 使用SVD++
from surprise import SVDpp, evaluate
from surprise import Dataset

file_path = os.path.expanduser('./popular_music_suprise_format.txt')
# 指定文件格式
reader = Reader(line_format='user item rating timestamp', sep=',')
# 从文件读取数据
music_data = Dataset.load_from_file(file_path, reader=reader)
# 构建数据集和建模
algo = SVDpp()
trainset = music_data.build_full_trainset()
algo.train(trainset)
### 基于 Python推荐系统项目示例 在 GitHub 上有许多适合新手学习的开源项目,其中包括基于 Python 实现的推荐系统。这类项目可以帮助开发者理解如何构建个性化推荐算法以及实际应用中的实现细节[^1]。 #### 推荐系统的常见类型 推荐系统通常分为两种主要类型:协同过滤和基于内容的推荐。 - **协同过滤**:通过分析用户行为数据来发现相似用户或物品之间的关系。常见的方法包括基于用户的协同过滤 (User-Based Collaborative Filtering) 和基于物品的协同过滤 (Item-Based Collaborative Filtering)[^2]。 - **基于内容的推荐**:利用物品本身的特征向量计算相似度,并为用户提供与他们过去喜欢的内容类似的推荐项[^3]。 以下是几个典型的基于 Python推荐系统项目: --- ### 1. Surprise —— 协同过滤框架 Surprise 是一个专注于构建推荐系统Python ,支持多种经典的推荐算法,例如 SVD、KNN 等。它提供了简单易用的 API 来加载数据集并训练模型。 ```python from surprise import Dataset, Reader, KNNBasic from surprise.model_selection import cross_validate # 数据读取器 reader = Reader(line_format='user item rating timestamp', sep=',') data = Dataset.load_from_df(ratings[['userId', 'movieId', 'rating']], reader) # 使用 KNN 算法进行建模 algo = KNNBasic() cross_validate(algo, data, measures=['RMSE', 'MAE'], cv=5, verbose=True) ``` 此非常适合初学者快速入门推荐系统的设计与实现。 --- ### 2. MovieLens 数据集 + 自定义推荐引擎 MovieLens 是一个广泛使用的公开数据集,包含大量电影评分记录。许多开发者会结合该数据集创建自己的推荐系统。以下是一个简单的例子: ```python import pandas as pd from sklearn.metrics.pairwise import cosine_similarity # 加载数据 ratings = pd.read_csv('ml-latest-small/ratings.csv') # 构造用户-物品矩阵 pivot_table = ratings.pivot(index='userId', columns='movieId', values='rating').fillna(0) # 计算余弦相似度 similarity_matrix = cosine_similarity(pivot_table.T) def recommend_movies(user_id): user_ratings = pivot_table.loc[user_id].values.reshape(-1, 1) scores = similarity_matrix.dot(user_ratings).flatten() recommended_movie_ids = (-scores).argsort()[:10] return list(recommended_movie_ids) print(recommend_movies(1)) ``` 上述代码展示了如何使用 Pandas 处理数据并通过 Cosine Similarity 方法生成推荐列表。 --- ### 3. TensorFlow Recommenders (TFRS) TensorFlow 提供了一套专门用于构建推荐系统的高级工具 TFRS。它可以轻松集成深度学习模型到推荐流程中,适用于更复杂的场景。 ```python import tensorflow as tf import tensorflow_recommenders as tfrs class MovielensModel(tfrs.models.Model): def __init__(self, unique_user_ids, unique_movie_titles): super().__init__() self.user_embedding = tf.keras.Sequential([ tf.keras.layers.StringLookup(vocabulary=unique_user_ids), tf.keras.layers.Embedding(len(unique_user_ids)+1, embedding_dim) ]) # 定义其他组件... model.compile(optimizer=tf.keras.optimizers.Adagrad()) model.fit(train_data, epochs=num_epochs) ``` 这段代码片段说明了如何借助 TensorFlow 构建端到端的推荐解决方案。 --- ### §相关问题§ 1. 如何评估推荐系统的性能指标? 2. 是否存在更适合处理大规模稀疏矩阵的推荐算法? 3. 在工业界中,推荐系统有哪些主流架构设计模式? 4. 如果想进一步优化推荐效果,可以尝试哪些改进措施? 5. 对于冷启动问题,有哪些有效的解决策略?
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值