机器学习->推荐系统->给用户推荐标签

本文介绍了一种基于用户行为的标签推荐系统,旨在提高用户给物品打标签的质量与效率。系统提供了四种推荐方法:PopularTags、ItemPopularTags、UserPopularTags 和 HybridPopularTags,并通过实验评估了这些方法的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当用户浏览某个物品时,标签系统非常希望用户能给这个物品打出高质量的标签,这样才能促进标签系统的良性循环。

为什么要给用户推荐标签?一般看来有以下好处。
1)方便用户输入标签。用户一般不愿意通过从键盘输入标签来给物品打标签。给用户推荐标签,可以提高用户打标签参与度。
2)提高标签质量。用户给物品打标签,同一个语义不同内容的词很庞大,而且会使计算相似度不太准确。而使用推荐标签时,我们可以对词表进行选择,首先保证词表不会出现太多的同义词,同时保证出现的词是一些比较热门的,有代表性的词。

如何给用户推荐标签,有以下四个方法。
1)PopularTags
给用户推荐整个系统中最热门的标签,这个算法太简单,以至于不能称为一种推荐算法。

def RecommendPopularTags(user,item,tags,N):
    ##tags字典:tag->用户使用tag的次数
    tags=dict(sorted(tags.items(),key=lambda x:x[1],reverse=True)[0:N])
    return tags.keys()

2)ItemPopularTags
给用户u推荐物品i最热门的标签

def RecommendItemPopularTags(user,item,item_tags,N):
    ##item_tags两层字典:item->(tag->物品item被打tag次数)
    return dict(sorted(item_tags[item].items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

3)UserPopularTags
给用户推荐他经常使用的标签

def RecommendUserPopularTags(user,item,user_tags,N):
    ##user_tags两层字典:user->(tags->用户打tag的次数)
    return dict(sorted(user_tags[user].items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

4)HybridPopularTags
前两种算法的融合,该方法通过一个系数将以上两种方法结果线性加权,然后生成最终的结果。

def RecommendHybridPopularTags(user,item,user_tags,item_tags,alpha,N):
    ret=dict()
    max_user_tag_weight=max(user_tags[user].values())
    for tag,weight in user_tags[user].items():
        ret[tag]=(1-alpha)*weight/max_user_tag_weight

    max_item_tags_weight=max(item_tags[item].values())
    for tag,weight in item_tags[item].items():
        if tag not in ret:
            ret[tag]=alpha*weight/max_item_tags_weight
        else:
            ret[tag]+=alpha*weight/max_item_tags_weight
    return dict(sorted(ret.items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

实现完整Python代码:数据源deilicous上200509数据,我们取前5万行数据进行实验,随机分为10份,其中一份做测试,另外9份做训练。这里我们根据上述四种算法,在训练集数据中分别计算出最热门的标签,物品i最热门的标签,用户u经常使用的标签。所以在划分训练测试集时,训练集和测试集中用户,物品,标签不能有任何重复,故在这里划分训练测试集时需要以user,item,tag作为主键划分。

#coding:utf-8
import pandas as pd
import numpy as np
import random


def genData():
    data=pd.read_csv('200509',header=None,sep='\t')
    data.columns=['date','user','item','tag']
    data.drop('date',axis=1,inplace=True)
    print 'genData successed!!!'
    return data[:50000]

def user_item_tag(data):
    ##在将源数据以user,item,tag为主键构造数据,元组列表(列表里面每个元素是元组)
    UIT=[]
    for i in range(len(data)):
        lst=list(data.loc[i])
        user=lst[0]
        item=lst[1]
        tag=lst[2]
        temp=(user,item,tag)
        if temp not in UIT:
            UIT.append(temp)
    return UIT

def splitData(records,train,test):
    ##以9:1划分训练集测试集
    for user,item,tag in records:
        if random.randint(1,10)==1:
            test.append([user,item,tag])
        else:
            train.append([user,item,tag])
    print 'split succeed!'
    return train,test

def Initstate(data):
    ##以训练集里数据分别计算出
    ##tags字典:tag->tag被打次数
    ##item_tags字典:item->(tag->物品item被打tag标签的次数)
    ##user——tags字典:user->(tag->用户user打tag标签的次数)
    tags=dict()
    item_tags=dict()
    user_tags=dict()
    for lst in data:
        user=lst[0]
        item=lst[1]
        tag=lst[2]
        if tag not in tags:
            tags[tag]=0
        tags[tag]+=1

        if item not in item_tags:
            item_tags[item]=dict()
        if tag not in item_tags[item]:
            item_tags[item][tag]=0
        item_tags[item][tag]+=1

        if user not in user_tags:
            user_tags[user]=dict()
        if tag not in user_tags[user]:
            user_tags[user][tag]=0
        user_tags[user][tag]+=1
    return tags,item_tags,user_tags

def RecommendPopularTags(user,item,tags,N):
    ##tags字典:tag->用户使用tag的次数
    tags=dict(sorted(tags.items(),key=lambda x:x[1],reverse=True)[0:N])
    return tags.keys()

def RecommendItemPopularTags(user,item,item_tags,N):
    ##item_tags两层字典:item->(tag->物品item被打tag次数)
    return dict(sorted(item_tags[item].items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

def RecommendUserPopularTags(user,item,user_tags,N):
    ##user_tags两层字典:user->(tags->用户打tag的次数)
    return dict(sorted(user_tags[user].items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

def RecommendHybridPopularTags(user,item,user_tags,item_tags,alpha,N):
    ##上面两种算法的线性加权
    ret=dict()
    max_user_tag_weight=max(user_tags[user].values())
    for tag,weight in user_tags[user].items():
        ret[tag]=(1-alpha)*weight/max_user_tag_weight

    max_item_tags_weight=max(item_tags[item].values())
    for tag,weight in item_tags[item].items():
        if tag not in ret:
            ret[tag]=alpha*weight/max_item_tags_weight
        else:
            ret[tag]+=alpha*weight/max_item_tags_weight
    return dict(sorted(ret.items(),key=lambda x:x[1],reverse=True)[0:N]).keys()

def getTU(test,user,item):
    tags=[]
    for lst in test:
        t_user=lst[0]
        t_item=lst[1]
        t_tag=lst[2]
        if (user==t_user) and (item==t_item):
            tags.append(t_tag)
    return tags

def GetRecommend(user,item,item_tags,user_tags,tags,N,state):
    if state==1:
        return RecommendItemPopularTags(user,item,item_tags,N)
    if state==2:
        return RecommendPopularTags(user,item,tags,N)
    if state==3:
        return RecommendUserPopularTags(user,item,user_tags,N)
    if state==4:
        return RecommendHybridPopularTags(user,item,user_tags,item_tags,0.8,N)


def Recall(train,test,tags,item_tags,user_tags,N,a):
    '''
    :param train: 训练集
    :param test: 测试集
    :param N: TopN推荐中N数目
    :param k:
    :return:返回召回率
    '''
    hit=0# 预测准确的数目
    totla=0# 所有行为总数
    for lst in train:
        user=lst[0]
        item=lst[1]
        tu=getTU(test,user,item)
        rank=GetRecommend(user,item,item_tags,user_tags,tags,N,a)
        for item in rank:
            if item in tu:
                hit+=1
        totla+=len(tu)
    #print "Recall successed!",hit/(totla*1.0)
    return hit/(totla*1.0)

def Precision(train,test,tags,item_tags,user_tags,N,a):
    '''

    :param train:
    :param test:
    :param N:
    :param k:
    :return:准确率
    '''
    hit=0
    total=0
    for lst in train:
        user=lst[0]
        item=lst[1]
        tu = getTU(test,user,item)
        rank = GetRecommend(user,item,item_tags,user_tags,tags,N,a)
        for item in rank:
            if item in tu:
                hit += 1
        total += N
    #print "Precision successed!",hit / (total * 1.0)
    return hit / (total * 1.0)

def Coverage(train,test,tags,item_tags,user_tags,N,a):
    '''
    计算覆盖率
    :param train:训练集 字典user->items
    :param test: 测试机 字典 user->items
    :param N: topN推荐中N
    :param k:
    :return:覆盖率
    '''
    recommend_items=set()
    all_items=set()
    for lst in train:
        user=lst[0]
        item=lst[1]
        all_items.add(item)
        rank=GetRecommend(user,item,item_tags,user_tags,tags,N,a)
        for item in rank:
            recommend_items.add(item)
    #print "Coverage successed!",len(recommend_items)/(len(all_items)*1.0)
    return len(recommend_items)/(len(all_items)*1.0)

def evaluate(train,test,tags,item_tags,user_tags,N,state):
    ##计算一系列评测标准

    recall=Recall(train,test,tags,item_tags,user_tags,N,state)
    precision=Precision(train,test,tags,item_tags,user_tags,N,state)
    coverage=Coverage(train,test,tags,item_tags,user_tags,N,state)
    return recall,precision,coverage


data=genData()
train=[]
test=[]
UIT=user_item_tag(data)
train,test=splitData(UIT,train,test)
tags,item_tags,user_tags=Initstate(train)
N=10
for stat in range(1,5):
    recall,precision,coverage=evaluate(train,test,tags,item_tags,user_tags,N,stat)
    print stat
    print("Recall: ", recall)
    print("Precision: ", precision)
    print("Coverage: ", coverage)

实验结果
1
(‘Recall: ‘, 0.16858299595141701)
(‘Precision: ‘, 0.006946019883899379)
(‘Coverage: ‘, 0.6197057512260365)
2
(‘Recall: ‘, 0.10375168690958164)
(‘Precision: ‘, 0.0042748159516025)
(‘Coverage: ‘, 0.000743052459503641)
3
(‘Recall: ‘, 0.20259109311740892)
(‘Precision: ‘, 0.008347234269700406)
(‘Coverage: ‘, 0.523480457720315)
4
(‘Recall: ‘, 0.28842105263157897)
(‘Precision: ‘, 0.011883632481483953)
(‘Coverage: ‘, 0.6334522217268539)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值