SVD在餐馆菜肴推荐系统中的应用

摘要:餐馆可以分为很多类别,比如中式、美式、日式等等。但是这些类别不一定够用,有的人喜欢混合类别。对用户对菜肴的点评数据进行分析,可以提取出区分菜品的真正因素,利用这些因素我们可以估计人们对没去过的餐厅的看法。提取这些信息的方法就是SVD(Singular Value Decomposition)。本文首先介绍SVD的数学原理,然后简单介绍推荐系统的相关原理,最后通过python编程实现简单的基于协同过滤的菜肴推荐系统。

关键词:SVD;推荐系统;python;协同过滤;

1. SVD数学原理

SVD是矩阵最终也是最好的分解,任意矩阵可分解为A=U,分解结果为正交矩阵U,对角阵和正交矩阵。

1.1 SVD在子空间的解释

可以将矩阵A 看做是一种线性变换,将其行空间的一个向量v1变换为其列空间中的向量u1=Av1。奇异值分解就是在行空间寻找一组正交基,将其通过矩阵A线性变换生成列空间中的一组正交基,将其通过矩阵A线性变换生成列空间中的一组正交基。如图1。

图1     四个子空间

1.1.1 SVD求解

问题核心:寻找行空间中一组特殊的正交基。

AV=U,由于V是正交矩阵,其逆等于转置,所以有A=U。

为了得到这两个正交矩阵,先处理其中一个。在等式A=U两侧分别乘上:

上式其实是正定矩阵的正交分解,vi是矩阵的特征向量,是特征值,用同样的办法可以求U,它的列向量就是矩阵 的特征向量。

1.2 SVD应用

1.2.1 推荐系统

简单版本的推荐系统能够计算事物或者人之间的相似度。更先进的方法是先利用SVD从数据中构建一个主题空间,然后再在该空间下计算器相似度。图14-1中给出的矩阵,它是由餐馆的菜和品菜师对这些菜的意见构成的。品菜师可以采用1到5之间的整数对菜品进行打分。如果没有吃过,打分为0。

图2     菜品打分矩阵

对以上矩阵进行SVD分解,我们可以得到2个奇异值,代表2种主题。右图阴影Ed, Peter和Tracy对“烤牛肉”和“手撕猪肉”进行了评级,同时这三人未对其他菜评级。烤牛肉和手撕猪肉都是美式烧烤餐馆才有的菜,其他日式餐馆才有。所以2个奇异值代表这2种主题。

我们可以把奇异值想象成一个新的空间。与图2矩阵的5*7的矩阵不同,奇异值矩阵是2维的。在A=U中,将用户(行空间)映射到2个主题菜品空间中去,U将菜肴(列空间)映射到2个主题菜品空间中去。

推荐系统中可能用噪声数据,比如某个人对某些菜进行故意低分或高分。但是推荐系统抽取数据是基于主题的,这样就会取得比原始数据更好的推荐结果。

2. python实现

2.1 SVD实现

Numpy中有一个linalg的线性代数工具,可以帮我实现SVD分解。

U,Sigma,VT =linalg.svd(M)

输入矩阵M 返回U,Sigma,VT。

矩阵分解后Sigma是对角阵,而且Sigma对角线上的元素依次减小,而且前面的元素远远大于后面的元素,所以我们可以用前面的元素进行近似计算,从而减少计算量。原始数据就可以用下面的式子近似:

如图3,浅灰色区域是原始数据,黑色区域是矩阵近似计算所需要的数据。

图3 矩阵分解示意图

确定保留前几个奇异值,有很多启发式的策略,其中一个是保留矩阵中90%的能量信息。为了计算总能量信息我们将所有的奇异值平方求和。于是可以将奇异值的平方和累加到90%为止。另一个就是根据我们对数据的理解,指定保留前几个奇异值,这种方法虽然粗暴,但是也很有效。

2.2 基于协同过滤的推荐系统实现

协同过滤是将用户和其他用户的数据进行对比来进行推荐。本文的方法是在Python3.5下实现。

2.2.1程序模块

1读取矩阵(有2个矩阵可以读入)

2相似度计算(欧式距离,皮尔逊系数,余弦相似度)

3计算用户评分(从矩阵中选择用户没有品尝过的菜品,计算这些菜品与原来品尝过菜品的相似度)

4推荐(向用户推荐评分最高的K个菜,试验中K=3)

2.2.2运行

主函数中我们向用户1推荐,相似度计算采用余弦相似度,返回菜品编号及菜品得分。

[参考文献]

[1]  Peter Harrington.《机器学习实战》.2013

[2] G.Strang.《Introduction to Linear Algebra》,2003

 from numpy import *
from numpy import linalg as la def loadExData():
return array([[4, 4, 0, 2, 2],
[4, 0, 0, 3, 3],
[4, 0, 0, 1, 1],
[1, 1, 1, 2, 0],
[2, 2, 2, 0, 0],
[1, 1, 1, 0, 0],
[5, 5, 5, 0, 0]]) def loadExData2():
return array([[0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 5],
[0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 3],
[0, 0, 0, 0, 4, 0, 0, 1, 0, 4, 0],
[3, 3, 4, 0, 0, 0, 0, 2, 2, 0, 0],
[5, 4, 5, 0, 0, 0, 0, 5, 5, 0, 0],
[0, 0, 0, 0, 5, 0, 1, 0, 0, 5, 0],
[4, 3, 4, 0, 0, 0, 0, 5, 5, 0, 1],
[0, 0, 0, 4, 0, 4, 0, 0, 0, 0, 4],
[0, 0, 0, 2, 0, 2, 5, 0, 0, 1, 2],
[0, 0, 0, 0, 5, 0, 0, 0, 0, 4, 0],
[1, 0, 0, 0, 0, 0, 0, 1, 2, 0, 0]]) def ecludSim(inA,inB):
return 1.0/(1.0 + la.norm(inA - inB)) def pearsSim(inA,inB):
if len(inA) < 3 : return 1.0
return 0.5+0.5*corrcoef(inA, inB, rowvar = 0)[0][1] def cosSim(inA,inB):
num = float(inA.T*inB)
denom = la.norm(inA)*la.norm(inB)
return 0.5+0.5*(num/denom) def standEst(dataMat,user,simMeas,item):
n=shape(dataMat)[1]
simTotal=0.0; ratSimTotal=0.0
for j in range(n):
userRating=dataMat[user,j]
if userRating==0:continue
overLap=nonzero(logical_and(dataMat[:,item].A>0,dataMat[:,j].A>0))[0]
if len(overLap)==0:similarity=0
else: similarity=simMeas(dataMat[overLap,item],dataMat[overLap,j])
#print('the %d and%d similarity is: %f' %(item,j,similarity))
simTotal+=similarity
ratSimTotal+=similarity*userRating
if simTotal==0: return 0
else: return ratSimTotal/simTotal
def svdEst(dataMat, user, simMeas, item):
n = shape(dataMat)[1]
simTotal = 0.0; ratSimTotal = 0.0
U,Sigma,VT = la.svd(dataMat)
Sig4 = mat(eye(4)*Sigma[:4]) #arrange Sig4 into a diagonal matrix
xformedItems = dot(dataMat.T , U[:,:4] )* Sig4.I #create transformed items
for j in range(n):
userRating = dataMat[user,j]
if userRating == 0 or j==item: continue
similarity = simMeas(xformedItems[item,:].T,\
xformedItems[j,:].T)
print ('the item%d and item%d similarity is: %f' % (item, j, similarity))
simTotal += similarity
ratSimTotal += similarity * userRating
if simTotal == 0: return 0
else: return ratSimTotal/simTotal def recommend(dataMat, user, N=3, simMeas=ecludSim, estMethod=standEst): unratedItems =nonzero(dataMat[user,:]==0)[0]
print("item that user don't eat before :")
print(unratedItems)
if len(unratedItems) == 0: return ('you rated everything')
itemScores = []
for item in unratedItems:
estimatedScore = estMethod(dataMat, user, simMeas, item)
itemScores.append((item, estimatedScore))
list_=sorted(itemScores, key=lambda jj: jj[1], reverse=True)[:N]
print("top %d item of list and score that recommend to user %d :" %(N,user) )
return list_
def main():
myMat=loadExData2()#导入矩阵1
users=1
A=recommend(myMat,users,estMethod=svdEst)#用户0
print(A) if __name__ == '__main__':
main()

SVD在餐馆菜肴推荐系统中的应用的更多相关文章

  1. [机器学习笔记]奇异值分解SVD简介及其在推荐系统中的简单应用

    本文先从几何意义上对奇异值分解SVD进行简单介绍,然后分析了特征值分解与奇异值分解的区别与联系,最后用python实现将SVD应用于推荐系统. 1.SVD详解 SVD(singular value d ...

  2. NMF和SVD在推荐系统中的应用(实战)

    本文以NMF和经典SVD为例,讲一讲矩阵分解在推荐系统中的应用. 数据 item\user Ben Tom John Fred item 1 5 5 0 5 item 2 5 0 3 4 item 3 ...

  3. 多维数组分解----SVD在推荐系统中的应用-

    http://www.janscon.com/multiarray/rs_used_svd.html [声明]本文主要参考自论文<A SINGULAR VALUE DECOMPOSITION A ...

  4. SVD在推荐系统中的应用详解以及算法推导

    SVD在推荐系统中的应用详解以及算法推导     出处http://blog.csdn.net/zhongkejingwang/article/details/43083603 前面文章SVD原理及推 ...

  5. RS:推荐系统中的数据稀疏和冷启动问题

    如何在没有大量用户数据的情况下设计个性化推荐系统并且让用户对推荐结果满意从而愿意使用推荐系统,就是冷启动问题. 冷启动问题主要分为三类: (1) 用户冷启动:如何给新用户做个性化推荐的问题,新用户刚使 ...

  6. 14、RALM: 实时 look-alike 算法在推荐系统中的应用

    转载:https://zhuanlan.zhihu.com/p/71951411 RALM: 实时 look-alike 算法在推荐系统中的应用 0. 导语 本论文题为<Real-time At ...

  7. 广告行业中那些趣事系列10:推荐系统中不得不说的DSSM双塔模型

    摘要:本篇主要介绍了项目中用于商业兴趣建模的DSSM双塔模型.作为推荐领域中大火的双塔模型,因为效果不错并且对工业界十分友好,所以被各大厂广泛应用于推荐系统中.通过构建user和item两个独立的子网 ...

  8. Spark/Scala实现推荐系统中的相似度算法(欧几里得距离、皮尔逊相关系数、余弦相似度:附实现代码)

    在推荐系统中,协同过滤算法是应用较多的,具体又主要划分为基于用户和基于物品的协同过滤算法,核心点就是基于"一个人"或"一件物品",根据这个人或物品所具有的属性, ...

  9. 【疑难杂症】奇异值分解(SVD)原理与在降维中的应用

    前言 在项目实战的特征工程中遇到了采用SVD进行降维,具体SVD是什么,怎么用,原理是什么都没有细说,因此特开一篇,记录下SVD的学习笔记 参考:刘建平老师博客 https://www.cnblogs ...

随机推荐

  1. VMware 12安装虚拟机Mac OS X 10.10(VMware12安装/共享文件夹)

    推荐电脑配置 1:Inter I5及以上 (A卡请自行百度大神解决方案) 必须开启CPU虚拟化:开机进入BIOS--->Intel Virtualization Technology---> ...

  2. NGUI屏幕自适应(转)

      屏幕自适应 NGUI可以比较方便的实现屏幕自适应,但是它的官方教程里面针对这个问题没有详细的教程,所以可能在实现的时候会走比较多的弯路.以下是我在开发过程中找到的一个比较方便的实现方法. 主要组件 ...

  3. js正则函数match、exec、test、search、replace、split使用介绍集合,学习正则表达式的朋友可以参考下。

    match 方法 使用正则表达式模式对字符串执行查找,并将包含查找的结果作为数组返回. stringObj.match(rgExp) 参数 stringObj 必选项.对其进行查找的 String 对 ...

  4. UIGestureRecognizer学习笔记2

    The concrete subclasses of UIGestureRecognizer are the following: UITapGestureRecognizer UIPinchGest ...

  5. Android 使用Spinner实现下拉列表

    课程目标1.了解Spinner下拉列表的使用和功能2.学会使用系统默认的Spinner3.学会使用自定义样式的Spinner 执行步骤第一步:添加一个下拉列表项的list,这里添加的项就是下拉列表的菜 ...

  6. iOS 自动布局 Autolayout 优先级的使用

    一.约束的优先级 0.屏幕适配 发展历程 代码计算frame -> autoreszing(父控件和子控件的关系) -> autolayout(任何控件都可以产生关系) -> siz ...

  7. 谷歌Volley网络框架讲解——第一篇

    自从公司新招了几个android工程师后,我清闲了些许.于是就可以有时间写写博客,研究一些没来的研究的东西. 今年的谷歌IO大会上,谷歌推出了自己的网络框架——Volley.不久前就听说了但是没有cl ...

  8. poj_3461 kmp

    题目大意 给定两个字符串S1, S2,求S1中包含多少个S2串.其中S1长度最大为 1000000, S2长度最大为10000. 题目分析 典型的字符串匹配问题,直接匹配显然会超时,考虑使用kmp算法 ...

  9. 【微信开发】PC端 微信扫码支付成功之后自动跳转

    场景: PC端   微信扫码支付 结果: 支付成功 自动跳转 实现思路: 支付二维码页面,写ajax请求支付状态,请求到结果,无论成功还是失败,都跳转到相应的结果页面 具体实现方法: html部分: ...

  10. windows环境下最简单的nginx + tomcat负载均衡配置示例

    后端是两台tomcat服务器,我们简称为node1 和node2,访问地址分别是 http://192.168.1.2:8080 和 http://192.168.1.4:8080 前端使用nginx ...