初学数据挖掘——相似性度量(二)

  上一篇中介绍了四个算法,并用四个算法分别计算了两个人的相似度。这篇就来讲讲相似性算法在实际当中怎么用。第一:将指定的人与其他人作相似性比较,并从高到低进行排序;第二:对指定的人推荐未看过的电影。同样还是先给出具体分析,然后给出相应算法,再最后一起给出代码。

  根据相似性从高到底排序。

def topMatchs(prefs, person, n=5, similarity=sim_pearson):
        scores=[(similarity(prefs, person, other), other) for other in prefs if other!=person]

        scores.sort()
        scores.reverse()
        return scores[0:n]

  以上是这一部分的算法。其中涉及到Python的函数式编程,由于我也是才在学Python,所以在以后也会顺带解释相应的Python代码,topMatchs方法一共有四个参数,第一、二个参数是必传的参数,第三、四是选传的参数,如果不传入参数,则传入其默认的值,注意第四个参数传入的是一个函数,所以将函数作为一个参数来进行传递也就是函数式编程,sim_pearson方法在上一篇中有相应代码,在本文末也有相应代码。这个算法比较简单,就是指定一人与每个人进行相似性度量,讲比较的结果存入一个list,然后进行排序、返回。

  推荐未看过的电影。

def getRecommendations(prefs, person, similarity=sim_pearson):
    totals = { }    #与指定人(person)的相似度 x 对person未看过电影的评分(加权值)。所有人的总和
    simSums = { } #所有人的相似度(是对该电影有过评价且对person来说未看过的人)
    #
    for other in prefs:
        if other == person: continue    #肯定不和自己比较
        sim = similarity(prefs, person, other) #返回的是与此人的相似度

        #忽略相似度为0或者小于0的情况,
        if sim <= 0: continue

        for item in prefs[other]:
            #只对自己还未看过的电影进行推荐
            if item not in prefs[person] or prefs[person][item] == 0:
                #相似度 x 对该电影的评论
                totals.setdefault(item, 0)  #该方法是Dictionary方法,若键key不存在于此Dictionary中,将会添加该键到Dictionary中,并设默认值(0)
                totals[item] += prefs[other][item] * sim
                #相似度之和
                simSums.setdefault(item, 0)
                simSums[item] += sim

    rankings = [(total/simSums[item], item) for item, total in totals.items()]

    rankings.sort()
    rankings.reverse()
    return rankings

  这个算法有两点,第一:未看过的电影,这个好解决。第二:推荐,怎么个推荐?是否能根据某一个人和我的相似度很高,所以就将他看过我没看过的电影推荐给我?当然不行,就算他和我相似度很高,但是还是存在他对某一部电影的评分很低,而我又没有看过就推荐给我,所以单单从某人和我的相似度高低这一个因素来进行显然不可以。同样存在某一个人一部电影的评分很高,但他的相似度和我很低,而且其他人对此电影的评分很低,这种情况也不可以。所以引用原文中的话“我们需要通过一个经过加权的评价值来为影片打分”。我们还是按照上周给出过的例子,小明A对《左耳》、《何以笙箫默》、《速度与激情》的评分分别是3、4、5,小红对这三部电影的评分是2、5、1,再加上“我”。我们假设这三部电影我没有看过,根据上面一个算法得出A对我的相似度是0.99,B是0.38。现在列出一个表格来进行说明。

。每个电影的评价值,也就是经过加权后的评价值=相似度x对该电影的评分。Total代表每个电影的经过加权后评价值总和,相似度总和则是所有评论者的相似度总和,最后Total/相似度总和即得到影片的推荐值,由此可见推荐度分别是《何以》、《速度》、《左耳》。注意,这里的所有评论者指的都是评论过该电影的评论者,若没有评论过该电影者,Total和相似度总和都不包括此人。如果想要更加详细的了解,请参阅中文版《集体智慧编程》P15。我认为最关键的地方在于——加权,如何加权,怎么加权合适,这是个问题。

  下面就贴出所有的代码,只需要将以下代码直接贴在上章的最后即可。

 1 #指定一人与其他人的相似度排名
 2 def topMatchs(prefs, person, n=5, similarity=sim_pearson):
 3         scores=[(similarity(prefs, person, other), other) for other in prefs if other!=person]
 4 
 5         scores.sort()
 6         scores.reverse()
 7         return scores[0:n]
 8 
 9 print u"与Toby相似度最高的人"
10 print topMatchs(critics, 'Toby', n=3)
11 
12 #以下方法在topMatchs方法的基础上直接根据相似度x加权值(对每个电影的评分)推荐电影
13 def getRecommendations(prefs, person, similarity=sim_pearson):
14     totals = { }    #与指定人(person)的相似度 x 对person未看过电影的评分(加权值)。所有人的总和
15     simSums = { } #所有人的相似度(是对该电影有过评价且对person来说未看过的人)
16     #
17     for other in prefs:
18         if other == person: continue    #肯定不和自己比较
19         sim = similarity(prefs, person, other) #返回的是与此人的相似度
20 
21         #忽略相似度为0或者小于0的情况,
22         if sim <= 0: continue
23 
24         for item in prefs[other]:
25             #只对自己还未看过的电影进行推荐
26             if item not in prefs[person] or prefs[person][item] == 0:
27                 #相似度 x 对该电影的评论
28                 totals.setdefault(item, 0)  #该方法是Dictionary方法,若键key不存在于此Dictionary中,将会添加该键到Dictionary中,并设默认值(0)
29                 totals[item] += prefs[other][item] * sim
30                 #相似度之和
31                 simSums.setdefault(item, 0)
32                 simSums[item] += sim
33 
34     rankings = [(total/simSums[item], item) for item, total in totals.items()]
35 
36     rankings.sort()
37     rankings.reverse()
38     return rankings
39 
40 print u"推荐给Toby的电影"
41 print getRecommendations(critics, "Toby")

  在这章中,相似性度度量算法使用了“皮尔逊相关系数”,书中提到“选择不同的相似性度量方法,对结果的影响是微乎其微的”。事实的确如此,使用上章的四个算法,影片的推荐都是一致的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java面试通关手册

六道面试中常见的智力题 来看看你会做几道?

下面的题目来自滴滴出行2017秋招题。这些题目是我自己觉得比较难或者比较容易出错的题目。

32740
来自专栏闪电gogogo的专栏

P问题、NP问题、NPC问题

   看师兄们的论文经常说一句这是个NP难问题,所以采用另外一种方法来代替(比如凸松弛,把l0范数的问题松弛为l1范数的问题来求解)。然后搜索了相关知识,也还是...

42160
来自专栏WOLFRAM

偶述 Wolfram 中文分词算法

从 2000 年开始学习和使用 Mathematica,《Mathematica 演示项目笔记》作者,发表Wolfram Demonstrations Proj...

22020
来自专栏天天P图攻城狮

Android上实现频域均衡器

本篇文章主要介绍了将录音从时域数据转化成频域数据的方法。

51620
来自专栏C语言及其他语言

【每日一题】问题 1429[蓝桥杯][历届试题]兰顿蚂蚁

题目描述 ? 兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。 平面上的正方形格子被填上黑色或白色。在其中一格正方形内有...

30060
来自专栏C语言及其他语言

[每日一题]矩阵转置(1242)

题目描述 输入N*N的矩阵,输出它的转置矩阵。 输入 第一行为整数N。 接着是一个N*N的矩阵。 输出 转置矩阵 样例输入 2 1 2 1 2 样例输出 1 ...

38690
来自专栏mathor

第五届蓝桥杯决赛B组C/C++——殖民地

19450
来自专栏腾讯NEXT学位

你需要知道的算法之基础篇

40870
来自专栏C语言及其他语言

[每日一题]老王赛马

题目描述 赛马是一古老的游戏,早在公元前四世纪的中国,处在诸侯割据的状态,历史上称为“战国时期”。在魏国作官的孙膑,因为受到同僚庞涓的迫害,被齐国使臣救出后,到...

29890
来自专栏苦逼的码农

循序渐进带你学习时间复杂度和空间复杂度。

写了这么久的算法文章,可以说凡是算法的文章都会涉及到时间复杂度和空间复杂度,可能有些读者对时间复杂度和空间复杂度还有点迷糊,今天特地找了一篇关于时间复杂度和空间...

13250

扫码关注云+社区

领取腾讯云代金券