实现一个简单的推荐系统。

sddtc 于 2016-03-27 发布

本文转载自:不到100行代码实现一个简单的推荐系统

这篇文章写得很简短,代码我也部署执行过,是非常有趣的一件事,这其中的点,还是想记录下来,在接下来可以扩展的地方,也是非常多的。

推荐系统的第一步,需要想办法收集信息

数据有了,推荐系统要干些什么呢?以电影推荐来说,推荐系统需要解决的几个主要问题:

  1. 判断两个电影,两个观影人之间的相似度
  2. 找到和某影片最相似的影片, 或找到和某观影人有同样兴趣的人
  3. 找到某观影人可能喜欢的电影,或找到对某影片感兴趣的人

推荐系统的基础,判断相似度:1.欧几里德距离计算相似度;2.归一化处理

数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性。
原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价。
归一化化就是要把你需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。
简单的说,我们希望,处理后的数据取值范围在0-1之间.
在数学上有很多归一化处理的方法,常用的有:
一、min-max标准化(Min-Max Normalization)
也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 – 1]之间。
二、Z-score标准化方法
这种方法给予原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。经过处理的数据符合标准正态分布,即均值为0,标准差为1
我们可以根据需要选择,不过,针对该系统采用的是欧几里德距离,可以用下面的更简单的公式:
假设计算出来的欧几里德距离为:n
1 / (1 + n)
当距离为0,归一化后的值为:1
距离越大,归一化后的值越接近0

找到和和某观影人有同样兴趣的人,某影片最相似的影片

a.找到和某用户有同样兴趣的人,只要将某用户和其它所有用户的相似度计算出来,排下序就行了
b.找到和某影片相似的影片,这个需要稍微变化下。例子输入数据是以用户为行数据,影片为列数据,只要改成以影片为行数据,用户为列数据,一样的调用。 所以需要一个函数,将矩阵转置

找到某观影人可能喜欢的电影,找到对某影片感兴趣的人

最理想的是找到两个相似度一样的人,可以认为某个人喜欢的电影,另外那个也喜欢。 但是这样有它的缺点,比较好的办法是把所有人的数据都用上
方法如下:

  1. 先计算所有人和sddtc的相似度
  2. 对于sddtc没有看过,没有评分,而其它人有评分的的影片,将其评分与相似度相乘,得到的值再除以相似度之和
  3. 排序
    先以给sddtc推荐影片为例来说明,Dawn of the Planet of the Apes 和 RoboCop 这两部影片sddtc都没有看,我们该推荐他看哪部呢?假设我们计算出来sddtc与其它人的相似度如下:
    [(0.3333333333333333, ‘yeyezi’),
    (0.29429805508554946, ‘jiyu’),
    (0.2857142857142857, ‘kaikai’),
    (0.2553967929896867, ‘xiaojiufen’),
    (0.252650308587072, ‘xiaoyanqiao’),
    (0.2474401533514073, ‘teemo’)]
    即sddtc与yeyezi相似度为0.3333333333333333,与jiyu相似度为0.29429805508554946, 其它类似…
    那么计算Dawn of the Planet of the Apes对sddtc的推荐值过程如下:
    1.找到yeyezi对Dawn of the Planet of the Apes的评价值,乘以yeyezi与sddtc的相似度:3 * 0.252650308587072
    2.找到jiyu对Dawn of the Planet of the Apes的评价值 乘以其与Kai Zhou的相似度: 2 * 0.3333333333333333
    3.找到kaikai对Dawn of the Planet of the Apes的评价值 乘以其与Kai Zhou的相似度: 3 * 0.29429805508554946
    4.xiaojiufen没有对Dawn of the Planet of the Apes评价,不用计算
    5.找到xiaoyanqiao对Dawn of the Planet of the Apes的评价值 乘以其与Kai Zhou的相似度: 1.5 * 0.2553967929896867
    6.teemo没有对Dawn of the Planet of the Apes评价,不用计算
    7.将1,2,3,5步的计算结果相加,得到:3 * 0.252650308587072 + 2 * 0.3333333333333333 + 3 * 0.29429805508554946 + 1.5 * 0.2553967929896867 = 2.6906069471690612
    8.将1,2,3,5步的参与计算的人的相似度相加:0.252650308587072 + 0.3333333333333333 + 0.29429805508554946 + 0.2553967929896867 = 1.1356784899956416
    9.将第7步结果除以第8步的结果,就是Dawn of the Planet对sddtc的推荐值:2.6906069471690612 / 1.1356784899956416 = 2.369162549851047

同样的方法,计算出来RoboCop对sddtc的推荐值为:3.9277923180363326,所以RoboCop应该对sddtc的吸引力比Dawn of the Planet of the Apes更大.
找到对某影片感兴趣的人和之前类似,需要将矩阵转置就行了

这就是一个简单的推荐系统的雏型,当然,要实现一个可用的推荐系统,还有很多工作要做。
比如推荐的精确度,用户喜欢打斗片,咱不可能给他推荐爱情片吧?
比如数据量大了之后,性能问题,扩展性?是基于用户推荐还是物品推荐?……