基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)

2024-05-07 13:38

本文主要是介绍基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

基于上下文的推荐

    基于时间特征的推荐
        时间衰减
            基于时间衰减的ItemCF算法
                算法核心两部分,都加入了时间衰减项
                    以movielens数据集实现ItemCF
            基于时间衰减的UserCF算法
                    以movielens数据集实现UserCF
    基于地点和热度推荐
            原理(包含三种数据集)
            以home-less数据集为例实现代码

基于时间特征的推荐

时间信息对用户兴趣的影响:

    物品具有生命周期(例如春节档电影)
    用户兴趣随时间变化
    季节效应(冬奶茶夏圣代,吸溜)
    所以在给定时间信息后,对于推荐系统变成了一个时变的系统。

对于Delicious数据集(包括4部分–用户ID,日期,网页URL和标签)我们用不同的指标可以度量网站中物品的生命周期:

    物品评价在线天数
    相隔T天系统物品流行度向量的平均相似度(判断用户兴趣的转变)
    在这里插入图片描述
    可以看到成指数级下降,即我们推荐时要降低几天前的权重。
    实现实时性要求推荐算法:
    要求每个用户访问时,要根据用户当前时间点前的行为实时计算推荐列表。
    推荐算法要平衡考虑用户近期和长期行为(用户有长期的兴趣爱好)

对于现实中的推荐系统表现可以看出:对于推荐的书籍会在你搜索某本书籍时发生一两本的变化,但是整体还是稳定的,维持着用户长期兴趣的推荐。

通过对用户调查的实验观察得出:
在这里插入图片描述
对于没有用户行为时,实现时间多样性的方法:

    在生成结果时加入随机性
    记录用户每天看到的推荐结果,再次推荐时针对前几天看到很多次的推荐结果降权
    (若降权后,推荐的仍在列表前面则继续推荐)

时间衰减

在这里插入图片描述
基于时间衰减的ItemCF算法
算法核心两部分,都加入了时间衰减项

时间衰减函数:在这里插入图片描述
在这里插入图片描述
以movielens数据集实现ItemCF

import json
import pandas as pd
import math
import os
from operator import itemgetter
from sklearn.model_selection import train_test_split


class NewItemCF:
    def __init__(self,datafile,simfile):
        self.alpha = 0.5
        self.beta = 0.8
        #文件目录
        self.datafile = datafile
        #存放相似度矩阵的文件目录
        self.simfile=simfile
        #最大的时间
        self.max_time=self.get_maxtime()
        #获得训练集与测试集
        self.train, self.test = self.loadData()
        if os.path.exists(simfile):
            self.items_sim=json.load(open('data/items_sim.json', 'r'))
        else:
            self.items_sim = self.ItemSimilarityBest()
    def loadData(self):
        data = list()
        with open(self.datafile, 'r') as f:
            lines = f.readlines()
        for line in lines:

            userid, itemid, record, timestamp = line.split("::")
            data.append((userid, itemid, int(record), int(timestamp)))


        train_list, test_list = train_test_split(data, test_size=0.3,random_state=1)

        train_dict = self.transform(train_list)
        test_dict = self.transform(test_list)

        return train_dict, test_dict
    def get_maxtime(self):
        title = ['user', 'movie', 'rating', 'time']
        data = pd.read_csv(self.datafile, sep='::', names=title,engine = 'python')
        return data['time'].max()
    def transform(self,data):
        data_dict=dict()
        for userid,itemid,record,timestamp in data:
            data_dict.setdefault(userid,{})
            data_dict[userid].setdefault(itemid,{})
            data_dict[userid][itemid]['rate']=record
            data_dict[userid][itemid]['time']=timestamp
        return data_dict

    def ItemSimilarityBest(self):
        items_sim=dict()
        #统计每个物品的关联用户数
        item_user_count=dict()
        #两两物品相似度计算的分子部分
        C=dict()

        for user,items in self.train.items():
            for i in items.keys():
                item_user_count.setdefault(i,0)
                if self.train[user][i]['rate']>0:
                    item_user_count[i]+=1
                if i not in C.keys():
                    C[i]=dict()
                for j in items.keys():
                    if i==j:
                        continue
                    if j not in C[i].keys():
                        C[i][j]=0
                    if self.train[user][i]['rate']>0 and self.train[user][j]['rate']>0:
                        C[i][j]+=1/(1+self.alpha*abs(self.train[user][i]['time']-self.train[user][j]['time'])/(24*60*60))

        for i,related_items in C.items():
            items_sim.setdefault(i,dict())
            for j,cij in related_items.items():
                items_sim[i][j]=cij/math.sqrt(item_user_count[i]*item_user_count[j])

        json.dump(items_sim, open(self.simfile, 'w'))
        return items_sim

    def recommand(self,user,K=20,N=10):
        items_sim=self.items_sim
        rank=dict()

        ru=self.train.get(user,{})
        for i,rui in ru.items():
            for j,wij in sorted(items_sim[i].items(),key=itemgetter(1),reverse=True)[:K]:
                if j in ru.keys():
                    continue
                if j not in rank.keys():
                    rank[j]=0.0

                rank[j]+=rui['rate']*wij*(1/(1+self.beta*(self.max_time-rui['time'])/(24*60*60)))
        return sorted(rank.items(),key=itemgetter(1),reverse=True)[:N]

    def precision(self, K=20, N=10):
        hit = 0
        num=0
        for user in self.train.keys():
            tu = self.test.get(user, {})
            rank = self.recommand(user, K=K, N=N)
            for item, rate in rank:
                if item in tu:
                    hit += 1
            num += N
        precision=hit/num
        return precision

if __name__ == '__main__':
    b=NewItemCF('ml-1m/ratings.dat','data/items_sim.json')
    print(b.precision())

基于时间衰减的UserCF算法

原理同上面的ItemCF算法,这里不再解释。
以movielens数据集实现UserCF

import json
import math
import pandas as pd
import os
from operator import itemgetter
from sklearn.model_selection import train_test_split


class NewUserCF:
    def __init__(self,datafile,simfile):
        self.alpha=0.5
        self.beta=0.8
        #文件目录
        self.datafile=datafile
        #存放相似度矩阵的文件
        self.simfile=simfile
        #获取最大的时间
        self.max_time=self.get_maxtime()
        #获取数据
        self.train,self.test=self.loadData()
        #用户之间相似度
        if os.path.exists('data/users_sim.json'):
            self.users_sim=json.load(open('data/users_sim.json','r'))
        else:
            self.users_sim=self.UsersSimilarity()
    def get_maxtime(self):
        title = ['user', 'movie', 'rating', 'time']
        data = pd.read_csv(self.datafile, sep='::', names=title, engine='python')
        return data['time'].max()

    def loadData(self):
        data=list()
        with open(self.datafile,'r') as f:
            lines=f.readlines()
        for line in lines:
            userid,itemid,record,timestamp=line.split("::")
            data.append([userid,itemid,int(record),int(timestamp)])
        train_data,test_data=train_test_split(data,test_size=0.3,random_state=1)
        train_data=self.transform(train_data)
        test_data=self.transform(test_data)
        return train_data,test_data

    def transform(self,data):
        data_dict=dict()
        for userid,itemid,record,timestamp in data:
            if userid not in data_dict.keys():
                data_dict[userid]={}
            if itemid not in data_dict[userid].keys():
                data_dict[userid][itemid]={}
            data_dict[userid][itemid]['rate']=record
            data_dict[userid][itemid]['time']=timestamp
        return data_dict

    def UsersSimilarity(self):


        #物品-用户倒查表
        item_users=dict()
        for u,items in self.train.items():
            for i in items.keys():
                item_users.setdefault(i,set())
                if self.train[u][i]['rate']>0:
                    item_users[i].add(u)
        #计算两两用户相似的分子部分
        C=dict()
        #统计每个用户评价过多少个电影
        N=dict()
        for user,item_dict in self.train.items():
            if user not in N.keys():
                N[user]=0

            items=[item for item in item_dict.keys() if item_dict[item]['rate']>0]
            N[user]=len(items)
        for item,users in item_users.items():
            for u in users:
                C.setdefault(u,dict())
                for v in users:
                    C[u].setdefault(v,0.0)
                    if v==u:
                        continue
                    C[u][v]+=(1/(1+self.alpha*abs(self.train[u][item]['time']-self.train[v][item]['time'])/(24*60*60)))*(1/math.log(1+len(users)))

        users_sim=dict()
        for u,related_users in C.items():
            users_sim.setdefault(u,dict())
            for v,wuv in related_users.items():
                if u==v:
                    continue
                users_sim[u][v]=wuv/math.sqrt(N[u]*N[v])
        json.dump(users_sim,open('data/users_sim.json','w'))
        return users_sim


    def recommand(self,user,K=20,N=10):
        """

        :param user: 用户id
        :param K: 取和user相似的前K的其他用户
        :param N: 推荐N个物品
        :return: 推荐列表及用户对其的兴趣的字典
        """
        rank=dict()
        related_items=self.train.get(user,{})
        for v,wuv in sorted(self.users_sim[user].items(),key=itemgetter(1),reverse=True)[:K]:
            for i,rvi in self.train[v].items():
                if i in related_items.keys():
                    continue
                if i not in rank.keys():
                    rank[i]=0.0
                else:
                    rank[i]+=wuv*rvi['rate']*(1/(1+self.beta*(self.max_time-rvi['time'])))
        return sorted(rank.items(),key=itemgetter(1),reverse=True)[:N]
    def precision(self,K=20,N=10):
        hit=0
        num=0

        for user in self.train.keys():
            tu=self.test.get(user,{})
            rank=self.recommand(user,K=K,N=N)
            for item,rate in rank:
                if item in tu:
                    hit+=1
            num+=N
        precision=hit/num
        return precision

if __name__ == '__main__':
    a=NewUserCF('ml-1m/ratings.dat','data/users_sim.json')
    print(a.precision())


   

基于地点和热度推荐
原理(包含三种数据集)

在这里插入图片描述
以home-less数据集为例实现代码

# 这里用了老师给的代码
# 这个数据集与上面三种数据集采用的思想不一样
import pandas as pd

class RecBasedAh:
    def __init__(self,path=None,Addr='朝阳区',type='score',k=10):
        self.path=path
        self.Addr=Addr
        self.type=type
        self.k=k

        self.data=self.load_mess()
    def load_mess(self):
      # 这个函数筛选出用户位置周围的数据
        data=pd.read_csv(self.path,header=0,sep=',',encoding='GBK')
        return data[data['addr']==self.Addr]

    def recommand(self):
      # 判断推荐所依据的原因
      # else 中是综合原因 对于评分 评论条数 开业时间 装修时间分别做了加权
      # 可以自己设计自己的要求 比如对于开业时间等不做考虑
        if self.type in ['score','comment_num','lowest_price','decoration_time','open_time']:
            data=self.data.sort_values(by=[self.type,'lowest_price'],ascending=False)[:self.k]
            return dict(data.filter(items=['name',self.type]).values)
        elif self.type=='combine':
            data=self.data.filter(items=['name','score','comment_num','lowest_price','decoration_time','open_time'])
            #装修时间越近越好
            data['decoration_time']=data['decoration_time'].apply(lambda x:int(x)-2017)
            #开业时间越早越好
            data['open_time']=data['open_time'].apply(lambda x:2017-int(x))

            for col in data.keys():
                if col!='name':
                    data[col]=(data[col]-data[col].min())/(data[col].max())


            data[self.type]=1*data['score']+2*data['comment_num']+1.5*data['lowest_price']+0.5*data['decoration_time']+0.5*data['open_time']
            data=data.sort_values(by=self.type,ascending=False)[:self.k]
            return dict(data.filter(items=['name',self.type]).values)


if __name__ == '__main__':
    path='hotel-mess/hotel-mess.csv'

    hotel_rec=RecBasedAh(path,Addr='朝阳区',type='combine',k=10,sort=False)
    print(hotel_rec.recommand())

这篇关于基于上下文的推荐 -- 包括时间衰减算法和位置推荐算法(代码实现)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967506

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

服务器集群同步时间手记

1.时间服务器配置(必须root用户) (1)检查ntp是否安装 [root@node1 桌面]# rpm -qa|grep ntpntp-4.2.6p5-10.el6.centos.x86_64fontpackages-filesystem-1.41-1.1.el6.noarchntpdate-4.2.6p5-10.el6.centos.x86_64 (2)修改ntp配置文件 [r

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi