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

本文介绍了基于隐语义模型的推荐系统原理及其实现过程,重点讲述了如何通过隐含特征连接用户兴趣与物品,解决了物品分类、用户兴趣度确定等问题,并给出了具体的数学推导与代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上一篇博客,我们大致讲解了《推荐系统实践》中基于邻域的算法和代码实现,在这一篇博客,我们继续讲解基于隐语义模型(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(ruipTuqi)2+λ||pu||22+λ||qi||22

假设隐因子个数为 F 个,则可以重写为
C=(u,i)K(ruif=1Fpufqif)2+λ||pu||22+λ||qi||22

其中 λ||pu||22+λ||qi||22 是正则化项。要最小化上面的损失函数,可以利用随机梯度下降法。上面的目标函数对 puf qif 分别偏导数,得到
CpufCqif=2(u,i)K(ruif=1Fpufqif)qif+2λpuf=2(u,i)K(ruif=1Fpufqif)puf+2λqif

然后,根据根据梯度下降法,迭代公式为
pufqif:=puf+α((u,i)K(ruif=1Fpufqif)qifλpuf):=qif+α((u,i)K(ruif=1Fpufqif)pufλqif)

其中, α 是学习速率(learning rate)。
对于导数,也可以直接使用向量表示:

CpuCqi=2(u,i)K(ruipTuqi)qf+2λpu=2(u,i)K(ruipTuqi)pu+2λqi

其中, pu qi 分别为大小为 F <script type="math/tex" id="MathJax-Element-17">F</script>的列向量,表示用户和物品的隐因子向量。

代码实现如下:

# -*- 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhengjihao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值