`

近似度计算-欧几里得和皮尔逊

阅读更多

在数据挖掘中经常会计算相似度,用java实现了欧几里得和皮尔逊算法

1、欧几里得

找出可以作为衡量物品或人的数,作为坐标,最后计算坐标之间的距离L

最后计算: r = 1/(1 + L) r属于[0, 1]   1表示完全相似, 0代表没有共同点

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;
		
		int common = 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);
				common ++;
			}
		}
		
		//没有共同处
		if(common == 0) return 0;
		
		//近似度 [0, 1]  1:完全近似
		//较简单的计算相似度,朴素相似度
		// double sim = 1 / (Math.sqrt(sum) + 1);
		
		//较精确的计算
		double sim = Math.sqrt(sum/(double) common);
		sim = 1.0 - Math.tanh(sim);
		int max = Math.min(map1.size(), map2.size());
		sim = sim * ((double)common / (double)max);
		
		return sim;
	}
	
	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", 10.5);
		map2.put("b", 2.1);
		map2.put("c", 0.9);
		map2.put("d", 20.22);
		map2.put("e", 6.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));
	}
}

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics