SimpleTagBased算法(基于用户标签做推荐)

一、SimpleTagBased算法简介

step1:统计每个用户的常用标签;
step2:对每个标签,统计被打过这个标签次数最多的商品;
step3:对于某一个具体用户,找到他最常用的标签,将这些标签最热门的物品推荐给他;
step4:排序推荐。
排序得分公式如下:
在这里插入图片描述
针对用户1排序如下:
得分= 用户1使用标签t的次数(n)*商品i被打过标签t的次数(n)

二、数据结构化

针对三个变量(user,item,tag)的数据结构,对其定义如下:
用户打标签记录:record[i] = {user,item,tag}
用户打过的标签:user_tags[u][t]
用户打过标签的商品:user_items[u][i]
打上某标签的商品:tag_items[t][i]

三、评价指标

使用混淆矩阵的召回率、精确率等,来判断推荐的情况

四、案例的数据

用户给书打标签的数据集:Delicious数据集
网址:https://grouplens.org/datasets/hetrec-2011/
数据的格式如下,文件格式为dat格式:
userID bookmarkID tagID timestamp
在这里插入图片描述
userID = user
bookmarkID = item
tagID = tag
timestamp(时间戳本案例用不到)

五、SimpleTagBased算法实现思路

step1:将数据集导入,并存储到字典中,储存格式为{user:{item:tag}}
step2:划分训练集和测试集;
step3:针对用户1计算score,score计算为{user1:{tag:n}}中的n(即用户使用该标签的次数n)与{tag:{item:m}}中的m(即该物品被打该标签的次数m)相乘,score=n*m,按从大到小进行排序,取topn;
step4:使用测试集进行评估

六.具体代码和数据集如下

#使用SimpleTagBased算法对Delicious数据集进行推荐
#原始数据集:https://grouplens.org/datasets/hetrec-2011/
# 数据格式:userID     bookmarkID     tagID     timestamp
import pandas as pd
import warnings
import math
import random
import operator
warnings.filterwarnings('ignore')

file_path = 'user_taggedbookmarks-timestamps.dat'
#采用字典格式,保存user对item的tag,{user:{item1:[tag1,rag2]...}...}
records = {}
#训练集、测试集
train_data = {}
test_data = {}
#用户标签,商品标签
user_tags = dict()
user_items = dict()
tag_items = dict()

#数据加载
def load_data():
    print('数据正在加载中...')
    df = pd.read_csv(file_path,sep = '\t')
    #将df放入设定的字典格式中
    for i in range(len(df)):
    #for i in range(10):
        uid = df['userID'][i]
        iid = df['bookmarkID'][i]
        tag = df['tagID'][i]
        #setdefault将uid设置为字典,iid设置为[]
        records.setdefault(uid,{})
        records[uid].setdefault(iid,[])
        records[uid][iid].append(tag)
    #print(records)
    print('数据集大小为:%d.' %len(df))
    print('设置tag的人数:%d.' %len(records))
    print('数据加载完成\n')

#将数据集拆分为训练集及测试集,ratio为测试集划分比例
def train_test_split(ratio,seed = 100):
    random.seed(seed)
    for u in records.keys():
        for i in records[u].keys():
            #ratio为设置的比例
            if random.random()<ratio:
                test_data.setdefault(u,{})
                test_data[u].setdefault(i,[])
                for t in records[u][i]:
                    test_data[u][i].append(t)
            else:
                train_data.setdefault(u,{})
                train_data[u].setdefault(i,[])
                for t in records[u][i]:
                    train_data[u][i].append(t)
    print("训练集user数为:%d,测试机user数为:%d." % (len(train_data),len(test_data)))

#设置矩阵mat[index,item],来储存index与item 的关系, = {index:{item:n}},n为样本个数
def addValueToMat(mat,index,item,value = 1):
    if index not in mat:
        mat.setdefault(index,{})
        mat[index].setdefault(item,value)
    else:
        if item not in mat[index]:
            mat[index].setdefault(item,value)
        else:
            mat[index][item] +=value

#使用训练集,初始化user_tags,user_items,tag_items,/user_tags为{user1:{tags1:n}}
#{user1:{tags2:n}}...{user2:{tags1:n}},{user2:{tags2:n}}....n为样本个数等
# user_items为{user1:{items1:n}}......原理同上
# tag_items为{tag1:{items1:n}}......原理同上
def initStat():
    records = train_data
    for u,items in records.items():
        for i,tags in records[u].items():
            for tag in tags:
                #users和tag的关系矩阵
                addValueToMat(user_tags,u,tag,1)
                #users和item的关系
                addValueToMat(user_items,u,i,1)
                #tag和item的关系
                addValueToMat(tag_items,tag,i,1)
    print('user_tags,user_items,tag_items初始化完成.')

#对某一用户user进行topN推荐
def recommend(user,N):
    recommend_item = dict()
    tagged_items = user_items[user]
    for tag,utn in user_tags[user].items():
        for item,tin in tag_items[tag].items():
            #如果某一user已经给某一item打过标签,则不推荐
            if item in tagged_items:
                continue
            if item not in recommend_item:
                recommend_item[item] = utn * tin
            else:
                recommend_item[item] = recommend_item[item]+utn*tin
    #按value值,从大到小排序
    return sorted(recommend_item.items(), key=operator.itemgetter(1), reverse=True)[0:N]

#使用测试集,计算准确率和召回率
def precisionAndRecall(N):
    hit = 0
    h_recall = 0
    h_precision = 0
    for user,items in test_data.items():
        if user not in train_data:
            continue
        rank = recommend(user,N)
        for item,rui in rank:
            if item in items:
                hit = hit+1
        h_recall = h_recall +len(items)
        h_precision = h_precision+N

    #返回准确率和召回率
    return (hit/(h_precision*1.0)), (hit/(h_recall*1.0))

#使用test_data对推荐结果进行评估
def testRecommend():
    print('推荐结果评估如下:')
    print("%3s %10s %10s" % ('N', "精确率", '召回率'))
    for n in [5,10,20,40,60,80,100]:
        precision,recall = precisionAndRecall(n)
        print("%3d %10.3f%% %10.3f%%" % (n, precision * 100, recall * 100))


load_data()
train_test_split(0.2)
initStat()
testRecommend()

SimpleTagBased基于用户标签做对书的推荐

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

蓝翔厨师长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值