推荐系统已经成为我们日常生活中不可或缺的一部分,从流媒体平台上的电影推荐到电子商务网站上的产品推荐无处不在。在这里,我们将探索如何使用Surprise库以及融入一点基于内容的过滤来构建一个混合推荐系统。
推荐系统概述
推荐系统大致分为以下几类:
在这篇文章中,我们将演示如何:
Surprise
Surprise是基于“scikit的Python”库之一,用于利用显式评分数据开发推荐系统。对于熟悉使用scikit系列库(如scikit-learn)的开发人员来说,Surprise相对容易上手。方便地是,Surprise提供了多种算法来开发协同过滤推荐系统,从基于内存的方法(即K近邻或KNN)到基于模型的方法(即奇异值分解或SVD)。
TF-IDF(词频-逆文档频率)
TF-IDF是一种数值统计量,它反映了单个词语在一个文档中的重要性,相对于一个文档集合(即语料库)而言。TF-IDF背后的思想是量化一个词语在文档中的重要性,这种重要性是通过该词在文档中的频率以及它在多个文档中的稀有程度来衡量的。
安装
按照以下步骤安装必要的库:
安装pandas:
这个库用于数据操作和分析。
pip install pandas
安装scikit-surprise:
Surprise是一个用于构建和分析推荐系统的库。
pip install scikit-surprise
安装scikit-learn:
sklearn库提供了机器学习工具,包括TF-IDF向量化和相似性计算。
pip install scikit-learn
解决scikit-surprise安装问题:安装Microsoft Build Tools
如果在安装scikit-surprise库时遇到问题,很可能是由于缺少编译某些组件所需的构建工具。请按照以下步骤解决此问题:
第一步:安装Microsoft Build Tools
1. 下载Microsoft Build Tools:
访问Microsoft Build Tools for Visual Studio页面并下载安装程序。
2. 运行安装程序:
在安装过程中,选择“C++构建工具”工作负载,并包含Windows 10 SDK和适用于Windows组件的C++ CMake工具。
3. 完成安装:
点击安装按钮,等待安装过程完成。
第二步:验证安装
1. 安装完成后,重启你的终端或命令提示符。
2. 再次尝试安装scikit-surprise库:
pip install scikit-surprise
第一步:加载和预处理数据
我们将使用MovieLens 100k数据集,该数据集包含用户对电影的评分以及电影的元数据,如标题和类型。
import pandas as pd
from surprise import Dataset, Reader
# Load ratings data
ratings_data = pd.read_csv(“ml-100k/u.data”, sep=”\t”, names=[“user_id”,
“item_id”, “rating”, “timestamp”])
# Load movies data
movies_data = pd.read_csv(“ml-100k/u.item”, sep=”|”, names=[“movie_id”,
“title”, “genres”], encoding=”latin-1", usecols=[0, 1, 2])
# Merge and clean data
ratings_data = ratings_data.merge(movies_data, left_on=”item_id”,
right_on=”movie_id”)[[“user_id”, “movie_id”, “rating”]]
Step 2: Collaborative Filtering with Surprise
We’ll use the SVD (Singular Value Decomposition) algorithm and optimize its
hyperparameters using GridSearchCV.
from surprise import SVD
from surprise.model_selection import GridSearchCV
# Prepare data for Surprise
reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(ratings_data[[“user_id”, “movie_id”, “rating”]],
reader)
# Define hyperparameter grid
param_grid = {“n_factors”: [50, 100], “reg_all”: [0.02, 0.1], “lr_all”:
[0.005, 0.01]}
# Optimize SVD using GridSearchCV
gs = GridSearchCV(SVD, param_grid, measures=[“rmse”], cv=3)
gs.fit(data)
# Train the best model
algo = gs.best_estimator[“rmse”]
trainset = data.build_full_trainset()
algo.fit(trainset)
第三步:使用TF-IDF进行基于内容的过滤
基于内容的过滤侧重于项目的元数据。我们将使用TF-IDF(词频-逆文档频率)来分析类型,并计算电影之间的相似度得分。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import linear_kernel
# Build TF-IDF matrix for genres
movies_data[“genres”] = movies_data[“genres”].fillna(“”) # Handle missing genres
tfidf = TfidfVectorizer(stop_words=”english”)
tfidf_matrix = tfidf.fit_transform(movies_data[“genres”])
# Compute content similarity matrix
content_sim_matrix = linear_kernel(tfidf_matrix, tfidf_matrix)
第四步:混合推荐系统
混合系统结合了协同过滤和基于内容的过滤。通过参数alpha对这两种方法的得分进行加权。
def get_hybrid_recommendations(user_id, algo, n=5, alpha=0.7):
“””
Hybrid recommendations combining collaborative filtering and
content-based filtering.
:param user_id: User ID
:param algo: Trained collaborative filtering algorithm
:param n: Number of recommendations
:param alpha: Weight for collaborative filtering (0 <= alpha <= 1)
:return: Top-N recommended movies
“””
# Get collaborative filtering predictions
all_movie_ids = ratings_data[“movie_id”].unique()
watched_movies = ratings_data[ratings_data[“user_id”] == user_id][“movie_id”]
cf_predictions = {
movie_id: algo.predict(user_id, movie_id).est
for movie_id in all_movie_ids if movie_id not in watched_movies.values
}
# Get content-based similarity scores
cb_predictions = {}
user_watched_movie_ids = watched_movies.values
for movie_id in all_movie_ids:
if movie_id not in user_watched_movie_ids:
content_scores = [content_sim_matrix[movie_id — 1, watched_id — 1] for
watched_id in user_watched_movie_ids]
# Scale CB scores to match CF rating scale (1 to 5)
cb_predictions[movie_id] = (sum(content_scores) / len(content_scores)
if content_scores else 0.0) * 5
# Combine collaborative and content-based scores
hybrid_scores = {
movie_id: alpha * cf_predictions.get(movie_id, 0) + (1 — alpha) *
cb_predictions.get(movie_id, 0)
for movie_id in all_movie_ids if movie_id not in watched_movies.values
}
# Get top-N recommendations
top_n_movies = sorted(hybrid_scores.items(), key=lambda x: x[1], reverse=True)[:n]
recommended_movies = [(movies_data[movies_data[“movie_id”] == movie_id][“title”].values[0], score)
for movie_id, score in top_n_movies]
return recommended_movies
第五步:生成推荐
最后,我们将通过为特定用户生成推荐来测试混合系统。
# Example usage
user_id = 1
recommended_movies = get_hybrid_recommendations(user_id, algo, n=5, alpha=0.7)
print(f”Top 5 hybrid recommendations for User {user_id}:”)
for idx, (movie, score) in enumerate(recommended_movies, 1):
print(f”{idx}. {movie} (Score: {score:.2f})”)
Sample Output:
Top 5 hybrid recommendations for User 1:
1. Schindler’s List (1993) (Score: 3.46)
2. L.A. Confidential (1997) (Score: 3.42)
3. Once Were Warriors (1994) (Score: 3.41)
4. Leaving Las Vegas (1995) (Score: 3.40)
5. Some Folks Call It a Sling Blade (1993) (Score: 3.38)
结论
我们演示了如何结合协同过滤(使用Surprise)和基于内容的过滤(使用TF-IDF)来构建一个混合推荐系统。混合方法解决了单一方法的局限性,并提供了更稳健的推荐。