数据挖掘之【协同过滤算法简版】

来源:互联网 发布:数据车床编程步骤 编辑:程序博客网 时间:2024/05/16 14:55

算法简介    

    协同过滤算法在数据挖掘算法中属于比较简单的,在《集体智慧编程》一书中,开篇讲的就是协同过滤算法。这章早就看完了,没有用代码区实现而已,今天动手敲了代码,返现还是有些感触,特此记录下。

    协同过滤的算法核心在于以下两方面:

        1)怎么衡量两个向量之间的相似性,此处可以参见我转载的一片博客:数据挖掘之距离计算算法

        2)从集合中找出与自己喜好相似度不为零的人中,找出偏好没有出现在我的集合中或打分为0的选项

        3)为了避免某些项打分过高产生的影响,采用权重,权重的计算可以由相似度来计算。参见以下代码。

相关性系数计算

#--------------Euclidean distance------------#def calc_ed_distance(fans,p1_name,p2_name):    sim = {}    for k in fans[p1_name].keys():        if k in fans[p2_name].keys():            sim[k] = 1    if len(sim) == 0:        return 0        score = sum([math.pow(fans[p1_name][item] - fans[p2_name][item], 2)                 for item in fans[p1_name] if item in fans[p2_name]])    return 1/(1+score)#--------------------#def calc_pearson_distance(fans,p1_name,p2_name):    #find the same preference    sim = {}    for k in fans[p1_name].keys():        if k in fans[p2_name].keys():            sim[k] = 1    n = len(sim)            if n == 0:return 0            x_sum = sum([ fans[p1_name][k] for k in sim.keys()])    y_sum = sum([ fans[p2_name][k] for k in sim.keys()])        xy_sum = sum([fans[p1_name][k] * fans[p2_name][k] for k in sim.keys()])    xpow =  sum([ math.pow(fans[p1_name][k],2) for k in sim.keys()])    ypow =  sum([ math.pow(fans[p2_name][k],2) for k in sim.keys()])        score = (n * xy_sum - x_sum * y_sum)/(math.sqrt(n * xpow - math.pow(x_sum,2))                                          * math.sqrt(n * ypow - math.pow(y_sum,2)))    return score

计算推荐项

def getRecommendation(fans,person,similar_method=calc_ed_distance):    total={}    simsum={}    for other in fans.keys():        if other == person:continue        sim = similar_method(fans,person,other)        if sim <= 0: continue        for item in fans[other].keys():            if not item in fans[person] or fans[person][item] == 0:                total.setdefault(item,0)                total[item] += fans[other][item] * sim                simsum.setdefault(item,0)                simsum[item] += sim #次数计算权重    ranking = [(total[item]/simsum[item],item) for item in total.keys()]     ranking.sort()    ranking.reverse()    return ranking

    上面讨论的是User-Based协同过滤,另外一种替代是Item-Based协同过滤。User-Based算法需要所有用户的dataset,当此数据集非常大时,处理效率会很低。例如亚马逊每天有数以百万的用户购买记录,但与每个产品相关的人比较起来,数据量会小的很多,但是有一个缺点,个人购买产品之间的重叠很小,导致很难看出哪些用户是相似的。

Item-Based协同过滤算法思想

    1)首先计算全局item对应的相似item集合
    2)在全局item相似度集合基础上,根据用户user的喜好items,迭代计算item对应的相似度(加权)
    3)最后推荐返回user相似度较高的item

#翻转item和persondef transfer_prefers(pep_fans):    prefers={}    for person in pep_fans:        for item in pep_fans[person]:            prefers.setdefault(item,{})            prefers[item][person]=pep_fans[person][item]    return prefers
#找出与person(可以是user或item)相似度较高集合def topMatch(fans,person,top=5,similar_method=calc_ed_distance):    scoreset = [(similar_method(fans,person,other),other) for other in fans.keys()                  if other != person]    scoreset.sort()    scoreset.reverse()    return scoreset[0:top]
#构建一个完整的相似item集合def calc_item_sim(prefers,n=10):    prefers_new = transfer_prefers(prefers)    dataset={}    for item in prefers_new:        scores=topMatch(prefers_new,item,top=n,similar_method=calc_pearson_distance)        dataset[item]=scores    return dataset

def getRecommendItems(prefers,itemmatch,user):    usrRating=perfers[user]    socre={}    totalsim={}    #用户user的喜好以及得分,item为喜好,rating为得分    for (item,rating) in usrRating.items():        #所有item相似度全集        for (similarity,item2) in itemmatch[item]:            if item2 not in usrRating:continue            socre.setdefault(item2,0)            score[item2]+=similarity*rating            totalsim.setdefault(item2,0)            totalsim[item2]+=similarity    rankings=[(score/totalSim[item],item) for item,score in scores.items( )]        rankings.sort()    rankings.reverse()    return rankings            




原创粉丝点击