name: 推荐系统 description: 构建协同和基于内容的推荐引擎,用于产品推荐、个性化和提高用户参与度
推荐系统
概览
这项技能实现了协同和基于内容的推荐系统,采用矩阵分解技术来预测用户偏好,增加参与度,并通过个性化的项目建议来推动转化。
使用场景
- 开发推荐功能以提高用户参与度和留存
- 实施个性化产品建议以增加销售和转化率
- 构建结合协同和基于内容方法的混合推荐系统
- 分析和优化推荐覆盖率、多样性和准确性
- 处理稀疏的用户-项目交互矩阵和冷启动场景
- 运行A/B测试以衡量推荐算法对业务指标的影响
方法
- 协同过滤:与你相似的用户喜欢X
- 基于内容:与你喜欢的项目相似的项目
- 混合:结合多种方法
- 矩阵分解:潜在因子模型
- 深度学习:神经网络用于嵌入
关键指标
- Precision@K:%推荐相关
- Recall@K:%找到的相关项目
- NDCG:排名质量指标
- 覆盖率:%推荐的项目
- 多样性:推荐中的多样性
Python实现
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.decomposition import NMF
import seaborn as sns
# 创建样本用户-项目交互数据
np.random.seed(42)
users = [f'user_{i}' for i in range(100)]
items = [f'item_{i}' for i in range(50)]
# 生成评分(稀疏矩阵)
ratings_list = []
for user in users:
n_items_rated = np.random.randint(5, 20)
rated_items = np.random.choice(items, n_items_rated, replace=False)
for item in rated_items:
rating = np.random.randint(1, 6)
ratings_list.append({'user': user, 'item': item, 'rating': rating})
ratings_df = pd.DataFrame(ratings_list)
print("样本评分:")
print(ratings_df.head(10))
# 创建用户-项目矩阵
user_item_matrix = ratings_df.pivot_table(
index='user', columns='item', values='rating', fill_value=0
)
print(f"
用户-项目矩阵形状: {user_item_matrix.shape}")
print(f"稀疏度: {1 - (user_item_matrix != 0).sum().sum() / (user_item_matrix.shape[0] * user_item_matrix.shape[1]):.2%}")
# 1. 用户基础协同过滤
user_similarity = cosine_similarity(user_item_matrix)
user_similarity_df = pd.DataFrame(
user_similarity, index=user_item_matrix.index, columns=user_item_matrix.index
)
print("
1. 用户相似度矩阵(样本):")
print(user_similarity_df.iloc[:5, :5])
# 为用户获取推荐
def get_user_based_recommendations(user_id, user_sim_matrix, user_item_mat, n=5):
similar_users = user_sim_matrix[user_id].sort_values(ascending=False)[1:11]
recommendations = {}
for item in user_item_mat.columns:
if user_item_mat.loc[user_id, item] == 0: # 尚未评分
score = (similar_users * user_item_mat.loc[similar_users.index, item]).sum()
recommendations[item] = score
top_recs = sorted(recommendations.items(), key=lambda x: x[1], reverse=True)[:n]
return [rec[0] for rec in top_recs]
# 示例:为user_0获取推荐
user_recommendations = get_user_based_recommendations('user_0', user_similarity_df, user_item_matrix)
print(f"
user_0的推荐: {user_recommendations}")
# 2. 基于项目的协同过滤
item_similarity = cosine_similarity(user_item_matrix.T)
item_similarity_df = pd.DataFrame(
item_similarity, index=user_item_matrix.columns, columns=user_item_matrix.columns
)
print("
2. 项目相似度矩阵(样本):")
print(item_similarity_df.iloc[:5, :5])
# 3. 基于内容的过滤
item_features = np.random.rand(len(items), 10) # 模拟项目特征
item_feature_similarity = cosine_similarity(item_features)
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 用户相似度热图
sns.heatmap(user_similarity_df.iloc[:10, :10], annot=True, fmt='.2f', cmap='coolwarm',
ax=axes[0, 0], cbar_kws={'label': '相似度'})
axes[0, 0].set_title('用户相似度矩阵(样本)')
# 项目相似度热图
sns.heatmap(item_similarity_df.iloc[:10, :10], annot=True, fmt='.2f', cmap='coolwarm',
ax=axes[0, 1], cbar_kws={'label': '相似度'})
axes[0, 1].set_title('项目相似度矩阵(样本)')
# 评分分布
axes[1, 0].hist(ratings_df['rating'], bins=5, color='steelblue', edgecolor='black', alpha=0.7)
axes[1, 0].set_xlabel('评分')
axes[1, 0].set_ylabel('计数')
axes[1, 0].set_title('评分分布')
axes[1, 0].grid(True, alpha=0.3, axis='y')
# 按用户稀疏度
user_rating_counts = user_item_matrix.astype(bool).sum(axis=1)
axes[1, 1].hist(user_rating_counts, bins=20, color='lightcoral', edgecolor='black', alpha=0.7)
axes[1, 1].set_xlabel('评分项目数')
axes[1, 1].set_ylabel('用户数')
axes[1, 1].set_title('用户活动分布')
axes[1, 1].grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
# 4. 矩阵分解(NMF)
nenmf = NMF(n_components=10, init='random', random_state=42, max_iter=200)
user_latent = nmf.fit_transform(user_item_matrix)
item_latent = nmf.components_.T
print(f"
4. 矩阵分解:")
print(f"用户潜在因子形状: {user_latent.shape}")
print(f"项目潜在因子形状: {item_latent.shape}")
# 重构评分
reconstructed_ratings = user_latent @ item_latent.T
reconstructed_df = pd.DataFrame(
reconstructed_ratings, index=user_item_matrix.index, columns=user_item_matrix.columns
)
# 计算RMSE
original_ratings = user_item_matrix[user_item_matrix > 0]
predicted_ratings = reconstructed_df[user_item_matrix > 0]
rmse = np.sqrt(np.mean((original_ratings - predicted_ratings) ** 2))
print(f"重构RMSE: {rmse:.4f}")
# 5. 评估指标
def precision_at_k(actual, predicted, k=5):
if len(actual) == 0:
return 0
return len(set(actual[:k]) & set(predicted)) / k
def recall_at_k(actual, predicted, k=5):
if len(actual) == 0:
return 0
return len(set(actual[:k]) & set(predicted)) / len(actual)
# 模拟测试集
test_user = 'user_0'
actual_items = ratings_df[ratings_df['user'] == test_user]['item'].values
predicted_items = get_user_based_recommendations(test_user, user_similarity_df, user_item_matrix, n=10)
p_at_5 = precision_at_k(predicted_items, actual_items, k=5)
r_at_5 = recall_at_k(predicted_items, actual_items, k=5)
print(f"
5. 评估指标:")
print(f"Precision@5: {p_at_5:.2%}")
print(f"Recall@5: {r_at_5:.2%}")
print(f"F1@5: {2 * (p_at_5 * r_at_5) / (p_at_5 + r_at_5):.2%}")
# 6. 覆盖率和多样性
recommended_items = set()
for user in user_item_matrix.index[:20]:
recs = get_user_based_recommendations(user, user_similarity_df, user_item_matrix, n=5)
recommended_items.update(recs)
coverage = len(recommended_items) / len(items)
print(f"
覆盖率: {coverage:.2%}")
# 7. 热门度分析
item_popularity = ratings_df['item'].value_counts()
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 热门项目
axes[0].barh(item_popularity.head(10).index, item_popularity.head(10).values,
color='steelblue', edgecolor='black', alpha=0.7)
axes[0].set_xlabel('评分数量')
axes[0].set_title('前10个最受欢迎的项目')
axes[0].grid(True, alpha=0.3, axis='x')
# 热门度分布
axes[1].hist(item_popularity, bins=20, color='lightcoral', edgecolor='black', alpha=0.7)
axes[1].set_xlabel('评分数量')
axes[1].set_ylabel('项目数量')
axes[1].set_title('项目热门度分布')
axes[1].grid(True, alpha=0.3, axis='y')
plt.tight_layout()
plt.show()
# 8. 冷启动问题分析
new_user = 'new_user'
new_user_ratings = pd.DataFrame({
'user': [new_user] * 2,
'item': ['item_0', 'item_1'],
'rating': [5, 4]
})
print(f"
8. 冷启动问题:")
print(f"新用户评分: {len(new_user_ratings)} 项目")
print(f"推荐挑战:有限的用户历史")
# 9. 随时间变化的推荐准确性"k_values = [1, 3, 5, 10]
metrics_over_k = []
for k in k_values:
precision_scores = []
for user in user_item_matrix.index[:10]:
recs = get_user_based_recommendations(user, user_similarity_df, user_item_matrix, n=k)
actual = ratings_df[ratings_df['user'] == user]['item'].values
precision_scores.append(precision_at_k(recs, actual, k=k))
metrics_over_k.append({
'K': k,
'Precision': np.mean(precision_scores),
'Recall': np.mean([recall_at_k(get_user_based_recommendations(user, user_similarity_df, user_item_matrix, n=k),
ratings_df[ratings_df['user'] == user]['item'].values, k=k)
for user in user_item_matrix.index[:10]])
})
metrics_df = pd.DataFrame(metrics_over_k)
fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(metrics_df['K'], metrics_df['Precision'], marker='o', linewidth=2, label='Precision', markersize=8)
ax.plot(metrics_df['K'], metrics_df['Recall'], marker='s', linewidth=2, label='Recall', markersize=8)
ax.set_xlabel('K(推荐数量)')
ax.set_ylabel('得分')
ax.set_title('Precision和Recall与K的关系')
ax.legend()
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
# 10. A/B测试结果(模拟)
print("
10. A/B测试结果(模拟):")
print("控制组(无推荐):5.2%转化率")
print("对照组(有推荐):7.8%转化率")
print("提升:50%(统计显著,p < 0.05)")
print("
推荐系统完成!")
算法比较
- 协同过滤:简单,不需要内容
- 基于内容:适用于冷启动
- 矩阵分解:可扩展,发现潜在模式
- 深度学习:复杂模式,需要数据
- 混合:结合多种方法的优势
实施考虑
- 处理冷启动(新用户/项目)
- 大规模计算效率
- 解决稀疏性(大多数项目未评分)
- 多样性与相关性权衡
- 实时与批量推荐
交付物
- 用户-项目交互矩阵
- 相似度矩阵
- 样本用户的推荐
- 评估指标(精确度、召回率、NDCG)
- 覆盖率和多样性分析
- 结果可视化
- 生产实施代码