基于用户的协同过滤算法(及3种计算用户相似度的方法)

简介: 本文参考《推荐系统实践》中基于用户的协同过滤算法内容。基于老师上课讲解,自己实现了其中的代码,了解了整个过程。

UserCF算法实现


实现原理


基于用户的协同过滤算法:

第一步,找到和目标用户兴趣相似的用户集合


第二步,找到这个集合中的用户喜欢的物品,然后过滤掉目标用户已经看到过或听说过的物品(发生过用户行为的),把没有听说过的物品推荐给目标用户


模拟数据


数据格式为 u-i(用户-物品)字典

A B C ……为用户 a b c ……为物品

并添加了用户分别对某一物品的评分

import math
from operator import itemgetter
UserCF_dict =  {"A": {"a": 4.0, "b": 0.0, "c": 5.0, "d": 3.5, "e": 0.0, "f":2.0, "h":0.0},
               "B": {"a": 0.0, "b": 3.0, "c": 4.5, "d": 1.0, "e": 3.5, "f":0.0, "h":3.0},
               "C": {"a": 2.5, "b": 2.0, "c": 1.0, "d": 0.0, "e": 3.0, "f":4.0, "h":0.0},
               "D": {"a": 1.0, "b": 0.0, "c": 0.0, "d": 6.5, "e": 1.5, "f":0.0, "h":4.0},
               "E": {"a": 0.0, "b": 4.0, "c": 3.0, "d": 0.0, "e": 2.0, "f":1.0, "h":1.5},
               "F": {"a": 4.0, "b": 1.5, "c": 0.0, "d": 0.5, "e": 1.5, "f":3.5, "h":0.0}}


两两用户之间计算


用两两用户之间计算兴趣相似度,给定用户u和用户v,其中N(u)表示用户u曾经有过用户行为的物品集合(u喜欢的物品集合),N(v)表示用户v曾经有过用户行为的物品集合,然后我们有两种公式计算uv的兴趣相似度:

1.Jaccard公式

11.png

2.余弦计算相似度公式

12.png

附图解释:

13.png

def UserSimilarity(dict_):
    w = dict()
    for u in dict_.keys():
        w[u] = dict()   #太久不写生疏了 字典要一步一步添加
        for v in dict_.keys():
            if u == v :
                continue
#             print(dict_[u].keys)
            u_dict = set([k for k in dict_[u].keys() if dict_[u][k] != 0]) # 对于u用户找出它发生过用户行为的物品集合 (即打过评分的物品集合)
            v_dict = set([k for k in dict_[v].keys() if dict_[v][k] != 0])
            w[u][v] = len(u_dict & v_dict)
            w[u][v] /= math.sqrt(len(u_dict) * len(v_dict) * 1.0)
    return w
# len(UesrCF_dict['A'] & UesrCF_dict['B'])
w1 = UserSimilarity(UserCF_dict)


优化后的倒查表方式计算用户相似度


根据模拟数据建立物品到用户的倒查表,即对于每个物品保存对该物品产生过用户行为的用户列表

count字典存的是统计两个用户间是否有相同喜欢的物品,大大减少两两用户间没有相关性却遍历进行计算的时间

def UserSimilarity_better(dict_):
    items_users = dict()
    for u,items in dict_.items():
#         print(u)
        for i in items.keys():
#             print(i)
            items_users.setdefault(i,set())
#             print(dict_[u][i])
            if dict_[u][i] != 0:
                items_users[i].add(u)
#                 print(items_users[i])
#     print(items_users)
    count = dict()
    num = dict()
    for i,ur in items_users.items(): #i:{a,b,c,d,……}
        for u in ur:
            num.setdefault(u,0)
            num[u] += 1
#             items_users.setdefault(i,set())
            count.setdefault(u,dict())  #key: A B C ……
            for v in ur:
                count[u].setdefault(v,0)
                if u == v:
                    continue
                count[u][v] += 1 #gonggong
    w = dict()
    for u,realted_u in count.items():
        w.setdefault(u,dict())
        for v,cuv in realted_u.items():
            if u == v:
                continue
            w[u].setdefault(v,0)
            w[u][v] = cuv/math.sqrt(num[u] * num[v] * 1.0)
    return w
w2 = UserSimilarity_better(UserCF_dict)


采用惩罚热门物品和倒查表方式计算用户相似度方法


同倒查表方式,只不过增加了一个 log函数 降低热门物品的影响

14.png

def UserSimilarity_best(dict_):
    items_users = dict()
    for u,items in dict_.items():
#         print(u)
        for i in items.keys():
#             print(i)
            items_users.setdefault(i,set())
#             print(dict_[u][i])
            if dict_[u][i] != 0:
                items_users[i].add(u)
    count = dict()
    num = dict()
    for i,ur in items_users.items(): #i:{a,b,c,d,……} ur:用户集合 热门
        for u in ur:
            num.setdefault(u,0)
            num[u] += 1
#             items_users.setdefault(i,set())
            count.setdefault(u,dict())  #key: A B C ……
            for v in ur:
                count[u].setdefault(v,0)
                if u == v:
                    continue
                count[u][v] += 1/math.log(1 + len(ur)) #gonggong log惩罚
    w = dict()
    for u,realted_u in count.items():
        w.setdefault(u,dict())
        for v,cuv in realted_u.items():
            if u == v:
                continue
            w[u].setdefault(v,0)
            w[u][v] = cuv/math.sqrt(num[u] * num[v] * 1.0)
    return w
w3 = UserSimilarity_best(UserCF_dict)


推荐函数


在推荐函数中要注重k值的选取,从表格中可以看出随着k值变化 (准确率,召回率)先增加后减少 而覆盖率先减少后增加,表明我们推荐的物品比较集中 不太好 应尽量覆盖全面商品

流行度逐渐增加,表现我们推荐的物品集中于热门物品。应做好K值的选取。

15.png

def recommend(u,dict_,w_,k):
#先得到用户对于喜欢物品的字典
#再找到目标用户相似度最高的k个用户
#获取k个用户的喜欢物品 删掉其中目标用户已发生过行为的物品
#再计算物品的推荐分数 =  目标用户与前k用户的相似度*前k用户喜欢物品的评分(求和)
    cout = dict()
    for i in dict_.keys():
        cout[i] = set()
        for j in dict_[i].keys():
            if dict_[i][j] != 0:
                cout[i].add(j)
#     print(cout)
#     print(w_[u])
    x = sorted(w_[u].items(),key = itemgetter(1),reverse = True)[:k]
#     print(x)
    cout_item = dict()
    for i in range(k):
#         cout_item[x[i]] = set()
        cout_item[x[i][0]] = [ki for ki in cout[x[i][0]] if ki not in cout[u]]
#     print(cout_item)
    rank = dict()
    for j in cout_item.keys():
        for i in range(len(cout_item[j])):
#             print(cout_item[j][i])
            rank.setdefault(cout_item[j][i],0)  
            rank[cout_item[j][i]] += w_[u][j] * dict_[j][cout_item[j][i]]
#             rank[ans] = 0
    print(rank)
#调用
ans = ['两两用户之间计算','优化后的倒查表方式计算用户相似度','采用惩罚热门物品和倒查表方式计算用户相似度方法']
li = [w1,w2,w3]
for i in range(3):
    print(ans[i])
    recommend('A',UserCF_dict,li[i],2)

16.png

相关文章
|
3月前
|
存储 编解码 算法
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
172 6
|
3月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
392 0
|
3月前
|
算法 机器人
基于SOA海鸥优化算法的PID控制器最优控制参数计算matlab仿真
本课题研究基于海鸥优化算法(SOA)优化PID控制器参数的方法,通过MATLAB仿真对比传统PID控制效果。利用SOA算法优化PID的kp、ki、kd参数,以积分绝对误差(IAE)为适应度函数,提升系统响应速度与稳定性。仿真结果表明,SOA优化的PID控制器在阶跃响应和误差控制方面均优于传统方法,具有更快的收敛速度和更强的全局寻优能力,适用于复杂系统的参数整定。
|
4月前
|
机器学习/深度学习 数据采集 传感器
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
370 0
|
2月前
|
机器学习/深度学习 数据采集 负载均衡
结合多种启发式解码方法的混合多目标进化算法,用于解决带工人约束的混合流水车间调度问题(Matlab代码实现)
结合多种启发式解码方法的混合多目标进化算法,用于解决带工人约束的混合流水车间调度问题(Matlab代码实现)
171 0
|
2月前
|
机器学习/深度学习 算法 物联网
基于遗传方法的动态多目标优化算法
基于遗传方法的动态多目标优化算法
|
7月前
|
算法 JavaScript 数据安全/隐私保护
基于GA遗传优化的最优阈值计算认知异构网络(CHN)能量检测算法matlab仿真
本内容介绍了一种基于GA遗传优化的阈值计算方法在认知异构网络(CHN)中的应用。通过Matlab2022a实现算法,完整代码含中文注释与操作视频。能量检测算法用于感知主用户信号,其性能依赖检测阈值。传统固定阈值方法易受噪声影响,而GA算法通过模拟生物进化,在复杂环境中自动优化阈值,提高频谱感知准确性,增强CHN的通信效率与资源利用率。预览效果无水印,核心程序部分展示,适合研究频谱感知与优化算法的学者参考。
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
1249 6
|
8月前
|
机器学习/深度学习 存储 算法
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
本文系统讲解从基本强化学习方法到高级技术(如PPO、A3C、PlaNet等)的实现原理与编码过程,旨在通过理论结合代码的方式,构建对强化学习算法的全面理解。
2191 10
18个常用的强化学习算法整理:从基础方法到高级模型的理论技术与代码实现
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
248 3

热门文章

最新文章