推荐算法: 基于用户的协同过滤算法

  • 参考《推荐系统实践》项亮
  • 概念: 协同过滤算法
    在一个在线个性化推荐系统中,当一个用户 A 需要个性化推荐
    时,可以先找到和他有相似兴趣的其他用户,然后把那些用户喜欢的、而用户 A 没有听说过的物品推荐给 A

概念:协同过滤算法

基于用户的协同过滤算法主要包括两个步骤。
(1) 找到和目标用户兴趣相似的用户集合。
(2) 找到这个集合中的用户喜欢的,且目标用户没有听说过的物品推荐给目标用户。

  1. 如何计算两个用户的兴趣相似度?
    协同过滤算法(UserCF), 具体计算如下:
    给定用户 u 和用户 v ,令 N(u) 表示用户 u 曾经有过正反馈的物品集合,令 N(v)
    为用户 v 曾经有过正反馈的物品集合。那么,我们可以通过如下几种的相似度计算公式简单地计算 u 和 v 的兴趣相似度:
    推荐算法: 基于用户的协同过滤算法

  2. 如何计算: 用户对某商品的感兴趣程度?
    得到用户之间的兴趣相似度后, UserCF 算法会给用户推荐和他兴趣最相似的 K 个用户喜欢的物品。
    如下的公式度量了 用户 u 对物品 i 的感兴趣程度:
    推荐算法: 基于用户的协同过滤算法

如何使用python编码实现?

假设有用户-商品数据如下:

1::a	1::b	1::c	2::a	
2::b	3::c	4::a	4::d

1. 第一步:求出两个用户之间的相似度

使用<用户相似度算法>:如 jaccard相似度算法
推荐算法: 基于用户的协同过滤算法
得到的结果如下:
推荐算法: 基于用户的协同过滤算法

2. 第二步:选择最相似的用户群

推荐算法: 基于用户的协同过滤算法

3. 第三步:过滤&生成商品推荐列表

推荐算法: 基于用户的协同过滤算法
完整代码如下:

# -*-coding:utf-8-*-
##################第一步:求出两个用户之间的相似度############
#john breese相似度算法
import math
def userLikenessJohnbreese(u,userItemsDict,v,itemUsersDict):
    # 相似度
    sum = 0.0
    setA = set(userItemsDict[u])
    setB = set(userItemsDict[v])
    common = setA.intersection(setB)
    # 循环交集
    for i in common:
        # 商品的交互用户数==商品i的流行度
        iusers = itemUsersDict[i].__len__()
        sum = sum + (1.0 / math.log10(iusers + 1))
    return sum / math.sqrt(setA.__len__() * setB.__len__())

##################第二步:选择最相似的用户群 ############
def getMostLikeUserGroupK(userItemsDict,itemUsersDict):
    # 字典
    M = {}
    for u,itemsU in userItemsDict.items():
        for v,itemsV in userItemsDict.items():
            if u < v:
                if u not in M.keys():
                    M[u] = {}
                if v not in M.keys():
                    M[v] = {}
                # 计算相似度
                ratio = userLikenessJohnbreese(u,userItemsDict,v,itemUsersDict)
                M[u][v] = ratio
                M[v][u] = ratio
    # 对M中每个用的相似度字典按照相似度倒排序
    M2 = {}
    for k,v in M.items():
        M2[k] = sorted(v.items(), key=lambda e: e[1], reverse=True)
    return M2

#################第三步:过滤&生成商品推荐列表#############
def recommUserCF(u , K):
    # 准备数据:返回的推荐字典[],用户->商品之间的字典, 商品->用户之间的字典
    recommDict = {}
    userItemsDict = {}
    itemUsersDict = {}
    file = open("/home/wang/IdeaProjects/big124/mypython/a")
    while True :
        line = file.readline()
        if line != '':
            arr = line.replace("\n","").split("\t").split("::")
            uid = int(arr[0])
            iid = str(arr[1])
            # userItemDict
            if uid in userItemsDict.keys():
                userItemsDict[uid].append(iid)
            else :
                userItemsDict[uid] = [iid]
            # itemUsersDict
            if iid in itemUsersDict.keys():
                itemUsersDict[iid].append(uid)
            else:
                itemUsersDict[iid] = [uid]
        else:
            break ;

    # 1, 得到最相似的K个用户
    kUsers = getMostLikeUserGroupK(userItemsDict,itemUsersDict)[u][:K]
    for v, simV in kUsers:
        vitems = userItemsDict[v]
        for vi in vitems:
            if vi not in userItemsDict[u]:
                if vi not in recommDict.keys():
                    recommDict[vi] = 0.0
                recommDict[vi] = recommDict[vi] + simV
                #2, 过滤商品,生成推荐列表: { 商品1:sum相似度值 , 商品2:sum相似度值  }
    return sorted(recommDict.items() , key = lambda e : e[1] ,reverse=True)

##################测试结果#################
if __name__ =="__main__":
    recommList=recommUserCF(2,3)
    for i in recommList:
        print i
#('c', 1.533734661597076)
#('d', 0.8304820237218405)