06 人以群分 基于邻域的协同过滤算法
这一讲我们将正式进入算法内容的学习。
推荐算法本质
推荐算法本质上是一一种信息处理方法,它将用户信息和物品信息处理后,最终输出了推荐结果。因为 05 讲中基于热门推荐、基于内容推荐、基于关联规则推荐等方法比较粗放,所以推荐结果往往不够精准。如果我们想打造一个千人千面、真正符合用户个性化推荐需求的推荐系统,就需要使用到更为复杂的运算逻辑——推荐算法。
而推荐算法又分为传统机器学习算法和深度学习算法,因此我们会分别通过模块二、三两大模块单独进行介绍,模块二我们主要学习传统机器学习算法。
根据是否使用了辅助信息(如商品的类名、店铺名等),传统机器学习算法分为了基于邻域的方法和基于特征的方法这两类。06 讲我们主要介绍基于邻域的推荐算法——协同过滤算法,基于特征的方法将在 07 中着重介绍。
我们把用户编号作为纵坐标,帖子编号作为横坐标,并通过将用户与帖子是否存在交互过程进行标记,然后填写到如下所示表格中。这时,一个用户与物品的行为矩阵就这样搭建成功了。

请注意:表中的帖子数量和用户数量十分庞大。
针对上表中的内容,如果我们对行为分类进行打分(比如点击浏览 1 分、打电话 3 分、58 微聊 3 分、收藏 5分等),再把对应分数填充到矩阵中,就可以得到一个评分矩阵,具体细节这里不作描述。
此时,如果我们需要对用户 A 进行推荐,根据如下所示表格,我们发现用户 A、用户 B 与用户 C 都对帖子 1、帖子 2、帖子 3 感兴趣,因此我们认为用户 A、用户 B、用户 C 比较相似。


同时,我们还发现用户 B 还看过帖子 4,用户 C 还看过帖子 5,而这 2 个帖子用户 A 都没看过。基于相似性原则,我们认为用户 A 很大概率上会对帖子 4 和帖子 5 感兴趣。因此,生成推荐时,我们也会向用户 A 推荐帖子 4 和帖子 5。
以上就是协同过滤算法的基本思想,接下来我们将协同过滤算法逐个拆解进行说明。
协同过滤算法分类
在互联网应用场景中,存在大量用户看了又看、买了又买、买过还买等情况,因此,我们需要利用集体智慧将用户和物品的所有交互行为实现个性化推荐,此时就可以考虑使用协同过滤算法。
协同过滤算法(Collaborative Filtering,简称 CF)是推荐算法中最成熟、应用最广的一种算法。根据模型相似度计算的对象,我们把协同过滤算法(CF)分为了 UserCF、ItemCF 、ModelCF 这 3 种,下面我们逐一展开说明。
基于用户的协同过滤算法(UserCF)
通过分析用户喜欢的物品,我们发现如果两个用户(用户A 和用户 B)喜欢过的物品差不多,则这两个用户相似。此时,我们可以将用户 A 喜欢过但是用户 B 没有看过的物品推荐给用户 B。
基于用户的协同过滤算法(UserCF)的具体实现思路如下:
(1)计算用户之间的相似度;
(2)根据用户的相似度,找到这个集合中用户未见过但是喜欢的物品(即目标用户兴趣相似的用户有过的行为)进行推荐。
基于物品的协同过滤算法(ItemCF)
通过分析用户喜欢的物品,我们发现如果两个物品被一拨人喜欢,则这两个物品相似。此时,我们就会将用户喜欢相似物品中某个大概率物品推荐给这群用户。
基于物品的协同过滤算法的具体实现思路如下:
(1)计算物品之间的相似度;
(2)根据物品的相似度和用户的历史行为进行推荐。
基于模型的协同过滤算法(ModelCF)
基于模型的协同过滤算法也叫基于学习的方法,通过定义一个参数模型,我们可以描述用户和物品、用户和用户、物品和物品之间的关系,然后将已有的用户与物品评分矩阵(例如矩阵分解、隐语义模型 LFM 等)作为样本优化求解,最终得到模型参数。
关于这个算法的具体实现思路我们会在下面的内容中进行着重说明。
了解了协同过滤算法的具体实现思路,下面我们来看看具体的计算过程,这也是本节课的重点内容,一定要好好学哦~
协同过滤算法计算过程
协同过滤算法(CF) 的本质是矩阵填充问题(Matrix Completion),即基于矩阵内部的已知值填充剩下的未知值。已知值指用户对已经交互过的物品的打分,未知值指用户对未交互过的物品的打分,对未知值的填充也就是指整个模型预测过程。
协同过滤算法(CF)的计算基础是相似度计算,因此,协同过滤算法(CF)计算过程的第一步就是找到与目标用户相似的用户或者与目标物品相似的物品,例如 UserCF 依赖计算用户之间的相似度,ItemCF 依赖计算物品之间的相似度等。
一般来说,常见的相似度计算方法主要分为基于欧式距离的相似度计算、基于 Jaccard 公式的相似度计算、余弦相似度计算、皮尔逊相似度计算等。这里,我们将重点说一下使用最多的 Jaccard 相似度计算、余弦相似度计算和皮尔逊相似度计算。
Jaccard相似度计算
关于 Jaccard 相似度的计算公式如下图所示:

其中 N(u) 表示用户 u 购买物品的数量,N(v) 表示用户 v 购买物品的数量,N(u)⋂N(v) 表示用户 u 和 v 购买相同物品的数量。
余弦相似度计算
关于余弦相似度的计算公式如下图所示:

其中,数学公式: R{ik} 表示用户 i 对物品 k 的打分,数学公式: R{jk} 表示用户 j 对物品 k 的打分,n 为总物品数量。
皮尔逊相似度计算

数学公式: I{ij} 表示用户 i 和用户 j 的打分物品集合,R{i,c} R{j,c} 分别表示用户 i 对物品 c 的打分数、用户 j 对物品 c 的打分数,image.png分别表示用户 i 所有评分的平均数、用户 j 所有评分的平均数。
由此可见,Jaccard 相似度计算和余弦相似度计算结果为绝对距离,而皮尔逊相似度计算结果是相对距离。Jaccard 相似度计算和余弦相似度计算通过将各个用户在评分上的差异性去均值,从而避免了分数膨胀问题的发生,关于相似度算法的细节在 06 讲中我们不作深入讨论。
相似度计算结果输出后,下一步我们需要做的事情是对未知值进行预测。
对 UserCF 来说,假设存在用户 u 和用户 v,由第一步已知用户 u 与用户 v 的相似度是w{uv} ,其中用户 v 对物品 i 有过交互行为,打分为 r{vi} ,用户 u 对物品 i 没有交互行为,即没有打分。于是,通过利用与用户 u 最相似的 k 个用户 S(u,k)对物品 i 的打分,我们就可以得到用户 u 对未交互的物品 i 的预测分数,具体的计算公式如下图所示:

其中 N(i) 是所有对物品 i 有过交互行为和打分的用户集合, w{uv} 代表用户 u 和用户 v 的相似度,r{vi}代表用户 v 对物品 i 进行直接交互的行为打分。
对 ItemrCF 来说,假设存在物品 i 和物品 j,由第一步已知物品 i 和物品 j 的相似度为w{ji} ,其中用户 u 对物品 i 有过交互行为,打分为 r{ui},用户 u 对物品 j 没有交互行为和打分。于是,利用用户 u 对物品 i 最相似的 k 个物品的打分 S(j,k),我们就可以得到用户 u 对未交互的物品 j 的预测分数,具体的计算公式如下图所示:

其中 N(u)代表用户喜欢的物品的集合,w{ji}代表物品 j 和物品 i 的相似度, r{ui}是用户 u 对物品 i 进行直接交互的行为打分。
以上我们介绍了 UserCF 和 ItemCF 算法的计算过程,二者都是基于用户和物品的交互行为进行计算。其中,UserCF 计算用户间的相似度,ItemCF 计算物品间的相似度,然后我们利用相似度计算结果给用户推荐行为历史记录相似度较高的物品。
当然,除了以上两种计算算法外,推荐系统还可以依照用户兴趣分类给用户推荐该类别的物品,也就是我们前面所说的基于模型的协同过滤算法(ModelCF)。
关于基于模型的协同过滤算法(ModelCF)的具体实现思路如下:
(1)根据用户行为得到用户在各个分类的兴趣打分;
(2)将不用的物品分别放入各个分类下。
这里需要说明的是,同一个物品可以分别属于不同的分类,比如对《道德经》这本书进行分类,它既可以归为“哲学”,也可以归为“古典文学”,至于它更偏向于哪个分类,我们以其在这两个分类上对应的权重系数进行判断,即完全取决于用户把《道德经》当成哲学著作来读还是当作文学作品来读,这就是用户行为的具象化。对用户行为进行分类后,我们就能够计算出该用户在每个分类上的偏好权重。
基于模型的协同过滤算法(ModelCF)通过基于用户行为统计的自动聚类,指定了表征用户偏好和物品的向量维度,最终得到用户的偏好向量和物品的表征向量,最终利用表征向量实现对应物品推荐,具体实现步骤为:
(1)计算物品的分类、用户和物品的表征向量;
(2)根据用户和物品的表征向量进行推荐。
这里可以看出,我们需要解决的核心问题是计算用户和物品的表征向量(是不是出现深度学习的影子了?)。而隐语义模型(LFM)正是基于这样的思路,因此它完美解决了这个核心问题。下面我们具体讲解下隐语义模型的实现思路。
假设物品有若干个分类,不同用户对不同分类的兴趣度不同,同时每个分类中又包含若干种物品,每个物品在该分类中又会存在一个对应权重。因此,任何一个用户 u 对物品 i 的偏好计算(用户和物品的表征向量),我们可以使用如下图所示的计算公式:

其中, p{u,k}表示用户 u 和分类 f 的偏好权重, q{i,k} 表示物品 i 和分类 f 的权重。
从公式中,我们发现 LFM 把用户评分矩阵分解为了用户偏好矩阵和物品分类矩阵,这就是所谓的矩阵分解方法。其实,LFM 属于矩阵分解方法中最基础的一种方法,之后逐步衍生出了 FunkSVD、BiasSVD、 SVD++ 等广泛应用的方法。
小结与预告
协同过滤算法曾经是推荐算法中经典的存在,曾几何时只要我们提到推荐系统,就会提起协同过滤算法。因此,06 讲我们主要介绍了典型的推荐算法——协同过滤算法,它本质上是一个矩阵填充问题,通过相似度计算即可完美解决(包括基于用户的相似、基于物品的相似等)。另外,我们还可以通过矩阵分解方法找到用户和物品在某个维度上的表征向量。
《道德经》中说:“和其光,同其尘,是谓玄同”,协同过滤算法真正做到了“从用户中来到用户中去”,它通过摆脱硬性规则,从而在效果上超越了其他策略。07 讲我将带你深入了解传统机器学习算法的另外一种方法——推荐特征交叉算法。
对于协同过滤算法,你是否还有不同的见解?欢迎在留言区与我进行互动、交流。
另外,如果你觉得本专栏有价值,欢迎分享给更多好友哦~

相关文章:
06 人以群分 基于邻域的协同过滤算法
这一讲我们将正式进入算法内容的学习。 推荐算法本质 推荐算法本质上是一一种信息处理方法,它将用户信息和物品信息处理后,最终输出了推荐结果。因为 05 讲中基于热门推荐、基于内容推荐、基于关联规则推荐等方法比较粗放,所以推荐结果往往…...
SQL性能下降的原因
一、SQL性能下降的原因 主要是性能下降SQL慢、执行时间长、等待时间长 不是一条SQL抓出来就要优化,在真实的生产环境下这种故障第一个要去复线,有可能去排查的时候没,所以没法复线。 可能需要它跑半天或者一天来缩小筛查的范围,…...
js的原型
原型: 1定义:原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。 通过该构造函数产生的对象,以继承该原型的属性和方法。原型也是对象。 2.利用原型特点和概念,可以提取共有属性。 3.对象如…...
FastAPI 学习之路(三十七)元数据和文档 URL
实现前的效果 那么如何实现呢,第一种方式如下: from routers.items import item_router from routers.users import user_router""" 自定义FastApi应用中的元数据配置Title:在 OpenAPI 和自动 API 文档用户界面中作为 API 的…...
C 语言结构体
本博客涉及的结构体知识有: 1.0:结构体的创建和使用 2.0: typedef 关键字与#define 关键字的区别 3.0: 结构体成员的访问【地址访问与成员访问】 4.0: 结构体嵌套调用 5.0 数组访问赋值结构体成员 ...... 1.0:结构体的创建和使用 结…...
MySQl高级篇-主从复制
主从复制 复制的基本原理 slave会从master读取binlog来进行数据同步 MySQL复制过程分成三步: master将改变记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;slave将master的binary log events拷贝到它的中继日志(r…...
JMeter案例分享:通过数据验证的错误,说说CSV数据文件设置中的线程共享模式
前言 用过JMeter参数化的小伙伴,想必对CSV Data Set Config非常熟悉。大家平时更关注变量名称,是否忽略首行等参数,其余的一般都使用默认值。然而我最近遇到一个未按照我的预想读取数据的案例,原因就出在最后一个参数“线程共享模…...
数学建模·Topsis优劣解距离法
Topsis优劣解 一种新的评价方法,特点就是利用原有数据,客观性强。 相较于模糊评价和层次评价 更加客观,充分利用原有数据,精确反映方案差距 基本原理 离最优解最近,离最劣解越远 具体步骤 正向化 代码与原理与熵权…...
数学建模中常用的数据处理方法
常用的数据处理方法 本文参考 B站西电数模协会的讲解视频 ,只作笔记提纲,想要详细学习具体内容请观看 up 的学习视频。国赛的 C 题一般数据量比较大。 这里介绍以下两种方法: 数据预处理方法 数据分析方法 数据预处理方法 1. 数据清洗 为…...
C嘎嘎:函数模版和类模版
目录 泛型编程 函数模版 函数模版概念 函数模版的格式 函数模版的原理 函数模版的实例化 函数参数的匹配原则 类模版 类模版的定义格式 类模版的实例化 泛型编程 如何实现一个通用的交换函数呢 void Swap(int& left, int& right) {int temp left;left rig…...
使用 Apache Pulsar 构建弹性可扩展的事件驱动应用
本视频来自 2024 Apache Pulsar 欧洲峰会,由 David Kjerrumgaard, 《Pulsar in Action》书作者给大家带来的《使用 Apache Pulsar 构建弹性可扩展的事件驱动应用》分享。 嘉宾|David Kjerrumgaard,Apache Pulsar Committer,《Pul…...
【国产开源可视化引擎Meta2d.js】视频
视频 meta2d 支持Html音视频。 // 音频 const pen {name: video,x: 100,y: 100,width: 100,height: 10,audio: https://down.ear0.com:3321/preview?soundid37418&typemp3,autoPlay: true, }; meta2d.addPen(pen); meta2d.inactive();// 视频 const pen {name: video,x…...
零信任网络安全
随着数字化转型的发生,网络边界也在不断被重新定义,因此,组织必须使用新的安全方法重新定义其防御策略。 零信任是一种基于“永不信任,永远验证”原则的安全方法,它强调无论在公司内部或外部,任何用户、设…...
Python酷库之旅-第三方库Pandas(022)
目录 一、用法精讲 55、pandas.lreshape函数 55-1、语法 55-2、参数 55-3、功能 55-4、返回值 55-5、说明 55-6、用法 55-6-1、数据准备 55-6-2、代码示例 55-6-3、结果输出 56、pandas.wide_to_long函数 56-1、语法 56-2、参数 56-3、功能 56-4、返回值 56-5…...
数据建设实践之大数据平台(一)准备环境
大数据组件版本信息 zookeeper-3.5.7hadoop-3.3.5mysql-5.7.28apache-hive-3.1.3spark-3.3.1dataxapache-dolphinscheduler-3.1.9大数据技术架构 大数据组件部署规划 node101node102node103node104node105datax datax datax ZK ZK ZK RM RM NM...
VUE2用elementUI实现父组件中校验子组件中的表单
需求是VUE2框架用elementUI写复杂表单组件,比如,3个相同功能的表单共用一个提交按钮,把相同功能的表单写成一个子组件,另一个父组件包含子组件的重复调用和一个提交按钮,并且要求提交时校验必填项。 注意: …...
人工智能算法工程师(中级)课程9-PyTorch神经网络之全连接神经网络实战与代码详解
大家好,我是微学AI,今天给大家介绍一下人工智能算法工程师(中级)课程9-PyTorch神经网络之全连接神经网络实战与代码详解。本文将给大家展示全连接神经网络与代码详解,包括全连接模型的设计、数学原理介绍,并从手写数字识别到猫狗识…...
UDP网络通信(发送端+接收端)实例 —— Python
简介 在网络通信编程中,用的最多的就是UDP和TCP通信了,原理这里就不分析了,网上介绍也很多,这里简单列举一下各自的优缺点和使用场景 通信方式优点缺点适用场景UDP及时性好,快速视网络情况,存在丢包 与嵌入…...
从零开始实现大语言模型(五):缩放点积注意力机制
1. 前言 缩放点积注意力机制(scaled dot-product attention)是OpenAI的GPT系列大语言模型所使用的多头注意力机制(multi-head attention)的核心,其目标与前文所述简单自注意力机制完全相同,即输入向量序列 x 1 , x 2 , ⋯ , x n x_1, x_2, \cdots, x_n x...
PTA 7-15 希尔排序
本题目要求读入N个整数,采用希尔排序法进行排序,采用增量序列{5,3,1},输出完成增量5和增量3后的5子排序和3子排序结果。 输入格式: 输入不超过100的正整数N和N个整数(空格分隔)。 输出格式: …...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践
前言:本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中,跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南,你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案,并结合内网…...
