您的位置:首页 > 编程语言

推荐系统-基于隐语义模型(LFM)

2018-01-06 13:22 489 查看
在上一篇博客,我们大致讲解了《推荐系统实践》中基于邻域的算法和代码实现,在这一篇博客,我们继续讲解基于隐语义模型(Latent Factor Model)的推荐系统。

隐语义模型是近几年推荐系统领域最为热门的研究话题,它的核心思想是通过隐含特征(Latent factor)联系用户兴趣和物品。

隐语义模型需要解决三个问题:

1 如何给物品进行分类

2 如何确定用户对哪些类的物品感兴趣以及感兴趣的程度

3 对于一个给定的类,选择哪些属于这个类的物品推荐给用户,以及如何确定物品在一个类中的权重?

隐含语义分析技术,基于用户历史数据,采取基于用户行为统计的自动聚类,较好的实现了对隐因子的挖掘。

推荐系统的用户行为分为显性反馈和隐性反馈。隐性反馈中只有正样本,灭有负样本。论文’ One-Class Collaborative Filtering’中对这个问题进行了输入的探讨。在我们的算法实现中,采用的是随机采样法。经过采样之后,得到用户-物品集K={(u,i)},其中,如果(u,i)是正样本,则rui=1,否则rui=0。则目标函数如下:

C=∑(u,i)∈K(rui−pTuqi)2+λ||pu||22+λ||qi||22

假设隐因子个数为F个,则可以重写为

C=∑(u,i)∈K(rui−∑f=1Fpufqif)2+λ||pu||22+λ||qi||22

其中λ||pu||22+λ||qi||22是正则化项。要最小化上面的损失函数,可以利用随机梯度下降法。上面的目标函数对puf和qif分别偏导数,得到

∂C∂puf∂C∂qif=−2∑(u,i)∈K(rui−∑f=1Fpufqif)qif+2λpuf=−2∑(u,i)∈K(rui−∑f=1Fpufqif)puf+2λqif

然后,根据根据梯度下降法,迭代公式为

pufqif:=puf+α(∑(u,i)∈K(rui−∑f=1Fpufqif)qif−λpuf):=qif+α(∑(u,i)∈K(rui−∑f=1Fpufqif)puf−λqif)

其中,α是学习速率(learning rate)。

对于导数,也可以直接使用向量表示:

∂C∂pu∂C∂qi=−2∑(u,i)∈K(rui−pTuqi)qf+2λpu=−2∑(u,i)∈K(rui−pTuqi)pu+2λqi

其中,pu和qi分别为大小为F的列向量,表示用户和物品的隐因子向量。

代码实现如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Jan  5 14:51:55 2018

@author: lanlandetian
"""

import random
import operator

allItemSet = set()
def InitAllItemSet(user_items):
allItemSet.clear()
for user, items in user_items.items():
for i, r in items.items():
allItemSet.add(i)

def InitItems_Pool(items):
interacted_items = set(items.keys())
items_pool = list(allItemSet - interacted_items)
#    items_pool = list(allItemSet)
return items_pool

def RandSelectNegativeSample(items):
ret = dict()
for i in items.keys():
ret[i] = 1
n = 0
for i in range(0,len(items) * 3):
items_pool = InitItems_Pool(items)
item = items_pool[random.randint(0,len(items_pool) - 1 )]
if item in ret:
continue
ret[item] = 0
n += 1
if n > len(items):
break
return ret

def Predict(user,item,P,Q):
rate = 0
for f,puf in P[user].items():
qif = Q[item][f]
rate += puf * qif
return rate

def InitModel(user_items,F):
P = dict()
Q = dict()
for user, items in user_items.items():
P[user] = dict()
for f in range(0,F):
P[user][f] = random.random()
for i,r in items.items():
if i not in Q:
Q[i] = dict()
for f in range(0,F):
Q[i][f] = random.random()
return P,Q

def LatentFactorModel(user_items, F,T, alpha, lamb):
InitAllItemSet(user_items)
[P,Q] = InitModel(user_items, F)
for step in range(0,T):
for user, items in user_items.items():
samples = RandSelectNegativeSample(items)
for item, rui in samples.items():
eui = rui - Predict(user, item, P,Q)
for f in range(0,F):
P[user][f] += alpha * (eui * Q[item][f] - \
lamb * P[user][f])
Q[item][f] += alpha * (eui * P[user][f] - \
lamb * Q[item][f])
alpha *= 0.9
return P,Q

def Recommend(user,train,P,Q):
rank = dict()
interacted_items = train[user]
for i in Q:
if i in interacted_items.keys():
continue
rank.setdefault(i,0)
for f,qif in Q[i].items():
puf = P[user][f]
rank[i] += puf * qif
return rank

def Recommendation(users, train,P,Q):
result = dict()
for user in users:
rank = Recommend(user,train,P,Q)
R = sorted(rank.items(), key = operator.itemgetter(1), \
reverse = True)
result[user] = R
return result


代码中,我们的Recommend函数和原文有些不同。同时补充了原书中提到的函数。

在我们github上有整体的代码,包括数据读取,推荐,评估等。github网址为:

https://github.com/1092798448/RecSys.git
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息