zoukankan      html  css  js  c++  java
  • 《推荐系统实践》笔记(转)

    本文来源:http://www.yeolar.com/note/2013/10/03/recommend-system/

    放假在家看项亮的《推荐系统实践》,觉得写得不错。因为我接触推荐系统的时间也不长,这本书正好适合入门。书里面的理论篇幅不多,比较偏重综述和实验分析,让人能有个感性的认识。如果想加强一下理论背景的话,个人推荐《数据挖掘导论》和《机器学习》。写了一份笔记,书里面有一些错误和不清晰的地方,自己做了些修改,本文是前半部分。

    1 好的推荐系统

    1.1 什么是推荐系统

    推荐系统和搜索引擎都是为了帮助用户从大量信息中找到自己感兴趣的信息。区别是搜索引擎由用户主动提供关键词来查找信息,推荐系统则不需要,而通过分析用户的历史行为给用户的兴趣建模,主动给用户推荐他们可能感兴趣的信息。

    从物品的角度出发,推荐系统可以更好地发掘物品的长尾。长尾商品往往代表了一小部分用户的个性化需求,发掘这类信息正是推荐系统的长项。

    1.2 个性化推荐系统的应用

    推荐系统广泛存在于各类网站中,作为一个应用为用户提供个性化推荐。它需要依赖用户的行为数据,因此一般都由后台日志系统、推荐算法系统和前台展示页面3部分构成。

    应用推荐系统的领域包括:

    • 电子商务 - 亚马逊:基于物品、好友的个性化推荐,相关推荐,20~30%
    • 电影视频 - Netflix:基于物品的推荐,60%;YouTube、Hulu
    • 音乐 - Pandora:专家标记;Last.fm:用户行为
    • 社交网络 - Facebook、Twitter
    • 阅读 - Google Reader
    • 基于位置的服务 - Foursquare
    • 个性化邮件 - Tapestry
    • 广告 - Facebook

    1.3 推荐系统评测

    主要有3种评测推荐效果的实验方法:

    • 离线实验:划分训练集和测试集,在训练集训练用户兴趣模型,在测试集预测
      • 优点:快速方便
      • 缺点:无法用真实的商业指标来衡量
    • 用户调查:用抽样的方法找部分用户试验效果
      • 优点:指标比较真实
      • 缺点:规模受限,统计意义不够
    • 在线实验:AB测试
      • 优点:指标真实
      • 缺点:测试时间长,设计复杂

    实际中,这三种方法在推荐算法上线前都要完成。

    评测指标较多,一些重要的如下:

    • 用户满意度:调查问卷,线上的用户行为统计、其他的指标转化得到

    • 预测准确度:可通过离线实验计算

      • 评分预测,通过均方根误差和平均绝对误差计算,前者更为苛刻。设 rui 为用户 u 对物品 i 的实际评分, rˆui 为预测评分

        RMSE=u,iT(ruirˆui)2|T|‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾√
        MAE=u,iT∣∣ruirˆui∣∣|T|
      • TopN推荐,通过准确率或召回率衡量。设 R(u) 为根据训练建立的模型在测试集上的推荐, T(u) 为测试集上用户的选择

        Precision=uU|R(u)T(u)|uU|R(u)|
        Recall=uU|R(u)T(u)|uU|T(u)|
    • 覆盖率:表示对物品长尾的发掘能力(推荐系统希望消除马太效应)

      Coverage=|uUR(u)||I|

      上面的公式无法区分不同的分布,可以用熵或基尼系数来更准确地表述覆盖率

      H=i=1np(i)logp(i)

      p(i) 为物品 i 的流行度的比例。

      G=1n1j=1n(2jn1)p(j)

      p(j) 为按流行度由小到大排序的物品列表中的第 j 个物品的流行度的比例。

    • 多样性:推荐需要满足用户的广泛的兴趣,表示推荐列表中物品两两之间的不相似性。设 s(i,j) 表示物品 i 和 j之间的相似度

      Diversity(R(u))=1i,jR(u),ijs(i,j)12|R(u)|(|R(u)|1)
      Diversity=1|U|uUDiversity(R(u))
    • 新颖性:指给用户推荐他们不知道的物品,可以用平均流行度做粗算,或者更精确地通过做用户调查。

    • 惊喜度:推荐和用户的历史兴趣不相似,却使用户满意的物品。

    • 信任度:只能通过问卷调查来评价,可以通过增加推荐系统的透明度和利用好友信息推荐来提高信任度。

    • 实时性:保持物品的时效性,主要涉及推荐系统实时更新和对新物品的处理。

    • 健壮性:开发健壮性高的算法,清理脏数据,使用代价较高的用户行为设计推荐系统。

    • 商业目标:推荐系统对于网站的价值。

    作者认为,离线实验的优化目标是在给定覆盖率、多样性、新颖性等限制条件下,最大化预测准确度。

    对推荐系统还需要从多维度来评测,如用户维度、物品维度和时间维度,这样可以更全面地了解推荐系统的性能。

    2 利用用户行为数据

    2.1 用户行为

    用户行为数据一般从日志中获得,可以按反馈的明确性把用户行为分为显性反馈和隐性反馈。

    用户行为数据很多满足长尾分布(Zipf定律)

    f(x)=αxk

    另外,用户活跃度高,倾向于看冷门的物品。

    基于用户行为分析的推荐算法一般称为协同过滤算法,包括基于邻域的方法、隐语义模型、基于图的随机游走算法等,应用最广的是基于邻域的方法。

    2.2 基于邻域的算法

    基于邻域的算法可以分为基于用户的协同过滤算法(UserCF)和基于物品的协同过滤算法(ItemCF)。

    2.2.1 基于用户的协同过滤算法

    UserCF算法主要有两步:

    1. 找到和目标用户兴趣相似的用户集合
    2. 找到这个集合中的用户喜欢的,且目标用户没有听说过的物品,推荐给目标用户

    设 N(u) 为用户 u 有过正反馈的物品集合, N(v) 为用户 v 有过正反馈的物品集合, u 和 v 的兴趣相似度可以用Jaccard公式或余弦相似度计算

    wuv=|N(u)N(v)||N(u)N(v)|
    wuv=|N(u)N(v)||N(u)||N(v)|‾‾‾‾‾‾‾‾‾‾√

    以余弦相似度为例:

    def calcUserSimilarity1(t):
        w = defaultdict(dict)               # 相似度矩阵
        for u in t:
            for v in t:
                if u != v:
                    w[u][v] = len(t[u] & t[v]) / math.sqrt(len(t[u]) * len(t[v]))
    

    可以利用稀疏矩阵的性质优化上面的算法:

    def calcUserSimilarity2(t):
        itemUsers = defaultdict(set)        # 物品-用户倒排表
        n = defaultdict(int)                # 用户喜欢的物品数
        w = defaultdict(dict)               # 相似度矩阵
        # 建立倒排表
        for u, items in t.iteritems():
            for i in items:
                itemUsers[i].add(u)
        # 计算相似度
        for i, users in itemUsers.iteritems():
            for u in users:
                n[u] += 1
                for v in users:
                    if u != v:
                        w[u][v] = w[u].get(v, 0) + 1
        for u in w:
            for v in w[u]:
                w[u][v] /= math.sqrt(n[u] * n[v])
        return w
    

    然后用上面的相似度矩阵来给用户推荐和他兴趣相似的用户喜欢的物品。用户 u 对物品 i 的兴趣程度可以估计为

    p(u,i)=vS(u,K)N(i)wuvrvi

    S(u,K) 为和用户 u 兴趣最接近的 K 个用户, N(i) 为对物品 i 有正反馈的用户集合, wuv 为用户 u 和用户 v 的兴趣相似度, rvi 为用户 v 对物品 i 的兴趣。

    def recommend(u, t, w, k):
        rank = defaultdict(float)           # 推荐结果
        su = sorted(w[u].items(), key=itemgetter(1), reverse=True)
        for v, wuv in su[:k]:
            for i, rvi in t[v].iteritems():
                if i not in t[u]:           # 排除已经有过反馈的物品
                    rank[i] += wuv * rvi
        return rank
    

    通过对不同 K 值下的测量发现:

    • 准确率和召回率并不和 K 成线性关系,通过多次测量可以选择合适的 K 值
    • K 越大,推荐的结果越热门,流行度增大
    • K 越大,推荐结果的覆盖率越低

    可以调整计算用户兴趣相似度的公式来改进算法。注意到用户对冷门物品采取同样的行为更能说明他们的兴趣相似度,可以改用下式计算兴趣相似度

    wuv=iN(u)N(v)1log(1+|N(i)|)|N(u)||N(v)|‾‾‾‾‾‾‾‾‾‾√

    上式用 1log(1+|N(i)|) (IIF参数)减小了热门物品对用户兴趣相似度的影响。将 calcUserSimilarity2 第15行改为

    w[u][v] = w[u].get(v, 0) + 1 / math.log(1 + len(users))
    

    UserCF算法用的并不多。它的问题是运算复杂度大,并且难以解释推荐的结果。

    2.2.2 基于物品的协同过滤算法

    ItemCF算法是目前应用最多的算法。它也主要分为两步:

    1. 根据用户行为计算物品之间的相似度
    2. 根据物品的相似度和用户的历史行为给用户生成推荐列表

    设 N(i) 为喜欢物品 i 的用户数, N(j) 为喜欢物品 j 的用户数, i 和 j 的相似度可以计算为

    wij=|N(i)N(j)||N(i)||N(j)|‾‾‾‾‾‾‾‾‾‾√

    这里面包含的假设是每个用户的兴趣都局限在某几个方面。

    计算物品相似度使用和计算用户兴趣相似度类似的方法:

    def calcItemSimilarity(t):
        n = defaultdict(int)            # 喜欢物品的用户数
        w = defaultdict(dict)           # 相似度矩阵
        for u, items in t.iteritems():
            for i in items:
                n[i] += 1
                for j in items:
                    if i != j:
                        w[i][j] = w[i].get(j, 0) + 1
        for i in w:
            for j in w[i]:
                w[i][j] /= math.sqrt(n[i] * n[j])
        return w
    

    然后计算用户 u 对物品 i 的兴趣程度

    p(u,i)=jS(i,K)N(u)wijruj

    S(i,K) 为和物品 i 最相似的 K 个物品, N(u) 为用户 u 喜欢的物品集合, wij 为物品 i 和物品 j 的相似度, ruj 为用户 u 对物品 j 的兴趣。它的意思是和用户感兴趣的物品越相似的物品,越应该被推荐。

    def recommend(u, t, w, k):
        rank = defaultdict(float)           # 推荐结果
        reason = defaultdict(dict)          # 推荐解释
        for j, ruj in t[u].iteritems():
            sj = sorted(w[j].items(), key=itemgetter(1), reverse=True)
            for i, wij in sj[:k]:
                if i not in t[u]:           # 排除已经喜欢的物品
                    rank[i] += wij * ruj
                    reason[i][j] = wij * ruj
        return rank
    

    ItemCF算法的一个好处是可以给出推荐解释。

    对不同 K 值的测量可以看到:

    • 准确率和召回率和 K 也不成线性关系
    • K 和流行度不完全正相关
    • K 增大仍会降低覆盖率

    活跃用户对物品相似度的贡献要小于不活跃用户,可以用和IIF类似的IUF参数来修正物品相似度的计算公式

    wij=uN(i)N(j)1log(1+|N(u)|)|N(i)||N(j)|‾‾‾‾‾‾‾‾‾‾√

    将 calcItemSimilarity 第9行改为

    w[i][j] = w[i].get(j, 0) + 1 / math.log(1 + len(items))
    

    实际计算中,对于过于活跃的用户,一般直接做忽略处理。

    对ItemCF的另一个改进是将相似度矩阵归一化,这样可以提高推荐的准确率,以及覆盖率和多样性。

    wij=wijmaxiwij

    2.2.3 UserCF算法和ItemCF算法的比较

    UserCF算法的特点是:

    • 用户较少的场合,否则用户相似度矩阵计算代价很大
    • 适合时效性较强,用户个性化兴趣不太明显的领域
    • 用户有新行为,不一定造成推荐结果的立即变化
    • 对新用户不友好,对新物品友好,因为用户相似度矩阵需要离线计算
    • 很难提供令用户信服的推荐解释

    对应地,ItemCF算法的特点:

    • 适用于物品数明显小于用户数的场合,否则物品相似度矩阵计算代价很大
    • 适合长尾物品丰富,用户个性化需求强的领域
    • 用户有新行为,一定导致推荐结果的实时变化
    • 对新用户友好,对新物品不友好,因为物品相似度矩阵需要离线计算
    • 用用户历史行为做推荐解释,比较令用户信服

    和UserCF算法相比,ItemCF算法的离线实验结果要差一些,不过这是在两者优化前的结果,实际优化后性能是接近的。原始ItemCF算法的覆盖率和新颖度不高的原因可以归结为哈利波特问题,也就是热门物品和其他物品的相似度都很高,这个问题一个办法是惩罚热门物品,同时可能还需要引入物品的内容数据来修正。

    2.3 隐语义模型

    隐语义模型(LFM)最近几年非常热门,核心思想是通过隐含特征联系用户兴趣和物品。简单说就是对物品的兴趣分类,对于用户,首先确定他的兴趣分类,然后从分类中选择他可能喜欢的物品。

    这里的对物品分类的问题,可以用隐含语义分析技术较好地解决。它基于用户行为统计做分类,和专家标记相比:

    • 能代表各种用户的看法
    • 能控制分类的粒度
    • 能给一个物品多个分类
    • 带维度属性
    • 可以确定物品在某个分类中的权重

    这些都是专家标记不能或者很难做到的。

    隐含语义分析技术其他相关的技术:pLSA、LDA、隐含类别模型、隐含主题模型、矩阵分解等

    LFM如下计算用户 u 对物品 i 的兴趣

    Preference(u,i)=rui=pTuqi=k=1Kpu,kqi,k

    参数 pu,k 表示用户 u 的兴趣和第 k 个隐类的关系度, qi,k 表示物品 i 和第 k 个隐类的关系度。这两个参数需要通过机器学习得到,利用最优化理论,可以通过最小化下式来计算 p 和 q

    C=u,iK(ruirˆui)2=u,iK(ruipTuqi)2+λpu2+λqi2

    λpu2+λqi2 是用来防止过拟合的正则化项, λ 可通过实验获得。

    利用随机梯度下降法,令 eui=ruipTuqi ,求导,得到递推关系

    pupu+α(euiqiλpu)
    qiqi+α(euipuλqi)

    α 为学习速率。

    对于隐性反馈数据,LFM的一个问题是如何给每个用户生成负样本。研究表明,较好的方案是:对每个用户,保证正负样本数相近(设比例为 R );选取那些热门但用户却没有选择的物品作为负样本(更能明确表明用户对它不感兴趣)。

    下面是LFM推荐算法的一个实现:

    def selectRandomSample(items, positiveItems):
        n = len(items)
        mp = len(positiveItems)
        mn = 0
        s = {}                          # 采样
        for i in positiveItems:
            s[i] = 1                    # 正样本 rui = 1
        for k in range(0, n * 3):
            i = items[random.randint(0, n - 1)]
            if i in s:
                continue
            s[i] = 0                    # 负样本 rui = 0
            mn += 1
            if mn > mp:                 # 正负样本比例为1
                break
        return s
    
    def calcLatentFactorModel(t, k, step, alpha, lamb):
        p, q = initModel(t, k)          # numpy.matrix
        for j in range(0, step):
            for u, positiveItems in t.iteritems():
                sampleItems = selectRandomSample(items, positiveItems)
                for i, rui in sampleItems.iteritems():
                    eui = rui - p[u] * q[i]
                    p[u] = sum(alpha * (eui * q[i] - lamb * p[u]))
                    q[i] = sum(alpha * (eui * p[u] - lamb * q[i]))
            alpha *= 0.9
        return p, q
    
    def recommend(u, p, q):
        rank = {}                       # 推荐结果
        for i in q:
            rank[i] = sum(p[u] * q[i])
        return rank
    

    作者通过实验测量了LFM的主要参数 K 、 α 、 λ 和 R 对推荐效果的影响。实验表明,正负样本比例 R 对性能的影响最大,随着负样本数增加,准确率和召回率明显提高,但达到10倍以后,就比较稳定了;同时覆盖率降低,流行度增加。即 R 控制了发掘长尾的能力。

    LFM的效果要优于UserCF和ItemCF算法,但是在数据集非常稀疏时比较差。

    设有 M 个用户, N 个物品, T 条行为记录,LFM取 K 个隐类,迭代 S 次,离线计算时,时间复杂度:UserCF为 O(N(TN)2) ,ItemCF为 O(M(TM)2) ,LFM为 O(TKS) ,LFM略高;空间复杂度:UserCF为 O(M2) ,ItemCF为 O(N2) ,LFM为 O(K(M+N)) , M 和 N 很大时LFM要小很多。

    LFM在实际使用中的一个困难是难以实现实时的推荐,它的训练要依赖于所有的用户行为。雅虎提出了一个解决方案,使用用户的历史行为得到的用户兴趣分类和物品内容属性直接生成的物品分类来计算实时的 rui ,之后再使用 pTuqi 来得到更准确的预测值。

    2.4 基于图的模型

    用户行为数据可以用二分图来表示,令 G(V,E) 表示用户物品二分图, V=VUVI ,对于用户行为数据集中的每个二元组 (u,i) ,图中都有一套对应的边 e(vu,vi) 。

    使用二分图,给用户 u 推荐物品的问题可以转化为度量用户顶点 vu 和与它没有边相连的物品顶点在图上的相关性,相关性越高,物品在推荐列表中的权重越高。

    相关性高的顶点对一般有:

    • 顶点间的路径数多
    • 顶点间的路径长度都比较短
    • 顶点间的路径不会经过出度比较大的顶点

    书中介绍了一种基于随机游走的PersonalRank算法。对用户 u ,从它对应的顶点 vu 开始在二分图上随机游走。在每个顶点,首先按概率 α 决定是继续游走,还是停止而从 vu 重新开始游走,如果继续,就从当前顶点指向的顶点中按均匀分布随机选择一个继续游走。多次游走后,每个物品顶点被访问的概率会收敛到一个值,即推荐列表中物品的权重。

    PR(v)=⎧⎩⎨⎪⎪⎪⎪αvin(v)PR(v)|out(v)|αvin(v)PR(v)|out(v)|+(1α)vvuv=vu
    def calcPersonalRank(g, u, step, alpha):
        rank = defaultdict(float)           # 推荐结果
        rank[u] = 1.0
        for k in range(step):
            temp = defaultdict(float)
            for i in g:
                for j in g[i]:
                    temp[j] += alpha * rank[i] / len(g[i])
                    if j == u:
                        temp[j] += 1 - alpha
            rank = temp
        return rank
    

    PersonalRank算法的问题是时间复杂度很高,可以考虑减少迭代次数或者利用矩阵计算的办法改进。

    3 推荐系统冷启动问题

    在没有大量用户数据的情况下设计个性化推荐系统要面对冷启动问题。有三类:解决增加新用户的用户冷启动;解决增加新物品的物品冷启动;解决新上线的网站的系统冷启动。

    对于这三类问题,可以考虑下面这些办法:

    1. 提供非个性化的推荐。比如使用热门排行榜作为推荐结果,在用户数据充足之后再改为个性化推荐。

    2. 利用用户注册信息。可以利用用户注册时填写的年龄、性别、国家、职业等人口统计学信息,让用户填写兴趣描述,从其他网站导入用户行为数据等。

      基于用户注册信息的推荐算法核心是计算每种特征 f 的用户喜欢的物品,或者说对物品 i 的喜好程度 p(f,i)

      p(f,i)=|Nu(i)Nu(f)||Nu(i)|+α

      α 是一个比较大的参数,用来解决数据稀疏时没有统计意义的问题。

    3. 选择合适的物品启动用户的兴趣。就是在用户首次访问时,通过让用户反馈一些物品来收集用户的兴趣,可以按决策树的思路设计多个步骤。对物品的选择一般需要比较热门,具有代表性和区分性,物品集合需要有多样性。

    4. 利用物品的内容信息。前面3个方法针对的是新用户,而物品的冷启动则在物品时效性较强的场景中非常重要。和UserCF相比,ItemCF算法的物品冷启动问题比较严重。解决物品冷启动问题的一个办法是利用内容信息计算物品的内容相似度,给用户推荐内容相似的物品。

      物品的内容可以用向量空间模型表示,对于文本,该模型通过分词、实体检测、关键词排名等步骤将文本表示成一个关键词向量 {(e1,w1),(e2,w2),...} 。

      权重 wi 可以用TF-IDF公式计算

      wi=TF(ei)IDF(ei)=N(ei)jN(ej)log|D|1+|Dei|

      N(ei) 为文本中 ei 出现的次数, |D| 为语料库的文档总数。

      物品的内容相似度可以通过向量的余弦相似度来计算,和前面类似,可以通过关键词-物品倒排表降低时间开销。

      尽管内容相似度算法简单,又能解决物品冷启动问题,但一般效果要比协同过滤算法差,因为它没有考虑用户行为的影响。

      向量空间模型的一个问题是不能理解含义近似的关键词,因此在内容较少时准确度很差。话题模型通过首先计算文本的话题分布,然后再计算相似度来解决这个问题,如LDA模型。LDA包含文档、话题、词3种元素,每个词属于一个话题,通过迭代收敛得到话题的分布,文档的相似度由话题分布的相似度来度量。分布相似度的计算可以用KL散度(相对熵):

      DKL(PQ)=iP(i)lnP(i)Q(i)

      KL散度越大,分布相似度越低。

    5. 很多推荐系统在刚建立时,既没有用户行为数据,又没有足够的物品内容信息,这时的一个常用办法是对物品做专家标记。这个过程也可以加入机器学习和用户反馈的机制。

    6. 除了上一篇中的基于用户和基于物品的推荐算法,还有一种通过一些特征联系用户和物品的形式。特征可能是物品的属性、隐语义向量和标签等。标签可以分为作者或专家打的标签和用户打的标签(UGC的标签)。UGC标签是联系用户和物品的一种重要方式,既表明了用户的兴趣,又描述了物品的语义。

      UGC标签的应用在Web 2.0网站中很常见,如:Delicious、CiteULike、Last.fm、豆瓣、Hulu等。

      4.1 用户打标签

      因为标签的特点,它很适合用到推荐系统中。

      标签和用户、物品类似,它的流行度分布也满足长尾分布。

      用户打的标签有各种类型,总体来说,一些是和物品相关的标签,类似于关键词和分类;另一些是和用户相关的标签,比如用户的信息、看法、状态等。

      4.2 基于标签的推荐

      考虑到标签后,用户的标签行为数据可以表示为 (u,i,b) ,表示用户 u 给物品 i 打了个标签 b 。

      在设计推荐算法时,可以把标签近似于用户的反馈或物品的关键词来考虑。

      对于评测指标,如果实际的标签可以视作为用户的正反馈,那么准确率和召回率中的 T(u) 表示测试集上用户打过标签的物品集合。物品的相似度可以用它们的标签向量的相似度来度量。

      一个简单的想法是通过计算用户的标签向量和物品的标签向量来得到用户对物品的兴趣

      p(u,i)=bN(u,b)N(i,b)

      上面的方法同样有热门标签和热门物品权重很大的问题,采用和IIF、IUF和TF-IDF类似的想法改进

      p(u,i)=bN(u,b)log(1+Nu(b))N(i,b)log(1+Nu(i))

      N(u,b) 表示用户 u 打过标签 b 的次数, N(i,b) 表示物品 i 被打过标签 b 的次数, Nu(b) 表示用过标签 b 的用户数, Nu(i) 表示给物品 i 打过标签的用户数。

      对于新用户或新物品,标签数会很少,为提高推荐的准确率,可能需要对标签集合做扩展。常用的扩展方法有话题模型等,作者介绍了一种基于邻域的方法:标签扩展也就是找到相似的标签,即计算标签的相似度,可以从数据中采用余弦公式计算标签的相似度。

      使用标签的一个问题是不是所有标签都反映了用户的兴趣,另外将标签作为推荐解释也需要清理标签。常用的标签清理方法有:

      • 去除词频很高的停止词
      • 去除因词根不同造成的同义词
      • 去除因分隔符造成的同义词

      这里也可以加入用户反馈的途径。

      也可以利用图模型来做基于标签的个性化推荐。方法和二分图的推荐模型类似,不过这里需要用户、物品和标签三种顶点。同样可以用PersonalRank算法计算所有物品顶点相对于当前用户顶点在图上的相关性,排序得到推荐列表。

      基于标签的推荐的最大好处是可以利用标签做推荐解释。一些网站还使用了标签云表示用户的兴趣分布,标签的尺寸越大,表示用户对这个标签相关的物品越感兴趣。

      分析表明:

      • 用户对标签的兴趣能帮助用户理解为什么给他推荐某个物品
      • 物品与标签的相关度能帮助用户判定被推荐物品是否符合他的兴趣
      • 用户对标签的兴趣和物品与标签的相关度对于用户判定有同样的作用
      • 客观事实类标签比主观感受类标签作用更大

      4.3 给用户推荐标签

      标签系统会希望用户能够给物品打上优质的标签,这样有利于标签系统的良性循环。给用户推荐标签的好处是方便用户打标签,同时提高标签质量,减少同义词。

      给用户推荐标签的方法可以是:给用户推荐物品 i 的最热门标签;给用户推荐他最常用的标签;或者前两种方法的结合。以最后一种为例:

      pui(b)=αwu,bmaxbwu,b+(1α)wi,bmaxbwi,b

      上面的方法同样有类似于冷启动的问题,解决的办法可以考虑用抽取关键词(没有标签)和关键词扩展(有标签但是很少)。

      图模型同样可以用于标签推荐。在生成用户-物品-标签图后,可以用PersonalRank算法生成推荐结果。但这里和之前不同,可以重新定义顶点的启动概率为

      rv=⎧⎩⎨⎪⎪α1α0v=vuv=viothers

      5 利用上下文信息

      5.1 时间上下文

      时间上下文表现在:用户的兴趣是变化的,物品是有生命周期的,季节效应。时效性强的物品,平均在线天数短。

      考虑时间信息后,推荐系统就变为一个时变的系统,可以用 (u,i,t) 表示用户 u 在时刻 t 对物品 i 的行为。

      推荐系统的实时性要求:

      • 在每个用户访问推荐系统时,根据用户在此之前的行为实时计算推荐列表。
      • 推荐算法需要平衡考虑用户的近期行为和长期行为,保证对用户兴趣预测的延续性。

      推荐系统的时间多样性为推荐结果的变化程度,时间多样性高能够提高用户满意度。

      加入时间效应后,最简单的非个性化推荐算法是推荐最近最热门物品。给定时间 T ,物品最近的流行度 ni(T) 定义为

      ni(T)=(u,i,t),t<T11+α(Tt)

      5.1.1 时间上下文相关的ItemCF算法

      根据时间效应,

      • 用户在相隔很短的时间内喜欢的物品具有更高的相似度;
      • 用户近期行为比很久以前的行为更能体现用户现在的兴趣。

      由ItemCF算法,考虑到时间效应后(未使用IUF做修正)

      wij=uN(i)N(j)f(|tuituj|)|N(i)||N(j)|‾‾‾‾‾‾‾‾‾‾√

      f 为时间衰减函数,用户对物品 i 和 j 产生行为的时间距离越远,则 f(|tuituj|) 越小。取

      f(Δ)=11+αΔ

      将 calcItemSimilarity 第9行改为

      w[i][j] = w[i].get(j, 0) + 1 / (1 + alpha * abs(items[i] - items[j]))
      

      另外,类似地

      p(u,i)=jS(i,K)N(u)11+β|t0tuj|wijruj

      其中 t0 为当前时间, tuj 越靠近 t0 ,和物品 j 相似的物品就会更受推荐。

      5.1.2 时间上下文相关的UserCF算法

      和ItemCF算法的思路类似,

      • 用户兴趣的相似度在间隔较短的时间较高;
      • 给用户推荐和他兴趣相似的用户最近喜欢的物品。

      由UserCF算法,考虑时间效应后(未使用IIF做修正)

      wuv=iN(u)N(v)11+α|tuitvi||N(u)||N(v)|‾‾‾‾‾‾‾‾‾‾√
      p(u,i)=vS(u,K)N(i)11+β|t0tvi|wuvrvi

      5.2 地点上下文

      不同地区的用户兴趣会不同,用户在不同的地方,兴趣也会变化。研究表明,用户具有兴趣本地化和活动本地化的特征。

      可以从3种数据形式来分析地点上下文的影响:

      • (用户, 用户位置, 物品, 评分)
      • (用户, 物品, 物品位置, 评分)
      • (用户, 用户位置, 物品, 物品位置, 评分)

      对于第一种,可以把用户按地理位置做树状划分,对每一级树节点生成推荐列表,最终对各级推荐结果加权(金字塔模型)。

      对于第二种,可以先计算忽略物品位置的 p(u,i) ,然后减去物品位置对用户的代价。

      实验表明,考虑了用户位置的算法要优于ItemCF算法。

      7 推荐系统实例

      作者基于他在Hulu使用的架构总结了基于物品的推荐的推荐系统架构。

      推荐系统在网站中所处的位置如下图所示。用户行为存储系统将日志系统中的行为日志提取出并存储起来,推荐系统以这些行为日志为输入,把推荐结果提供给UI做展示。

      /media/note/2013/10/06/recommend-system-2/fig1.png

      推荐系统

      用户行为数据可以分为匿名的如浏览、搜索等,非匿名的评论、购买等。按数据规模和是否需要实时存取,数据会被保存到缓存、数据库或者分布式文件系统中。

      以基于特征的推荐系统为例,推荐系统一般要考虑多种特征,可以由多个推荐引擎组成,每个引擎负责一类特征或一种任务,推荐系统只需要将推荐引擎的结果合并、排序。这样做的好处是:

      • 可以方便地增加或删除推荐引擎,以不同的推荐引擎组合来决定推荐结果。
      • 可以实现推荐引擎级别的用户反馈。推荐引擎对应于推荐策略,不同的用户可能喜欢不同的推荐策略,通过分析,可以给不同的用户不同的推荐引擎权重。

      下图是推荐引擎的架构,主要包括三部分:

      • 生成用户特征向量的部分
      • 将用户特征向量通过特征-物品矩阵转化为初始推荐列表的部分
      • 对初始推荐列表做过滤、排名的部分。
      /media/note/2013/10/06/recommend-system-2/fig2.png

      推荐引擎架构

      1. 生成用户特征向量

        用户特征可以分成用户注册时填写的人口统计学特征和从用户行为中计算得到的特征。特征向量由特征和它的权重组成。在利用用户行为计算特征向量时,需要考虑:

        • 用户行为的种类。有些行为比其他的行为更重要,一般用户付出代价越大的行为权重应该更高。
        • 用户行为产生的时间。一般地用户近期的行为权重应该更高。
        • 用户行为的次数。对同一物品可能有多次行为,对应的物品的特征权重应该更高。
        • 物品的热门程度。热门物品往往不能代表用户的个性,因此应该加重不热门物品的特征权重。
      2. 特征-物品相关推荐

        相关推荐使用的特征-物品相关表一般不止一个,不同的算法、不同的用户行为数据会有不同的相关表,系统会根据配置和权重叠加相关表,直接使用叠加后的相关表。

        如果需要在一个较小的候选物品集合中给用户推荐物品,可以考虑用候选物品集合先做过滤,避免热门度带来的影响。

      3. 过滤

        过滤模块会过滤掉:

        • 用户已经产生过行为的物品
        • 候选物品以外的物品
        • 某些质量很差的物品,比如以评分为依据
      4. 排名

        排名模块一般需要包括很多不同的子模块:

        • 新颖性:目的是给用户尽量推荐他不知道的、长尾中的物品。一般要对热门物品降权,对ItemCF算法,要对 wij 和 ruj 降权。
        • 多样性:很多时候需要增加多样性来提高覆盖率。可以通过分类,或者让推荐理由(来自特征)尽量不同。
        • 时间多样性:为了保证用户能看到不同的推荐结果。一方面要保证推荐系统的实时性;另外对于没有新行为的用户,也要记录他看到的推荐结果,并给这些物品降权。
        • 用户反馈:这是排名模块最重要的部分,主要通过分析用户之前和推荐结果的交互日志,预测用户会对什么样的推荐结果感兴趣。如果关注点是点击率,可以使用点击模型。

      9 最后

      Strand研究人员总结的10条设计推荐系统的经验:

      1. 确定你真的需要推荐系统
      2. 确定商业目标和用户满意度之间的关系
      3. 选择合适的开发人员
      4. 忘记冷启动的问题
      5. 平衡数据和算法之间的关系
      6. 找到相关物品容易,但如何展现给用户则很困难
      7. 不要浪费时间计算相似兴趣的用户,可以直接利用社会网络数据
      8. 需要不断提升算法的扩展性
      9. 选择合适的用户反馈方式
      10. 设计合理的评测系统,时刻关注推荐系统各方面的性能

     http://www.yeolar.com/note/2013/10/03/recommend-system/

  • 相关阅读:
    2015年要做的150件事
    再见2014,你好2015
    页面滚动事件的使用
    简单的进度条演示
    mybatis foreach批量处理
    mysql执行顺序
    spring声明式事务 同一类内方法调用事务失效
    Semaphore
    springmvc使用JSR-303对复杂对象进行校验
    springmvc全局异常后返回JSON异常数据
  • 原文地址:https://www.cnblogs.com/peizhe123/p/6138038.html
Copyright © 2011-2022 走看看