基于用户行为特征的推荐算法

简述:基于用户行为分析的推荐算法是个性化推荐系统的重要算法,也被称为协同过滤算法,即通过用户与网站不断互动,来不断过滤自己感兴趣的物品。

基础概念

用户行为分类

  1. 按照反馈的明确性分
    显性反馈行为:
    用户明确表示对物品的喜好的行为,如点赞,评分等
    隐形反馈行为:
    不能明确反映用户喜好的行为,浏览日志,观看日志等
  2. 按照反馈的⽅向分
    正反馈:指⽤户的⾏为倾向于指⽤户喜欢该物品。
    负反馈:负反馈指⽤户的⾏为倾向于指⽤户不喜欢该物品

用户行为表示

在这里插入图片描述

用户行为分析

用户行为数据满足power law的分布,即长尾分布
在这里插入图片描述
在这里插入图片描述

基于邻域的推荐算法

基于用户的协同过滤算法

核心思想

找到与目标用户兴趣相似的用户集合,找到这个集合中用户喜欢且目标用户没有听说过的物品推荐给目标用户。

  1. 计算用户相似度
    在这里插入图片描述
    其中分子部分,即交集部分,如果两两计算时间复杂度较大,可以先建立用户倒查表,来存储对该物品产⽣过⾏为的⽤户列表。同时在改良方法中为降低热门物品的影响,引入惩罚项。
    在这里插入图片描述
    在这里插入图片描述

  2. 计算用户对物品的感兴趣程度
    在这里插入图片描述

代码实现
#初始数据
user_item_dict = {"A": ['a','b','e'],
                  "B": ['c','e','g'],
                  "C": ['a','d','f','g'],
                  "D": ['b','c','e','f'],
                  "E": ['b','d'],
                  "F": ['c','d','f']
                 }

#基于用户的协同过滤算法
class UserCF():
    def __init__(self,user_item_dict):
        #将每个用户的物品取集合
        self.user_item_dict = {key:set(user_item_dict[key]) for key in user_item_dict.keys()}
        #用户列表
        self.users_list = list(self.user_item_dict.keys())
    #两两用户之间计算用户相似度
    def compute_similer_twouser(self):
        #记录与其他用户相似度的字典
        user_similer_list = dict()
        
        for i in self.users_list:
            user_similer_list[i] = dict()
            for j in self.users_list:
                #去除自身相似度
                if i !=  j:
                    #两用户间物品并集,并计算余弦相似度
                    similer_item = self.user_item_dict[i] & self.user_item_dict[j]
                    user_similer_list[i][j]= round(len(similer_item)/(len(self.user_item_dict[i]) * len(self.user_item_dict[j]))**0.5,3)
        return user_similer_list
    
#     优化后的倒查表方式计算用户相似度
    def computer_similer_backform_normal(self):
        import numpy as np
        #记录物品的所有用户的字典
        item_user_dict = dict()
        #建立物品到用户的倒查表
        for i,items in self.user_item_dict.items():
            for j in items:
                if j not in item_user_dict.keys():
                    item_user_dict[j] = list()
                item_user_dict[j].append(i)
                
        #建立用户物品二维矩阵
        user_matrix = np.zeros((len(self.users_list),len(self.users_list)),dtype = int)
        for  item, users in item_user_dict.items():
            for user1 in users:
                for user2 in users:
                    if user1 != user2:
                        #记录不同用户间共同物品的数目
                        user_matrix[self.users_list.index(user1)][self.users_list.index(user2)] += 1
                
        #计算用户相似度
        user_similer_list = dict()
        for user1 in self.users_list:
            user_similer_list[user1] = dict()
            for user2 in self.users_list:
                if user1 != user2:
                    #利用二维矩阵存储的用户相似度进行计算
                    user_similer_list[user1][user2] =round(user_matrix[self.users_list.index(user1)][self.users_list.index(user2)]/
                                                           (len(self.user_item_dict[user1]) * len(self.user_item_dict[user2]))**0.5,3)   
        return user_similer_list
    #惩罚热门物品和倒查表方式计算用户相似度(同倒查表方式一致,只是在相似度计算中引入惩罚))
    def computer_similer_backform_punish(self):
        import numpy as np
        import math
        item_user_dict = dict()
        #建立物品到用户的倒查表
        for i,items in self.user_item_dict.items():
            for j in items:
                if j not in item_user_dict.keys():
                    item_user_dict[j] = list()
                item_user_dict[j].append(i)
                
        #建立用户矩阵
        self.user_matrix = np.zeros((len(self.users_list),len(self.users_list)))
        for  item, users in item_user_dict.items():
            for user1 in users:
                for user2 in users:
                    if user1 != user2:
                        #对热门物品进行惩罚
                        self.user_matrix[self.users_list.index(user1)][self.users_list.index(user2)] += 1/math.log(1+len(users))
                
        #计算用户相似度
        user_similer_list = dict()
        for user1 in self.users_list:
            user_similer_list[user1] = dict()
            for user2 in self.users_list:
                if user1 != user2:
                    user_similer_list[user1][user2] =round(self.user_matrix[self.users_list.index(user1)][self.users_list.index(user2)]/ 
                    (len(self.user_item_dict[user1]) * len(self.user_item_dict[user2]))**0.5,3)
                    self.user_matrix[self.users_list.index(user1)][self.users_list.index(user2)] = user_similer_list[user1][user2]
        return user_similer_list,item_user_dict
    
    #计算指定用户的推荐物品
    def compute_interest_item(self,user):
        
        user_similer_list,item_user_dict = self.computer_similer_backform_punish()
        #本处相似用户集合大小为3,取相似度高的前三名用户
        sort_coor = np.argsort(self.user_matrix[self.users_list.index(user)])[::-1][:3]
    
        recommend_item = dict()
        for item in item_user_dict.keys():
            recommend_item[item] = 0
            for i in sort_coor:
                #推荐不在指定用户物品集中,但在相似用户物品集中的物品,r=1
                if item not in self.user_item_dict[user] and item in self.user_item_dict[self.users_list[i]]:
                    recommend_item[item] += self.user_matrix[self.users_list.index(user)][i]
        
        #对推荐的物品按照感兴趣程度降序
        recommend_item = {k:v for k,v in sorted(recommend_item.items(), key = lambda item :item[1] ,reverse=True) if v != 0}
        return recommend_item
    
usercf = UserCF(user_item_dict)
print('两两用户之间计算用户相似度:')
print(usercf.compute_similer_twouser())
print('优化后的倒查表方式计算用户相似度:')
print(usercf.computer_similer_backform_normal())
print('惩罚热门物品和倒查表方式计算用户相似度:')
print(usercf.computer_similer_backform_punish()[0])
print('推荐物品:')
print(usercf.compute_interest_item('A'))

在这里插入图片描述

缺点
  • 随着⽹站的⽤户数⽬越来越⼤,计算⽤户兴趣相似度矩阵将越来越困难,其运算时间复杂度和空间复杂度的增⻓和⽤户数的增⻓近似于平⽅关系。
  • 基于⽤户的协同过滤很难对推荐结果作出解释。

基于物品的协同过滤算法

核心思想

同基于用户的协同过滤算法一致,只是从物品的角度进行推荐。给用户推荐那些和他们之前喜欢的物品相似的物品。

  1. 计算物品之间的相似度。
    在这里插入图片描述
    为减轻了热⻔物品会和很多物品相似的可能性,替换为:
    在这里插入图片描述
  • 直接两两取交集
  • 建立倒查表
  • 建立倒查表+惩罚项
  1. 相似度归一化
    在研究中发现如果将 ItemCF 的相似度矩阵按最⼤值归⼀化,可以提⾼推荐的准确率
    在这里插入图片描述

  2. 根据物品的相似度和⽤户的历史⾏为给⽤户⽣成推荐列表。
    在这里插入图片描述

代码实现
  • 实验数据同上
#基于物品的协同过滤算法
class ItemCF():
    def __init__(self,user_item_dict):
        #将每个用户的物品取集合
        self.user_item_dict = {key:set(user_item_dict[key]) for key in user_item_dict.keys()}
        #用户列表
        self.users_list = list(self.user_item_dict.keys())
        
        #物品的用户集合
        self.item_user_dict = dict()
        #建立物品到用户的倒查表
        for i,items in self.user_item_dict.items():
            for j in items:
                if j not in self.item_user_dict.keys():
                    self.item_user_dict[j] = set()
                self.item_user_dict[j].add(i)
        
        #物品列表
        self.items_list = list(self.item_user_dict.keys())
    #两两用户之间计算物品相似度
    def compute_similer_twouser(self):
        #记录与其他物品相似度的字典
        item_similer_list = dict()
        
        for i in self.items_list:
            item_similer_list[i] = dict()
            for j in self.items_list:
                #去除自身相似度
                if i !=  j:
                    #两物品间用户并集,并计算余弦相似度
                    similer_user = self.item_user_dict[i] & self.item_user_dict[j]
                    item_similer_list[i][j]= round(len(similer_user)/(len(self.item_user_dict[i]) * len(self.item_user_dict[j]))**0.5,3)
        return item_similer_list
    
#     优化后的倒查表方式计算物品相似度
    def computer_similer_backform_normal(self):
        import numpy as np
        
        #建立物品二维矩阵
        item_matrix = np.zeros((len(self.items_list),len(self.items_list)),dtype = int)
        for  users,items in self.user_item_dict.items():
            for item1 in items:
                for item2 in items:
                    if item1 != item2:
                        #记录不同物品间共同用户的数目
                        item_matrix[self.items_list.index(item1)][self.items_list.index(item2)] += 1
                
        #计算物品相似度
        item_similer_list = dict()
        for item1 in self.items_list:
            item_similer_list[item1] = dict()
            for item2 in self.items_list:
                if item1 != item2:
                    #利用二维矩阵存储的物品相似度进行计算
                    item_similer_list[item1][item2] =round(item_matrix[self.items_list.index(item1)][self.items_list.index(item2)]/
                                                           (len(self.item_user_dict[item1]) * len(self.item_user_dict[item2]))**0.5,3)   
        return item_similer_list
    #惩罚活跃用户和倒查表方式计算物品相似度(同倒查表方式一致,只是在相似度计算中引入惩罚))
    def computer_similer_backform_punish(self):
        import numpy as np
        import math
        #建立物品二维矩阵
        self.item_matrix = np.zeros((len(self.items_list),len(self.items_list)))
        for  users,items in self.user_item_dict.items():
            for item1 in items:
                for item2 in items:
                    if item1 != item2:
                        #记录不同物品间共同用户的数目
                        self.item_matrix[self.items_list.index(item1)][self.items_list.index(item2)] += 1/math.log(1+len(items))
                
        #计算物品相似度
        item_similer_list = dict()
        for item1 in self.items_list:
            item_similer_list[item1] = dict()
            for item2 in self.items_list:
                if item1 != item2:
                    #利用二维矩阵存储的物品相似度进行计算
                    item_similer_list[item1][item2] =round(self.item_matrix[self.items_list.index(item1)][self.items_list.index(item2)]/
                                                           (len(self.item_user_dict[item1]) * len(self.item_user_dict[item2]))**0.5,3)   
                    self.item_matrix[self.items_list.index(item1)][self.items_list.index(item2)] = item_similer_list[item1][item2]
        #物品相似度归一化
        self.item_matrix = self.item_matrix/self.item_matrix.max(axis = 1)
        return item_similer_list
    
    #计算指定用户的推荐物品
    def compute_interest_item(self,user):
        #物品相似度矩阵
        item_similer_list = self.computer_similer_backform_punish()
        recommend_item = dict()
        
        for item in self.items_list:
            recommend_item[item] = 0
            sort_coor = np.argsort(self.item_matrix[self.items_list.index(item)])[::-1][:3]
            for i in sort_coor :
                #对不在该用户的喜欢列表,但其相似物品在该用户物品列表的物品,进行计算
                if user in self.item_user_dict[self.items_list[i]] and user not in self.item_user_dict[item]:
                    recommend_item[item] += self.item_matrix[self.items_list.index(item)][i]

        
        #对推荐的物品按照感兴趣程度降序
        recommend_item = {k:v for k,v in sorted(recommend_item.items(), key = lambda item :item[1] ,reverse=True) if v != 0}
        return recommend_item



itemcf = ItemCF(user_item_dict)
print('两两物品之间计算物品相似度:')
print(itemcf.compute_similer_twouser())
print('优化后的倒查表方式计算物品相似度:')
print(itemcf.computer_similer_backform_normal())
print('惩罚活跃用户和倒查表方式计算物品相似度:')
print(itemcf.computer_similer_backform_punish())
print('推荐物品:')
print(itemcf.compute_interest_item('A'))

在这里插入图片描述

缺点

在这里插入图片描述

基于隐语义模型(LFM)

实现原理

基于用户兴趣分类,先对物品的兴趣进⾏分类,再对于某个⽤户,⾸先得到他的兴趣分类,然后从分类中挑选他可能喜欢的物品,而为将物品自动分类,引入隐含语义分析技术。在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

基于图模型

在这里插入图片描述

实现原理

利用图来表示用户和物品之间的关系,
相关性高的一对顶点特征:

  • 两个顶点之间有很多路径相连;
  • 连接两个顶点之间的路径⻓度都⽐较短;
  • 连接两个顶点之间的路径不会经过出度⽐较⼤的顶点。
    在这里插入图片描述

代码实现

#初始数据
user_item_dict = {"A": ['a','b','e'],
                  "B": ['c','e','g'],
                  "C": ['a','d','f','g'],
                  "D": ['b','c','e','f'],
                  "E": ['b','d'],
                  "F": ['c','d','f']
                 }
#基于图的推荐系统
import numpy as np

def person_rank(user_item_dict,user = 'A',alpha = 0.8,maxdeep=10):
    #用户列表
    user_list = list(user_item_dict.keys())
    
    item_list = list()
    for i in user_item_dict.values():
        item_list+= i
    #物品列表
    item_list = list(set(item_list))
#     建立用户物品矩阵,便于查询连接关系
    user_item_matrix = np.zeros((len(user_list),len(item_list)))
    for u in user_list:
        for item in item_list:
            if item in user_item_dict[u]:
                user_item_matrix[user_list.index(u)][item_list.index(item)] = 1
            
    #用户节点访问概率,并将指定节点初始为1
    pru =  [0]*len(user_list)
    pru[user_list.index(user)] = 1
    #物品节点访问概率,并将指定节点初始为1
    pri = [0]*len(item_list)
    #递归收敛
    for time in range(maxdeep):
        #新的用户节点概率与物品节点概率
        temp_pru = [0]*len(user_list)
        temp_pri = [0]*len(item_list)
        #新的物品节点概率
        for i in range(len(pri)):
            for j in range(len(user_list)):
                if user_item_matrix[j][i] ==1 :
                    temp_pri[i] += alpha*pru[j]/(1.0*len(user_item_matrix[j,:][user_item_matrix[j,:] != 0]))

#         新的用户节点概率
        for i in range(len(pru)):
            for j in range(len(item_list)):
                if user_item_matrix[i][j] ==1 :
                    temp_pru[i] += alpha*pri[j]/(1.0*len(user_item_matrix[:,j][user_item_matrix[:,j] != 0]))
        #指定的起始节点
        temp_pru[user_list.index(user)] += (1-alpha)

        pru = temp_pru
        pri = temp_pri
    #过滤与排序物品节点
    pri = {item_list[i]:pri[i] for i in range(len(pri)) if item_list[i] not in user_item_dict[user]}
    pri = {k:v for k,v in sorted(pri.items(),key=lambda item:item[1],reverse=True)}

    return pri

person_rank(user_item_dict,user='B')
#执行结果
{'f': 0.034595570273312,
 'b': 0.028538137484245288,
 'd': 0.02653204121030331,
 'a': 0.021514739831448457}
  • 13
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值