推荐学习笔记:矩阵补充和矩阵分解

news2025/1/8 5:52:17

参考:

召回

fun-rec/docs/ch02/ch2.1/ch2.1.1/mf.md at master · datawhalechina/fun-rec · GitHub

业务

隐语义模型与矩阵分解

协同过滤算法的特点:

  • 协同过滤算法的特点就是完全没有利用到物品本身或者是用户自身的属性, 仅仅利用了用户与物品的交互信息就可以实现推荐,是一个可解释性很强, 非常直观的模型。
  • 但是也存在一些问题,处理稀疏矩阵的能力比较弱。

为了使得协同过滤更好处理稀疏矩阵问题, 增强泛化能力。从协同过滤中衍生出矩阵分解模型(Matrix Factorization, MF)或者叫隐语义模型:

  • 在协同过滤共现矩阵的基础上, 使用更稠密的隐向量表示用户和物品。
  • 通过挖掘用户和物品的隐含兴趣和隐含特征, 在一定程度上弥补协同过滤模型处理稀疏矩阵能力不足的问题。

近似最近邻查找

  • 支持最近邻查找的系统
  • 系统:Milvus、Faiss、HnswLib、等等
    • 快速最近邻查找的算法已经被集成到这些系统中
  • 衡量最近邻的标准:
    • 欧式距离最小(L2 距离)
    • 向量内积最大(内积相似度)
      • 矩阵补充用的就是内积相似度
    • 向量夹角余弦最大(cosine 相似度)
      • 最常用
      • 对于不支持的系统:把所有向量作归一化(让它们的二范数等于 1),此时内积就等于余弦相似度

音乐评分实例

假设每个用户都有自己的听歌偏好, 比如用户 A 喜欢带有小清新的, 吉他伴奏的, 王菲的歌曲,如果一首歌正好是王菲唱的, 并且是吉他伴奏的小清新, 那么就可以将这首歌推荐给这个用户。 也就是说是小清新, 吉他伴奏, 王菲这些元素连接起了用户和歌曲。

当然每个用户对不同的元素偏好不同, 每首歌包含的元素也不一样, 所以我们就希望找到下面的两个矩阵:

  1. 潜在因子—— 用户矩阵Q 这个矩阵表示不同用户对于不同元素的偏好程度, 1代表很喜欢, 0代表不喜欢, 比如下面这样:

在这里插入图片描述

2. 潜在因子——音乐矩阵P 表示每种音乐含有各种元素的成分, 比如下表中, 音乐A是一个偏小清新的音乐, 含有小清新的Latent Factor的成分是0.9, 重口味的成分是0.1, 优雅成分0.2...

在这里插入图片描述

**计算张三对音乐A的喜爱程度**

利用上面的这两个矩阵,将对应向量进行内积计算,我们就能得出张三对音乐A的喜欢程度:

在这里插入图片描述

  • 张三对小清新的偏好 * 音乐A含有小清新的成分 + 张三对重口味的偏好 * 音乐A含有重口味的成分 + 张三对优雅的偏好 * 音乐A含有优雅的成分...

  • 根据隐向量其实就可以得到张三对音乐A的打分,使用内积相似度

    0.6∗0.9+0.8∗0.1+0.1∗0.2+0.1∗0.4+0.7∗0=0.680.6∗0.9+0.8∗0.1+0.1∗0.2+0.1∗0.4+0.7∗0=0.68

计算所有用户对不同音乐的喜爱程度

按照这个计算方式, 每个用户对每首歌其实都可以得到这样的分数, 最后就得到了我们的评分矩阵:

在这里插入图片描述

+ 红色部分表示用户没有打分,可以通过隐向量计算得到的。

小结

  • 上面例子中的小清晰, 重口味, 优雅这些就可以看做是隐含特征, 而通过这个隐含特征就可以把用户的兴趣和音乐的进行一个分类, 其实就是找到了每个用户每个音乐的一个隐向量表达形式(与深度学习中的embedding等价)

  • 这个隐向量就可以反映出用户的兴趣和物品的风格,并能将相似的物品推荐给相似的用户等。 有没有感觉到是把协同过滤算法进行了一种延伸, 把用户的相似性和物品的相似性通过了一个叫做隐向量的方式进行表达

  • 现实中,类似于上述的矩阵 P,QP,Q 一般很难获得。有的只是用户的评分矩阵,如下:

    在这里插入图片描述

    • 这种矩阵非常的稀疏,如果直接基于用户相似性或者物品相似性去填充这个矩阵是不太容易的。
    • 并且很容易出现长尾问题, 而矩阵分解就可以比较容易的解决这个问题。
  • 矩阵分解模型:

    • 基于评分矩阵,将其分解成Q和P两个矩阵乘积的形式,获取用户兴趣和物品的隐向量表达。
    • 然后,基于两个分解矩阵去预测某个用户对某个物品的评分了。
    • 最后,基于预测评分去进行物品推荐。

编程实现

import random
import math


class BiasSVD():
    def __init__(self, rating_data, F=5, alpha=0.1, lmbda=0.1, max_iter=100):
        self.F = F          # 这个表示隐向量的维度
        self.P = dict()     # 用户矩阵P  大小是[users_num, F]
        self.Q = dict()     # 物品矩阵Q  大小是[item_nums, F]
        self.bu = dict()    # 用户偏置系数
        self.bi = dict()    # 物品偏置系数
        self.mu = 0         # 全局偏置系数
        self.alpha = alpha  # 学习率
        self.lmbda = lmbda  # 正则项系数
        self.max_iter = max_iter        # 最大迭代次数
        self.rating_data = rating_data  # 评分矩阵

        for user, items in self.rating_data.items():
            # 初始化矩阵P和Q, 随机数需要和1/sqrt(F)成正比
            self.P[user] = [random.random() / math.sqrt(self.F) for x in range(0, F)]
            self.bu[user] = 0
            for item, rating in items.items():
                if item not in self.Q:
                    self.Q[item] = [random.random() / math.sqrt(self.F) for x in range(0, F)]
                    self.bi[item] = 0

    # 采用随机梯度下降的方式训练模型参数
    def train(self):
        cnt, mu_sum = 0, 0
        for user, items in self.rating_data.items():
            for item, rui in items.items():
                mu_sum, cnt = mu_sum + rui, cnt + 1
        self.mu = mu_sum / cnt

        for step in range(self.max_iter):
            # 遍历所有的用户及历史交互物品
            for user, items in self.rating_data.items():
                # 遍历历史交互物品
                for item, rui in items.items():
                    rhat_ui = self.predict(user, item)  # 评分预测
                    e_ui = rui - rhat_ui  				# 评分预测偏差

                    # 参数更新
                    self.bu[user] += self.alpha * (e_ui - self.lmbda * self.bu[user])
                    self.bi[item] += self.alpha * (e_ui - self.lmbda * self.bi[item])
                    for k in range(0, self.F):
                        self.P[user][k] += self.alpha * (e_ui * self.Q[item][k] - self.lmbda * self.P[user][k])
                        self.Q[item][k] += self.alpha * (e_ui * self.P[user][k] - self.lmbda * self.Q[item][k])
            # 逐步降低学习率
            self.alpha *= 0.1


    # 评分预测
    def predict(self, user, item):
        return sum(self.P[user][f] * self.Q[item][f] for f in range(0, self.F)) + self.bu[user] + self.bi[
            item] + self.mu


# 通过字典初始化训练样本,分别表示不同用户(1-5)对不同物品(A-E)的真实评分
def loadData():
    rating_data={1: {'A': 5, 'B': 3, 'C': 4, 'D': 4},
           2: {'A': 3, 'B': 1, 'C': 2, 'D': 3, 'E': 3},
           3: {'A': 4, 'B': 3, 'C': 4, 'D': 3, 'E': 5},
           4: {'A': 3, 'B': 3, 'C': 1, 'D': 5, 'E': 4},
           5: {'A': 1, 'B': 5, 'C': 5, 'D': 2, 'E': 1}
          }
    return rating_data

# 加载数据
rating_data = loadData()
# 建立模型
basicsvd = BiasSVD(rating_data, F=10)
# 参数训练
basicsvd.train()
# 预测用户1对物品E的评分
for item in ['E']:
    print(item, basicsvd.predict(1, item))

# 预测结果:E 3.685084274454321

梯度下降推导

 

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

构造函数与析构函数错题汇总

构造函数不能定义返回类型,也没有返回类型。 堆、栈、静态存储区。栈上的对象main函数结束就释放,堆上的需要手动释放,静态存储区的在所在作用域的程序结束时释放。这里static在main函数内,是局部变量,所以作用域为…

[免费]SpringBoot+Vue景区订票(购票)系统【论文+源码+SQL脚本】

大家好,我是java1234_小锋老师,看到一个不错的SpringBootVue大景区订票(购票)系统,分享下哈。 项目视频演示 【免费】SpringBootVue景区订票(购票)系统 Java毕业设计_哔哩哔哩_bilibili 项目介绍 现代经济快节奏发展以及不断完善升级的信息…

fastdds:编译、安装并运行helloworld

fastdds安装可以参考官方文档: 3. Linux installation from sources — Fast DDS 3.1.0 documentation 从INSTALLATION MANUAL这一节可以看出来,fastdds支持的操作系统包括linux、windows、qnx、MAC OS。本文记录通过源码和cmake的方式来安装fastdds的…

HTTP 探秘之旅:从入门到未来

文章目录 导言:目录:第一篇:HTTP,互联网的“快递员”第二篇:从点开网页到看到内容,HTTP 究竟做了什么?第三篇:HTTP 的烦恼与进化史第四篇:HTTP 的铠甲——HTTPS 的故事第…

【软件项目测试文档大全】软件测试方案,验收测试计划,验收测试报告,测试用例,集成测试,测试规程和指南,等保测试(Word原件)

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.…

前端拿不到 response 响应流返回的 header 例如 Content-Disposition 等

同步发布于我的网站 🚀 背景介绍默认可访问的响应头问题分析解决方案 示例 前端代码示例注意事项总结 背景介绍 在进行前后端交互时,前端有时需要读取服务器返回的特定响应头(如 Content-Disposition),以便根据这些…

SQL进阶——C++与SQL进阶实践

在C开发中,SQL数据库的操作是开发者常见的任务之一。虽然前面我们已经介绍了如何在C中通过数据库连接执行基本的SQL查询,但在实际项目中,我们通常需要更加复杂和高效的数据库操作。存储过程与函数的调用、复杂SQL查询的编写、以及动态构造SQL…

论文概览 |《Urban Analytics and City Science》2023.05 Vol.50 Issue.4

本次给大家整理的是《Environment and Planning B: Urban Analytics and City Science》杂志2023年5月第50卷第4期的论文的题目和摘要,一共包括19篇SCI论文! 论文1 Data analytics and sustainable urban development in global cities 全球城市的数据…

HarmonyOS4+NEXT星河版入门与项目实战(24)------Stage模型

文章目录 1、概念2、配置文件1、全局配置文件2、模块配置文件3、UIAbility生命周期1、图文归纳2、生命周期方法入口4、页面生命周期1、图文描述1、概念 2、配置文件 1、全局配置文件 2、模块配置文件 统一修改配置文件技巧:点击任意json 文件,选择 Open editor ,在显示的列表…

kubernetes——part3-2 集群声明式文件YAML

一、YAML介绍 YAML 的意思是:仍是一种标记语言,但为了强调这种语言以数据做为中心,而不是以标记语言为重点。是一个可读性高,用来表达数据序列的格式。 二、基本语法 1.低版本缩进时不允许使用Tab键,只允许使用空格…

告别 Kafka,拥抱 Databend:构建高效低成本的用户行为分析体系

用户行为数据埋点指标是数据仓库中不可或缺的重要数据源之一,同时也是企业最宝贵的资产之一。通常情况下,用户行为数据分析包含两大数据源:用户行为分析日志和上游关系型数据库(如 MySQL)。基于这些数据,企…

产出一篇论文的各个步骤

产出一篇论文的各个步骤 建议–实用 如何看论文: (前提:优秀论文,如顶会论文/杂志,了解顶会是那些,召开时间是什么时候) 创新点 记录下来说过的别的文章/方法的缺陷 – 看文章就是看优点/指出…

AtomicIntegerFieldUpdater能否降低内存

1. 代码如下: import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger;public class AtomicIntegerTest {final AtomicInteger startPosition new AtomicInteger(0);final AtomicInteger wrotePosition new Atom…

ClickHouse数据迁移(远程)

一、背景 公司最近买了新的服务器,旧的服务器上面安装了ClickHouse22.2.2.1,新的服务器上面安装了ClickHouse24.9.2.42,两个版本之间要做历史数据迁移 旧服务器:80(IP最后一段,以下代称),ClickHouse版本&am…

Flutter:页面滚动

1、单一页面,没有列表没分页的,推荐使用:SingleChildScrollView() return Scaffold(backgroundColor: Color(0xffF6F6F6),body: SingleChildScrollView(child: _buildView()) );2、列表没分页,如购物车页,每个item之间…

Artec Leo:航海设备维护的便携式3D扫描利器【沪敖3D】

挑战:海军服务提供商USP Maritime需要CAD数据来执行维修和改装任务,特别是在偏远地区的任务,以及原始设计丢失的情况下。 解决方案:Artec Leo, Artec Studio, Autodesk Inventor 效果:高精度船舶组件和船坞机械模型&…

复杂网络(三)

一、几种常见的中心性指标 1.1 度中心性 度中心性分为节点度中心性和网络度中心性。前者指的是节点在其与之直接相连的邻居节点当中的中心程度,二后者则侧重节点在整个网络的中心程度,表征的是整个网络的集中或集权程度,即整个网络围绕一个…

蓝桥杯嵌入式入门指南-UART【7】

在all.c定义缓存变量 char uart_tx[50];//uart缓冲区 char uart_rx[50];//uart缓冲区USRT发送(使用strlen时需要在all.h添加string.h) sprintf(uart_tx ," PB15:%.4f V \r\n ",adc_data_PB15);HAL_UART_Transmit(&huart1,(uint8_t *)uart_tx,strlen(uart_tx)…

docker 在ubuntu系统安装,以及常用命令,配置阿里云镜像仓库,搭建本地仓库等

1.docker安装 1.1 先检查ubuntu系统有没有安装过docker 使用 docker -v 命令 如果有请先卸载旧版本,如果没有直接安装命令如下: 1.1.0 首先,确保你的系统包是最新的: 如果是root 权限下面命令的sudo可以去掉 sudo apt-get upda…

IOS ARKit进行图像识别

先讲一下基础控涧,资源的话可以留言,抽空我把它传到GitHub上,这里没写收积分,竟然充值才能下载,我下载也要充值,牛! ARSCNView 可以理解画布或者场景 1 配置 ARWorldTrackingConfiguration AR追…