加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

推荐系统中的相似性度量

发布时间:2020-12-14 02:00:22 所属栏目:大数据 来源:网络整理
导读:1、 皮尔逊相关系数 在早期的推荐系统中皮尔逊相关系数是一个基础的相似性衡量标准,先从这个参数定义开始说起。 皮尔逊系数度量两个一一对应数列之间的线性相关程度,上述四种公式都是计算该系数方法,下面python 代码使用就是公式4。 def sim_pearson(pref

1、 皮尔逊相关系数
在早期的推荐系统中皮尔逊相关系数是一个基础的相似性衡量标准,先从这个参数定义开始说起。

这里写图片描述


皮尔逊系数度量两个一一对应数列之间的线性相关程度,上述四种公式都是计算该系数方法,下面python 代码使用就是公式4。

def sim_pearson(prefs,p1,p2):
    # Get the list of mutually rated items
    si={}
    for item in prefs[p1]: 
        if item in prefs[p2]: si[item]=1
    # if they are no ratings in common,return 0
    if len(si)==0: 
        return 0
    # Sum calculations
    n=len(si)
    # Sums of all the preferences
    sum1=sum([prefs[p1][it] for it in si])
    sum2=sum([prefs[p2][it] for it in si])  
    # Sums of the squares
    sum1Sq=sum([pow(prefs[p1][it],2) for it in si])
    sum2Sq=sum([pow(prefs[p2][it],2) for it in si])      
# Sum of the products
    pSum=sum([prefs[p1][it]*prefs[p2][it] for it in si])  
# Calculate r (Pearson score)
    num=pSum-(sum1*sum2/n)
    den=sqrt((sum1Sq-pow(sum1,2)/n)*(sum2Sq-pow(sum2,2)/n))
    if den==0:
        return 0
    r=num/den
    return r

说完皮尔逊系数的计算后我们来分析该系数的优势和不足。
优势:该系数可以修正‘夸大分值’的情况,举例就是user1 倾向总是评分为高分,user2 倾向总是评分在低分区域,加入使用时欧式距离这样两个user的相似性比较低,但是其实两个user爱好可能类似,只是他们对分数的标准不是那么一致。
不足:首先没有考虑到两个用户的给出评分数目,两个看过200部电影的用户,即便他们偶尔有些评分不一致,但我们也会觉得比两个仅仅看了2部相同电影用户相似。
其次,根据公式可以发现,如果两个user重叠的评分只有一个item 这样,该公式定义是无法进行计算的,在稀疏数据集上面这个问题尤其凸显出来,当然如果两个用户重叠次数太少我们也基本可以认为两者相似性不高。
最后,根据公式可以明显发现,如果一个user评分序列中所有的评分都是一样的,这样导致该公式是未定义的。

2、 欧式距离定义相似度
这是最常用相似度,不做详细介绍。
3、 余弦相似性度量
简单贴下mahout中余弦公式实现

public static double distance(double[] p1,double[] p2) {
    double dotProduct = 0.0;
    double lengthSquaredp1 = 0.0;
    double lengthSquaredp2 = 0.0;
    for (int i = 0; i < p1.length; i++) {
      lengthSquaredp1 += p1[i] * p1[i];
      lengthSquaredp2 += p2[i] * p2[i];
      dotProduct += p1[i] * p2[i];
    }
    double denominator = Math.sqrt(lengthSquaredp1) * Math.sqrt(lengthSquaredp2);

    // correct for floating-point rounding errors
    if (denominator < dotProduct) {
      denominator = dotProduct;
    }

    // correct for zero-vector corner case
    if (denominator == 0 && dotProduct == 0) {
      return 0;
    }

    return 1.0 - dotProduct / denominator;
  }

4、 斯皮尔曼相关系数
理论可以参考这个博客:http://www.voidcn.com/article/p-uqiylhyk-u.html
下面是mahout中该参数实现主要部分

@Override
  public double userSimilarity(long userID1,long userID2) throws TasteException {
    PreferenceArray xPrefs = dataModel.getPreferencesFromUser(userID1);
    PreferenceArray yPrefs = dataModel.getPreferencesFromUser(userID2);
    int xLength = xPrefs.length();
    int yLength = yPrefs.length();

    if (xLength <= 1 || yLength <= 1) {
      return Double.NaN;
    }

    // Copy prefs since we need to modify pref values to ranks
    xPrefs = xPrefs.clone();
    yPrefs = yPrefs.clone();

    // First sort by values from low to high
    xPrefs.sortByValue();
    yPrefs.sortByValue();

    // Assign ranks from low to high
    float nextRank = 1.0f;
    for (int i = 0; i < xLength; i++) {
      // ... but only for items that are common to both pref arrays
      if (yPrefs.hasPrefWithItemID(xPrefs.getItemID(i))) {
        xPrefs.setValue(i,nextRank);
        nextRank += 1.0f;
      }
      // Other values are bogus but don't matter
    }
    nextRank = 1.0f;
    for (int i = 0; i < yLength; i++) {
      if (xPrefs.hasPrefWithItemID(yPrefs.getItemID(i))) {
        yPrefs.setValue(i,nextRank);
        nextRank += 1.0f;
      }
    }

    xPrefs.sortByItem();
    yPrefs.sortByItem();

    long xIndex = xPrefs.getItemID(0);
    long yIndex = yPrefs.getItemID(0);
    int xPrefIndex = 0;
    int yPrefIndex = 0;

    double sumXYRankDiff2 = 0.0;
    int count = 0;

    while (true) {
      int compare = xIndex < yIndex ? -1 : xIndex > yIndex ? 1 : 0;
      if (compare == 0) {
        double diff = xPrefs.getValue(xPrefIndex) - yPrefs.getValue(yPrefIndex);
        sumXYRankDiff2 += diff * diff;
        count++;
      }
      if (compare <= 0) {
        if (++xPrefIndex >= xLength) {
          break;
        }
        xIndex = xPrefs.getItemID(xPrefIndex);
      }
      if (compare >= 0) {
        if (++yPrefIndex >= yLength) {
          break;
        }
        yIndex = yPrefs.getItemID(yPrefIndex);
      }
    }

    if (count <= 1) {
      return Double.NaN;
    }

    // When ranks are unique,this formula actually gives the Pearson correlation
    return 1.0 - 6.0 * sumXYRankDiff2 / (count * (count * count - 1));
  }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读