集体智慧编程学习(一)推荐商品

以一个旅游网站为例,当用户登录的时候,可以自动给用户推荐一些可能喜欢的景点,这种应用在一些卖东西网站,比如Amazon也会见到
首先认为网站是具有评论系统的,用户可以对自己去过的景点进行打分,分数在(1-5)之间,分越高表示这个用户对这个景点的喜欢程度越高。
假设总共有7个景点被用户评论过,而发表过评论的用户有刘, 王, 唐,张,徐,吴6个用户,那么我们系统中就保存了如下的数据:
每一行代表一个景点,而用户名后面的分数,表示了这个用户对这个景点的评分。
spot_data = {
         '杭州':{'刘':5.0,'王':3.0, '唐':4.5, '张':2.0, '徐':4.5},
         '香港':{'刘':3.0,'王':2.0, '唐':4.0, '张':1.0, '徐':4.0},
         '三亚':{'刘':2.0,'王':4.5, '唐':1.0, '张':4.0, '徐':4.0},
         '大连':{'刘':1.0,'王':4.0, '唐':1.5, '张':4.5, '徐':4.5,'李':4.0},
         '苏州':{'刘':4.0,'王':1.0, '唐':4.0, '张':1.5, '徐':5.0,'李':1.5},
         '青岛':{'刘':1.0, '唐':4.0, '张':4.0, '徐':5.0,'李':5},
         '上海':{'刘':4.5,'唐':4.0, '张':1.0, '徐':3.0},
         '拉萨':{'吴':4.0}
         }

如果我们要为用户李推荐一些感兴趣的景点,可以按照下面的方法:
1.找出李曾经评论过的景点以及对这些景点的打分:
李去过的景点有{'苏州': 1.5, '大连': 4.0, '青岛': 5},看得出这个用户比较喜欢海边,对江南的城市似乎兴趣不大
2.李没去过的景点有{杭州,香港,三亚,上海,拉萨},我们就需要从这些景点中选出一些推荐的景点。但实际环境中,李没去过的景点可能很多很多,有必要缩小范围,只要从和李去过的那三个景点比较相似的景点中选可以了,差别太大的景点,我们也没有必要进行推荐。
所以,我们需要有一个景点相似度之间关系的数据表,假设名称叫similarMap,这个表是预先生成好的,过程会比较耗时,我们放到后面再说,现假设有以下的表:
{'大连': [(0.33333333333333331, '三亚'), (0.11428571428571428, '青岛'), (0.038461538461538464, '香港')],
'香港': [(0.23529411764705882, '上海'), (0.18181818181818182, '苏州'), (0.14814814814814814, '杭州')],
'上海': [(0.23529411764705882, '香港'), (0.21052631578947367, '杭州'), (0.18181818181818182, '苏州')],
'拉萨': [],
'杭州': [(0.26666666666666666, '苏州'), (0.21052631578947367, '上海'), (0.14814814814814814, '香港')],
'苏州': [(0.26666666666666666, '杭州'), (0.18181818181818182, '上海'), (0.18181818181818182, '香港')],
'青岛': [(0.11428571428571428, '大连'), (0.083333333333333329, '三亚'), (0.066666666666666666, '香港')],
'三亚': [(0.33333333333333331, '大连'), (0.083333333333333329, '青岛'), (0.041666666666666664, '香港')]}
上表中每一行都存储了一个景点名称以及与这个景点相似度最高的三个景点,小数表示相似程度,越高表示景点之间越相似。
所以,在我们选择范围的景点只有{杭州,香港,三亚,上海},我们把拉萨排除掉,因为它和李去过的景点都不相似

3.假设我们最多推荐2个景点,那我们就逐个计算上面四个景点的推荐度,做个排序,取前两位就可以了
4.接下来的问题就是,怎么计算每个景点的推荐度
思路是,一个景点的推荐度取决于两个要素
1)这个景点和李曾经评论过的景点的相似度
2)李对与这个景点相似的景点的评分
先找出一个没有去过的景点(A),分别和用户去过的景点(B)逐个进行比较
1)如果两个景点比较相似,那么用户对B的评价,对A的打分影响很大
2)如果两个景点差别很大,那么用户对B的评价,对A的打分影响不大
另外也要考虑到相关联景点数量可能不同,比如在李去过的城市中,杭州只和苏州有相似关系, 而三亚和大连,苏州,青岛都有关系
例如:
三亚的推荐度是:(和大连的相似度x用户给大连的评分 + 和青岛的相似度 x 用户给青岛的评分)/(和大连的相似度 +和青岛的相似度)= 4.20
杭州的推荐度是:(和苏州的相似度 x用户给苏州的评分)/ 和苏州的相似度 = 1.5
同理,香港的评分是2.64, 上海的推荐度是1.5

因此,经过排序后,我们推荐给用户李的两个景点是:1)三亚 2)香港。

最后,我们来看一下第2步中提到的similarMap是如何生成的。
先来看看其中的一行{'大连': [(0.33333333333333331, '三亚'), (0.11428571428571428, '青岛'), (0.038461538461538464, '香港')]
这一行的数据其实就是找出大连和其他所有景点的相似度,取出排名前三,经过计算得到三亚,青岛,香港排名前三,保存到这个表中。
那最后的问题就是,如何计算两个景点之间的相似度。
对于相似度的计算,这里是以用户的评价为基准的。
比如如果对所有去过大连和三亚用户对这两个地方的的打分都相似,那么可以说这大连和三亚的相似度较高,反之相似度较低。
如 下图,左图以刘和王两个用户的维度,把这两个用户分别对大连和三亚的打分作为坐标点。从中可以看出,这两个用户对大连和三亚打分都比较接近,所以两点间距 离较近。作为比对,两个用户对大连和杭州的打分差异较大,两点之间距离较远。右图站在王和张两个用户的维度进行了比较,大连和三亚的距离还是比较近的。




最后问题就归结成了站在n个用户的维度,计算大连和三亚的空间距离,计算两点在N维空间的距离有一个数学公式-欧几里德距离公式
其中n表示空间的维度,比如上面比较了3个用户,站在这三个用户的角度,大连和三亚的距离就是
sqrt(pow(4-4.5) + pow(1-2) + pow(4.5-4))
以此类推,算出从N个用户角度来看,大连和三亚的相似度,记作D
最后,因为D其实是大连和三亚的空间距离,D越大,只能表示这两个地方的差异程度,为了表示相似程度,需要取一下倒数
得出相似度 Similarity = 1/(1+D)
各个景点之间逐个计算,就得到了上面的similarMap。

以上方法的总结
缺点:similarMap需要定期buiid, 而build的过程估计会相当的慢
       欧几里德距离算法在用户打分标准差异很大的时候不太准确,比如有些用户总是倾向于打高分,有些用户总是打分偏低。可以改用皮尔逊相关度系数来解决,算法也要复杂些。
优点:在similarMap生成好之后,推荐的过程比较的数据少,进行推荐的过程会比较快。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值