笔者的毕业设计是基于图算法的推荐系统实现,写点blog作为论文笔记,不足之处望多多指正
为什么是图算法?
推荐系统的目的是解决海量数据下的信息精准推荐问题,白话说:现在我们身边的信息是海量的,可供人们选择的商品、书籍、电影也是数不胜数,而人的精力是有限的,推荐系统恰好可以为个人提供较为准确的推荐,帮助人们更快更好的找到自己需要的事物。
现阶段的,商业收集到用户的大部分数据都是发生在用户与商品之间的,如老王买了香烟、小王买了鲜花等一类人对物的行为数据,这些行为行为数据恰好可以通过一连串的二元祖来进行表示,这恰好可以利用图算法来帮助开发者,设计出更好的推荐算法。
算法思路
此处借用《推荐系统实践》一书中的案例来阐述:比如现在有用户:A、B、C、D和物品:a、b、c、d、e,组成的闭环生态,我们将这其中的购买行为通过二分图进行表示(如下图):
利用行为数据进行推荐,本质上是找用户最有可能选择的物品(与用户最为相似的物品),那研究者认为二分图里物品最有可能被用户接受的因素有以下几个:
- 两顶点间的路径数;
点点间路径数越多说明有越多和用户喜欢同a的人也喜欢b,可说明a、b相似度高
- 两顶点间的路径长度;
- 两顶点间的路径经过的点
在计算相关性时,现实中相关性越高的物品的共同点往往有:
- 顶点间有多条路径连接;
- 连接两顶点的路径长度比较短;
- 连接两顶点间的路径不会出现出度比较大的点
因为现实生活,爆款产品的出度往往很大,算法中直接使用容易出现长尾效应
Personalrank算法原理
基于上述思想,产生Personalrank算法,其算法原理如下:
PR ( v ) = { α ∑ v ′ ∈ i n ( v ) P R ( v ′ ) ∣ out ( v ′ ) ∣ ( v ≠ v u ) ( 1 − alpha ) + α ∑ v ′ ∈ i n ( v ) PR ( v ′ ) ∣ out ( v ′ ) ∣ ( v = v u ) \operatorname{PR}(v)=\left\{\begin{array}{l}\alpha \sum_{v^{\prime} \in \mathrm{in}(v)} \frac{\mathrm{PR}\left(v^{\prime}\right)}{\left|\operatorname{out}\left(v^{\prime}\right)\right|}\left(v \neq v_{u}\right) \\ (1-\text { alpha })+\alpha \sum_{v^{\prime} \in \mathrm{in}(v)} \frac{\operatorname{PR}\left(v^{\prime}\right)}{\left|\operatorname{out}\left(v^{\prime}\right)\right|} \quad\left(v=v_{u}\right)\end{array}\right. PR(v)=⎩⎨⎧α∑v′∈in(v)∣out(v′)∣PR(v′)(v=vu)(1− alpha )+α∑v′∈in(v)∣out(v′)∣PR(v′)(v=vu)
其中:v为顶点集,pr(i)是户选择i的可能性,这里初始情况下认为pr(i)=1(原物)pr(i)=0(非原物i),out(i)为顶点的出度;a可以看成是用户下次选择下一种物品的可能性。从节点i出发后,开始随机游走,(上式迭代),经过多次游走后(迭代)后,访问每个节点的概率会趋于收敛,这个收敛值就被认为是物品被用户选中的概率。
算法实现
基于python,通过Personalrank实现算法代码如下:
#personalrank算法的简单算例实现
import time
#设计personalrank算法函数
def Personalrank(Graph,alpha,root,max_depth):
#推荐排序
rank=dict()
rank={
x:0 for x in Graph.keys()}
rank[root]=1
#迭代
begin=time.time()
for k in range(max_depth):
tmp={
x:0 for x in Graph.keys()}
#取出节点i和他的出边节点集合
for i,ri in Graph.items():
for j,wij in ri.items():
tmp[j]+= alpha * rank[i] / (1.0 * len(ri))
tmp[root] += (1 - alpha)
rank = tmp
end=time.time()
print('使用时间:',end-begin)
#lst=sorted(rank.items(),key=lambda x:x[1],reverse=True)
#for ele in lst:
#print('%s:%.3f , \n'%(ele[0],ele[1]))
return rank
if __name__=='__main__':
alpha=0.8
Graph={
'A':{
'a':1,'b':1,'d':1},
'B':{
'a':1,'c':1},
'C':{
'b':1,'e':1},
'D': {
'c': 1, 'e': 1},
'a':{
'A':1,'B':1},
'b':{
'A':1,'C':1},
'c':{
'D':1,'B':1},
'd':{
'A':1,'D':1},
'e':{
'C':1,'D':1},
}
print(Personalrank(Graph,alpha,'b',50))
以节点b为例,利用Personalrank算法可以得到其与节点的相似性为:
‘A’: 0.16577257339161164, ‘B’: 0.043444835869696115, ‘C’: 0.16109189469317547, ‘D’: 0.07412879716688255, ‘a’: 0.06158614968457111, ‘b’: 0.308644973214133, ‘c’: 0.04703252728649955, ‘d’: 0.04420689787736918, ‘e’: 0.09409135081606143
思考
- 现算法在现大规模行为数据的应用场景中计算量会很大,后续可以转化成矩阵计算来改进算法;
- 如果从人节点出发得到推荐结果后,其与基于用户的协同过滤算法的异同在哪里?同样的,如果从物节点出发那么其与基于物品的协同过滤算法的异同又在哪里?