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

2023-11-13

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

实现原理

基于用户的协同过滤算法:
第一步,找到和目标用户兴趣相似的用户集合

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

模拟数据

数据格式为 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公式
在这里插入图片描述
2.余弦计算相似度公式
在这里插入图片描述
附图解释:
在这里插入图片描述

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函数 降低热门物品的影响在这里插入图片描述

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值的选取。
在这里插入图片描述

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)

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 如何查看Databricks中的所有数据库和表

    我想列出 Azure Databricks 中每个数据库中的所有表 所以我希望输出看起来像这样 Database Table name Database1 Table 1 Database1 Table 2 Database1 Table
  • 将 Matplotlib 误差线放置在不位于条形中心的位置

    我正在 Matplotlib 中生成带有错误栏的堆积条形图 不幸的是 某些层相对较小且数据多样 因此多个层的错误条可能重叠 从而使它们难以或无法读取 Example 有没有办法设置每个误差条的位置 即沿 x 轴移动它 以便重叠的线显示在彼此
  • 使 django 服务器可以在 LAN 中访问

    我已经安装了Django服务器 可以如下访问 http localhost 8000 get sms http 127 0 0 1 8000 get sms 假设我的IP是x x x x 当我这样做时 从同一网络下的另一台电脑 my ip
  • 为 Anaconda Python 安装 psycopg2

    我有 Anaconda Python 3 4 但是每当我运行旧代码时 我都会通过输入 source activate python2 切换到 Anaconda Python 2 7 我的问题是我为 Anaconda Python 3 4 安
  • 通过最小元素比较对 5 个元素进行排序

    我必须在 python 中使用元素之间的最小比较次数来建模对 5 个元素的列表进行排序的执行计划 除此之外 复杂性是无关紧要的 结果是一个对的列表 表示在另一时间对列表进行排序所需的比较 我知道有一种算法可以通过 7 次比较 总是在元素之间
  • 使用带有关键字参数的 map() 函数

    这是我尝试使用的循环map功能于 volume ids 1 2 3 4 5 ip 172 12 13 122 for volume id in volume ids my function volume id ip ip 我有办法做到这一点
  • 从字符串中删除识别的日期

    作为输入 我有几个包含不同格式日期的字符串 例如 彼得在16 45 我的生日是1990年7月8日 On 7 月 11 日星期六我会回家 I use dateutil parser parse识别字符串中的日期 在下一步中 我想从字符串中删除
  • 根据列值突出显示数据框中的行?

    假设我有这样的数据框 col1 col2 col3 col4 0 A A 1 pass 2 1 A A 2 pass 4 2 A A 1 fail 4 3 A A 1 fail 5 4 A A 1 pass 3 5 A A 2 fail 2
  • 如何从网页中嵌入的 Tableau 图表中抓取工具提示值

    我试图弄清楚是否有一种方法以及如何使用 python 从网页中的 Tableau 嵌入图形中抓取工具提示值 以下是当用户将鼠标悬停在条形上时带有工具提示的图表示例 我从要从中抓取的原始网页中获取了此网址 https covid19 colo
  • 基于代理的模拟:性能问题:Python vs NetLogo & Repast

    我正在 Python 3 中复制一小段 Sugarscape 代理模拟模型 我发现我的代码的性能比 NetLogo 慢约 3 倍 这可能是我的代码的问题 还是Python的固有限制 显然 这只是代码的一个片段 但 Python 却花费了三分
  • 以编程方式停止Python脚本的执行? [复制]

    这个问题在这里已经有答案了 是否可以使用命令在任意行停止执行 python 脚本 Like some code quit quit at this point some more code that s not executed sys e
  • BeautifulSoup 中的嵌套标签 - Python

    我在网站和 stackoverflow 上查看了许多示例 但找不到解决我的问题的通用解决方案 我正在处理一个非常混乱的网站 我想抓取一些数据 标记看起来像这样 table tbody tr tr tr td td td table tr t
  • 如何在ipywidget按钮中显示全文?

    我正在创建一个ipywidget带有一些文本的按钮 但按钮中未显示全文 我使用的代码如下 import ipywidgets as widgets from IPython display import display button wid
  • Flask如何获取请求的HTTP_ORIGIN

    我想用我自己设置的 Access Control Allow Origin 标头做出响应 而弄清楚请求中的 HTTP ORIGIN 参数在哪里似乎很混乱 我在用着烧瓶 0 10 1 以及HTTP ORIGIN似乎是这个的特点之一object
  • 在Python中获取文件描述符的位置

    比如说 我有一个原始数字文件描述符 我需要根据它获取文件中的当前位置 import os psutil some code that works with file lp lib open path to file p psutil Pro
  • 如何在Python中对类别进行加权随机抽样

    给定一个元组列表 其中每个元组都包含一个概率和一个项目 我想根据其概率对项目进行采样 例如 给出列表 3 a 4 b 3 c 我想在 40 的时间内对 b 进行采样 在 python 中执行此操作的规范方法是什么 我查看了 random 模
  • 将图像分割成多个网格

    我使用下面的代码将图像分割成网格的 20 个相等的部分 import cv2 im cv2 imread apple jpg im cv2 resize im 1000 500 imgwidth im shape 0 imgheight i
  • 如何在seaborn displot中使用hist_kws

    我想在同一图中用不同的颜色绘制直方图和 kde 线 我想为直方图设置绿色 为 kde 线设置蓝色 我设法弄清楚使用 line kws 来更改 kde 线条颜色 但 hist kws 不适用于显示 我尝试过使用 histplot 但我无法为
  • 解释 Python 中的数字范围

    在 Pylons Web 应用程序中 我需要获取一个字符串 例如 关于如何做到这一点有什么建议吗 我是 Python 新手 我还没有找到任何可以帮助解决此类问题的东西 该列表将是 1 2 3 45 46 48 49 50 51 77 使用
  • Python Selenium:如何在文本文件中打印网站上的值?

    我正在尝试编写一个脚本 该脚本将从 tulsaspca org 网站获取以下 6 个值并将其打印在 txt 文件中 最终输出应该是 905 4896 7105 23194 1004 42000 放置的动物 的 HTML span class

随机推荐

  • JS(ES5,ES6)实现栈数据结构

    栈是一种遵从后进先出原则的有序集合 新添加的或待删除的元素都保存在栈的同一端 称作栈顶 另一端叫做栈底 栈也被用在编程语言的编译器和内存中保存变量 方法调用等 ES5实现 function Stack let items 向栈添加元素 th
  • Git拉取分支代码小结以及问题解决

    更全面的版本 三分钟学会git 一 拉取代码 git clone git example com myproject 默认拉取的master 若需要切换分支 git branch a master origin HEAD origin ma
  • vlc-android源码的编译

    一 编译前须知 1 参考官方文档 https wiki videolan org AndroidCompile 2 必须要在Linux环境下 3 我使用的是ubuntu 二 编译前安装开发工具 1 Linux操作系统 我选择的是在windo
  • 七牛云存储java_api代码实现

    这是思维图 画的有点拉 看官老爷凑合看 接下来就按照这个逻辑来实现 七牛云本身是提供的Java SDK的 可以完成图片上传和删除 我们可以参考官方提供的例子 官方文档 https developer qiniu com kodo sdk 1
  • Python组合数据的输入问题

    以输入5个数据为例 以前是单个变量的处理 所以习惯单个数据输入 a eval input 输入5个数据 自然想到的就是让它循环5次 这种方式执行时 因为每次输入回车 相当于竖着输 能不能一次输入呢 在一行横着输 元组 t eval inpu
  • 网络攻防——Fiddler工具的使用

    Fiddler工具的使用 1 引言 2 什么是Fiddler 3 Fiddler的基本使用 4 基于手机模拟器的APP抓包 5 接口捕获 6 引言 7 鸣谢 1 引言 虽然之前写了退出一切关于编程的学习 其实我还想学react typesc
  • 【cdk的使用】C语言 跨平台生成伪随机数

    Github地址 https github com wujin1989 cdk C标准库中有rand 和srand 函数用来生成伪随机数 但是虽然在标准库里 确依然不能跨平台 因为C标准里没有明确rand 函数生成的随机数范围 比如 win
  • 【Xilinx DMA SG】Xilinx DMA SG 模式

    DMA简介 AXI 直接存储器访问 AXI DMA IP 提供高带宽直接存储器 AXI4 存储器映射和 AXI4 Stream IP 接口之间的访问 它SG模式还可以从中央处理中卸载数据移动任务 基于处理器的系统中的单元 CPU 初始化 状
  • 机器学习入门——线性回归预测广告投入数据集

    0 Advertising数据集 Advertising数据集是关于广告收益与广告在不同的媒体上投放的相关数据 分别是在TV Radio Newspaper三种媒体上投放花费与 投放所产生的收益的数据 数据共有200条 数据的格式如下 1
  • 线性回归最小二乘法和梯度下降法-详细

    原文 https blog csdn net y990041769 article details 69567838 问题描述 首先我们定义问题 线性回归要解决的问题就是根据给出的数据学习出一个线性模型 例如我们最常说的身高和体重的关系 以
  • EasyConnect linux(ubuntu 20.04)下运行报错

    EasyConnect 67186 Pango ERROR 10 01 20 576 Harfbuzz version too old 1 3 1 报错原因 本地系统更新导致相关依赖包的版本高于EasyConnect需要的版本 解决方式 下
  • vue3中采用pinia集中管理数据

    Pinia 起始于 2019 年 11 月左右的一次实验 其目的是设计一个拥有组合式 API 的 Vue 状态管理库 从那时起 我们就倾向于同时支持 Vue 2 和 Vue 3 并且不强制要求开发者使用组合式 API 下载依赖 yarn a
  • go基础+面试题(持续更新中...)

    go基础 面试题 Go基础 main 变量 变量的声明 局部变量 全局变量 常量与iota 常量 string和 byte如何取舍 string与nil类型的问题 Iota编译原理 内存四区 struct结构体 函数 make与new的区别
  • globbing

    1 globbing是什么 globbing表示通配符 BASH支持文件名通配 2 globbing常用列表及使用心得 序号 符号 使用心得 1 表示任意一个字符 注意与常规的正则表达式的区别 正则中 表示可选的 2 表示任意长度任意字符
  • STM32HAL----USB模拟串口(VCP)

    想要实现的功能是 USB模拟串口收发数据 串口助手发送数据至MCU MCU接收后返回给串口助手 当初是想用标准库做这个功能的 但是因为后来了解到STM32CubeMX这个软件 在尝试之后实在是感觉 太方便了 所以 并没有使用标准库 而是直接
  • Python---函数

    PP2study5 一 函数定义 二 函数调用 三 可变对象和不可变对象的使用 四 参数传递 4 1 以下是调用函数时可使用的正式参数类型 1 必需参数 2 关键字参数 3 默认参数 4 不定长参数 4 2 return 一 函数定义 Py
  • autoReconnect及查看和连接时间有关的系统变量与通常产生的异常

    MySQL官方不推荐使用autoReconnect true 参见http bugs mysql com bug php id 5020 注意这里说的版本是3 0 14 production 需要另外找别的办法来解决超过8小时 链接断开的问
  • 【数据结构和算法】字符串操作

    作者 Linux猿 简介 CSDN博客专家 华为云享专家 Linux C C 云计算 物联网 面试 刷题 算法尽管咨询我 关注我 有问题私聊 关注专栏 数据结构和算法成神路 精讲 优质好文持续更新中 欢迎小伙伴们点赞 收藏 留言 目录 一
  • CAsyncSocket进行UDP通信

    CAsyncSocket进行UDP通信 客户端代码 CString m ServerIP CString m ClientIP int m ClientPort CString m ReceiveData UINT m ServerPort
  • 基于用户的协同过滤算法(及3种计算用户相似度的方法)

    本文参考 推荐系统实践 中基于用户的协同过滤算法内容 基于老师上课讲解 自己实现了其中的代码 了解了整个过程 UserCF算法实现 实现原理 模拟数据 两两用户之间计算 优化后的倒查表方式计算用户相似度 采用惩罚热门物品和倒查表方式计算用户