学会观察他人的恐惧,我们会清晰地看到自己。--- 雾满拦江
对于推荐方法,基于内容 和 基于协同过滤 是目前的主流推荐算法,很多电子商务网站的推荐系统都是基于这两种算法的。
协同过滤 是一种基于相似性来进行推荐的算法,主要分为 基于用户的协同过滤算法 和 基于项目的协同过滤算法,第3种是基于模型(model based)的协同过滤。
协同:通过在线数据找到用户可能喜欢的物品; 过滤:滤掉一些不值得推荐的数据
基于用户的(User based)协同过滤算法:
采用统计计算方式,搜索目标用户的相似用户(通过相似性度量方法计算出最近邻居集合),并根据相似用户对项目的打分来预测目标用户对某些项目的评分,然后找出预测最高的若干个物品推荐给用户。
基于项目的(Item一based)协同过滤算法:
基于项目(item-based)的协同过滤和基于用户的协同过滤类似,只不过这时我们转向物品和物品之间的相似度。如果目标用户对某些物品已经评分,我们就可以找出与这些物品相似度高的物品并预测目标用户对它们的评分,将评分最高的若干个相似物品推荐给用户。比如你在网上买了一本机器学习相关的书,网站马上会推荐一堆机器学习相关的书给你,这里就明显用到了基于项目的协同过滤思想。
基于用户的协同过滤可以帮助用户找到新类别的有惊喜的物品。而基于项目的协同过滤,由于物品的相似性一段时间不会变,很难带给用户惊喜了。一般对于小型的推荐系统来说,基于项目的协同过滤肯定是主流。
举例理解协同滤波 以及 SVD在协同滤波中的使用:
首先,关于奇异值分解(SVD)的数学理论,这里暂且不讲。
假设我们有一个矩阵,该矩阵每一列代表一个user,每一行代表一个item,例如这些item可以是电影。
矩阵值代表user对item的评分,0代表未评分。
SVD是将一个大的矩阵进行有损地压缩。用一个具体的例子展示svd:
首先是A矩阵,对应上面的评分矩阵:
A =
5 5 0 5
5 0 3 4
3 4 0 3
0 0 5 3
5 4 4 5
5 4 5 5
使用matlab调用svd函数:
[U,S,Vtranspose]=svd(A)
U =
-0.4472 -0.5373 -0.0064 -0.5037 -0.3857 -0.3298
-0.3586 0.2461 0.8622 -0.1458 0.0780 0.2002
-0.2925 -0.4033 -0.2275 -0.1038 0.4360 0.7065
-0.2078 0.6700 -0.3951 -0.5888 0.0260 0.0667
-0.5099 0.0597 -0.1097 0.2869 0.5946 -0.5371
-0.5316 0.1887 -0.1914 0.5341 -0.5485 0.2429
S =
17.7139 0 0 0
0 6.3917 0 0
0 0 3.0980 0
0 0 0 1.3290
0 0 0 0
0 0 0 0
Vtranspose =
-0.5710 -0.2228 0.6749 0.4109
-0.4275 -0.5172 -0.6929 0.2637
-0.3846 0.8246 -0.2532 0.3286
-0.5859 0.0532 0.0140 -0.8085
SVD将矩阵A分解成三个矩阵的乘积:A = U * S * (Vtranspose)',这里我用(x)‘表示x的转置。其中S是一个对角线矩阵,对角线上的元素非负,是A的奇异值,从上到下逐渐减小。
为了对矩阵A进行降维压缩,取S对角线上前k个元素。当k=2时候,将S(6*4)
降维成S(2*2)
,同时U(6*6)
变为 U(6*2)
, (Vtranspose)'(4*4)
变为 (Vtranspose)'(2*4)
.
如下图:
此时我们用降维后的U,S,(Vtranspose)'
来相乘得到A2
A2 =
5.2885 5.1627 0.2149 4.4591
3.2768 1.9021 3.7400 3.8058
3.5324 3.5479 -0.1332 2.8984
1.1475 -0.6417 4.9472 2.3846
5.0727 3.6640 3.7887 5.3130
5.1086 3.4019 4.6166 5.5822
此时我们可以很直观地看出,A2和A很接近----有损压缩。
既然两者很接近,那么我们就可以利用压缩后的数据来进行相似性分析啦:
将降维后的U的第一列当成x值,第二列当成y值,即U的每一行作为一个数据点画在图中;
类似地,将降维后(Vtranspose)'的每一列作为一个数据点画在图中
:
之所以这样,是因为降维后U中的各个行之间的相似性 可以近似代表 原始矩阵A中各个行(each user)之间的相似性;
降维后(Vtranspose)'
中的各个列之间的相似性 可以近似代表 原始矩阵A中各个列(each item)之间的相似性;
从纯数学上可以这样理解:
A = USV ---> (US) * V = A,所以A中的第i列 是由V中的第i列变换而来的!
A = USV ---> U * (SV) = A,所以A中的第i行 是由U中的第i行变换而来的!
从图中可以看出: Season5,Season6特别靠近, 用户Ben和Fred特别靠近。
观察A矩阵可以看出,A矩阵的第5行向量和第6行向量特别相似,Ben所在列向量和Fred所在列向量也特别相似。从直观上我们发现U矩阵和V矩阵可以近似来代表A矩阵,换据话说就是将A矩阵压缩成U矩阵和V矩阵。
至此,数据压缩的部分已经完成,接下来需要解决实际问题:
以寻找相似用户为例子(基于user的推荐):
假设,现在我们突然得到了名字叫Bob的新用户,且已知Bob对6个item评分向量为:[5 5 0 0 0 5](列向量)。任务是要给做出个性化的推荐,即向他推荐他可能喜欢的item。
首先, 利用Bob的评分向量找出其相似用户。现在,我们在使用svd, 我们已经将之前得到的其他的用户进行了降维,前面已经提到原始矩阵A中的各列与降维后(Vtranspose)'的各列相似,相当于我们对原始的各个列(用户)施加了一个降维动作,将其由6*1压缩为了2*1。
现在,我们得到了新用户Bob的数据,相当于一个6*1的列,需要对其也施加一个相同的降维动作,将其压缩压缩为2*1,然后将这个得到的2*1向量与其他的进行快速比较,这个降维动作是什么呢?接下来先理解一下
::(下面这一段用的符号与前面无关)
对于一个m*n的矩阵A,进行奇异值分解后得到:A(m,n) = U(m,m)*S(m,n)*V(n,n),先直观地理解一下svd分解之后,通过去掉小的奇异值来进行降维的过程:
假设m=5,n=3:
看US: S的最后两行为0,从而U中的最后2列在相乘的过程中不起作用,可以直接去掉,另外,S中的第三行的奇异值为0.03,很小,可以将第三行去掉,从而U中的倒数第三列也可以直接去掉;
看SV:由于S中的第三个奇异值可以去掉,相当于S的第三列全部为0,从而V中的第三行可以去掉,实现降维;
从而,这个降维的过程在UV上的体现就是U中的列可以被去掉,V中的行可以被去掉,降维后:
U(5,2)*S(2,2)*V(2,3)
那么,接着上面的问题:如何对新用户(列数据)进行降维打击呢:
(US)V = A,A中的列与V中的列相似,V中的列更短。又,U为正交矩阵,SV = trans(U) *A => V = inv(S)*trans(U) *A
=> V中列向量 = inv(S)*trans(U) * A中列向量, 这个变换过程体现在inv(S)*trans(U),这个矩阵可以用降维后的S和U来近似带代替:inv( S(2,2) )*trans( U(5,2) ):
trans( U(5,2) )中的两行对应的是U(5,5)中保留的前两行;
现在我们得到了这个降维动作,可以直接对Bob用户的列数据进行降维:
用户Bob的降维列向量 = inv( S(2,2) ) * trans( U(5,2) ) * 用户Bob的列向量
将Bob坐标(-0.377,0.08)添加进原来的图中:
然后从图中找出和Bob最相似的用户,这里的相似用余弦相似度计算各个用户之间的相似性,(关于相似度还有很多种计算方法),即夹角与Bob最小的用户坐标,可以计算出最相似的用户是ben。
找出相似用户之后,剩下的就是个人喜欢的推荐策略了。
Ref:
https://blog.csdn.net/hhtnan/article/details/79854525
https://yanyiwu.com/work/2012/09/10/SVD-application-in-recsys.html
机器学习实战
http://blog.sina.com.cn/s/blog_73de143c010153vp.html