机器学习-08-推荐算法-案例

总结

本系列是机器学习课程的系列课程,主要介绍机器学习中关联规则

参考

机器学习(三):Apriori算法(算法精讲)

Apriori 算法 理论 重点

MovieLens:一个常用的电影推荐系统领域的数据集

23张图,带你入门推荐系统

本门课程的目标

完成一个特定行业的算法应用全过程:

懂业务+会选择合适的算法+数据处理+算法训练+算法调优+算法融合
+算法评估+持续调优+工程化接口实现

机器学习定义

关于机器学习的定义,Tom Michael Mitchell的这段话被广泛引用:
对于某类任务T性能度量P,如果一个计算机程序在T上其性能P随着经验E而自我完善,那么我们称这个计算机程序从经验E中学习
在这里插入图片描述

要构建一个包含用户、商品和评分的数据集,并基于 Python 实现基于用户的商品推荐,我们可以使用协同过滤算法(Collaborative Filtering)。以下是实现的步骤:


基于用户的协同过滤推荐案例

在真实的推荐系统场景中,用户通常只会对少量商品进行评分,而大部分商品的评分为 0(表示未评分)。为了模拟这种稀疏性,我们可以调整数据生成逻辑,使得每个用户的评分矩阵中有更多的 0 值。

以下是如何生成稀疏评分矩阵的完整代码实现:


1. 构建稀疏评分矩阵

我们将通过随机生成的方式,确保每个用户只对少量商品评分(例如每个用户平均评分 3-5 个商品),其余商品的评分为 0

import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 设置随机种子以确保结果可复现
np.random.seed(42)

# 参数设置
num_users = 10  # 用户数量
num_items = 10  # 商品数量
max_ratings_per_user = 5  # 每个用户最多评分的商品数量

# 初始化评分矩阵 (初始值为 0)
ratings = np.zeros((num_users, num_items))

# 随机生成稀疏评分数据
for i in range(num_users):
    # 随机选择该用户评分的商品数量(1 到 max_ratings_per_user)
    num_rated_items = np.random.randint(1, max_ratings_per_user + 1)
    # 随机选择该用户评分的商品索引
    rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)
    # 随机生成评分(1 到 5)
    ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)

# 构建 DataFrame
user_ids = [f"用户{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)

# 打印评分矩阵
print("用户-商品评分矩阵:")
print(df)
输出示例:

在这里插入图片描述

2. 计算用户相似度并预测评分

接下来,我们基于稀疏评分矩阵计算用户相似度,并为目标用户预测未评分商品的评分。

# 计算用户之间的相似度
user_similarity = cosine_similarity(df)
user_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)

print("\n用户相似度矩阵:")
print(user_similarity_df)


# 预测目标用户对未评分商品的评分
def predict_ratings(target_user, df, user_similarity_df):
    # 获取目标用户的评分
    target_ratings = df.loc[target_user]
    
    # 修改这里:初始化预测评分为float类型
    predicted_ratings = pd.Series(0.0, index=df.columns, dtype='float64')
    
    for item in df.columns:
        if target_ratings[item] == 0:  # 只预测未评分的商品
            # 获取对该商品评分过的用户
            users_who_rated = df[df[item] > 0].index
            
            # 计算加权平均评分
            weighted_sum = 0.0
            similarity_sum = 0.0
            for user in users_who_rated:
                rating = df.loc[user, item]
                similarity = user_similarity_df.loc[target_user, user]
                weighted_sum += rating * similarity
                similarity_sum += similarity
            
            if similarity_sum > 0:
                predicted_ratings[item] = weighted_sum / similarity_sum
    
    return predicted_ratings

# 目标用户
target_user = '用户1'

# 预测评分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)

print(f"\n为目标用户 {target_user} 预测的评分:")
print(predicted_ratings)

# 推荐商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推荐给用户 {target_user} 的商品:")
print(recommended_items)

3. 运行结果解释

假设运行上述代码后,输出如下:

用户相似度矩阵(部分):

在这里插入图片描述

为目标用户 用户1 预测的评分:

在这里插入图片描述

推荐给用户 用户1 的商品:

在这里插入图片描述

4. 总结

通过引入稀疏评分矩阵,我们更贴近真实场景,其中大多数商品的评分为 0。对于目标用户 用户1,我们预测了其对未评分商品的评分,并推荐了预测评分最高的商品(如 商品3商品10 等)。

你可以根据需要进一步优化算法,例如:

  • 调整评分稀疏度(例如减少评分的商品数量)。
  • 使用其他相似度计算方法(如皮尔逊相关系数)。
  • 引入隐式反馈数据(如点击、浏览等行为)。

5.代码改进方法

在计算用户相似度时,如果用户评分数据过于稀疏(比如某些用户没有共同评分的商品),可能会导致计算相似度时出现问题。以下是改进后的代码,增加了数据预处理和异常处理:

import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 设置随机种子以确保结果可复现
np.random.seed(42)

# 参数设置
num_users = 10  # 用户数量
num_items = 10  # 商品数量
max_ratings_per_user = 5  # 每个用户最多评分的商品数量

# 初始化评分矩阵 (初始值为 0)
ratings = np.zeros((num_users, num_items))

# 随机生成稀疏评分数据
for i in range(num_users):
    # 随机选择该用户评分的商品数量(1 到 max_ratings_per_user)
    num_rated_items = np.random.randint(1, max_ratings_per_user + 1)
    # 随机选择该用户评分的商品索引
    rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)
    # 随机生成评分(1 到 5)
    ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)

# 构建 DataFrame
user_ids = [f"用户{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)

# 打印评分矩阵
print("用户-商品评分矩阵:")
print(df)

# 计算用户之间的相似度(改进版)
def calculate_user_similarity(df):
    # 填充缺失值为0(如果还没有填充)
    df_filled = df.fillna(0)
    
    # 计算余弦相似度
    user_similarity = cosine_similarity(df_filled)
    
    # 将对角线设置为0(避免用户与自己比较)
    np.fill_diagonal(user_similarity, 0)
    
    # 转换为DataFrame
    user_similarity_df = pd.DataFrame(
        user_similarity, 
        index=df.index, 
        columns=df.index
    )
    return user_similarity_df

user_similarity_df = calculate_user_similarity(df)

# 计算用户之间的相似度
# user_similarity = cosine_similarity(df)
# user_similarity_df = pd.DataFrame(user_similarity, index=df.index, columns=df.index)

print("\n用户相似度矩阵:")
print(user_similarity_df)

# 预测目标用户对未评分商品的评分
# def predict_ratings(target_user, df, user_similarity_df):
#     # 获取目标用户的评分
#     target_ratings = df.loc[target_user]
    
#     # 修改这里:初始化预测评分为float类型
#     predicted_ratings = pd.Series(0.0, index=df.columns, dtype='float64')
    
#     for item in df.columns:
#         if target_ratings[item] == 0:  # 只预测未评分的商品
#             # 获取对该商品评分过的用户
#             users_who_rated = df[df[item] > 0].index
            
#             # 计算加权平均评分
#             weighted_sum = 0.0
#             similarity_sum = 0.0
#             for user in users_who_rated:
#                 rating = df.loc[user, item]
#                 similarity = user_similarity_df.loc[target_user, user]
#                 weighted_sum += rating * similarity
#                 similarity_sum += similarity
            
#             if similarity_sum > 0:
#                 predicted_ratings[item] = weighted_sum / similarity_sum
    
#     return predicted_ratings


# 预测目标用户对未评分商品的评分(改进版)
def predict_ratings(target_user, df, user_similarity_df, min_similar_users=1):
    target_ratings = df.loc[target_user]
    predicted_ratings = pd.Series(0.0, index=df.columns,dtype='float64')
    
    for item in df.columns:
        if target_ratings[item] == 0:
            users_who_rated = df[df[item] > 0].index
            weighted_sum = 0
            similarity_sum = 0
            valid_users = 0
            
            for user in users_who_rated:
                similarity = user_similarity_df.loc[target_user, user]
                # 只考虑正相似度的用户
                if similarity > 0:
                    rating = df.loc[user, item]
                    weighted_sum += rating * similarity
                    similarity_sum += similarity
                    valid_users += 1
            
            # 至少有min_similar_users个相似用户才进行预测
            if valid_users >= min_similar_users and similarity_sum > 0:
                predicted_ratings[item] = weighted_sum / similarity_sum
    
    return predicted_ratings

# 目标用户
target_user = '用户1'

# 预测评分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)

print(f"\n为目标用户 {target_user} 预测的评分:")
print(predicted_ratings)

# 推荐商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推荐给用户 {target_user} 的商品:")
print(recommended_items)

输出如下:
在这里插入图片描述

主要改进点:

增加了calculate_user_similarity函数来封装相似度计算逻辑
在计算相似度前确保数据已填充缺失值
将对角线相似度设为0(避免用户与自己比较)
在预测评分时增加了min_similar_users参数,确保有足够多的相似用户才进行预测
只考虑正相似度的用户参与预测
这些改进可以解决以下潜在问题:

处理缺失值问题
避免用户与自己的相似度影响结果
确保预测时有足够的参考用户
提高预测结果的可靠性

基于物品的协同过滤推荐案例

基于物品的协同过滤(Item-Based Collaborative Filtering)是一种推荐算法,其核心思想是:如果两个商品被相似的用户评分,那么这两个商品可能是相似的。我们可以根据商品之间的相似性,为目标用户推荐他们未评分但可能感兴趣的商品。

以下是基于上述稀疏评分矩阵实现基于物品的协同过滤的完整代码:


1. 数据准备

我们使用之前生成的稀疏评分矩阵 df,其中包含 10 个用户和 10 个商品。

import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 设置随机种子以确保结果可复现
np.random.seed(42)

# 参数设置
num_users = 10  # 用户数量
num_items = 10  # 商品数量
max_ratings_per_user = 5  # 每个用户最多评分的商品数量

# 初始化评分矩阵 (初始值为 0)
ratings = np.zeros((num_users, num_items))

# 随机生成稀疏评分数据
for i in range(num_users):
    # 随机选择该用户评分的商品数量(1 到 max_ratings_per_user)
    num_rated_items = np.random.randint(1, max_ratings_per_user + 1)
    # 随机选择该用户评分的商品索引
    rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)
    # 随机生成评分(1 到 5)
    ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)

# 构建 DataFrame
user_ids = [f"用户{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)

print("用户-商品评分矩阵:")
print(df)

输出如下:
在这里插入图片描述

2. 计算商品相似度

在基于物品的协同过滤中,我们需要计算商品之间的相似度。可以使用余弦相似度来衡量商品之间的相似性。

# 转置评分矩阵,使得行表示商品,列表示用户
item_similarity = cosine_similarity(df.T)  # 对转置后的矩阵计算相似度
item_similarity_df = pd.DataFrame(item_similarity, index=df.columns, columns=df.columns)

print("\n商品相似度矩阵:")
print(item_similarity_df)
输出示例:

在这里插入图片描述

3. 基于商品相似度预测评分

对于目标用户未评分的商品,我们可以利用商品相似度和用户已评分的商品来预测评分。

def predict_item_based(target_user, df, item_similarity_df):
    # 获取目标用户的评分
    target_ratings = df.loc[target_user]
    
    # 初始化预测评分
    predicted_ratings = pd.Series(0, index=df.columns)
    
    for item in df.columns:
        if target_ratings[item] == 0:  # 只预测未评分的商品
            # 获取与当前商品相似的商品
            similar_items = item_similarity_df[item]
            
            # 计算加权平均评分
            weighted_sum = 0
            similarity_sum = 0
            for other_item in df.columns:
                if target_ratings[other_item] > 0 and similar_items[other_item] > 0:
                    rating = target_ratings[other_item]
                    similarity = similar_items[other_item]
                    weighted_sum += rating * similarity
                    similarity_sum += similarity
            
            if similarity_sum > 0:
                predicted_ratings[item] = weighted_sum / similarity_sum
    
    return predicted_ratings

# 目标用户
target_user = '用户1'

# 预测评分
predicted_ratings = predict_item_based(target_user, df, item_similarity_df)

print(f"\n为目标用户 {target_user} 预测的评分:")
print(predicted_ratings)

# 推荐商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推荐给用户 {target_user} 的商品:")
print(recommended_items)

输出如下:
在这里插入图片描述

4. 总结

通过基于物品的协同过滤算法,我们成功为目标用户 用户1 推荐了未评分但可能感兴趣的商品(如 商品3商品10 等)。这种算法的核心在于计算商品之间的相似性,并利用相似商品的评分来预测目标用户对未评分商品的兴趣。

你可以根据需要进一步优化算法,例如:

  • 使用其他相似度计算方法(如皮尔逊相关系数)。
  • 引入隐式反馈数据(如点击、浏览等行为)。
  • 结合基于用户的协同过滤和基于物品的协同过滤,形成混合推荐系统。

推荐算法流程优化版本-召回过滤精排混排强规则

import numpy as np
import pandas as pd
from sklearn.metrics.pairwise import cosine_similarity

# 设置随机种子以确保结果可复现
np.random.seed(42)

# 参数设置
num_users = 10  # 用户数量
num_items = 10  # 商品数量
max_ratings_per_user = 5  # 每个用户最多评分的商品数量

# 初始化评分矩阵 (初始值为 0)
ratings = np.zeros((num_users, num_items))

# 随机生成稀疏评分数据
for i in range(num_users):
    # 随机选择该用户评分的商品数量(1 到 max_ratings_per_user)
    num_rated_items = np.random.randint(1, max_ratings_per_user + 1)
    # 随机选择该用户评分的商品索引
    rated_items = np.random.choice(num_items, size=num_rated_items, replace=False)
    # 随机生成评分(1 到 5)
    ratings[i, rated_items] = np.random.randint(1, 6, size=num_rated_items)

# 构建 DataFrame
user_ids = [f"用户{i+1}" for i in range(num_users)]
item_ids = [f"商品{j+1}" for j in range(num_items)]
df = pd.DataFrame(ratings, index=user_ids, columns=item_ids)

# 打印评分矩阵
print("用户-商品评分矩阵:")
print(df)

# 计算用户之间的相似度(改进版)
def calculate_user_similarity(df):
    # 填充缺失值为0(如果还没有填充)
    df_filled = df.fillna(0)
    
    # 计算余弦相似度
    user_similarity = cosine_similarity(df_filled)
    
    # 将对角线设置为0(避免用户与自己比较)
    np.fill_diagonal(user_similarity, 0)
    
    # 转换为DataFrame
    user_similarity_df = pd.DataFrame(
        user_similarity, 
        index=df.index, 
        columns=df.index
    )
    return user_similarity_df

user_similarity_df = calculate_user_similarity(df)

print("\n用户相似度矩阵:")
print(user_similarity_df)

# 预测目标用户对未评分商品的评分(改进版)
def predict_ratings(target_user, df, user_similarity_df, min_similar_users=1):
    target_ratings = df.loc[target_user]
    predicted_ratings = pd.Series(0.0, index=df.columns,dtype='float64')
    
    for item in df.columns:
        if target_ratings[item] == 0:
            users_who_rated = df[df[item] > 0].index
            weighted_sum = 0
            similarity_sum = 0
            valid_users = 0
            
            for user in users_who_rated:
                similarity = user_similarity_df.loc[target_user, user]
                # 只考虑正相似度的用户
                if similarity > 0:
                    rating = df.loc[user, item]
                    weighted_sum += rating * similarity
                    similarity_sum += similarity
                    valid_users += 1
            
            # 至少有min_similar_users个相似用户才进行预测
            if valid_users >= min_similar_users and similarity_sum > 0:
                predicted_ratings[item] = weighted_sum / similarity_sum
    
    return predicted_ratings

# 目标用户
target_user = '用户1'

# 预测评分
predicted_ratings = predict_ratings(target_user, df, user_similarity_df)

print(f"\n为目标用户 {target_user} 预测的评分:")
print(predicted_ratings)

# 推荐商品
recommended_items = predicted_ratings[predicted_ratings > 0].sort_values(ascending=False)
print(f"\n推荐给用户 {target_user} 的商品:")
print(recommended_items)

# 评估推荐系统
def evaluate_recommendation(df, user_similarity_df, test_ratio=0.2):
    from sklearn.model_selection import train_test_split
    
    # 转换为长格式
    melted_df = df.reset_index().melt(id_vars='index', var_name='item', value_name='rating')
    melted_df.columns = ['user', 'item', 'rating']
    
    # 分割训练集和测试集
    train_df, test_df = train_test_split(melted_df[melted_df['rating'] > 0], test_size=test_ratio)
    
    # 重建训练矩阵
    train_matrix = pd.pivot_table(train_df, values='rating', index='user', columns='item').fillna(0)
    
    # 计算用户相似度
    train_similarity = calculate_user_similarity(train_matrix)
    
    # 评估每个测试用户
    mae = 0
    test_users = test_df['user'].unique()
    
    for user in test_users:
        # 获取测试用户的实际评分
        actual_ratings = test_df[test_df['user'] == user].set_index('item')['rating']
        
        # 预测评分
        predicted = predict_ratings(user, train_matrix, train_similarity)
        
        # 计算MAE
        common_items = actual_ratings.index.intersection(predicted.index)
        if len(common_items) > 0:
            mae += np.mean(np.abs(actual_ratings[common_items] - predicted[common_items]))
    
    mae /= len(test_users)
    print(f"\n推荐系统评估结果(MAE): {mae:.4f}")

# 运行评估
evaluate_recommendation(df, user_similarity_df)

# ... 已有代码保持不变 ...

# 1. 召回阶段 - 多种召回策略
def recall_strategies(target_user, df, user_similarity_df):
    # 策略1: 基于用户的协同过滤召回
    cf_recall = predict_ratings(target_user, df, user_similarity_df)
    cf_items = cf_recall[cf_recall > 0].index.tolist()
    
    # 策略2: 热门商品召回
    popular_items = df.sum().sort_values(ascending=False).head(5).index.tolist()
    
    # 策略3: 新商品召回
    new_items = df.columns[-3:].tolist()  # 假设最后3个是新商品
    
    # 合并召回结果并去重
    recalled_items = list(set(cf_items + popular_items + new_items))
    return recalled_items

# 2. 过滤阶段 - 过滤掉不合适的商品
def filter_items(target_user, recalled_items, df):
    # 获取用户已购买/已评价的商品
    rated_items = df.loc[target_user][df.loc[target_user] > 0].index.tolist()
    
    # 过滤掉用户已经购买/评价过的商品
    filtered_items = [item for item in recalled_items if item not in rated_items]
    
    # 强规则过滤示例:过滤掉特定商品
    blacklist = ['商品5']  # 假设商品5被列入黑名单
    filtered_items = [item for item in filtered_items if item not in blacklist]
    
    return filtered_items

# 3. 精排阶段 - 对过滤后的商品进行精细排序
def ranking(target_user, filtered_items, df, user_similarity_df):
    # 计算每个商品的预测评分
    predicted_ratings = predict_ratings(target_user, df, user_similarity_df)
    
    # 计算商品热度
    item_popularity = df.sum()
    
    # 综合评分 = 预测评分 * 0.7 + 热度 * 0.3 (加权得分)
    ranked_items = {}
    for item in filtered_items:
        score = predicted_ratings[item] * 0.7 + item_popularity[item] * 0.3
        ranked_items[item] = score
    
    # 按得分排序
    ranked_items = sorted(ranked_items.items(), key=lambda x: x[1], reverse=True)
    return ranked_items

# 4. 混排阶段 - 结合多种策略生成最终推荐列表
def mixed_sorting(ranked_items):
    final_list = []
    
    # 强规则:确保特定商品排在前面
    promoted_item = '商品2'  # 假设商品2是推广商品
    for i, (item, score) in enumerate(ranked_items):
        if item == promoted_item:
            final_list.insert(0, (item, score))  # 推广商品置顶
        else:
            final_list.append((item, score))
    
    # 多样性控制:避免同类型商品扎堆
    # 这里简化为限制连续出现相似商品
    diversified_list = []
    prev_item_type = None
    for item, score in final_list:
        current_type = item[-1]  # 假设商品类型由商品ID最后一位决定
        if current_type == prev_item_type:
            score *= 0.9  # 相似类型商品降权
        diversified_list.append((item, score))
        prev_item_type = current_type
    
    return sorted(diversified_list, key=lambda x: x[1], reverse=True)

# 5. 完整推荐流程
def full_recommendation_pipeline(target_user, df, user_similarity_df):
    print(f"\n开始为用户 {target_user} 生成推荐...")
    
    # 召回
    recalled_items = recall_strategies(target_user, df, user_similarity_df)
    print(f"\n召回阶段结果: {recalled_items}")
    
    # 过滤
    filtered_items = filter_items(target_user, recalled_items, df)
    print(f"过滤后结果: {filtered_items}")
    
    # 精排
    ranked_items = ranking(target_user, filtered_items, df, user_similarity_df)
    print(f"精排后结果: {ranked_items}")
    
    # 混排
    final_recommendations = mixed_sorting(ranked_items)
    print(f"最终推荐列表: {final_recommendations}")
    
    return final_recommendations

# 运行完整推荐流程
final_recommendations = full_recommendation_pipeline(target_user, df, user_similarity_df)

# 输出最终推荐结果
print("\n=== 最终推荐结果 ===")
for item, score in final_recommendations:
    print(f"{item}: {score:.2f}")

输出如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于scikit-surprise实现推荐

scikit-surprise 是一个用于构建推荐系统的 Python 库,专注于协同过滤(Collaborative Filtering)算法。以下是基于 scikit-surprise 实现一个简单的推荐系统的完整代码示例。


1. 安装依赖

首先,确保你已经安装了 scikit-surprise

pip install scikit-surprise==1.1.4

2. 数据准备

我们使用 scikit-surprise 提供的内置数据集(例如 MovieLens 数据集),或者自定义数据集。

示例:加载 MovieLens 数据集
from surprise import Dataset
from surprise import Reader
from surprise.model_selection import train_test_split

# 加载内置的 MovieLens 数据集
data = Dataset.load_builtin('ml-100k')

# 将数据划分为训练集和测试集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)

如果你有自己的数据集(例如用户、物品、评分),可以按照以下方式加载:

import pandas as pd
from surprise import Dataset, Reader

# 假设你的数据是一个 Pandas DataFrame
ratings_dict = {
    "user_id": [1, 1, 1, 2, 2, 3, 3, 3],
    "item_id": [101, 102, 103, 101, 104, 102, 103, 104],
    "rating": [5, 3, 4, 4, 2, 5, 3, 1],
}
df = pd.DataFrame(ratings_dict)

# 定义评分范围
reader = Reader(rating_scale=(1, 5))

# 加载自定义数据集
data = Dataset.load_from_df(df[["user_id", "item_id", "rating"]], reader)

# 划分训练集和测试集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)

3. 构建推荐模型

scikit-surprise 提供了多种协同过滤算法,例如 SVD(奇异值分解)、KNN(最近邻算法)等。以下以 SVD 为例:

from surprise import SVD
from surprise import accuracy

# 初始化 SVD 模型
model = SVD()

# 在训练集上训练模型
model.fit(trainset)

# 在测试集上进行预测
predictions = model.test(testset)

# 计算 RMSE(均方根误差)
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")

4. 推荐物品

我们可以为特定用户生成推荐物品列表。以下是一个示例函数,用于获取某个用户的前 N 个推荐物品:

def get_top_n_recommendations(model, user_id, items, n=5):
    # 预测用户对所有物品的评分
    predictions = [(item, model.predict(user_id, item).est) for item in items]
    
    # 按评分排序
    predictions.sort(key=lambda x: x[1], reverse=True)
    
    # 返回前 N 个推荐物品
    return predictions[:n]

# 获取所有物品 ID
items = df["item_id"].unique()

# 为用户 1 生成推荐
user_id = 1
top_n_recommendations = get_top_n_recommendations(model, user_id, items, n=5)
print(f"为用户 {user_id} 推荐的物品:")
for item, score in top_n_recommendations:
    print(f"物品 ID: {item}, 预测评分: {score:.2f}")

5. 使用 KNN 算法

如果你想使用 KNN 算法(基于用户的协同过滤或基于物品的协同过滤),可以按照以下方式实现:

from surprise import KNNBasic

# 初始化 KNN 模型(基于用户的协同过滤)
sim_options = {
    "name": "cosine",       # 相似度计算方法
    "user_based": True      # 基于用户(True)还是基于物品(False)
}
model = KNNBasic(sim_options=sim_options)

# 在训练集上训练模型
model.fit(trainset)

# 在测试集上进行预测
predictions = model.test(testset)

# 计算 RMSE
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")

6. 完整代码整合

以下是完整的代码示例,包含数据加载、模型训练、评估和推荐:

import pandas as pd
from surprise import Dataset, Reader, SVD, accuracy
from surprise.model_selection import train_test_split

# 自定义数据集
ratings_dict = {
    "user_id": [1, 1, 1, 2, 2, 3, 3, 3],
    "item_id": [101, 102, 103, 101, 104, 102, 103, 104],
    "rating": [5, 3, 4, 4, 2, 5, 3, 1],
}
df = pd.DataFrame(ratings_dict)

# 定义评分范围
reader = Reader(rating_scale=(1, 5))

# 加载数据集
data = Dataset.load_from_df(df[["user_id", "item_id", "rating"]], reader)

# 划分训练集和测试集
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)

# 初始化 SVD 模型
model = SVD()

# 在训练集上训练模型
model.fit(trainset)

# 在测试集上进行预测
predictions = model.test(testset)

# 计算 RMSE
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse}")

# 获取所有物品 ID
items = df["item_id"].unique()

# 为用户生成推荐
def get_top_n_recommendations(model, user_id, items, n=5):
    predictions = [(item, model.predict(user_id, item).est) for item in items]
    predictions.sort(key=lambda x: x[1], reverse=True)
    return predictions[:n]

# 为用户 1 生成推荐
user_id = 1
top_n_recommendations = get_top_n_recommendations(model, user_id, items, n=5)
print(f"为用户 {user_id} 推荐的物品:")
for item, score in top_n_recommendations:
    print(f"物品 ID: {item}, 预测评分: {score:.2f}")

7. 输出结果

运行上述代码后,你会得到以下输出:

  1. RMSE:模型在测试集上的均方根误差。
  2. 推荐列表:为指定用户生成的前 N 个推荐物品及其预测评分。

8. 扩展功能

  1. 超参数调优

    • 使用 GridSearchCV 或手动调整模型参数(如 n_factorslr_all 等)来优化模型性能。
  2. 交叉验证

    • 使用 cross_validate 函数评估模型的稳定性和泛化能力。
  3. 其他算法

    • 尝试其他算法(如 NMF、SlopeOne 或 CoClustering)并比较效果。

通过上述代码,你可以快速构建一个基于协同过滤的推荐系统!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT从业者张某某

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值