推荐系统如何开发
推荐系统实现了基于协同过滤的推荐功能
支持两种推荐模式:
- 基于用户的协同过滤(寻找相似用户喜欢的物品)
- 基于物品的协同过滤(寻找相似物品)
主要功能:
- 数据加载(支持自定义数据或内置的 MovieLens 数据集)
- 模型训练
- 模型评估(计算 RMSE 和 MAE 指标)
- 为指定用户生成推荐列表
使用前需要安装依赖库:
pip install surprise pandas numpy
可以通过修改
sim_options
参数来调整相似度计算方法,支持余弦相似度、皮尔逊相关系数等多种方式。
import numpy as np
import pandas as pd
from surprise import Dataset, Reader, KNNBasic
from surprise.model_selection import train_test_split
from surprise import accuracy
class SimpleRecommender:
def __init__(self, sim_options={'name': 'cosine', 'user_based': True}):
"""
初始化推荐系统
:param sim_options: 相似度计算选项,默认为基于用户的余弦相似度
"""
self.sim_options = sim_options
self.model = None
self.trainset = None
self.testset = None
def load_data(self, data=None, rating_scale=(1, 5)):
"""
加载数据
:param data: 包含user_id, item_id, rating的DataFrame
:param rating_scale: 评分范围
"""
# 如果没有提供数据,使用内置的movielens-100k数据集
if data is None:
self.data = Dataset.load_builtin('ml-100k')
else:
# 验证数据格式
required_columns = ['user_id', 'item_id', 'rating']
if not set(required_columns).issubset(data.columns):
raise ValueError("数据必须包含'user_id', 'item_id', 'rating'列")
reader = Reader(rating_scale=rating_scale)
self.data = Dataset.load_from_df(data[required_columns], reader)
# 分割训练集和测试集
self.trainset, self.testset = train_test_split(self.data, test_size=0.25)
def train(self):
"""训练推荐模型"""
self.model = KNNBasic(sim_options=self.sim_options)
self.model.fit(self.trainset)
print("模型训练完成!")
def evaluate(self):
"""评估模型性能"""
if self.model is None:
raise ValueError("请先训练模型")
predictions = self.model.test(self.testset)
rmse = accuracy.rmse(predictions)
mae = accuracy.mae(predictions)
return rmse, mae
def get_recommendations(self, user_id, n=5):
"""
为指定用户推荐物品
:param user_id: 用户ID
:param n: 推荐物品数量
:return: 推荐的物品ID列表及预测评分
"""
if self.model is None:
raise ValueError("请先训练模型")
# 获取所有物品ID
all_items = set(self.trainset.all_items())
# 获取用户已评分的物品
user_items = set([item for (user, item, _) in self.trainset.all_ratings()
if user == self.trainset.to_inner_uid(user_id)])
# 找出用户未评分的物品
items_to_predict = all_items - user_items
# 预测评分
predictions = []
for item in items_to_predict:
inner_item_id = self.trainset.to_raw_iid(item)
pred = self.model.predict(user_id, inner_item_id)
predictions.append((inner_item_id, pred.est))
# 按预测评分排序并返回前n个
predictions.sort(key=lambda x: x[1], reverse=True)
return predictions[:n]
# 示例用法
if __name__ == "__main__":
# 创建推荐系统实例 - 基于用户的协同过滤
user_based_recommender = SimpleRecommender(
sim_options={'name': 'cosine', 'user_based': True}
)
# 加载数据
print("加载数据中...")
user_based_recommender.load_data()
# 训练模型
print("训练模型中...")
user_based_recommender.train()
# 评估模型
print("\n评估模型性能:")
user_based_recommender.evaluate()
# 为用户196推荐5个物品
user_id = '196'
print(f"\n为用户 {user_id} 推荐的物品:")
recommendations = user_based_recommender.get_recommendations(user_id, n=5)
for i, (item_id, rating) in enumerate(recommendations, 1):
print(f"{i}. 物品ID: {item_id}, 预测评分: {rating:.2f}")
# 也可以创建基于物品的协同过滤推荐系统
print("\n----- 基于物品的推荐 -----")
item_based_recommender = SimpleRecommender(
sim_options={'name': 'pearson_baseline', 'user_based': False}
)
item_based_recommender.load_data()
item_based_recommender.train()
print(f"为用户 {user_id} 推荐的物品:")
recommendations = item_based_recommender.get_recommendations(user_id, n=5)
for i, (item_id, rating) in enumerate(recommendations, 1):
print(f"{i}. 物品ID: {item_id}, 预测评分: {rating:.2f}")