如何找到相似的用户 -距离公式

曼哈顿距离

推荐系统入门 - 图1

欧几里得距离

曼哈顿距离的优点之一是计算速度快,对于Facebook这样需要计算百万用户之间的相似度时就非常有利。

推荐系统入门 - 图2

皮尔逊相关系数

image.png
左边平方和的累加乘以右边平方和的累加

余弦相似度

推荐系统入门 - 图4
其中,“·”号表示数量积。“||x||”表示向量x的模,计算公式是:
推荐系统入门 - 图5

我们用上文中“偏好完全一致”的示例:
推荐系统入门 - 图6
所以两个向量为:
推荐系统入门 - 图7
它们的模是:
推荐系统入门 - 图8
数量积的计算:
推荐系统入门 - 图9
因此余弦相似度是:
推荐系统入门 - 图10
余弦相似度的范围从1到-1,1表示完全匹配,-1表示完全相悖。所以0.935表示匹配度很高**

距离公式使用范围

  • 如果数据存在“分数膨胀”问题,就使用皮尔逊相关系数。
  • 如果数据比较“密集”,变量之间基本都存在公有值,且这些距离数据是非常重要的,那就使用欧几里得或曼哈顿距离。
  • 如果数据是稀疏的,则使用余弦相似度。

只是选择一个最相似的人是不对的 —— K最邻近算法

按照选择的距离公式 来推荐k个距离最近的人;

欧几里得的 K最邻近算法 代码实现

  1. let target = {
  2. '张爽' :[2,3,5,6,undefined],
  3. "邓超" :[1,2,3,undefined,4],
  4. "吴亦凡" :[1,undefined,3,2,1],
  5. };
  6. // 计算两个对象的距离 例 "张爽” 和“吴亦凡”
  7. function ojld(p1,p2) {
  8. let sum = 0;
  9. for (let i=0; i<p1.length && i<p2.length;i++){
  10. if(p1[i] !== undefined && p2[i] !== undefined){
  11. sum += p1[i]*p1[i] - p2[i] * p2[i]
  12. }
  13. }
  14. return Math.pow(Math.abs(sum),0.5)
  15. }
  16. function getObstacle(obj,k) {
  17. let persons = Object.keys(obj);
  18. // 存储所有距离 返回一个 json对象
  19. let result = {};
  20. // 两层嵌套循环返回一个距离的矩阵
  21. for (let i=0; i<persons.length;i++){
  22. // 存放单个的距离
  23. let arr = [];
  24. for (let j= 0;j<persons.length;j++){
  25. if(i !== j) {
  26. arr.push({[persons[j]] : ojld(obj[persons[i]],obj[persons[j]])});
  27. }
  28. }
  29. // 如果计算的人数大于k才进行筛选
  30. if(k < Object.keys(arr).length){
  31. result[persons[i]] = arr.sort((a,b)=>{
  32. return Number(Object.values(b)) - Number(Object.values(a))
  33. }).slice(0,k)
  34. }else {
  35. result[persons[i]] = arr
  36. }
  37. }
  38. return result
  39. }
  40. console.log(getObstacle(target,1));
  41. // 可以看看数据结构
  42. // { '张爽': [ { '吴亦凡': 7.14142842854285 } ],
  43. // '邓超': [ { '张爽': 4.898979485566356 } ],
  44. // '吴亦凡': [ { '张爽': 7.14142842854285 } ] }