推荐系统——矩阵分解FM

矩阵分解

隐语义模型与矩阵分解

之所以我们提出隐语义模型与矩阵分解,原因就是[[协同过滤]]存在泛化能力弱的问题
而对于隐语义模型而言,我们可以利用隐向量来代表隐藏信息
此外,也可以在一定程度上弥补[[协同过滤]]处理稀疏矩阵能力不足的情况

隐语义模型

隐语义模型主要在于可以挖掘用户和物品的潜在特征来联系不同的用户和物品,接着对不同的用户和item进行聚类
可以举个例子,如果用户A喜欢看侦探小说、科普图书以及一些计算机技术书,而B喜欢数学和机器学习方面。

  • 对于UserCF而言,系统会先找到和其看了相同书的其他用户,然后给新用户推荐其他用户看的书
  • 对于ItemCF而言,系统会找到和新用户已经看的书相似的书(在这里所谓的相似并没有用到隐语义,可能只是简单的通过书籍的评分来寻找相似),然后给用户推荐这些书籍
    那么隐语义模型会尝试将用户兴趣和书进行归类,当用户来的时候会将用户的兴趣分类,再从兴趣分类中挑选他可能喜欢的书籍。

可以再使用一个对音乐评分的例子来看一下隐特征矩阵的含义:
A喜欢带有小清新,吉他伴奏,王菲的歌曲,如果一首歌正好是王菲唱的,并且是吉他伴奏的小清新,那么就可以将这首歌推荐给这个用户,所以这里是三个标签🏷连接起了用户和歌曲。又每首歌中所包含的元素不尽相同,因此,我们可以去找如下两个矩阵

  1. 潜在因子——用户矩阵

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

    小清新重口味优雅伤感五月天
    乐A0.90.10.20.4
    乐B0.50.60.10.9
    乐C00.60.10.2

那么有了以上矩阵,我们可以认为张三对音乐A的喜欢程度为
0.6∗0.9+0.8∗0.1+0.1∗0.2+0.1∗0.4+0.7∗0=0.690.6*0.9+0.8*0.1+0.1*0.2+0.1*0.4+0.7*0 = 0.690.60.9+0.80.1+0.10.2+0.10.4+0.70=0.69
基于此,我们也可以得到一个用户——音乐评分的共现矩阵

音乐A音乐B音乐C音乐D
张三0.681.580.280.51
李四0.310.430.470.11
王五1.061.570.730.69

  所以在此例子中,小清新,重口味,优雅这些就可以看作是隐含特征,而我们就可以用这些隐含特征来将用户的兴趣和音乐进行一个分类,其本质即为找到用户/音乐的一个隐向量表达形式,通过该隐向量就可以来进行用户/音乐之间相似度的判定。

但是在实际情况下,我们一般也是只能有最后的用户——物品打分矩阵,并且矩阵会存在很多缺失值如

音乐A音乐B音乐C音乐D
张三0.68??0.51

而对于使用UserCF或者ItemCF去填充也是很麻烦的,对此,我们可以使用[[矩阵分解]]

矩阵分解的原理

  如果我们有用户——物品打分的共线矩阵YYY(存在缺失值),基于[[矩阵分解]]的原理,我们求出矩阵PPPQQQ有:P×Q=YP \times Q = YP×Q=Y

  其中,矩阵乘法将m×nm\times nm×n的共现矩阵Y分分解为m×km \times km×k的用户矩阵和k×nk \times nk×n的物品矩阵,其中m为用户的个数,n为物品的个数,而k为隐向量的维度即隐含特征的个数,但是这里的隐含特征变得无法解释,并不是和我们之前矩阵小清新的例子一样是明显可解释的,而对于k而言,k的大小决定了隐向量的表达能力的强弱,k越大,表达信息就越强,划分得就更具体。

  在有了用户矩阵P和物品矩阵Q之后,如果我们想计算用户uuu对物品iii的评分,只需要
Preference(u,i)=rui=puTqi=∑f=1Fpu,kqk,iPreference(u, i) = r_{ui} = p^T_uq_i = \sum_{f=1}^Fp_{u,k}q_{k,i}Preference(u,i)=rui=puTqi=f=1Fpu,kqk,i
  其中,pup_upu为用户uuu所对应的隐向量,qiq_iqi为用户iii所对应的隐向量

矩阵分解算法的求解

矩阵分解常用方法为[[特征值分解EVD]]与[[奇异值分解SVD]],但是这两种方法在这里并不适用,比如EVD要求分解的矩阵为方阵,但是对于用户——物品打分矩阵而言,不一定是方阵的形式,而对于SVD分解计算机复杂度非常高

Basic SVD

Funk-SVD:把求解上面两个矩阵的参数问题转换成一个最优化问题,可以通过训练集里面的观察值利用最小化来学习用户矩阵和物品矩阵

  如果我们想计算用户uuu对物品iii的评分,可以使用Preference(u,i)=rui=puTqi=∑f=1Fpu,kqk,iPreference(u, i) = r_{ui} = p^T_uq_i = \sum_{f=1}^Fp_{u,k}q_{k,i}Preference(u,i)=rui=puTqi=f=1Fpu,kqk,i
而我们一般只会有ruir_{ui}rui的真实数据,并没有pup_upuqiq_iqi,所以基于修正的思想,我们可以初始化puRqip_u^Rq_ipuRqi,然后计算出r^ui=puTqi\hat{r}_{ui} = p_u^Tq_ir^ui=puTqi,从而得到误差
eui=rui−r^uie_{ui} = r_{ui} - \hat{r}_{ui}eui=ruir^ui
接着求出误差平方和
SSE=∑u,ieui2=∑u,i(rui−∑k=1Kpu,kqk,i)2SSE = \sum_{u, i}e_{ui}^2=\sum_{u, i}(r_{ui}-\sum_{k=1}^Kp_{u, k}q_{k, i})^2SSE=u,ieui2=u,i(ruik=1Kpu,kqk,i)2
有了误差之后,我们可以利用误差进行修正从而使SSE降到最小,转化为一个最优化问题,而目标函数为
min⁡q∗,p∗∑(u,i)∈K(rui−puTqi)2\min_{q^*, p^*}\sum_{(u, i) \in K}(r_{ui} - p_u^Tq_i)^2q,pmin(u,i)K(ruipuTqi)2

接下来可以使用梯度下降去降低损失,有
pu,k=pu,k−η(−euiqk,i)=pu,k+ηeuiqk,ip_{u, k} = p_{u, k} - \eta(-e_{ui}q_{k,i}) = p_{u, k}+\eta e_{ui}q_{k,i} pu,k=pu,kη(euiqk,i)=pu,k+ηeuiqk,i
qk,i=qk,i−η(−euipu,k)=qk,i+ηeuipu,kq_{k, i} = q_{k, i} - \eta(-e_{ui}p_{u,k}) = q_{k, i}+\eta e_{ui}p_{u,k} qk,i=qk,iη(euipu,k)=qk,i+ηeuipu,k
其中,η\etaη为学习率。

但在实际中,单纯的r^ui=puTqi\hat{r}_{ui} = p^T_uq_ir^ui=puTqi只能评判一部分属性,对于一个评分系统而言,有些固有属性和用户物品无关,而用户也有有些属性和物品无关,物品也有些属性和用户无关,所以提出了另一种[[LFM]],在原有基础上添加了偏置项。

LFM

LFM在原有基础上加了偏置项,来消除用户和物品打分的偏差,即预测公式如下:
r^ui=μ+bu+bi+puT⋅qi\hat{r}_{ui} = \mu + b_u + b_i + p^T_u \cdot q_ir^ui=μ+bu+bi+puTqi
加入了3个偏置项μ,bu,bi\mu, b_u, b_iμ,bu,bi

  • μ\muμ:训练集中,也就是那个矩阵Y所有非空元素的平均值。因为可能在一个网站的评价打分中,因为网站的定位和销售物品不同,所以网站的整体打分分布会产生差异,所以μ\muμ可以表示网站本身对用户评分的影响。
  • bub_ubu:用户偏差系数,是用户uuu所有打分的均值, 可以当作训练参数。这一项表示了用户的评分习惯中和物品没有关系的那种因素
  • bib_ibi:物品偏差系数,是物品iii收到的所有评分的均值,可以当作训练参数。表示了物品接受的评分中和用户没有关系的因素
    而此时添加了偏置系数之后,SSE的形式也需要改变,如果把bub_ububib_ibi当作训练参数的话,那么它俩的更新公式为bu+=η(eui−λbu)b_u += \eta (e_{ui} - \lambda b_u)bu+=η(euiλbu) bi+=η(eui−λbi)b_i += \eta(e_{ui} - \lambda b_i)bi+=η(euiλbi)而对于pu,kp_{u,k}pu,kpk,ip_{k,i}pk,i,导数没有变化,更新公式也没有变化。

实现例子的代码:

import numpy as np
import randomclass SVD():def __init__(self, rating_data, F=5, alpha=0.1, lmbda=0.1, max_iter=100):self.F = Fself.P = dict()self.Q = dict()self.rating_data = rating_dataself.bi = dict()self.bu = dict()self.mu = 0.0self.alpha = alphaself.lmbda = lmbdaself.max_iter = max_itercnt = 0for user, items in self.rating_data.items():self.P[user] = [random.random() / np.sqrt(self.F) for i in range(self.F)]self.bu[user] = 0cnt += len(items)for item, rating in items.items():if item not in self.Q:self.Q[item] = [random.random() / np.sqrt(self.F) for i in range(self.F)]self.bi[item] = 0self.mu /= cntdef train(self):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_uiself.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(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.1def predict(self, user, item):return sum(self.P[user][i] * self.Q[item][i] for i in range(self.F)) + self.bu[user] + self.bi[item] + self.mudef load_data():data = {'A':{1:5, 2:3, 3:4, 4:4},'B':{1:3, 2:1, 3:2, 4:3, 5:3},'C':{1:4, 2:3, 3:4, 4:3, 5:5},'D':{1:3, 2:3, 3:1, 4:5, 5:4},'E':{1:1, 2:5, 3:5, 4:2, 5:1}}return datarating_data = load_data()
basicsvd = SVD(rating_data, F=10)
basicsvd.train()
print(item, basicsvd.predict('A', 5))

在这里插入图片描述

FM模型

FM模型的引入

逻辑回归模型及其缺点

一般做CTR预估时最简单的思路即将特征做线性回归(逻辑回归LR),但这样本质上是一个线性模型,由于sigmoid函数是一个单调增函数不会改变里面的线性模型的CTR预测顺序,因此逻辑回归的效果会比较差,即LR的缺点有:

  1. 是一个线性模型
  2. 每个特征对最终输出结果独立,需要手动交叉特征(xi∗xjx_i * x_jxixj)

[[二叉交叉项的考虑及改进]]

考虑到做特征交叉较为麻烦,于是考虑所有的二次交叉,于是将目标函数由原来的y=w0+∑i=1nwixiy = w_0 + \sum_{i=1}^nw_ix_iy=w0+i=1nwixi改为y=w0+∑i=1nwixi+∑in−1∑j=i+1nwi,jxixjy = w_0 + \sum_{i=1}^nw_ix_i+\sum_{i}^{n-1}\sum_{j=i+1}^nw_{i,j}x_ix_jy=w0+i=1nwixi+in1j=i+1nwi,jxixj

但是针对上式存在一个问题即只有当xix_ixixjx_jxj同时不为0时此二阶交叉项才能起作用
于是提出FM,而FM将上述式子改为y=w0+∑i=1nwixi+∑in−1∑j=i+1n<vi,vj>xixjy = w_0 + \sum_{i=1}^nw_ix_i+\sum_{i}^{n-1}\sum_{j=i+1}^n<v_i,v_j>x_ix_jy=w0+i=1nwixi+in1j=i+1n<vi,vj>xixj

此处的解释为,在这里是对每个xix_ixi计算一个embeddingembeddingembedding,接着将两个embeddingembeddingembedding计算内积即<vi,vj><v_i,v_j><vi,vj>来代替之前的wi,jw_{i,j}wi,j,好处是这个模型的泛化能力强,即使存在有两个特征从未在训练集中同时出现过,我们也可以计算出它们的wi,jw_{i,j}wi,j,我们只需要xix_ixi和其他的xkx_kxk同时在训练集中出现过则可计算出xix_ixiEmbeddingEmbeddingEmbedding

FM公式的理解

对于FM公式而言,模型表达能力大于LR,只有当交叉项参数wijw_{ij}wij全为0的时候,才会退化为LR,而且后面的二阶交叉项的数量一共有1+2+3+⋯+n−1=n(n−1)21+2+3+\cdots + n-1 = \frac{n(n-1)}{2}1+2+3++n1=2n(n1),且任意两个参数之间是独立的。

def 任意一个实对称矩阵([[正定矩阵]])WWW都存在一个矩阵VVV,使得W=V⋅VTW = V \cdot V^TW=VVT

y^(X)=w0+∑i=1nwixi+∑in−1∑j=i+1n<vi,vj>xixj\hat{y}(X) = w_0 + \sum_{i=1}^nw_ix_i+\sum_{i}^{n-1}\sum_{j=i+1}^n<v_i,v_j>x_ix_jy^(X)=w0+i=1nwixi+in1j=i+1n<vi,vj>xixj
其中,需要估计的参数有w0∈R,wi∈R,V∈R,<⋅,⋅>w_0 \in R, w_i \in R, V \in R, <\cdot, \cdot>w0R,wiR,VR,<,>是两个长度为k的向量的内积

对于FM模型而言,在[[二叉交叉项的考虑及改进]]中,我们提出了使用<⋅,⋅><\cdot,\cdot><,>来代替wijw_{ij}wij的改进,从而使二次项的参数数量减少为knknkn个,远远少于多项式模型的二项式参数,此外,参数因子化使得xhxix_hx_ixhxixixjx_ix_jxixj不再是独立的。

FM模型是一个通用的拟合模型,可以采用不同的损失函数用以解决regression,classification问题。

FM的理解:FM可以用于解决大型稀疏数据中的特征组合问题。对于MF而言,只存在两个两个特征信息,而FM可以将两个特征进行二阶交叉组合,形成一个高阶特征。具体可以参考推荐系统之FM与MF傻傻分不清楚。
MF其实算是FM的特例,只有两个特征的特例,给出一个矩阵来帮助理解,希望自己之后看到这个例子可以想起来

user1user2user3
item1123
item2234
item3345

这个是MF的输入矩阵,而转化为FM的格式就变为

user1user2user3item1item2item3score
1001001
1000102
1000013
0101002
0100103
0100014
0011003
0010104
0010015

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

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

相关文章

千位分隔符的完整攻略

千位分隔符[1]是很常见的需求&#xff0c;但是输入文本千变万化&#xff0c;如何才能准确添加千分符呢&#xff1f; 纯整数情况 纯整数大概是所有情况里最简单的一种&#xff0c;我们只要正确匹配出千分位就好了。 观察上面的数字&#xff0c;我们可以得出千分位的特征是到字符…

限制按钮点击_Android | 使用 AspectJ 限制按钮快速点击

前言在Android开发中&#xff0c;限制按钮快速点击&#xff08;按钮防抖&#xff09;是一个常见的需求&#xff1b;在这篇文章里&#xff0c;我将介绍一种使用AspectJ的方法&#xff0c;基于注解处理器 & 运行时注解反射的原理。如果能帮上忙&#xff0c;请务必点赞加关注&…

svn不知道这样的主机 怎么解决_家里装修不知道怎么配置净水器,这几招教你轻松解决...

为了保障家庭饮水健康&#xff0c;很多业主都会选择在家中安装一台厨下净水器。但是&#xff0c;如若仅靠它来满足全家人日常洗漱&#xff0c;沐浴和饮用&#xff0c;这势必会极大地影响到全家人的生活品质。这个时候&#xff0c;实阳机电良心建议&#xff0c;全屋净水系统&…

redis系列:通过文章点赞排名案例学习sortedset命令

前言 这一篇文章将讲述Redis中的sortedset类型命令&#xff0c;同样也是通过demo来讲述&#xff0c;其他部分这里就不在赘述了。 项目Github地址&#xff1a;https://github.com/rainbowda/learnWay/tree/master/learnRedis/case-sortedset 案例 demo功能是文章点赞排名等等&am…

xml生成2维码_MyBatis(2)之MyBatis-Generator最佳实践

自定义注释自定义注解指定xml文件模式上一篇文章详细阐述了xml配置文件的各种标签及其含义。其实从标签开始&#xff0c;每一个标签都对应一个实体类。context.class对应标签&#xff0c;而每一个子标签都对应一个属性&#xff1b;如图&#xff1a;标签与实体类的对应关系。有了…

nginx 配置详解_Nginx 配置详解

序言Nginx是lgor Sysoev为俄罗斯访问量第二的http://rambler.ru站点设计开发的。从2004年发布至今&#xff0c;凭借开源的力量&#xff0c;已经接近成熟与完善。Nginx功能丰富&#xff0c;可作为HTTP服务器&#xff0c;也可作为反向代理服务器&#xff0c;邮件服务器。支持Fast…

推荐系统——GBDT+LR

[[逻辑回归模型]] 逻辑回归是在[[线性回归]]的基础上添加了一个Sigmoid函数&#xff08;非线形&#xff09;映射&#xff0c;从而可以使逻辑回归成为一个优秀的分类算法 逻辑回归假设数据服从[[伯努利分布]]&#xff0c;通过[[极大化似然函数]]的方法&#xff0c;运用[[梯度下降…

从燃尽图看项目管理:你的项目哪里出错了?(燃尽图类型全解析)

什么是燃尽图 燃尽图&#xff08;burn down chart&#xff09;是在项目完成之前&#xff0c;对需要完成的工作任务的一种可视化表示。理想情况下&#xff0c;该图表是一个向下的曲线&#xff0c;随着项目任务的逐渐完成“烧尽”至零。 燃尽图常常用于敏捷开发中&#xff0c;作为…

springtboot 引用子工程的文件_xmake从入门到精通11:如何组织构建大型工程

xmake是一个基于Lua的轻量级现代化c/c的项目构建工具&#xff0c;主要特点是&#xff1a;语法简单易上手&#xff0c;提供更加可读的项目维护&#xff0c;实现跨平台行为一致的构建体验。本文主要详细讲解下&#xff0c;如何通过配置子工程模块&#xff0c;来组织构建一个大规模…

依赖项出现感叹号怎么办_SpringBoot中如何对依赖进行管理?

SpringBoot中的起步依赖(starter)是一组特定功能的依赖项集合&#xff0c;SpringBoot通过starter来进行项目的依赖管理&#xff0c;而不是直接基于单独的依赖项来进行依赖管理。starter其实就是特殊的Maven依赖项或者Gradle依赖项&#xff0c;它把常用的库组合到一起构成了一个…

5g理论速度_5G是什么?5G速度有多快?

原标题&#xff1a;5G是什么&#xff1f;5G速度有多快&#xff1f;5G到底是什么东西&#xff1f;今年5G网络会普及吗&#xff1f;5G网速到底有多快&#xff0c;背后又有哪些黑科技&#xff1f;近日&#xff0c;全球首个5G火车站在上海虹桥火车站启动建设。而根据三大运营商的时…

c++ new一个结构体_「C/C++」构造类型及应用:数组、结构体、共用体、枚举类型...

3.1数组同类型、同性质、按顺序存放的一组数据集合&#xff0c;易于批量处理。3.1.1一维数组定义int 1.数组名为常量&#xff0c;指向首地址&#xff0c;由系统指定。2.数组长度为整型常量,但不能为03.上例取值image[0]-image[255]&#xff0c;取值可以修改。初始化int 输入for…

自动产生fsm代码的工具_代码自动生成工具

构建支持多种数据库类型的代码自动生成工具背景&#xff1a;一般的业务代码中写来写去&#xff0c;无外乎是先建好model&#xff0c;然后针对这个model做些CRUD的操作。(主要针对单表的业务操作)针对于数据库dao、mapper等的代码自动生成已经有了mybatisGenerator这种工具&…

gtest测试框架使用详解_测试框架TestNG使用介绍

近期接触到了一个比较全面的基于Java的接口自动化测试框架&#xff0c;作为一名Java小白&#xff0c;所以打算研究一下&#xff0c;顺带学习学习Java&#xff0c;该测试框架的逻辑控制层使用的HttpClient TestNG。在本期中&#xff0c;给大家分享一下TestNG测试框架的基础知识…

LOJ#6282. 数列分块入门 6

一个动态的插入过程&#xff0c;还需要带有查询操作。 我可以把区间先分块&#xff0c;然后每个块块用vector来维护它的插入和查询操作&#xff0c;但是如果我现在这个块里的vector太大了&#xff0c;我可能的操作会变的太大&#xff0c;所以这时候我需要把现在里面的数全部拿出…

fragment在activity中的静态和动态用法_使用Matlab修改压缩Gif动态图片制作微信表情...

脚本之家你与百万开发者在一起作者&#xff1a;theOwlAndPussyCat/焦旭光引言电脑里存了很多有意思的Gif动态图片&#xff0c;闲暇想把这些动图全导入微信表情&#xff0c;可是这些动图很多大小超过了微信表情大小1MB的限制&#xff0c;要制作成表情只能压缩图像文件大小。网上…

frontcon函数用不了_C++复制构造函数与析构函数

想用机器人赋能未来&#xff0c;少不了扎实的编程的基本功&#xff0c;让我们跟着清华大学的C语言程序设计课程一起过一遍C的语法知识吧&#xff01;当定义基本类型的变量时&#xff0c;经常会用已有的变量去初始化新定义的变量&#xff0c;当定义对象的时候也有类似的需求&…

软件项目立项书_2019年度上海市软件和集成电路产业发展专项资金项目立项

上海艾瑞德生物科技有限公司荣获2019年上海市软件和集成电路产业发展专项资金(集成电路和电子信息制造领域)项目立项&#xff01;上海艾瑞德生物科技有限公司的【医用体外诊断动态光场图像采集电子模块的研发及产业化】喜获2019年上海市软件和集成电路产业发展专项资金(集成电路…

mysql提供了表示日期和时间的数据类型_MySQL数据类型 - 日期和时间类型(1)

1.日期和时间数据类型语法用于表示时间值的日期和时间数据类型是DATE, TIME, DATETIME, TIMESTAMP和 YEAR。对于TIME, DATETIME和 TIMESTAMP值&#xff0c;MySQL支持小数秒&#xff0c;精度可达微秒(6位数)。要定义包含小数秒部分的列&#xff0c;请使用语法type_name(fsp)&…

软件质量保证计划_CMMI V2.0 精讲之“过程质量保证”

过程质量保证(PROCESS QUALITY ASSURANCE, PQA)目的&#xff1a;验证并改进已执行的过程和所产生的工作产品的质量。价值&#xff1a;增强过程使用和改进的一致性&#xff0c;以最大限度地提高业务效益和客户满意度。实践概述第1级PQA 1.1识别并解决过程和工作产品问题。第2级P…