集体智慧编程 读书笔记 二

来源:互联网 发布:mssql数据库迁移 编辑:程序博客网 时间:2024/05/05 23:02

还是第二章, 后面内容

        这部分讲了基于物品的协作过滤, 之前讲基于用户的协作过滤,  基于物品的协作过滤适用于大数据集, 因为我们可以体检对数据进行处理, 物品的变化很小,所以计算一次后,以后可以较少的修改,这部分内容比较简单,当有数据集后, 计算每种物品的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 所以第一个比较倾向的方法


第五题是构建一个音乐推荐系统。。。。 好大的题


0 0