推荐系统 ---- SVD矩阵分解

目录

目录

SVD

 转载      推荐算法之 Slope One 算法

转载 矩阵分解在协同过滤推荐算法中的应用

1. 矩阵分解用于推荐算法要解决的问题

2. 传统的奇异值分解SVD用于推荐

3. FunkSVD算法用于推荐

4. BiasSVD算法用于推荐

5. SVD++算法用于推荐

6. 矩阵分解推荐方法小结

SVDpp

NMF

文本主题模型之非负矩阵分解(NMF)

1. 非负矩阵分解(NMF)概述

2. NMF的优化思路

3. NMF 用于文本主题模型

4. scikit-learn NMF的使用

5. NMF的其他应用

6. NMF主题模型小结


 


SVD

 转载      推荐算法之 Slope One 算法

[[ 本文地址:http://www.cnblogs.com/breezedeus/archive/2011/03/11/1981781.html

转载请注明出处 ]]

Slope One 是一种很好理解的推荐算法,因为它的简单性而备受关注。网上有很多相关的博文介绍它的原理,但很少见到比较全面而且数学性比较强的介绍。我下面主要从数学的角度比较全面的介绍相关的三个算法。里面使用红色标记的文字是我自己的感想,欢迎大家的指正。

一些很好的参考文献

论文作者们试图建立满足如下性质的robust推荐算法:

1. 算法容易实现和维护

2. 对新的评分应该立即给予响应

3. 查询速度要快(虽然可能以牺牲存储量为代价)

4. 对新的用户也要能给出有效的推荐

5. 精度上要有竞争力

他们提出了三个算法,

Slope One

其基本的想法来自于简单的一元线性模型 w=f(v)=v+b w=f(v)=v+b 。已知一组训练点 (v i ,w i ) n i=1  (vi,wi)i=1n ,利用此线性模型最小化预测误差的平方和,我们可以获得

Image(1)

利用上式获得了b b 的取值后,对于新的数据点v new  vnew ,我们可以利用 w new =b+v new  wnew=b+vnew 获得它的预测值。

直观上我们可以把上面求偏移 b b 的公式理解为 w i  wi 和 v i  vi 差值的平均值。

Image(2)

利用上面的直观,我们定义item i i 相对于 item j j 的平均偏差:

Image(3)

其中 S j,i () Sj,i() 表示同时对item i i 和 j j 给予了评分的用户集合,而 card() card() 表示集合包含的元素数量。

有了上面的定义后,我们可以使用 Image(4) 获得用户 u u 对 item j j 的预测值。当把所有这种可能的预测平均起来,可以得到:

Image(5)

其中 R j  Rj 表示所有用户 u u 已经给予评分且满足条件 (i≠j i≠j 且 S j,i  Sj,i 非空) 的item集合。

对于足够稠密的数据集,我们可以使用近似

Image(6)

把上面的预测公式简化为

Image(7)

Weighted Slope One

Slope One中在计算 item i i 相对于 item j j 的平均偏差 dev j,i  devj,i 时没有考虑到使用不同的用户数量平均得到的 dev j,i  devj,i ,其可信度不同。假设有 2000 2000 个用户同时评分了 item j j 和 k k ,而只有20 20 个用户同时评分了 item j j 和 l l ,那么显然获得的 dev j,k  devj,k 比 dev j,l  devj,l 更具有说服力(类似于kNN中压缩相似度的思想)。所以一个修正是对最终的平均使用加权:

Image(8)

其中

Image(9)

(根据在Netflix上的经验,可能把 c j,i  cj,i 再开方更合适)

Bi-Polar Slope One

Bi-Polar Slope One 进一步把用户已经给予评分的item划分为两类——like和dislike,而其划分的方法是判断对应的评分是否大于此用户的平均评分:

Image(10)

Image(11)Image(12)

类似地,可以定义对item i i 和 j j 具有相同喜好的用户集合:

Image(13)

Image(14)

利用上面的定义,我们可以使用下面的公式为(like或dislike的item)获得新的偏差值:

Image(15)

这样可以计算从item i i 计算得到的预测值:

Image(16)  或者 Image(17)

最终 Bi-Polar Slope One 的预测公式为

Image(18)

最后的实验比较使用的度量为 MAE,其结果如下:

Image(19)

一些自己的想法:

1). Slope One 是基于一元线性模型 w=f(v)=v+b w=f(v)=v+b ,那么是否可以使用多元线性组合?比如可以先利用关联规则方法获得一些关联规则,然后对于找出的每个关联规则使用线性模型。作者在文中也提到可以尝试使用二次或更高次的回归模型。显然这些做法都会让整个模型更加复杂。

2). 在具体应用中,Weighted Slope One 中的 weight 的选取应该可以找到更好的方法

3). 在 Bi-Polar Slope One 中,作者只是简单地使用用户的平均评分来判断like和dislike,这应该会引入比较大的误差。用户的评分往往会随着时间的不同而变动很大,是否可以学习一个更加合理的分割阈值(如 r+r u +r j  r+ru+rj )?还有,是否可以把这种binary的分割更加细化,分为三类,乃至更多类……

转载 矩阵分解在协同过滤推荐算法中的应用

    在协同过滤推荐算法总结中,我们讲到了用矩阵分解做协同过滤是广泛使用的方法,这里就对矩阵分解在协同过滤推荐算法中的应用做一个总结。(过年前最后一篇!祝大家新年快乐!明年的目标是写120篇机器学习,深度学习和NLP相关的文章)

1. 矩阵分解用于推荐算法要解决的问题

    在推荐系统中,我们常常遇到的问题是这样的,我们有很多用户和物品,也有少部分用户对少部分物品的评分,我们希望预测目标用户对其他未评分物品的评分,进而将评分高的物品推荐给目标用户。比如下面的用户物品评分表:

用户\物品 物品1 物品2 物品3 物品4 物品5 物品6 物品7
用户1 3   5     1  
用户2   2         4
用户3       4      
用户4     2       1
用户5 1       4    

    对于每个用户,我们希望较准确的预测出用户对未评分物品的评分。对于这个问题我们有很多解决方法,本文我们关注于用矩阵分解的方法来做。如果将m个用户和n个物品对应的评分看做一个矩阵MM,我们希望通过矩阵分解来解决这个问题。

2. 传统的奇异值分解SVD用于推荐

    说道矩阵分解,我们首先想到的就是奇异值分解SVD。在奇异值分解(SVD)原理与在降维中的应用中,我们对SVD原理做了总结。如果大家对SVD不熟悉的话,可以翻看该文。

    此时可以将这个用户物品对应的m×n矩阵M进行SVD分解,并通过选择部分较大的一些奇异值来同时进行降维,也就是说矩阵MM此时分解为:

  

    其中k是矩阵M中较大的部分奇异值的个数,一般会远远的小于用户数和物品树。如果我们要预测第i个用户对第j个物品的评分mij,则只需要计算即可。通过这种方法,我们可以将评分表里面所有没有评分的位置得到一个预测评分。通过找到最高的若干个评分对应的物品推荐给用户。

    可以看出这种方法简单直接,似乎很有吸引力。但是有一个很大的问题我们忽略了,就是SVD分解要求矩阵是稠密的,也就是说矩阵的所有位置不能有空白。有空白时我们的M是没法直接去SVD分解的。大家会说,如果这个矩阵是稠密的,那不就是说我们都已经找到所有用户物品的评分了嘛,那还要SVD干嘛! 的确,这是一个问题,传统SVD采用的方法是对评分矩阵中的缺失值进行简单的补全,比如用全局平均值或者用用户物品平均值补全,得到补全后的矩阵。接着可以用SVD分解并降维。

    虽然有了上面的补全策略,我们的传统SVD在推荐算法上还是较难使用。因为我们的用户数和物品一般都是超级大,随便就成千上万了。这么大一个矩阵做SVD分解是非常耗时的。那么有没有简化版的矩阵分解可以用呢?我们下面来看看实际可以用于推荐系统的矩阵分解。

3. FunkSVD算法用于推荐

    FunkSVD是在传统SVD面临计算效率问题时提出来的,既然将一个矩阵做SVD分解成3个矩阵很耗时,同时还面临稀疏的问题,那么我们能不能避开稀疏问题,同时只分解成两个矩阵呢?也就是说,现在期望我们的矩阵MM这样进行分解:

    我们知道SVD分解已经很成熟了,但是FunkSVD如何将矩阵M分解为P和Q呢?这里采用了线性回归的思想。我们的目标是让用户的评分和用矩阵乘积得到的评分残差尽可能的小,也就是说,可以用均方差作为损失函数,来寻找最终的P和Q。

    对于某一个用户评分mij,如果用FunkSVD进行矩阵分解,则对应的表示为,采用均方差做为损失函数,则我们期望(mij−qTjpi)2(mij−qjTpi)2尽可能的小,如果考虑所有的物品和样本的组合,则我们期望最小化下式:

    只要我们能够最小化上面的式子,并求出极值所对应的pi,qj则我们最终可以得到矩阵P和Q,那么对于任意矩阵M任意一个空白评分的位置,我们可以通过计算预测评分。很漂亮的方法!

    当然,在实际应用中,我们为了防止过拟合,会加入一个L2的正则化项,因此正式的FunkSVD的优化目标函数J(p,q)J(p,q)是这样的:

    其中λ为正则化系数,需要调参。对于这个优化问题,我们一般通过梯度下降法来进行优化得到结果。

    将上式分别对pi,qjpi,qj求导我们得到:

    则在梯度下降法迭代时,pi,qj的迭代公式为:

    通过迭代我们最终可以得到PP和QQ,进而用于推荐。FunkSVD算法虽然思想很简单,但是在实际应用中效果非常好,这真是验证了大道至简。

4. BiasSVD算法用于推荐

    在FunkSVD算法火爆之后,出现了很多FunkSVD的改进版算法。其中BiasSVD算是改进的比较成功的一种算法。BiasSVD假设评分系统包括三部分的偏置因素:一些和用户物品无关的评分因素,用户有一些和物品无关的评分因素,称为用户偏置项。而物品也有一些和用户无关的评分因素,称为物品偏置项。这其实很好理解。比如一个垃圾山寨货评分不可能高,自带这种烂属性的物品由于这个因素会直接导致用户评分低,与用户无关。

    假设评分系统平均分为μ,第i个用户的用户偏置项为bi,而第j个物品的物品偏置项为bj,则加入了偏置项以后的优化目标函数J(p,q)是这样的

    这个优化目标也可以采用梯度下降法求解。和FunkSVD不同的是,此时我们多了两个偏执项bi,bj,pi,qj的迭代公式和FunkSVD类似,只是每一步的梯度导数稍有不同而已,这里就不给出了。而bi,bj一般可以初始设置为0,然后参与迭代。这里给出bi,bjbi,bj的迭代方法

    通过迭代我们最终可以得到P和Q,进而用于推荐。BiasSVD增加了一些额外因素的考虑,因此在某些场景会比FunkSVD表现好。

5. SVD++算法用于推荐

    SVD++算法在BiasSVD算法上进一步做了增强,这里它增加考虑用户的隐式反馈。好吧,一个简单漂亮的FunkSVD硬是被越改越复杂。

    对于某一个用户i,它提供了隐式反馈的物品集合定义为N(i), 这个用户对某个物品j对应的隐式反馈修正的评分值为cij, 那么该用户所有的评分修正值为∑s∈N(i)csj∑s∈N(i)csj。一般我们将它表示为用qTjysqjTys形式,则加入了隐式反馈项以后的优化目标函数J(p,q)是这样的:

    其中,引入是为了消除不同|N(i)|个数引起的差异。式子够长的,不过需要考虑用户的隐式反馈时,使用SVD++还是不错的选择。

6. 矩阵分解推荐方法小结

    FunkSVD将矩阵分解用于推荐方法推到了新的高度,在实际应用中使用也是非常广泛。当然矩阵分解方法也在不停的进步,目前张量分解和分解机方法是矩阵分解推荐方法今后的一个趋势。

    对于矩阵分解用于推荐方法本身来说,它容易编程实现,实现复杂度低,预测效果也好,同时还能保持扩展性。这些都是它宝贵的优点。当然,矩阵分解方法有时候解释性还是没有基于概率的逻辑回归之类的推荐算法好,不过这也不影响它的流形程度。小的推荐系统用矩阵分解应该是一个不错的选择。大型的话,则矩阵分解比起现在的深度学习的一些方法不占优势。

(欢迎转载,转载请注明出处。欢迎沟通交流: [email protected]) 

FunkSVDBiasSVD的思想实现 SVD的参数参考:http://surprise.readthedocs.io/en/stable/matrix_factorization.html#surprise.prediction_algorithms.matrix_factorization.SVD 主要参数:

  1. n_factors:给定隐因子的数目,默认为100
  2. n_epochs:梯度下降的迭代次数,默认为20
  3. biased:给定模型中是否使用偏置项,默认为True,及BiasSVD分解模型;设置为False,表示用FunkSVD
  4. lr_all:给定学习率,全部参数使用相同的学习率,默认为0.005
  5. reg_all:给定正则化系数,全部参数使用相同的正则化系数,默认为0.02

SVDpp

SVD++算法的思想实现

NMF

 

文本主题模型之非负矩阵分解(NMF)

    在文本主题模型之潜在语义索引(LSI)中,我们讲到LSI主题模型使用了奇异值分解,面临着高维度计算量太大的问题。这里我们就介绍另一种基于矩阵分解的主题模型:非负矩阵分解(NMF),它同样使用了矩阵分解,但是计算量和处理速度则比LSI快,它是怎么做到的呢?

1. 非负矩阵分解(NMF)概述

    非负矩阵分解(non-negative matrix factorization,以下简称NMF)是一种非常常用的矩阵分解方法,它可以适用于很多领域,比如图像特征识别,语音识别等,这里我们会主要关注于它在文本主题模型里的运用。

    回顾奇异值分解,它会将一个矩阵分解为三个矩阵:

    如果降维到k k维,则表达式为:

    但是NMF虽然也是矩阵分解,它却使用了不同的思路,它的目标是期望将矩阵分解为两个矩阵:

    分解成两个矩阵是不是一定就比SVD省时呢?这里的理论不深究,但是NMF的确比SVD快。不过如果大家读过我写的矩阵分解在协同过滤推荐算法中的应用,就会发现里面的FunkSVD所用的算法思路和NMF基本是一致的,只不过FunkSVD聚焦于推荐算法而已。

    那么如何可以找到这样的矩阵呢?这就涉及到NMF的优化思路了。

2. NMF的优化思路

     NMF期望找到这样的两个矩阵W,H,使WH的矩阵乘积得到的矩阵对应的每个位置的值和原矩阵 A 对应位置的值相比误差尽可能的小。用数学的语言表示就是:

    如果完全用矩阵表示,则为:

    其中,

    当然对于这个式子,我们也可以加上L1和L2的正则化项如下:

    

    其中,α 为L1&L2正则化参数,而ρ  为L1正则化占总正则化项的比例。||∗|| 1  为L1范数。

    我们要求解的有m∗k+k∗n 个参数。参数不少,常用的迭代方法有梯度下降法和拟牛顿法。不过如果我们决定加上了L1正则化的话就不能用梯度下降和拟牛顿法了。此时可以用坐标轴下降法或者最小角回归法来求解。scikit-learn中NMF的库目前是使用坐标轴下降法来求解的,,即在迭代时,一次固定m∗k+k∗n−1 个参数,仅仅最优化一个参数。这里对优化求W,H W,H 的过程就不再写了,如果大家对坐标轴下降法不熟悉,参看之前写的这一篇Lasso回归算法: 坐标轴下降法与最小角回归法小结

3. NMF 用于文本主题模型

    回到我们本文的主题,NMF矩阵分解如何运用到我们的主题模型呢?

    此时NMF可以这样解释:我们输入的有m个文本,n个词,而A ij对应第i个文本的第j个词的特征值,这里最常用的是基于预处理后的标准化TF-IDF值。k是我们假设的主题数,一般要比文本数少。NMF分解后,Wik 对应第i个文本的和第k个主题的概率相关度,而H kj  Hkj 对应第j个词和第k个主题的概率相关度。  

    当然也可以反过来去解释:我们输入的有m个词,n个文本,而A ij对应第i个词的第j个文本的特征值,这里最常用的是基于预处理后的标准化TF-IDF值。k是我们假设的主题数,一般要比文本数少。NMF分解后,Wik 对应第i个词的和第k个主题的概率相关度,而Hkj 对应第j个文本和第k个主题的概率相关度。

    注意到这里我们使用的是"概率相关度",这是因为我们使用的是"非负"的矩阵分解,这样我们的W,H矩阵值的大小可以用概率值的角度去看。从而可以得到文本和主题的概率分布关系。第二种解释用一个图来表示如下:

     和LSI相比,我们不光得到了文本和主题的关系,还得到了直观的概率解释,同时分解速度也不错。当然NMF由于是两个矩阵,相比LSI的三矩阵,NMF不能解决词和词义的相关度问题。这是一个小小的代价。

4. scikit-learn NMF的使用

    在 scikit-learn中,NMF在sklearn.decomposition.NMF包中,它支持L1和L2的正则化,而W,H W,H 的求解使用坐标轴下降法来实现。

    NMF需要注意的参数有:

    1) n_components:即我们的主题数k, 选择k值需要一些对于要分析文本主题大概的先验知识。可以多选择几组k的值进行NMF,然后对结果人为的进行一些验证。

    2) init : 用于帮我们选择W,H W,H 迭代初值的算法, 默认是None,即自动选择值,不使用选择初值的算法。如果我们对收敛速度不满意,才需要关注这个值,从scikit-learn提供的算法中选择一个合适的初值选取算法。

    3)alpha: 即我们第三节中的正则化参数α α ,需要调参。开始建议选择一个比较小的值,如果发现效果不好在调参增大。

    4) l1_ratio: 即我们第三节中的正则化参数ρ ρ ,L1正则化的比例,仅在α>0 α>0 时有效,需要调参。开始建议不使用,即用默认值0, 如果对L2的正则化不满意再加上L1正则化。

    从上面可见,使用NMF的关键参数在于主题数的选择n_components和正则化的两个超参数α,ρ α,ρ 。

    此外,W W 矩阵一般在调用fit_transform方法的返回值里获得,而H H 矩阵则保存在NMF类的components_成员中。

    下面我们给一个例子,我们有4个词,5个文本组成的矩阵,需要找出这些文本和隐含的两个主题之间的关系。代码如下:

    完整代码参见我的github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/nmf.ipynb

import numpy as np
X = np.array([[1,1,5,2,3], [0,6,2,1,1], [3, 4,0,3,1], [4, 1,5,6,3]])
from sklearn.decomposition import NMF
model = NMF(n_components=2, alpha=0.01)

    现在我们看看分解得到的W,H W,H :

W = model.fit_transform(X)
H = model.components_
print W
print H

    结果如下:

[[ 1.67371185  0.02013017]
 [ 0.40564826  2.17004352]
 [ 0.77627836  1.5179425 ]
 [ 2.66991709  0.00940262]]
[[ 1.32014421  0.40901559  2.10322743  1.99087019  1.29852389]
 [ 0.25859086  2.59911791  0.00488947  0.37089193  0.14622829]]

    从结果可以看出, 第1,3,4,5个文本和第一个隐含主题更相关,而第二个文本与第二个隐含主题更加相关。如果需要下一个结论,我们可以说,第1,3,4,5个文本属于第一个隐含主题,而第二个问题属于第2个隐含主题。

5. NMF的其他应用

    虽然我们是在主题模型里介绍的NMF,但实际上NMF的适用领域很广,除了我们上面说的图像处理,语音处理,还包括信号处理与医药工程等,是一个普适的方法。在这些领域使用NMF的关键在于将NMF套入一个合适的模型,使得W,H W,H 矩阵都可以有明确的意义。这里给一个图展示NMF在做语音处理时的情形:

6. NMF主题模型小结

    NMF作为一个漂亮的矩阵分解方法,它可以很好的用于主题模型,并且使主题的结果有基于概率分布的解释性。但是NMF以及它的变种pLSA虽然可以从概率的角度解释了主题模型,却都只能对训练样本中的文本进行主题识别,而对不在样本中的文本是无法识别其主题的。根本原因在于NMF与pLSA这类主题模型方法没有考虑主题概率分布的先验知识,比如文本中出现体育主题的概率肯定比哲学主题的概率要高,这点来源于我们的先验知识,但是无法告诉NMF主题模型。而LDA主题模型则考虑到了这一问题,目前来说,绝大多数的文本主题模型都是使用LDA以及其变体。下一篇我们就来讨论LDA主题模型。

(欢迎转载,转载请注明出处。欢迎沟通交流: [email protected]) 

分类: 0083. 自然语言处理

标签: 自然语言处理

 

非负矩阵分解的思想实现
备注:也支持bias偏置项的转换

 
 

猜你喜欢

转载自blog.csdn.net/weixin_41521681/article/details/86515152