基于用户的协同过滤算法(及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

相关文章
|
2月前
|
搜索推荐 前端开发 数据可视化
【优秀python web毕设案例】基于协同过滤算法的酒店推荐系统,django框架+bootstrap前端+echarts可视化,有后台有爬虫
本文介绍了一个基于Django框架、协同过滤算法、ECharts数据可视化以及Bootstrap前端技术的酒店推荐系统,该系统通过用户行为分析和推荐算法优化,提供个性化的酒店推荐和直观的数据展示,以提升用户体验。
|
2月前
|
JavaScript 算法 前端开发
JS算法必备之String常用操作方法
这篇文章详细介绍了JavaScript中字符串的基本操作,包括创建字符串、访问特定字符、字符串的拼接、位置查找、大小写转换、模式匹配、以及字符串的迭代和格式化等方法。
JS算法必备之String常用操作方法
|
2月前
|
JavaScript 算法 前端开发
JS算法必备之Array常用操作方法
这篇文章详细介绍了JavaScript中数组的创建、检测、转换、排序、操作方法以及迭代方法等,提供了数组操作的全面指南。
JS算法必备之Array常用操作方法
|
6天前
|
算法 C++
如何精确计算出一个算法的CPU运行时间?
如何精确计算出一个算法的CPU运行时间?
|
2月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
22 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
2月前
|
搜索推荐 前端开发 算法
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
本文介绍了一个基于用户画像和协同过滤算法的音乐推荐系统,使用Django框架、Bootstrap前端和MySQL数据库构建,旨在为用户提供个性化的音乐推荐服务,提高推荐准确性和用户满意度。
110 7
基于用户画像及协同过滤算法的音乐推荐系统,采用Django框架、bootstrap前端,MySQL数据库
|
1月前
|
算法 数据可视化 数据安全/隐私保护
基于LK光流提取算法的图像序列晃动程度计算matlab仿真
该算法基于Lucas-Kanade光流方法,用于计算图像序列的晃动程度。通过计算相邻帧间的光流场并定义晃动程度指标(如RMS),可量化图像晃动。此版本适用于Matlab 2022a,提供详细中文注释与操作视频。完整代码无水印。
|
2月前
|
算法 定位技术 vr&ar
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
146 0
一文了解PnP算法,python opencv中的cv2.solvePnP()的使用,以及使用cv2.sovlePnP()方法标定相机和2D激光雷达
|
3月前
|
机器学习/深度学习 编解码 监控
算法金 | 深度学习图像增强方法总结
**图像增强技术概括** 图像增强聚焦于提升视觉效果和细节,广泛应用于医学、遥感等领域。空间域增强包括直方图均衡化(增强对比度)、对比度拉伸、灰度变换、平滑滤波(均值、中值)和锐化滤波(拉普拉斯、高通)。频率域增强利用傅里叶变换、小波变换,通过高频和低频滤波增强图像特征。现代方法涉及超分辨率重建、深度学习去噪(如CNN、Autoencoder)、图像修复(如GAN)和GANs驱动的多种图像处理任务。
81 14
算法金 | 深度学习图像增强方法总结
|
2月前
|
算法 Go Python
[算法]计算斐波拉契数列
[算法]计算斐波拉契数列
下一篇
无影云桌面