美文网首页
隐语义模型--推荐算法实战

隐语义模型--推荐算法实战

作者: 郭彦超 | 来源:发表于2021-04-29 10:10 被阅读0次

隐语义模型(LFM)属于机器学习中的推荐算法,其中包含隐式因子部分,类似于深度学习网络的隐藏层(单层神经网络),所以很难解释隐含因子与模型最终输出结果的直接关系;但这并不妨碍我们使用该算法进行模型训练 ,因为目标最优才是我们衡量的效果。

LFM算法理解

  • userCF的思路是找到相似的用户,将其他用户喜欢的物品推荐给当前用户。
  • itemCF的思路找到与当前用户喜欢物品的相似物品推荐给他。见推荐算法入门
  • contentCF的思路是通过物品本身属性特征计算物品间的相似性,不考虑用户对物品的行为。
  • swing的思路是当同时购买物品A和物品B的用户里购买其它相同物品的比例越低,那么物品A和B越相近。见通过SQL实现阿里swing推荐算法
  • LFM的思路是在用户与物品间构建隐含‘兴趣‘分类,通过寻找与当前用户偏好分类的相近的物品推荐给当前用户。

计算兴趣度公式:

参数数说明:

  • P(u,k): 用户u和第k个隐类的关系,即用户u对k的偏好程度
  • Q(i,k): 第i个商品在第k个隐类的权重
  • F:隐类的个数
  • R(u,i): 用户u对商品i的实际评分

举例:
假如有三类电影,分别是[武打片,喜剧片,爱情片],用户A非常喜欢武打片,这里用户A的P矩阵就是[1, 0, 0];有电影如下:

  • 《战狼2》为武打片,那么Q的列向量表示Q(i,k)为[1, 0, 0]
  • 《你好李焕英》的Q向量为[0, 1, 0]

那么用户A对两部电影的偏好计算为:
R(A,战狼2) = P(u,k) * Q(k,i) = [1, 0, 0] * [1, 0, 0] = 1
R(A,你好李焕英) = P(u,k) * Q(k,i) = [1, 0, 0] * [, 1, 0] = 0

根据公式不难发现,其实LFM是在寻找合适的P&Q矩阵,需要注意的是这里的分类不需要用户提前指定,用户只需要设置好K的个数,分类特征是模型在训练的时候通过随机梯度分解得到的

LFM的缺点

  • 因P&Q矩阵需要提前算出,所有无法解决新用户与新商品冷启动的问题
  • 需要遍历全集才能计算R的关系,计算量大故无法应用于实时推荐场景

代码实现


import random
import pickle
import pandas as pd
import numpy as np
from math import exp
import time

class LFM:

    def __init__(self):
        self.class_count = 25  #K的个数
        self.iter_count = 10  #迭代次数
        self.lr = 0.02  #学习率
        self.lam = 0.01  #惩罚因子
        self._init_model()

    """
        构建P&Q矩阵,初始化参数
            randn: 从标准正态分布中返回n个值
            pd.DataFrame: columns 指定列顺序,index 指定索引
    """
    def _init_model(self):
        file_path = '03O2O优惠券/trains.csv'

        self.uiscores = pd.read_csv(file_path)
        self.user_ids = set(self.uiscores['user_id'].values)  # 6040
        self.item_ids = set(self.uiscores['product_id'].values) # 3706
        #self.items_dict = pickle.load(open(pos_neg_path,'rb'))
        self.user_items = {}
        for _, row in self.uiscores.iterrows():
            self.user_items.setdefault(row['user_id'],{})
            self.user_items[row['user_id']][row['product_id']] = row['score']
        
        array_p = np.random.randn(len(self.user_ids), self.class_count)
        array_q = np.random.randn(len(self.item_ids), self.class_count)
        self.p = pd.DataFrame(array_p, columns=range(0, self.class_count), index=list(self.user_ids))
        self.q = pd.DataFrame(array_q, columns=range(0, self.class_count), index=list(self.item_ids))

    # 使用误差平方和(SSE)作为损失函数
    def _loss(self, user_id, item_id, y, step):
        e = y - self._predict(user_id, item_id)
       # print('Step: {}, user_id: {}, item_id: {}, y: {}, loss: {}'.format(step, user_id, item_id, y, e))
        return e

    """
        计算用户 user_id 对 item_id的兴趣度
            p: 用户对每个类别的兴趣度
            q: 物品属于每个类别的概率
    """
    def _predict(self, user_id, item_id):
#         p = np.mat(self.p.loc[user_id].values)
#         q = np.mat(self.q.loc[item_id].values).T
#         r = (p * q).sum()
#         # 借助sigmoid函数,转化为是否感兴趣
#         loss = 1.0 / (1 + exp(-r))
         
        user_vector = self.p.loc[user_id].values
        item_vector = self.q.loc[item_id].values
        loss = np.dot(user_vector,item_vector)/(np.linalg.norm(user_vector)*np.linalg.norm(item_vector))
        return loss

   
   
    # 训练模型,每次迭代都要降低学习率,刚开始由于离最优值相差较远,因此下降较快,当到达一定程度后,就要减小学习率
    def train(self):
        for step in range(0, self.iter_count):
            
            for user_id, item_dict in self.user_items.items():
                #print('Step: {}, user_id: {}'.format(step, user_id))
                item_ids = list(item_dict.keys())
                random.shuffle(item_ids)
                for item_id in item_ids:
                    e = self._loss(user_id, item_id, item_dict[item_id], step)
                    self._optimize(user_id, item_id, e)
            self.lr *= 0.9
        print('train end...')
        self.save()


    def _optimize(self, user_id, item_id, e):
        gradient_p = -e * self.q.loc[item_id].values
        l2_p = self.lam * self.p.loc[user_id].values
        delta_p = self.lr * (gradient_p + l2_p)

        gradient_q = -e * self.p.loc[user_id].values
        l2_q = self.lam * self.q.loc[item_id].values
        delta_q = self.lr * (gradient_q + l2_q)

        self.p.loc[user_id] -= delta_p
        self.q.loc[item_id] -= delta_q

    

    # 计算用户未评分过的电影,并取top N返回给用户
    def predict(self, user_id, top_n=10):
        self.load()
        user_item_ids = set(self.uiscores[self.uiscores['user_id'] == user_id]['product_id'])
        other_item_ids = self.item_ids ^ user_item_ids # 交集与并集的差集
        interest_list = [self._predict(user_id, item_id) for item_id in other_item_ids]
        candidates = sorted(zip(list(other_item_ids), interest_list), key=lambda x: x[1], reverse=True)
        return candidates[:top_n]

    # 保存模型
    def save(self):
        f = open('data/lfm.model', 'wb')
        pickle.dump((self.p, self.q), f)
        f.close()

    # 加载模型
    def load(self):
        f = open('data/lfm.model', 'rb')
        self.p, self.q = pickle.load(f)
        f.close()

    # 模型效果评估,从所有user中随机选取10个用户进行评估,评估方法为:绝对误差(AE)
    def evaluate(self):
        self.load()
        users=random.sample(self.user_ids,10)
        user_dict={}
        for user in users:
            user_item_ids = set(self.uiscores[self.uiscores['user_id'] == user]['product_id'])
            _sum=0.0
            for item_id in user_item_ids: 
                _r = self._predict(user, item_id) 
                r=self.uiscores[(self.uiscores['user_id'] == user)
                                & (self.uiscores['product_id']==item_id)]["score"].values[0]
                _sum+=abs(r-_r)
            user_dict[user] = _sum/len(user_item_ids)
            print("userID:{},AE:{}".format(user,user_dict[user]))

        return sum(user_dict.values())/len(user_dict.keys())

if __name__=="__main__":
    lfm=LFM()
    lfm.train()
    print(lfm.predict('0000c9e938104b5d9ef2e16bbfb7489b',10))
    print(lfm.evaluate())
  • 该模型既可以用于推荐系统评分预测,也可以用在离线(CTR)点击预估

相关文章

  • 隐语义模型与推荐算法

    隐语义模型与推荐算法 标签:推荐算法 LFM(latent factor model)隐语义模型,这也是在推荐系统...

  • 隐语义模型--推荐算法实战

    隐语义模型(LFM)属于机器学习中的推荐算法,其中包含隐式因子部分,类似于深度学习网络的隐藏层(单层神经网络),所...

  • 隐语义模型与推荐算法

    隐语义模型与推荐算法 标签:机器学习深度学习 LFM(latent factor model)隐语义模型,这也是在...

  • 推荐系统

    主流的推荐算法协同过滤、隐语义模型、关联规则;基于人口统计学的推荐、基于物品内容的推荐 一、协同过滤二、隐语义模型...

  • 推荐算法——隐语义模型

    LFM(latent factor model) 通过隐含特征联系用户兴趣和物品。 计算用户u对物品i的兴趣: p...

  • 1.推荐算法串讲

    推荐算法 1、 基于内容的推荐 2、 基于近邻的推荐(协同过滤) 3、 基于矩阵分解的隐语义模型(LFM,FM,F...

  • 协同过滤算法

    协同过滤算法:基于用户行为数据设计的推荐算法,分为:基于邻域的方法、隐语义模型(LFM)、基于图的随机游走算法 1...

  • implicit 库 ALS 算法分析

    implicit 库 ALS 算法分析 ALS 算法 推荐模型基于“隐式反馈数据集的协同过滤”一文中描述的算法,其...

  • 第四章 相似度分析算法——基于语义主题模型的相似度算法

    4.6 基于语义主题模型的相似度算法 基于语义挖掘的方式即是主题模型的核心思想。利用主体模型可以较好地在文本之间进...

  • 推荐系统实践-利用用户行为数据(下)

    此文是根据《推荐系统实践》部分整理而来。 PART 1 隐语义模型 隐语义模型核心思想是:通过隐含特征联系用户...

网友评论

      本文标题:隐语义模型--推荐算法实战

      本文链接:https://www.haomeiwen.com/subject/wktvrltx.html