深入探索协同过滤:从原理到推荐模块案例

在这里插入图片描述

文章目录

  • 前言
  • 一、协同过滤
    • 1. 基于用户的协同过滤(UserCF)
    • 2. 基于物品的协同过滤(ItemCF)
    • 3. 相似度计算方法
  • 二、相似度计算方法
    • 1. 欧氏距离
    • 2. 皮尔逊相关系数
    • 3. 杰卡德相似系数
    • 4. 余弦相似度
  • 三、推荐模块案例
    • 1.基于文章的协同过滤推荐功能
    • 2.基于用户的协同过滤推荐功能


前言

    在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于协同过滤算法,这一实现个性化推荐的核心技术。我们将探讨基于用户和基于物品的两种协同过滤方法,并分析它们的优缺点。同时,深入讨论相似度计算方法,这是影响推荐效果的关键。通过两个具体案例——基于文章和基于用户的协同过滤推荐功能,我们将展示协同过滤算法在实际应用中的魅力。这些案例不仅帮助理解算法原理,也提供了实战参考。希望本文能引导你掌握协同过滤算法精髓,并能在实践中灵活运用,为构建精准、高效的推荐系统贡献力量。


一、协同过滤

    协同过滤(Collaborative Filtering, CF) 是一种广泛应用于推荐系统中的算法,它通过分析用户的行为和偏好,发现用户之间的相似性(或物品之间的相似性),从而为用户推荐他们可能感兴趣的物品。常用来实现推荐模块的协同过滤算法主要分为两类:基于用户的协同过滤(User-Based Collaborative Filtering, UserCF)基于物品的协同过滤(Item-Based Collaborative Filtering, ItemCF)

1. 基于用户的协同过滤(UserCF)

基本思想:

    基于用户的协同过滤算法通过分析用户对物品的喜好来找到与用户兴趣相似的其他用户,然后将这些相似用户喜欢的、且目标用户尚未听说过的物品推荐给目标用户。这种方法认为,如果两个用户在过去的喜好上有很多重叠,那么他们未来可能也会对相同的物品感兴趣。

算法步骤:

  1. 收集用户行为数据: 通常包括用户评分、购买、浏览等行为数据。
  2. 计算用户相似度: 使用相似度计算方法(如余弦相似度、皮尔逊相关系数等)来计算用户之间的相似度。
  3. 生成推荐列表: 根据相似用户的喜好来预测目标用户对未评分物品的兴趣程度,并生成推荐列表。

优点:

  • 能够捕捉到用户的动态兴趣变化。
  • 对于新用户来说,只要有足够的相似用户,也能产生不错的推荐效果。

缺点:

  • 随着用户数量的增加,计算用户相似度的开销会急剧上升。
  • 对于用户兴趣分布不均匀的情况,可能无法找到足够多的相似用户。

2. 基于物品的协同过滤(ItemCF)

基本思想:

    基于物品的协同过滤算法通过分析用户对不同物品的喜好来找到与目标物品相似的其他物品,然后将这些相似物品推荐给喜欢目标物品的用户。这种方法认为,如果两个物品被很多相同的用户喜欢,那么这两个物品之间就存在某种相似性,因此可以将一个物品推荐给喜欢另一个物品的用户。

算法步骤:

  1. 收集用户行为数据: 与用户CF相同。
  2. 计算物品相似度: 使用相似度计算方法(如余弦相似度、杰卡德相似度等)来计算物品之间的相似度。
  3. 生成推荐列表: 根据用户对已评分物品的喜好和物品之间的相似度来预测用户对未评分物品的兴趣程度,并生成推荐列表。

优点:

  • 能够处理大规模数据集,因为物品之间的相似度是静态的,可以离线计算并存储。
  • 能够发现物品之间的隐式关系,提高推荐的多样性。

缺点:

  • 对于新用户来说,如果没有足够的行为数据,可能无法产生有效的推荐。
  • 推荐的实时性较差,因为物品之间的相似度是预先计算好的。

3. 相似度计算方法

在实现协同过滤算法时,常用的相似度计算方法包括:

  • 余弦相似度: 衡量两个向量在方向上的相似程度,取值范围在[-1,1]之间。
  • 皮尔逊相关系数: 在余弦相似度的基础上考虑了向量的大小(即评分的尺度),更适合处理具有不同评分尺度的用户数据。
  • 杰卡德相似系数: 主要用于衡量两个集合之间的相似度,适用于用户-物品交互数据非常稀疏的情况。

    综上所述,协同过滤算法通过利用用户或物品之间的相似性来产生推荐,具有实现简单、效果显著等优点,是推荐系统中常用的算法之一。然而,它也存在一些局限性,如冷启动问题、稀疏性问题等,需要在实际应用中结合其他算法和技术来加以解决。


二、相似度计算方法

1. 欧氏距离

    在协同过滤算法中,物品之间的相似度计算是推荐系统的重要组成部分,而欧几里得距离(Euclidean Distance) 作为一种常用的距离度量方式,也可以被转化为相似度指标来评估物品之间的相似程度。

    欧几里得距离,也称为欧式距离,是在多维空间中两点之间的直线距离。在二维空间中,它可以通过勾股定理来计算;在多维空间中,则可以通过计算各维度上差的平方和的平方根来得到。对于物品之间的相似度计算,我们可以将每个物品视为多维空间中的一个点,其中每个维度代表物品的一个特征(如用户对物品的评分、物品的某些属性等)。

欧几里得距离转化为相似度:

    虽然欧几里得距离本身表示的是两点之间的物理距离,但在实际应用中,我们通常希望得到一个表示相似度的值,而不是距离。因此,需要将欧几里得距离转化为相似度。然而,需要注意的是,欧几里得距离与相似度是成反比的,即距离越大,相似度越小;距离越小,相似度越大。

为了将欧几里得距离转化为相似度,可以采用以下几种方法:

  1. 距离的倒数: 直接使用距离的倒数作为相似度值,即1/d。但这种方法在距离接近0时会导致相似度值趋于无穷大,因此可能需要进一步处理(如加1或设置上限)。
  2. 距离的倒数加常数: 为了避免上述问题,可以在距离的倒数上加一个常数(如1),即1/(d+1)。这样,即使距离很小,相似度值也不会过大。
  3. 归一化处理: 将计算得到的相似度值进行归一化处理,使其落在某个特定的区间内(如[0,1]),以便与其他相似度计算方法的结果进行比较。
  4. 使用其他相似度度量: 虽然欧几里得距离本身不适合直接作为相似度度量,但可以通过其他方式(如余弦相似度、皮尔逊相关系数等)来计算物品之间的相似度。

2. 皮尔逊相关系数

    皮尔逊相关系数(Pearson Correlation Coefficient) 是统计学中用于度量两个变量X和Y之间线性相关程度的一种方法。在协同过滤算法中,特别是基于用户的协同过滤(UserCF)中,皮尔逊相关系数被广泛应用于计算用户之间的相似度。

    在基于用户的协同过滤中,我们通常使用用户对物品的评分数据来计算用户之间的相似度。 设用户U1和用户U2分别对n个物品进行了评分,则可以通过计算这两个用户评分向量的皮尔逊相关系数来评估他们之间的相似度。具体地,将用户对每个物品的评分视为一个变量,则两个用户的评分向量就可以看作是这些变量的两个观测值序列。通过计算这两个序列的皮尔逊相关系数,我们就可以得到一个介于-1和1之间的数值,用于表示这两个用户之间的相似度。

3. 杰卡德相似系数

    用户之间的相似度计算方法中的杰卡德相似系数(Jaccard Similarity Coefficient) 是一种用于衡量两个集合之间相似度的指标,它也可以应用于用户之间的相似度计算,特别是在用户行为数据(如购买记录、浏览历史等)可以表示为集合形式时。

应用场景:
在用户相似度计算中,杰卡德相似系数适用于以下场景:

  • 电商推荐: 在电商平台中,可以根据用户的购买记录计算用户之间的杰卡德相似系数,从而找出具有相似购买行为的用户群体,并为他们推荐可能感兴趣的商品。
  • 社交网络: 在社交网络中,可以根据用户的关注、点赞、评论等行为数据计算用户之间的杰卡德相似系数,以发现潜在的朋友关系或兴趣群体。
  • 内容推荐: 在新闻、视频、音乐等内容推荐场景中,可以根据用户的历史浏览或消费记录计算用户之间的杰卡德相似系数,从而为用户推荐与其兴趣相似的内容。

4. 余弦相似度

    协同过滤中的余弦相似度是一种常用的用户或物品相似度计算方法,它通过计算两个向量在向量空间中夹角的余弦值来评估它们的相似度。

示例代码:

# -*- coding: utf-8 -*-
import numpy as np
import pandas as pduserid =1008
exportdata = []
goodsidlist = []def load_data(file_path):global useridglobal goodsidlist'''导入用户商品数据input:  file_path(string):用户商品数据存放的文件output: data(mat):用户商品矩阵'''filedata = pd.read_csv(file_path)# print(filedata.values[0][0])data1 = filedata.drop(['userid'],axis=1)data = pd.DataFrame(data1)goodsidlist = data.columns.values.tolist()return np.mat(data)def cos_sim(x, y):'''余弦相似性input:  x(mat):以行向量的形式存储,可以是用户或者商品y(mat):以行向量的形式存储,可以是用户或者商品output: x和y之间的余弦相似度'''numerator = x * y.T  # x和y之间的额内积denominator = np.sqrt(x * x.T) * np.sqrt(y * y.T) return (numerator / denominator)[0, 0]def similarity(data):'''计算矩阵中任意两行之间的相似度input:  data(mat):任意矩阵output: w(mat):任意两行之间的相似度'''m = np.shape(data)[0]  # 用户的数量# 初始化相似度矩阵w = np.mat(np.zeros((m, m)))for i in range(m):for j in range(i, m):if j != i:# 计算任意两行之间的相似度w[i, j] = cos_sim(data[i, ], data[j, ])w[j, i] = w[i, j]else:w[i, j] = 0return wdef user_based_recommend(data, w, user):'''基于用户相似性为用户user推荐商品input:  data(mat):用户商品矩阵w(mat):用户之间的相似度user(int):用户的编号output: predict(list):推荐列表'''m, n = np.shape(data)interaction = data[user, ]  # 用户user与商品信息# print(interaction)# 1、找到用户user没有互动过的商品not_inter = []for i in range(n):if interaction[0, i] == 0:  # 没有互动的商品not_inter.append(i)# 2、对没有互动过的商品进行预测predict = {}for x in not_inter:item = np.copy(data[:, x])  # 找到所有用户对商品x的互动信息for i in range(m):  # 对每一个用户if item[i, 0] != 0:  # 若该用户对商品x有过互动if x not in predict:predict[x] = w[user, i] * item[i, 0]else:predict[x] = predict[x] + w[user, i] * item[i, 0]# 3、按照预测的大小从大到小排序return sorted(predict.items(), key=lambda d:d[1], reverse=True)def top_k(predict, k):'''为用户推荐前k个商品input:  predict(list):排好序的商品列表k(int):推荐的商品个数output: top_recom(list):top_k个商品'''top_recom = []len_result = len(predict)if k >= len_result:top_recom = predictelse:for i in range(k):top_recom.append(predict[i])return top_recom   if __name__ == "__main__":# 1、导入用户商品数据# print ("------------ 1. load data ------------")data = load_data("orders.csv")# 2、计算用户之间的相似性# print ("------------ 2. calculate similarity between users -------------")   w = similarity(data)# 3、利用用户之间的相似性进行推荐# print ("------------ 3. predict ------------userid:::"+str(userid))   predict = user_based_recommend(data, w, userid)# 4、进行Top-K推荐# print ("------------ 4. top_k recommendation ------------")top_recom = top_k(predict, 5)relist=[]for i in top_recom:key = i[0]relist.append(goodsidlist[key])print(relist)

三、推荐模块案例

业务背景:
    在一个大型的在线内容平台,用户可以阅读各种类型的文章,包括新闻、博客、教程等。随着平台上内容的不断增长,用户面临着信息过载的问题,很难快速找到自己感兴趣的内容。为了提高用户体验,增加用户参与度和满意度,平台决定开发一个基于协同过滤算法的推荐模块,帮助用户发现个性化的内容。

1.基于文章的协同过滤推荐功能

    创建一个基于文章的协同过滤推荐功能的 Django 应用涉及到多个步骤,包括设计模型、收集用户行为数据、计算相似度和生成推荐。以下是一个简化的示例,展示如何使用 Django 实现协同过滤推荐功能。

步骤一:设计模型

Category(分类表)

字段名数据类型描述
nameVARCHAR(100)分类名称,唯一

Article(文章表)

字段名数据类型描述
titleVARCHAR(255)标题
contentTEXT内容
authorVARCHAR(100)作者
cateidForeignKey(Category)分类,外键关联分类表
tagsManyToManyField(Tag)标签,多对多关联标签表

Tag(标签表)

字段名数据类型描述
nameVARCHAR(100)标签名称,唯一

UserBrowseRecord(用户浏览记录表)

字段名数据类型描述
user_idForeignKey(User)用户ID,外键关联用户表
article_idForeignKey(Article)文章ID,外键关联文章表
tag_idForeignKey(Tag)标签ID,外键关联标签表
countINTEGER浏览次数,默认为0

步骤二:收集用户行为数据

    在这个示例中,假设用户已经浏览过多篇文章,用户浏览记录表UserBrowseRecord已有对应的浏览记录。

步骤三:计算相似度并生成推荐

    正常流程下,应该先构建一个方法用于计算用户之间的相似度(使用余弦相似度、皮尔逊相关系数等计算方法),并返回相似用户的分数;然后根据相似用户的评分来推荐文章。
    但是也可通过设置定时任务,每天晚上跑一次,查询用户浏览记录表根据次数排序,取前5个标签,根据标签去获取商品表中浏览次数最高前10篇文章,放到缓存。用户在推荐页获取推荐文章时,直接从缓存中获取。

class RecommendTest(APIView):def get(self, request):# 此函数中的内容可设置定时任务,定时更新对于不同用户的推荐信息# 获取所有用户信息users = User.objects.all()for user in users:# **对每个用户,获取其浏览记录,并将其推荐信息存储到redis中**uviews = UserBrowseRecord.objects.filter(user_id=user.id).order_by("-count").all()[:5]ids = [i.tag_id for i in uviews]recommend = Article.objects.filter(tags__in=ids).order_by("-id").all()[:10]recommend_data = ArticleSerializer(recommend,many=True).datar.set_str("usercommend"+str(user.id),json.dumps(recommend_data))return Response({"code":200,"mes":"推荐信息存储成功"})def post(self, request):#获取此userid缓存在redis中的推荐信息userid = request.data.get("userid")data = r.get_str("usercommend"+str(userid))return Response({"code":200,"mes":json.loads(data)})

2.基于用户的协同过滤推荐功能

1.收集数据,浏览记录表
2.查询与当前用户相似度最高的10个用户
3.查询那10个用户近期游览记录,取20条。与用户最近浏览取差集

def recommend_articles(request):# 获取当前用户的所有购买的商品标签user_ratings = list(UserBrowseRecord.objects.filter(user_id=1).values('article_id'))print("user_ratings ==> ",user_ratings)strs = [i['article_id'] for i in user_ratings]print("article_strs ==> ",strs)# 这文章被哪些人看过userlist = UserBrowseRecord.objects.filter(article_id__in=strs).values("user_id", 'count')print("userlist ==> ",userlist)print("len(userlist) ==> ",len(userlist))dict = {}for i in userlist:if i['user_id'] in dict:dict[i['user_id']] += i['count']else:dict[i['user_id']] = i['count']print("user_list ==> ",dict)# 相似度最高的用户列表similar_users = sorted(dict.items(), key=lambda x: x[1], reverse=True)[:10]print("similar_users ==> ",similar_users)# 获取这些用户看过的文章/标签?user_articles = [i['article_id'] for i in UserBrowseRecord.objects.filter(user_id__in=[i[0] for i in similar_users]).values('article_id')]print("user_articles ==> ",user_articles)# 文章 与 用户看过取差集recommend_articles = list(set(user_articles) - set(strs))print("recommend_articles ==> ",recommend_articles)# 根据tagid 获取此标签对应的阅读量最多的文章取前10个# recommend_articles_list = Article.objects.filter(id__in=recommend_articles).order_by("-id")[:10]return JsonResponse({"code": 200, 'recommend_articles_list': recommend_articles})

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/419778.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

Xilinx FPGA 原语解析(二):IBUFDS差分输入缓冲器(示例源码及仿真)

目录 前言: 一、原语使用说明 二、原语实例化代码模版 三、使用示例 1.设计文件代码 2.仿真文件代码 3.仿真结果 前言: 本文主要参考资料xilinx手册,《Xilinx 7 Series FPGA and Zynq-7000 All Programmable SoC Libraries Guide for…

全志A527 A133 A523 T527 T133 H6 H8应用无法开启后台服务

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析4.代码修改4.1 代码修改方法14.2 代码修改方法24.3 代码修改方法35.彩蛋1.前言 像全志的很多平台,普通的app并不能正常的启动后台的服务,这样对于应用层很困扰,无法启动后台的服务,功能就不能正常使用…

【自考zt】【软件工程】【21.10】

关键字: 软件需求基本性质、软件系统需求挑战、耦合(高内容,低无直接)、内聚(初始化时间)、uml包、rup边界类、测试首要目标、单元测试最后工作、性能需求 软件开发本质、软件需求规约三种风格、提炼、用…

【MySQL】MySQL库的操作

目录 创建数据库字符集和效验规则查看系统默认字符集和效验规则查看数据库支持的字符集查看数据库支持的字符集效验规则字符集对数据库的影响 操纵数据库查看数据库显示创建语句修改数据库数据库删除总结 数据库的备份和恢复备份恢复注意事项 查看数据库的连接情况 创建数据库 …

【C++】 Vector

文章目录 1 背景2 什么是 vector?3 vector 特性4 基本函数实现5 基本用法6 例子在 vector 最后移除和插入数据clear() 清除 vector 中所有数据排序访问(直接数组访问&迭代器访问)二维数组两种定义方法 7、参考 1 背景 C 中的容器&#x…

图片转pdf格式怎么弄?非常值得推荐的图片转PDF方法

图片转pdf格式怎么弄?在数字化办公和日常生活中,将图片转换成 PDF 格式已经成为一种常见而有效的处理方式。这种转换不仅能够将多张图片汇总到一个文件中,从而简化管理和共享的过程,还能够确保图像的原始质量和格式不会因不同设备…

WPS如何查看已添加到词典的单词

WPS Office(12.1.0.17827) ① 点击文件,在文件中找到选项 ② 找到拼写检查并点击自定义词典 ③ 如果要删除已添加到词典的"错词",则点击修改 ④ 选择"错词", 点击删除

STM32重定义printf,实现串口打印

在“usart.c”文件中加入以下代码 #ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch) #else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f) #endifPUTCHAR_PROTOTYPE{HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);return ch; }…

快速搞定会议记录,别错过这四款语音识别转文字!

作为一个偶尔需要在办公室做会议记录和采访录音整理的打工人。我表示,真的不想要练手速了,尤其是很多人在讲话的时候并不会在意别人来不来得及记录,只在意自己讲不讲的完,好在后面我找了几款语音识别转文字的工具,可算…

52%回报率背后:GPT-4o量化交易机器人的30天实战传奇

_本文介绍了如何利用GPT-4o,结合量化交易技术创建盈利的交易机器人策略,并通过回溯测试验证这一策略的有效性。 量化交易可以盈利,但只有拥有丰富资源、拥有编码和数学技能的交易者或大型机构才能使用。 但时代变了!现在有了 Cha…

idear获取git项目

最近想下载个ruoyi项目来包装简历,结果打开idear总是上一个项目,找不到get for vcs只好自己捣鼓了,顺便记录留着下次用。 步骤: 1. 2. 3.输入我们想访问的地址 eg: 点击克隆,我们就能获取项目到本地了。

【零基础必看的数据库教程】——SQL WHERE 子句

WHERE 子句用于提取那些满足指定条件的记录,过滤记录。 SQL WHERE 语法: SELECT column1, column2, ... FROM table_name WHERE condition; 参数说明: column1, column2, ...:要选择的字段名称,可以为多个字段。如…

网络层ip协议

一.概念 ip协议主要是为了在复杂的网络环境中确定一个合适的路径来传输主机间的数据。简单来说就是用来确定主机的位置。 ip协议中的一些设备如下: 主机: 配有 IP 地址, 但是不进行路由控制的设备;路由器: 即配有 IP 地址, 又能进行路由控制;节点: 主机和路由器的统…

浅谈OLTP 与 OLAP 数据建模的差异

OLTP 与 OLAP:常见工作流 联机分析处理 (OLAP) 和联机事务处理 (OLTP) 是两种主要的数据处理系统。两者之间存在多种差异。 OLTP 系统旨在处理来自多个用户的多个事务,它们通常用于许多应用程序的后端。例如,在线商务网站将使用 OLTP 系统来…

Spring6梳理7——依赖注入之特殊类型属性

目录 ①字面量赋值 ②null值 ③xml实体 ④CDATA节 ①字面量赋值 什么是字面量? int a10; 字面量是在源代码中用来表示固定值的表示法。几乎所有的计算机编程语言都支持基本值的字面量表示,例如整数、浮点数和字符串。许多语言还支持布尔类…

网络运维管理:确保企业网络系统稳定运行之道

在当今数字化时代,企业网络系统的稳定运行和高效管理是企业业务持续发展和创新的关键。网络运维管理的核心目标正是确保网络设备和服务的高可用性、优化网络性能、保护网络安全、快速解决网络故障以及有效管理网络配置。本文将深入探讨网络运维管理系统的关键组件、…

CSS - 搜索框小动效

点击搜索框动画变长&#xff0c;搜索框有内容不变&#xff0c;无内容失去焦点&#xff0c;变回原来模样。<div :class"type true ? s_r_z : s_r" click"onChange"><div class"input_s"><input blur"handleBlur" v-mo…

计算机毕业设计选题推荐-流浪动物领养管理系统-Java/Python项目实战(亮点:数据可视化分析、智能推荐)

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

uniapp 各个端接入腾讯滑动行为验证码示例

验证调起页面&#xff1a; <template><view class"app"><text>{{ obj.ret }}</text><button click"varify">验证</button></view> </template><script>export default{data(){return{obj: {}}},on…