基于用户的协同过滤以及ALS的混合召回算法

需求

要将基于用户的协同过滤(User-Based Collaborative Filtering,
UBCF)与交替最小二乘(Alternating Least Squares, ALS)结合起来,设计一个混合推荐系统。这种系统可以利用
ALS 的优点(如处理稀疏数据的能力)来改进基于用户的协同过滤

基于用户的协同过滤

基于用户之间的相似度来进行推荐。在基于用户的协同过滤中,系统寻找与目标用户兴趣相似的其他用户,然后推荐这些相似用户喜欢的物品给目标用户

基本步骤

基于用户的协同过滤的基本步骤如下:

  • 构建用户-物品评分矩阵:其中行代表用户,列代表物品。矩阵中的每个元素表示用户对物品的评分。
  • 计算用户相似度:
    使用某种相似度度量方法(如皮尔逊相关系数、余弦相似度等)计算用户之间的相似度。
    相似度度量反映了用户之间兴趣的一致性。
  • 找到最近邻用户:
    为每个目标用户找到一组最相似的用户(即最近邻用户)。
    这些最近邻用户的选择通常是基于最高的相似度得分。
  • 生成推荐列表:
    从最近邻用户喜欢的物品中选择未被目标用户评分过的物品作为推荐。
    可以根据最近邻用户的评分和相似度加权平均来预测目标用户对这些物品的潜在评分。

相似度计算

  • 皮尔逊相关系数:
    计算两个用户评分之间的相关性。
    适用于当用户评分分布相同时的情况。
  • 余弦相似度:
    衡量两个用户评分向量之间的角度。
    适用于当用户评分范围差异较大时的情况。
  • Jaccard 相似度:
    仅考虑用户是否对物品有过评分,而不考虑评分的具体数值。
    适用于二元评分(如喜欢/不喜欢)的情况。

代码示例(使用余弦相似度)

因为不同用户直接的评分范围差异比较大 使用余弦相似度来计算

import numpy as np
from scipy.spatial.distance import cosine
from collections import defaultdict

def calculate_similarity(ratings_matrix):
    # 计算用户之间的余弦相似度  返回相似度矩阵 user*user
    num_users = ratings_matrix.shape[0]
    similarity_matrix = np.zeros((num_users, num_users))
    for i in range(num_users):
        for j in range(i + 1, num_users):
            sim = 1 - cosine(ratings_matrix[i], ratings_matrix[j]) # 计算向量之间相似度
            similarity_matrix[i][j] = sim
            similarity_matrix[j][i] = sim
    return similarity_matrix

def get_top_n_recommendations(user_id, ratings_matrix, similarity_matrix, n=10):
    # 获取目标用户的最近邻用户
    target_user_ratings = ratings_matrix[user_id]
    target_user_similarities = similarity_matrix[user_id]
    
    # 计算每个物品的预测评分
    predicted_ratings = defaultdict(float)
    for neighbor_id, similarity in enumerate(target_user_similarities):
       ## 不考虑相似度低的用户
        if similarity < threshold:
            continue
        if neighbor_id == user_id:
            continue  # 跳过自身
        neighbor_ratings = ratings_matrix[neighbor_id] ## 相似用户的评分
        for item_id, rating in enumerate(neighbor_ratings):
        # 检查物品是否已经被目标用户评分过。
        #如果是未评分的物品(即目标用户对该物品的评分是 0),并且邻居用户对该物品有评分(评分大于 0),则进行以下操作
            if rating > 0 and target_user_ratings[item_id] == 0:
                predicted_ratings[item_id] += similarity * rating
    
    # 根据预测评分排序
    recommendations = sorted(predicted_ratings.items(), key=lambda x: x[1], reverse=True)[:n]
    return recommendations

# 示例数据
ratings_matrix = np.array([
    [5, 3, 0, 1],
    [4, 0, 0, 1],
    [1, 1, 0, 5],
    [1, 0, 0, 4],
    [0, 1, 5, 4]
])

similarity_matrix = calculate_similarity(ratings_matrix)

# 获取用户 0 的推荐
top_n_recommendations = get_top_n_recommendations(0, ratings_matrix, similarity_matrix, n=2)
print("Top 2 Recommendations for User 0:")
for item_id, prediction in top_n_recommendations:
    print(f"Item {item_id}: {prediction:.2f}")

基于用户的协同过滤是一种经典的推荐算法,它通过寻找具有相似兴趣的用户来推荐物品,它关注的是用户之间的相似性而非物品之间的相似性。然而,在大规模数据集上,这种方法可能会因为计算用户相似度矩阵所需的大量计算资源而变得不太实用

基于用户的协同过滤的缺点

  • 计算成本高:
    需要计算所有用户之间的相似度,这在用户基数很大的情况下是非常耗时且计算密集的。
    对于大型数据集,计算用户之间的相似度矩阵可能会成为瓶颈。
  • 冷启动问题:
    新加入系统的用户(新用户)没有历史评分记录,难以找到相似用户。
    同样地,新物品也面临相似问题,因为没有足够的用户对其进行评分。
  • 稀疏性问题:
    大多数用户只会对一小部分物品进行评分,导致用户-物品评分矩阵非常稀疏。
    稀疏性问题使得计算用户之间的相似度变得更加困难,因为可用的共同评分物品较少。
  • 可扩展性差:
    当用户基数增加时,计算所有用户之间的相似度变得越来越不可行。
    在实时推荐场景下,需要频繁更新用户之间的相似度,这会增加计算负担。
  • 数据稀疏性和噪声:
    由于用户通常只会对少数物品进行评分,导致评分数据非常稀疏,这会影响相似度计算的准确性。
    用户的评分可能存在噪声,比如误评、情绪化评分等,这也会影响到相似度计算的准确性。

实际推荐系统中的替代方案

鉴于上述缺点,现代推荐系统通常采用其他技术或组合多种技术来克服这些问题:

  • 基于物品的协同过滤(Item-Based Collaborative Filtering, IBCF):
    相比于用户之间的相似度,计算物品之间的相似度更加高效。
    物品的数量通常少于用户数量,因此计算物品相似度的成本相对较低。
  • 矩阵分解(Matrix Factorization):
    如交替最小二乘(Alternating Least Squares, ALS)、奇异值分解(SVD)等技术,可以有效处理稀疏性问题,并且能够处理大规模数据集。
  • 深度学习方法:
    利用神经网络模型来捕捉复杂的用户偏好和物品特征之间的关系。
    例如深度神经网络(DNN)、卷积神经网络(CNN)、循环神经网络(RNN)等。
  • 混合推荐系统:
    结合多种推荐技术的优点,比如结合基于用户的协同过滤、基于物品的协同过滤以及矩阵分解等。这样的系统可以更好地处理稀疏性、冷启动等问题,并提供更高质量的推荐。

ALS

参照
推荐系统中ALS验证

userBase CF+ALS混合推荐设计

  • 构建用户-物品评分矩阵。
  • 使用 ALS 训练模型。
  • 计算用户之间的相似度。
  • 生成基于用户相似度的推荐。
  • 融合 ALS 推荐和基于用户相似度的推荐

代码

import numpy as np
from scipy.sparse import csr_matrix
from scipy.sparse.linalg import svds
from sklearn.metrics.pairwise import cosine_similarity
from collections import defaultdict

def calculate_similarity(ratings_matrix):
    # 计算用户之间的余弦相似度
    similarity_matrix = cosine_similarity(ratings_matrix)
    return similarity_matrix

def als_train(ratings_matrix, latent_features=10, learning_rate=0.001, reg_param=0.02, iterations=100):
    # 初始化用户和物品的特征向量
    user_features = np.random.normal(scale=1./latent_features, size=(ratings_matrix.shape[0], latent_features))
    item_features = np.random.normal(scale=1./latent_features, size=(ratings_matrix.shape[1], latent_features))

    # 训练 ALS 模型
    for iteration in range(iterations):
        for u, rated_items in enumerate(ratings_matrix):
            items, ratings = zip(*[(i, r) for i, r in enumerate(rated_items) if r > 0])
            item_matrix = item_features[items]
            user_features[u] = np.linalg.solve(item_matrix.T @ item_matrix + reg_param * len(items) * np.eye(latent_features),
                                                item_matrix.T @ ratings).ravel()

        for i, rated_users in enumerate(ratings_matrix.T):
            users, ratings = zip(*[(u, r) for u, r in enumerate(rated_users) if r > 0])
            user_matrix = user_features[users]
            item_features[i] = np.linalg.solve(user_matrix.T @ user_matrix + reg_param * len(users) * np.eye(latent_features),
                                                user_matrix.T @ ratings).ravel()

    return user_features, item_features

def get_top_n_recommendations(user_id, ratings_matrix, user_features, item_features, n=10):
    # 生成基于 ALS 的推荐
    predictions_als = user_features[user_id].dot(item_features.T)
    
    # 生成基于用户相似度的推荐
    target_user_ratings = ratings_matrix[user_id]
    target_user_similarities = similarity_matrix[user_id]
    predicted_ratings = defaultdict(float)
    for neighbor_id, similarity in enumerate(target_user_similarities):
        if neighbor_id == user_id:
            continue  # 跳过自身
        neighbor_ratings = ratings_matrix[neighbor_id]
        for item_id, rating in enumerate(neighbor_ratings):
            if rating > 0 and target_user_ratings[item_id] == 0:
                predicted_ratings[item_id] += similarity * rating
    
    # 结合 ALS 和基于用户相似度的预测
    combined_predictions = defaultdict(float)
    for item_id in predicted_ratings.keys():
        combined_predictions[item_id] = 0.7 * predictions_als[item_id] + 0.3 * predicted_ratings[item_id]

    # 根据预测评分排序
    recommendations = sorted(combined_predictions.items(), key=lambda x: x[1], reverse=True)[:n]
    return recommendations

# 示例数据
ratings_data = np.array([
    [5, 3, 0, 1],
    [4, 0, 0, 1],
    [1, 1, 0, 5],
    [1, 0, 0, 4],
    [0, 1, 5, 4]
])

# 构建稀疏矩阵
ratings_matrix = csr_matrix(ratings_data)

# 训练 ALS 模型
user_features, item_features = als_train(ratings_matrix)

# 计算用户之间的相似度
similarity_matrix = calculate_similarity(ratings_matrix.toarray())

# 获取用户 0 的推荐
top_n_recommendations = get_top_n_recommendations(0, ratings_matrix, user_features, item_features, n=2)
print("Top 2 Recommendations for User 0:")
for item_id, prediction in top_n_recommendations:
    print(f"Item {item_id}: {prediction:.2f}")

说明

  • ALS 模型训练:
    使用 als_train 函数训练 ALS 模型,得到用户特征向量和物品特征向量。
    这些特征向量用于预测用户对未评分物品的潜在评分。
  • 计算用户相似度:
    使用 calculate_similarity 函数计算用户之间的余弦相似度。
  • 生成推荐:
    使用 get_top_n_recommendations 函数生成推荐列表。
    结合 ALS 的预测评分和基于用户相似度的预测评分。
    通过调整权重(在这个例子中是 0.7 和 0.3)来平衡这两种推荐方法的影响
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于协同过滤算法的在线图书推荐系统是利用用户对图书的评分行为以及图书之间的相似性来为用户推荐可能感兴趣的图书。在这个系统中,ALS矩阵分解算法是一种基于模型的协同过滤算法ALS矩阵分解算法是一种常用的协同过滤算法,其主要思想是将用户-图书评分矩阵分解为两个低维度的矩阵,通过学习用户和图书的隐含特征来预测用户对未评价图书的评分,并根据预测评分来进行推荐。 具体而言,ALS矩阵分解算法分为两个步骤:交替最小二乘法和优化用户/图书隐向量。在交替最小二乘法中,通过固定隐向量中一个变量,更新另一个变量,直到收敛。在优化用户/图书隐向量过程中,通过最小化预测评分和实际评分之间的差距来优化隐向量。 在在线图书推荐系统中,首先需要根据用户的历史评分数据构建用户-图书评分矩阵。然后,通过ALS矩阵分解算法来训练模型,得到用户和图书的隐向量。接下来,对于一个给定的用户,可以通过计算用户的隐向量与图书的隐向量之间的相似性来获取与用户兴趣最相似的图书。最后,根据相似性进行推荐,将推荐的图书推送给用户。 基于协同过滤算法的在线图书推荐系统不仅考虑用户的历史行为,还能通过挖掘图书之间的相似性来为用户推荐可能感兴趣的图书。通过使用ALS矩阵分解算法,系统可以根据用户行为数据进行模型训练和隐向量推断,从而提高图书推荐的准确性和个性化程度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值