本文目录导读:

我来详细介绍Python实现协同过滤推荐系统的几种方法。
基于用户的协同过滤(User-Based CF)
import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity
class UserBasedCF:
def __init__(self, k=5):
self.k = k # 邻居数量
self.user_similarity = None
self.user_ratings = None
self.user_mean = None
def fit(self, ratings_matrix):
"""
ratings_matrix: DataFrame,行是用户,列是物品
"""
self.user_ratings = ratings_matrix
# 计算用户间相似度(余弦相似度)
self.user_similarity = cosine_similarity(ratings_matrix.fillna(0))
# 计算每个用户的平均评分
self.user_mean = ratings_matrix.mean(axis=1)
def predict(self, user_id, item_id):
"""预测用户对物品的评分"""
# 获取该用户的相似度向量
user_sim = self.user_similarity[user_id]
# 找到最相似的k个用户(排除自己)
similar_users = np.argsort(user_sim)[::-1][1:self.k+1]
# 获取这些相似用户对目标物品的评分
item_ratings = self.user_ratings.iloc[similar_users, item_id]
# 过滤掉没有评分的用户
valid_users = similar_users[~item_ratings.isna()]
if len(valid_users) == 0:
return self.user_mean[user_id]
# 计算加权平均评分
weights = user_sim[valid_users]
ratings = self.user_ratings.iloc[valid_users, item_id].values
# 去中心化评分:考虑用户评分偏差
# 预测评分 = 用户平均评分 + 加权评分偏差
predicted = self.user_mean[user_id] + np.sum(weights * (ratings - self.user_mean[valid_users])) / np.sum(weights)
return predicted
def recommend(self, user_id, n_items=5):
"""为用户推荐n个物品"""
# 获取用户未评分的物品
user_ratings = self.user_ratings.iloc[user_id]
unrated_items = user_ratings[user_ratings.isna()].index
# 预测评分
predictions = []
for item_id in unrated_items:
pred = self.predict(user_id, item_id)
predictions.append((item_id, pred))
# 排序并返回top-n
predictions.sort(key=lambda x: x[1], reverse=True)
return predictions[:n_items]
基于物品的协同过滤(Item-Based CF)
class ItemBasedCF:
def __init__(self, k=5):
self.k = k
self.item_similarity = None
self.ratings_matrix = None
def fit(self, ratings_matrix):
"""计算物品间相似度"""
self.ratings_matrix = ratings_matrix
# 转置矩阵,计算物品间的相似度
item_ratings = ratings_matrix.T
self.item_similarity = cosine_similarity(item_ratings.fillna(0))
def predict(self, user_id, item_id):
"""预测用户对物品的评分"""
# 获取用户已评分的物品
user_ratings = self.ratings_matrix.iloc[user_id]
rated_items = user_ratings[~user_ratings.isna()].index
if len(rated_items) == 0:
return 0
# 计算目标物品与用户已评分物品的相似度
item_sims = []
item_ratings = []
for rated_item in rated_items:
sim = self.item_similarity[item_id][rated_item]
if sim > 0:
item_sims.append(sim)
item_ratings.append(user_ratings[rated_item])
if len(item_sims) == 0:
return 0
# 前k个最相似的物品
k = min(self.k, len(item_sims))
top_k_indices = np.argsort(item_sims)[::-1][:k]
# 加权平均
weights = [item_sims[i] for i in top_k_indices]
ratings = [item_ratings[i] for i in top_k_indices]
predicted = np.sum(np.array(weights) * np.array(ratings)) / np.sum(weights)
return predicted
def recommend(self, user_id, n_items=5):
"""为用户推荐物品"""
# 获取用户未评分的物品
user_ratings = self.ratings_matrix.iloc[user_id]
unrated_items = user_ratings[user_ratings.isna()].index
# 预测评分
predictions = []
for item_id in range(len(unrated_items)):
pred = self.predict(user_id, item_id)
predictions.append((unrated_items[item_id], pred))
predictions.sort(key=lambda x: x[1], reverse=True)
return predictions[:n_items]
矩阵分解方法(SVD)
from sklearn.decomposition import TruncatedSVD
from sklearn.preprocessing import StandardScaler
class MatrixFactorizationCF:
def __init__(self, n_factors=50):
self.n_factors = n_factors
self.svd = TruncatedSVD(n_components=n_factors)
self.scaler = StandardScaler()
self.ratings_matrix = None
def fit(self, ratings_matrix):
self.ratings_matrix = ratings_matrix
# 填充缺失值为0
filled_matrix = ratings_matrix.fillna(0)
# 标准化
normalized_matrix = self.scaler.fit_transform(filled_matrix)
# SVD分解
self.user_features = self.svd.fit_transform(normalized_matrix)
self.item_features = self.svd.components_
def predict(self, user_id, item_id):
"""预测评分"""
# 重建评分
user_vec = self.user_features[user_id]
item_vec = self.item_features[:, item_id]
prediction = np.dot(user_vec, item_vec)
# 反标准化
prediction = self.scaler.inverse_transform([[prediction]])[0][0]
return prediction
def recommend(self, user_id, n_items=5):
"""推荐物品"""
predictions = []
for item_id in range(self.ratings_matrix.shape[1]):
if pd.isna(self.ratings_matrix.iloc[user_id, item_id]):
pred = self.predict(user_id, item_id)
predictions.append((item_id, pred))
predictions.sort(key=lambda x: x[1], reverse=True)
return predictions[:n_items]
完整的使用示例
# 创建示例数据
def create_sample_data():
# 用户-物品评分矩阵
data = {
'用户1': {'物品A': 5, '物品B': 3, '物品C': 4, '物品D': 4},
'用户2': {'物品A': 3, '物品B': 1, '物品C': 2, '物品D': 3},
'用户3': {'物品A': 4, '物品B': 3, '物品C': 4, '物品D': 3},
'用户4': {'物品A': 3, '物品B': 3, '物品C': 1, '物品D': 5},
'用户5': {'物品A': 1, '物品B': 5, '物品C': 5, '物品D': 2}
}
df = pd.DataFrame(data).T
df.index.name = '用户'
df.columns.name = '物品'
return df
# 使用示例
if __name__ == "__main__":
# 创建数据
ratings = create_sample_data()
print("用户-物品评分矩阵:")
print(ratings)
print("\n")
# 基于用户的协同过滤
print("=== 基于用户的协同过滤 ===")
ucf = UserBasedCF(k=3)
ucf.fit(ratings)
# 为用户0推荐
recommendations = ucf.recommend(0, n_items=3)
print(f"用户{'用户1'}的推荐结果:")
for item, score in recommendations:
print(f" 推荐物品: {item}, 预测评分: {score:.2f}")
print("\n")
# 基于物品的协同过滤
print("=== 基于物品的协同过滤 ===")
icf = ItemBasedCF(k=3)
icf.fit(ratings)
recommendations = icf.recommend(0, n_items=3)
print(f"用户{'用户1'}的推荐结果:")
for item, score in recommendations:
print(f" 推荐物品: {item}, 预测评分: {score:.2f}")
print("\n")
# 矩阵分解
print("=== 矩阵分解 ===")
mf = MatrixFactorizationCF(n_factors=3)
mf.fit(ratings)
recommendations = mf.recommend(0, n_items=3)
print(f"用户{'用户1'}的推荐结果:")
for item, score in recommendations:
print(f" 推荐物品: {item}, 预测评分: {score:.2f}")
使用Surprise库(推荐)
from surprise import Dataset, Reader, KNNBasic, SVD
from surprise.model_selection import train_test_split
from surprise import accuracy
# 使用Surprise库的高级实现
def surprise_cf_example():
# 准备数据(格式:user, item, rating)
data = {
'user': ['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'D', 'D'],
'item': ['i1', 'i2', 'i3', 'i2', 'i3', 'i1', 'i2', 'i4', 'i1', 'i4'],
'rating': [5, 3, 4, 2, 5, 4, 5, 3, 3, 4]
}
df = pd.DataFrame(data)
# 创建Reader
reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(df[['user', 'item', 'rating']], reader)
# 划分训练集和测试集
trainset, testset = train_test_split(data, test_size=0.2)
# 使用基于用户的协同过滤
algo = KNNBasic(sim_options={'user_based': True})
algo.fit(trainset)
predictions = algo.test(testset)
# 评估
print("基于用户的协同过滤:")
accuracy.rmse(predictions)
# 使用SVD
algo = SVD()
algo.fit(trainset)
predictions = algo.test(testset)
print("\nSVD矩阵分解:")
accuracy.rmse(predictions)
# 预测新用户
user_id = 'E'
item_id = 'i2'
pred = algo.predict(user_id, item_id)
print(f"\n预测用户 {user_id} 对物品 {item_id} 的评分: {pred.est:.2f}")
# 运行示例
surprise_cf_example()
关键优化技巧
- 处理冷启动问题:对新用户使用流行度推荐
- 评分归一化:减去用户平均评分消除偏差
- 相似度计算优化:使用稀疏矩阵(Scipy sparse matrices)
- 增量更新:实时更新相似度矩阵
这些方法可以根据具体场景选择使用,基于用户的CF适合用户数较少的系统,基于物品的CF更适合物品数较少的系统,而矩阵分解在大规模系统中表现更好。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播