Making Recommendations - QLGQ/learning-python GitHub Wiki

相似度评价值

欧几里得距离评价(Euclidean Distance Score)

计算相似度评价值的一个非常简单的方法是使用欧几里得距离评价方法。它以经过人们一致评价的物品为坐标轴,然后将参与评价的人绘制到图上,并考查他们彼此间的距离远近。距离越近,兴趣爱好就越相似。

欧几里得距离(Euclidean Distance)

欧几里得距离是指多维空间中两点间的距离,这是一种用直尺测量出来的距离。如果我们将两个点分别记作P(p1, p2, p3, p4,...)和Q(q1, q2, q3, q4,...),则欧几里得距离的计算公式如下方程所示:

下面是上述公式的一个明确实现:

def euclidean(p, q):
    sunSq = 0.0
    # 将差值的平方累加起来
    for i in range(len(p)):
        sumSq += (p[i] - q[i]) ** 2

    # 求平方根
    return (sumSq ** 0.5)

上述公式可以计算出距离值,偏好越相似的人,其距离就越短。不过,我们还需要一个函数,来对偏好越相近的情况给出越大的值。为此,我们可以将函数值加1(这样就可以避免遇到被零整除的错误了),取其倒数,这一新的函数总是返回介于0到1之间的值,返回1则表示两人具有一样的偏好。

from math import sqrt
sqrt(pow(4.5-4, 2)+pow(1-2, 2))
1.1180339887498949

1/(1+sqrt(pow(4.5-4, 2)+pow(1-2, 2)))
0.47213595499957939

皮尔逊相关度评价(Pearson Correlation Score)

除了欧几里得距离,还有一种更复杂一些的方法可以用来判断人们兴趣的相似度,那就是皮尔逊相关系数。该相关系数是判断两组数据与某一直线拟合程度的一种度量。对应的公式比欧几里得距离评价的计算公式要复杂,但是它在数据不是很规范(normalized)的时候(比如,影评者对影片的评价总是相对于平均水平偏离很大时),会倾向于给出更好的结果。

皮尔逊相关系数(Pearson Correlation Coefficient)

皮尔逊相关系数是一种度量两个变量间相关程度的方法。它是一个介于1和-1之间的值,其中,1表示变量完全正相关,0表示无关,-1则表示完全负相关。以下方程式给出了皮尔逊相关系数的计算公式:

上述公式可以用下列代码加以实现:

def pearson(x, y):
    n = len(x)
    vals = range(n)

    # 简单求和
    sumx = sum([float(x[i]) for i in vals])
    sumy = sum([float(y[i]) for i in vals])

    # 求平方和
    sumxSq = sum([x[i]**2.0 for i in vals])
![](https://latex.codecogs.com/png.latex?%5Cdpi%7B150%7D%20%5Crho%20_%7BX%2C%20Y%7D%20%3D%20%5Cfrac%7Bcov%28X%2C%20Y%29%7D%7B%5Csigma%20_%7BX%7D%5Csigma%20_%7BY%7D%7D)
    sumySq = sum([y[i]**2.0 for i in vals])

    # 求乘积之和
    pSum = sum([x[i] * y[i] for i in vals])

    # 计算皮尔逊评价值
    num = pSum - (sumx*sumy/n)
    den = ((sumxSq-pow(sumx,2)/n) * (sumySq-pow(sumy,2)/n))**.5
    if den == 0: return 1

    r = num/den

    return r

在采用皮尔逊方法进行评价时,它修正了“夸大分值(grade inflation)”的情况。如果某人总是倾向于给出比另一个人更高的分值,而二者的分值之差又始终保持一致,则他们依然可能会存在很好的相关性。

加权平均(Weighted Mean)

加权平均是这样一类求平均的运算:参与求平均运算的每一个观测变量都有一个对应的权重值。加权平均的计算公式如下所示(其中x1, x2, ...是观测变量,w1, w2, ...是权重值):

上述公式的一个简单实现如下所示(函数接受一个数值列表和一个权重列表作为参数):

def weightedmean(x, w):
    num = sum([x[i]*w[i] for i in range(len(w))])
    den = sum([w[i] for i in range(len(w))])

    return num/den

每一项的最终评价值的计算方法——用每一项的评价值乘以相似度,并将所得乘积加起来,最后将每个总计值初一相似度之和,借此对评价值进行归一化处理,然后返回一个经过排序的结果。

协作型过滤(Collaborative Filtering)

基于用户的过滤(User-Based Filtering)

基于物品的过滤(Item-Based Filtering)

基于物品的过滤过程,其总体思路就是为每件物品预先算好最为相近的其他物品。然后,当我们想为某位用户提供推荐时,就可以查看他曾经评过分的物品,并从中选出排位靠前者,再构造出一个加权列表,其中包含了与这些选中物品最为相近的其他物品。此处最为显著的区别在于,尽管第一步要求我们检查所有的数据,但是物品间的比较不会像用户间的比较那么频繁变化。这意味着,无须不停地计算与每样物品最为相近的其他物品,我们可以将这样的运算任务安排在网络流量不是很大的时候进行,或者在独立于主应用之外的另一台计算机上单独进行。

构造物品比较数据集(Building the Item Comparison Dataset)

为了对物品进行比较,我们要做的第一件事情就是编写一个函数,构造一个包含相近物品的完整数据集,这项工作无须在每次推荐时都做一遍,构建完一次数据集之后,我们就可以在需要的时候重复使用它。