还是第二章, 后面内容
这部分讲了基于物品的协作过滤, 之前讲基于用户的协作过滤, 基于物品的协作过滤适用于大数据集, 因为我们可以体检对数据进行处理, 物品的变化很小,所以计算一次后,以后可以较少的修改,这部分内容比较简单,当有数据集后, 计算每种物品的topmatch 物品
def buildSimilarItems(prefs, n=10):
result = {}
itemPrefs = transformPrefs(prefs)
c = 0
for item in itemPrefs:
c += 1
print ("%d / %d" % (c,len(itemPrefs)))
scores = topMatches(itemPrefs, item, n=n)
result[item] = scores
return result
构建好相似物品后, 就可以利用它为用户做推荐, 还是利用加权的方法, 文中方法比较简单就是用户的评分做权值, 乘以相似度,代码就不贴了, 很好写
然后书中提供了一个比较好的数据集,http://www.grouplens.org/node/73, 格式如下
movies.dat里包含的是电影信息, 包含电影id, name, 和类型, 数据用冒号分割
1::Toy Story (1995)::Adventure|Animation|Children|Comedy|Fantasy
2::Jumanji (1995)::Adventure|Children|Fantasy
3::Grumpier Old Men (1995)::Comedy|Romance
ratings.dat里包含的是评价信息, 有用户id, 电影id, 评分, 和时间戳, 也是冒号分割
1::122::5::838985046
1::185::5::838983525
1::231::5::838983392
1::292::5::838983421
1::316::5::838983392
1::329::5::838983392
1::355::5::838984474
1::356::5::838983653
1::362::5::838984885
所以首先构建书中之前代码能够处理的数据集格式, 代码如下:
def loadMovies(path='your own path'):
count = 0
movies = {}
for line in open(path + '/movies.dat'):
(id, title) = line.split('::')[0:2]
movies[id] = title
prefs = {}
for line in open(path + '/ratings.dat'):
count += 1
if count > 100000: return prefs
(user, movie, rating, ts) = line.split('::')
prefs.setdefault(user, {})
prefs[user][movies[movie]] = float(rating)
return prefs
为了节省时间, 用count标识只处理10w行数据
有了数据集就可以验证之前的一些算法, 基于用户和物品的协作过滤了, 还发现了一个bug, 在上一篇文章里的 获取推荐的计算时, sim < 0 contiue, 改成 sim <=0 否则会出 divied by zero的错误
最后是习题:
第一个是 写tanimoto 分值的相似度计算方法,
def sim_tanimoto(prefs, p1, p2):
si = {}
for item in prefs[p1]:
if item in prefs[p2]:
si[item] = 1
length = len(si)
if length == 0: return 0
t = length/(len(prefs[p1]) + len(prefs[p2]) - length)
return t
上面是集合的求法, 我觉得也可以用转换后的公式来求(不知道可以不)
def sim_tanimoto(prefs, p1, p2):
si = {}
for item in prefs[p1]:
if item in prefs[p2]:
si[item] = 1
length = len(si)
if length == 0: return 0
# sum of multi
sumMul = sum(prefs[p1][item] * prefs[p2][item] for item in si)
# sum of pow
sumPow1 = sum(pow(prefs[p1][item], 2) for item in si)
sumPow2 = sum(pow(prefs[p2][item], 2) for item in si)
#den
den = sqrt(sumPow1) + sqrt(sumPow2) - sumMul
t = sumMul/den
return t
我觉得还是集合的方法靠谱, tanimoto系数适用于没有精确数值的情况, 比如存在为1不存在为0 所以第一个比较倾向的方法
第五题是构建一个音乐推荐系统。。。。 好大的题