在数据挖掘中经常会计算相似度,用java实现了欧几里得和皮尔逊算法
1、欧几里得
找出可以作为衡量物品或人的数,作为坐标,最后计算坐标之间的距离L
最后计算: r = 1/(1 + L) r属于[0, 1]?? 1表示完全相似, 0代表没有共同点
java的实现:
class="java">package com.euclid.sosop; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; /** * * @author sosop * euclid approximate 欧几里得距离计算,相似度算法之一 * */ public class EuclidApproximate { /** * Map的key为label,value为坐标值 * 只有相同的label才参与计算 */ public static double distance(Map<String, Double> map1, Map<String, Double> map2) { //平方和 double sum = 0; for (Entry<String, Double> entry : map1.entrySet()) { //判断是否具有共同处 if(map2.containsKey(entry.getKey())) { //(x-y)的平方和 sum += Math.pow(entry.getValue() - map2.get(entry.getKey()), 2); } } //没有共同处 if(sum == 0) return 0; //近似度 [0, 1] 1:完全近似 double distance = 1 / (Math.sqrt(sum) + 1); return distance; } public static void main(String[] args) { Map<String, Double> map1 = new HashMap<>(); map1.put("a", 10.88); map1.put("b", 2.5); map1.put("c", 0.9); map1.put("d", 20.76); map1.put("e", 6.3); Map<String, Double> map2 = new HashMap<>(); map2.put("a", 0.5); map2.put("b", 3.1); map2.put("c", 7.9); map2.put("d", 0.22); map2.put("e", 0.1); System.out.println(distance(map1, map2)); } }
?2、皮尔逊
关键在于一条拟合直线。
将所有作为衡量的数在坐标上标记出来,画一条离所有坐标最近的直线就是拟合直线。
最佳拟合线的优势在于不会受到噪声的影响很小
计算相对于欧几里得较复杂
取值范围:[-1, 1]???? 小于0, 负相关的 ; 大于0,正相关;取绝对值找相似度 |r|越大, 相似度越高
下面是java实现的算法:
package com.pearson.sosop; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; /** * * @author sosop * pearson approximate 皮尔逊相似度算法 * */ public class Pearson { public static double coefficient(Map<String, Double> map1, Map<String, Double> map2) { //找到共同之处,保存于List List<String> same = new ArrayList<>(); for (Entry<String, Double> entry : map1.entrySet()) { if (map2.containsKey(entry.getKey())) { same.add(entry.getKey()); } } //共同数目 int items = same.size(); if(items == 0) return 0; double sum1 = 0, sum2 = 0, sqrtSum1 = 0, sqrtSum2 = 0, pSum = 0; for (String label : same) { sum1 += map1.get(label); sum2 += map2.get(label); sqrtSum1 += Math.pow(map1.get(label), 2); sqrtSum2 += Math.pow(map2.get(label), 2); pSum += (map1.get(label) * map2.get(label)); } double num, den; num = pSum - (sum1 * sum2 / items); den = Math.sqrt((sqrtSum1 - Math.pow(sum1, 2) / items) * (sqrtSum2 - Math.pow(sum2, 2) / items)); if(den == 0) return 0; return num / den; } public static void main(String[] args) { Map<String, Double> map1 = new HashMap<>(); map1.put("a", 0.5); map1.put("b", 3.1); map1.put("c", 7.9); map1.put("d", 0.22); map1.put("e", 0.1); Map<String, Double> map2 = new HashMap<>(); map2.put("a", 10.88); map2.put("b", 2.5); map2.put("c", 0.9); map2.put("d", 20.76); map2.put("e", 6.3); System.out.println(coefficient(map1, map2)); } }
?
?