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

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

相关文章

pandas中位数填充空值的实现示例

《pandas中位数填充空值的实现示例》中位数填充是一种简单而有效的方法,用于填充数据集中缺失的值,本文就来介绍一下pandas中位数填充空值的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是中位数填充?为什么选择中位数填充?示例数据结果分析完整代码总结在数据分析和机器学习过程中,处理缺失数

Golang HashMap实现原理解析

《GolangHashMap实现原理解析》HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持高效的插入、查找和删除操作,:本文主要介绍GolangH... 目录HashMap是一种基于哈希表实现的键值对存储结构,它通过哈希函数将键映射到数组的索引位置,支持

Pandas使用AdaBoost进行分类的实现

《Pandas使用AdaBoost进行分类的实现》Pandas和AdaBoost分类算法,可以高效地进行数据预处理和分类任务,本文主要介绍了Pandas使用AdaBoost进行分类的实现,具有一定的参... 目录什么是 AdaBoost?使用 AdaBoost 的步骤安装必要的库步骤一:数据准备步骤二:模型

使用Pandas进行均值填充的实现

《使用Pandas进行均值填充的实现》缺失数据(NaN值)是一个常见的问题,我们可以通过多种方法来处理缺失数据,其中一种常用的方法是均值填充,本文主要介绍了使用Pandas进行均值填充的实现,感兴趣的... 目录什么是均值填充?为什么选择均值填充?均值填充的步骤实际代码示例总结在数据分析和处理过程中,缺失数

Java对象转换的实现方式汇总

《Java对象转换的实现方式汇总》:本文主要介绍Java对象转换的多种实现方式,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java对象转换的多种实现方式1. 手动映射(Manual Mapping)2. Builder模式3. 工具类辅助映

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

SpringBoot基于配置实现短信服务策略的动态切换

《SpringBoot基于配置实现短信服务策略的动态切换》这篇文章主要为大家详细介绍了SpringBoot在接入多个短信服务商(如阿里云、腾讯云、华为云)后,如何根据配置或环境切换使用不同的服务商,需... 目录目标功能示例配置(application.yml)配置类绑定短信发送策略接口示例:阿里云 & 腾

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模