在数据挖掘中经常会计算相似度,用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));
}
}
?
?