知识点:
1. 协作型过滤——Collaboraive Filtering
通常的做法是对一群人进行搜索,并从中找出与我们品味相近的一小群人,算法会对这些人的偏好进行考察,并将它们组合起来构造出一个经过排名的推荐列表
2.搜索偏好——Collecting Preferences
3.寻找相近的用户——Finding Similar Users
3.1 通过相似度评价值来寻找相近的用户
3.2 相似度评价值体系:欧几里得距离(Euclidean Distance ),皮尔逊相关度(Pearson Collelation)曼哈顿距离和Jaccard系数等
代码实现:
1 # !/usr/bin/local/python3 2 # -*- coding utf-8 -*- 3 from math import sqrt 4 5 # prepare data 6 critics = {'Lisa Rose':{'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5, 7 'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You,Me and Dupree': 2.5, 8 'The Night Listener': 3.0}, 9 'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 'Just My Luck': 1.5, 10 'Superman Returns': 5.0, 'The Night Listener': 3.0, 'You,Me and Dupree': 3.5}, 11 'Michale Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0, 'Superman Returns': 3.5, 12 'The Night Listener': 4.0}, 13 'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 'The Night Listener': 4.5, 14 'Superman Returns': 4.0,'You,Me and Dupree': 2.5}, 15 'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 'Just My Luck': 2.0, 16 'Superman Returns': 3.0, 'The Night Listener': 3.0,'You,Me and Dupree': 2.0}, 17 'Jack Mattews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 5.0, 'The Night Listener': '3.0', 18 'Superman Returns': 5.0, 'You,Me and Dupree': 3.5}, 19 'Toby': {'Snakes on a Plane': 4.5, 'You,Me and Dupree': 1.0, 'Superman Returns': 4.0}} 20 21 22 # 测试数据 23 #data =critics['Lisa Rose']['Lady in the Water'] 24 #print(data) 25 26 # 返回一个有关P1和P2的基于欧几里得距离的相似度评价 27 def sim_distance(prefs, p1, p2): 28 # 得到共同评价的电影列表 29 si = {} 30 for item in prefs[p1]: 31 if item in prefs[p2]: 32 si[item] = 1 33 # 如果两人没有共同之处,则返回0 34 if len(si) ==0: return 0 35 # 计算所有差值的的平方和 36 sum_of_squares = sum([pow(prefs[p1][item]-prefs[p2][item], 2) for item in prefs[p1] 37 if item in prefs[p2]]) 38 # 表示偏好越相近,返回的值越大,(避免被零整除的错误,当返回为1表示两人具有一样的偏好) 39 return 1/(1+sqrt(sum_of_squares)) 40 41 42 # 返回p1和p2的皮尔逊相关系数 43 def sim_pearson(prefs, p1, p2): 44 si={} 45 for item in prefs[p1]: 46 if item in prefs[p2]: 47 si[item] = 1 48 49 n = len(si) 50 51 if n == 0: return 1 52 # 求所有偏好之和 53 sum1 = sum([prefs[p1][it] for it in si]) 54 sum2 = sum([prefs[p2][it] for it in si]) 55 56 # 求偏好平方和 57 sum1Sq = sum([pow(prefs[p1][it], 2) for it in si]) 58 sum2Sq = sum([pow(prefs[p2][it], 2) for it in si]) 59 60 # 求两人偏好乘积之和 61 pSum = sum([prefs[p1][it] * prefs[p2][it] for it in si]) 62 63 # 计算皮尔逊评价值 64 num = pSum - (sum1*sum2/n) 65 den = sqrt((sum1Sq-pow(sum1, 2)/n)*(sum2Sq-pow(sum2, 2)/n)) 66 if den == 0: return 0 67 # 返回值介于-1和1之间,值为1则表示两个人对每一样物品均有着完全一致的评价 68 r = num/den 69 return r 70 71 72 # 从反映偏好的字典中返回最为匹配者 73 # 返回结果的个数和相似度函数均为可选参数 74 def topMatches(prefs, person, n=5, similarity=sim_pearson): 75 scores = [(similarity(prefs, person, other), other) for other in prefs if other != person] 76 77 # 对表进行排序,评价值最高的排在最前面 78 scores.sort() 79 scores.reverse() 80 return scores[0:n] 81 82 83 # 利用所有他人评价值的加权平均,为某人提供建议 84 def getRecommendations(prefs, person, similarity=sim_pearson): 85 totals = {} 86 simSum = {} 87 for other in prefs: 88 # 不和自己作比较 89 if other == person: continue 90 # 获取两人之间的相似度 91 sim = similarity(prefs, person, other) 92 93 # 忽略评价值小于零或者为零的情况 94 if sim <= 0: continue 95 for item in prefs[other]: 96 # 只对自己未看过的电影进行评价 97 if item not in prefs[person] or prefs[person][item] == 0: 98 # 相似度*评价值 99 totals.setdefault(item, 0) 100 totals[item] += sim * float(prefs[other][item]) 101 # 相似度之和(多人评价对于特定电影的相似度之和) 102 simSum.setdefault(item, 0) 103 simSum[item] += sim 104 105 # 建立一个归一化的列表 106 rankings = [(total/simSum[item], item) for item, total in totals.items()] 107 print(simSum) 108 # 返回经过排序的列表 109 rankings.sort() 110 rankings.reverse() 111 return rankings 112 113 114 # 将人名和物品进行对调 115 def transforPrefs(prefs): 116 result = {} 117 for person in prefs: 118 for item in prefs[person]: 119 result.setdefault(item,{}) 120 result[item][person] = prefs[person][item] 121 return result
总结:
1.相似性度量方法的选择问题:
1.1 当采用Pearson方法进行评价时,它修正了‘夸大分值’的情况
1.2 当采用Euclidean Distance方法进行评价时,适用于存在一定共性的数据之间
2.基于用户过滤和基于物品过滤的选择:
2.1 基于用户过滤方法更容易实现,而且无需额外步骤,更适用于规模较小的变化非常频繁的内存数据集
2.2 基于物品过滤明显比基于用户的过滤更快,不过在维护物品相似度表有额外的开销,更适用于稀疏数据集