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

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

为什么要给用户推荐标签?一般看来有以下好处。
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)

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言: 这是本人开发的个人知识管理软件,特别适合需要阅读大量pdf\word\mht\txt等格式文献的科研人员,有效提高个人知识管理能力,减轻记忆压力。因为这几年来都没有时间开发和维护,所以现在开源,希望有人能发扬光大。由于时间关系,没有很好整理文档,而且不是最新版,需要的请联系。本人曾参与Sourceforge的latex2rtf项目,在知识管理方面具有独创见解,希望大家能共同探讨,促进我国科研人员的个人知识管理水平。 本软件综合了Tag2Find、Leapfrog Tag等Tag管理软件的优点,同时克服了这类软件速度奇慢的缺点,具有Everything一样的即时搜索性能。所以叫Tagging-Taggie。 大致工作流程: ------------------------------------------------------------ 1. 启动Tagging软件,此时后台会运行一些针对常用阅读软件开发的AutoHotkey脚本(可以自定义); 2. 在你熟悉的阅读软件中(例如Acrobat Adobe、Pdf Xchange Viewer, Office Word等里面)按下快捷键 Ctrl+`,将弹出一个迷你窗口(叫Taggie),可以输入各类标签(也可以从常用词中选择,如文章类型,重要性),同时显示以前的关键词,所有标签和当前页码等信息会自动保存到数据库中。 如果按下快捷键 Alt+`,则不弹出任何窗口,但是数据库中将记录此文件的标题,当前选中的文字前20个字等信息,这样方便地保存了您的访问记录,而且不受软件的限制。 3. 打开Tagging主界面(类似Everything),可以一边打字输入一边获得检索结果,同时有最近浏览记录、访问最多记录、最常用Tag等信息。 注:上述快捷键可以自定义,例如设置为F1是最轻松的。 背景知识: ----------------------------------------------------------- 一般来说,我们阅读科技文献时,希望随时快速记下带有自己思维方式的Tag,比如这篇文章是欧洲某国的,这一页很重要,这篇文章很重要,这篇文章是90年代的,这篇文章是某公司或某大学的,这是会议文章/期刊文章/技术报告/国际标准等等。但是如果采用重命名文件的方法(适用于Tag较短的情况),就会疲于应付。 如果你是研究生或者科研工作者,那么自然需要阅读大量的文献,采用其它知识管理软件都需要大量的鼠标和键盘动作,同样会疲于应付。 换句话说,采用文件夹管理只是实现了文件的树状分类,但是一篇文献在每个人脑海里面还有特殊的标签,只有采用标签和树状分类才能保证我们的每一篇文献都能快速找到。 采用本软件,你就可以从各种蛛丝马迹中找到你曾经阅读过的文献。 工作机理 ------------------------------------------------------- 1. Taggie会自动获得当前文件的特定属性,例如文件创建日期、pdf的页数、已有关键词等,并根据这些信息为该文件创建一个UUID.lnk,如果开启了Distributed Link Tracking Client服务,在本地计算机你可以随意重命名或者移动该文件,以后用Tagging搜索Tag时都可以找到该文件。 2. 当前版本用到的数据库其实就是类似csv或者xls的文本文件,你也可以通过OneNote接口把数据保存到One文件里面去,这样可以在OneNote里面补充注释,管理起来更加富有层次。 细节和讨论: ---------------------------------------------------------- 1. 多个标签数据库的同步和合并; 可以为不同电脑指定一个特定的数据库名字,在Tagging里面可以勾选要搜索的数据库,一般不用考虑数据同步。但是最好能随时把个人的数据库上传到快盘之类的地方,或者用Groove同步,实现团队成员的知识管理。 2. 采用Symbolic link的方式与采用快捷方式的对比。 还没有测试。 3. 。。。。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值