时效性

推荐系统应该考虑时间效应,因为用户的兴趣是有时间变化的。用户一年前喜欢的东西现在不一定感兴趣,相比于推荐过去喜欢的物品,推荐用户近期喜欢的物品更有参考价值。而在新闻更是如此,推荐过去跟用户兴趣一致的新闻已经失去了意义。每个系统时间效应的大小不同,比如时间对电影的作用就没有新闻那么明显。要考虑时效性,必须加入时间参数,比如三元组(用户,物品,时间)代替简单的二元组(用户,物品)。给定时间 T ,一般化的时间衰减公式为:

距离失效日期剩余天数java_相似度

其中 

距离失效日期剩余天数java_用户兴趣_02

 是物品 i 最近的流行度,

距离失效日期剩余天数java_距离失效日期剩余天数java_03

是时间衰减参数,对于时效性明显的系统,

距离失效日期剩余天数java_推荐系统_04

应该越大。代码实现如下:

def RecentPopularity(records, alpha, T):
    ret = dict()
    for user, item ,tm in records:
        if tm > T:
            continue
        addToDict(ret , item, 1/(1.0 + alpha * (T - tm)))
    return ret

时效性的 ItemCF 算法

前面提到的 ItemCF 算法有两个核心组成,(1)物品相似度矩阵(2)基于用户历史行为做推荐

(1)加入时效性考虑,用户在相隔很短的时间内喜欢的物品的相似度应该高于时间跨度比较大的用户喜欢物品之间的相似度。原来的物品相似度公式为:

距离失效日期剩余天数java_距离失效日期剩余天数java_05

在得到时间信息(用户对物品产生行为的时间)后,加入时间衰减函数的公式如下:

距离失效日期剩余天数java_用户兴趣_06

衰减项

距离失效日期剩余天数java_相似度_07

中,其中

距离失效日期剩余天数java_用户兴趣_08

 是用户u 对物品 i 产生行为的时间。f 函数的意义是,用户对物品 i 和物品 j 产生行为的时间越远,则 

距离失效日期剩余天数java_距离失效日期剩余天数java_09

 越小。可以找到很多数学衰减函数,比如

距离失效日期剩余天数java_相似度_10

距离失效日期剩余天数java_距离失效日期剩余天数java_11

是时间衰减参数,它的取值在不同的系统中不同。系统用户兴趣变化的越快,

距离失效日期剩余天数java_用户兴趣_12

应该越大。改进后的 ItemCF 算法的物品相似度矩阵计算代码如下所示:

def ItemSimilarity(train, alpha):
    #计算 C[i][j] 矩阵
    C = dict()
    N = dict()
    for u,items in train.items():
        for i,tui in items.items(): #原来是没有 tui 的
            N[i] += 1
            for j, tuj in items.items():
                if i == j:continue
                C[i][j] += 1 / (1 + alpha * abs(tui - tuj))
    
    #计算 W[i][j]
    W = dict()
    for i, related_items in C.items():
        for j, cij in related_items.items():
            W[i][j] = cij / math.sqrt(N[i] * N[j])
    return W

除了考虑时间对物品相似度的影响,还要考虑时间信息对推荐预测的影响。一般来说,用户最近的喜好应该和用户兴趣关系更大,需要将时间比较久的过去的喜欢的物品加上时间衰减函数。

距离失效日期剩余天数java_推荐系统_13

其中 

距离失效日期剩余天数java_推荐系统_14

 是现在的时间,

距离失效日期剩余天数java_推荐系统_15

 是用户u 对 物品 i 评价过的时间。 代码修改如下:

def Recommendation(train, user_id, W, K,t0):
    rank = dict()
    ru = train[user_id]
    for i,pi in ru.items():
        rui, tui = pi
        for j, wji in sorted(W[i].items, key = itemgetter(1), reverse = True)[0:K]:
            if j in ru.keys():
                continue
            rank[j] += rui * wji / (1 + beta * (t0 - tui))
    return rank

时效性的 UserCF 算法

类似 ItemCF ,UserCF 也有两个核心。(1)计算用户相似度矩阵(2)基于相似用户兴趣做推荐

(1)加入时效性考虑,如果两个用户在比较近的时间里有共同的喜好,则比在不同时间段用户有相同喜好的参考意义更大。回顾原来的用户相似度公式如下:

距离失效日期剩余天数java_距离失效日期剩余天数java_16

其中 N(u) 是用户 u 喜欢的物品集合,N(v) 是用户 v 喜欢的物品集合。加入时间衰减因子修正公式如下:

距离失效日期剩余天数java_相似度_17

其中 

距离失效日期剩余天数java_距离失效日期剩余天数java_18

 是用户 u 喜欢物品 i 的时间,

距离失效日期剩余天数java_用户兴趣_19

 是用户 v 喜欢物品 i 的时间。代码如下:

def UserSimilarity(train):
    #建立倒排表,比原来多加入了时间信息
    item_users = dict()
    for u, items in train.items():
        for i, tui in items.items():
            if i not in item_users:
                item_users[i] = dict()
            item_users[i][u] = tui
    
    # 计算 C[u][v]
    C = dict()
    N = dict()
    for i, users in item_users.items():
        for u,tui in users.items():
            N[u] += 1
            for v,tvi in user.items():
                if u == v:continue
                C[u][v] += 1 / (1 + alpha * abs(tui - tvi))

    # 计算 W[u][v]
    W = dict()
    for u, related_users in C.items():
        for v,cuv in related_users.items():
            W[u][v] = cuv / math.sqrt(N[u] * N[v])
    return W

同样地,处了考虑时间信息对用户相似度矩阵的影响,还应该考虑时间信息对推荐算法的影响。找到相似的用户后,认为推荐相似用户近期感兴趣的物品比推荐过去感兴趣的物品更有意义。原来的 UserCF 算法中用户 u 对物品 i 的兴趣公式如下:

距离失效日期剩余天数java_用户兴趣_20

加入时间衰减函数后,改进 UserCF 推荐公式如下:

距离失效日期剩余天数java_时效性_21

其中

距离失效日期剩余天数java_相似度_22

 代表现在的时间,

距离失效日期剩余天数java_推荐系统_23

 代表相似的用户 v 喜欢物品 i 的时间。改进后的推荐算法代码如下:

def Recommend(user, t0, train, W):
    rank = dict()
    interacted_items = train[user] # user的已有物品
    for v, wuv in sorted(W[user].items, key = itemgetter(1), reverse = True)[0:K]:
        for i, pi in train[v].items:
            rvi, tvi = pi
            if i in interacted_items:continue
            rank[i] += wuv * rvi / (1 + alpha * (t0 - tvi))
    return rank