JAVA实现基于皮尔逊相关系数的相似度详解

最近在看《集体智慧编程》,相比其他机器学习的书籍,这本书有许多案例,更贴近实际,而且也很适合我们这种准备学习machinelearning的小白。

这本书我觉得不足之处在于,里面没有对算法的公式作讲解,而是直接用代码去实现,所以给想具体了解该算法带来了不便,所以想写几篇文章来做具体的说明。以下是第一篇,对皮尔逊相关系数作讲解,并采用了自己比较熟悉的java语言做实现。

皮尔逊数学公式如下,来自维基百科。

其中,E是数学期望,cov表示协方差,\sigma_X和\sigma_Y是标准差。

化简后得:

皮尔逊相似度计算的算法还是很简单的,实现起来也不难。只要求变量X、Y、乘积XY,X的平方,Y的平方的和。我的代码所使用的数据测试集来自集体智慧编程一书。代码如下:

package pearsonCorrelationScore;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
 * @author shenchao
 *
 *     皮尔逊相关度评价
 *
 *     以《集体智慧编程》一书用户评价相似度数据集做测试
 */
public class PearsonCorrelationScore {
	private Map<String, Map<String, double>> dataset = null;
	public PearsonCorrelationScore() {
		initDataSet();
	}
	/**
* 初始化数据集
*/
	private void initDataSet() {
		dataset = new HashMap<String, Map<String, double>>();
		// 初始化Lisa Rose 数据集
		Map<String, double> roseMap = new HashMap<String, double>();
		roseMap.put("Lady in the water", 2.5);
		roseMap.put("Snakes on a Plane", 3.5);
		roseMap.put("Just My Luck", 3.0);
		roseMap.put("Superman Returns", 3.5);
		roseMap.put("You, Me and Dupree", 2.5);
		roseMap.put("The Night Listener", 3.0);
		dataset.put("Lisa Rose", roseMap);
		// 初始化Jack Matthews 数据集
		Map<String, double> jackMap = new HashMap<String, double>();
		jackMap.put("Lady in the water", 3.0);
		jackMap.put("Snakes on a Plane", 4.0);
		jackMap.put("Superman Returns", 5.0);
		jackMap.put("You, Me and Dupree", 3.5);
		jackMap.put("The Night Listener", 3.0);
		dataset.put("Jack Matthews", jackMap);
		// 初始化Jack Matthews 数据集
		Map<String, double> geneMap = new HashMap<String, double>();
		geneMap.put("Lady in the water", 3.0);
		geneMap.put("Snakes on a Plane", 3.5);
		geneMap.put("Just My Luck", 1.5);
		geneMap.put("Superman Returns", 5.0);
		geneMap.put("You, Me and Dupree", 3.5);
		geneMap.put("The Night Listener", 3.0);
		dataset.put("Gene Seymour", geneMap);
	}
	public Map<String, Map<String, double>> getDataSet() {
		return dataset;
	}
	/**
* @param person1
*      name
* @param person2
*      name
* @return 皮尔逊相关度值
*/
	public double sim_pearson(String person1, String person2) {
		// 找出双方都评论过的电影,(皮尔逊算法要求)
		List<String> list = new ArrayList<String>();
		for (Entry<String, double> p1 : dataset.get(person1).entrySet()) {
			if (dataset.get(person2).containsKey(p1.getKey())) {
				list.add(p1.getKey());
			}
		}
		double sumX = 0.0;
		double sumY = 0.0;
		double sumX_Sq = 0.0;
		double sumY_Sq = 0.0;
		double sumXY = 0.0;
		int N = list.size();
		for (String name : list) {
			Map<String, double> p1Map = dataset.get(person1);
			Map<String, double> p2Map = dataset.get(person2);
			sumX += p1Map.get(name);
			sumY += p2Map.get(name);
			sumX_Sq += Math.pow(p1Map.get(name), 2);
			sumY_Sq += Math.pow(p2Map.get(name), 2);
			sumXY += p1Map.get(name) * p2Map.get(name);
		}
		double numerator = sumXY - sumX * sumY / N;
		double denominator = Math.sqrt((sumX_Sq - sumX * sumX / N)
		* (sumY_Sq - sumY * sumY / N));
		// 分母不能为0
		if (denominator == 0) {
			return 0;
		}
		return numerator / denominator;
	}
	public static void main(String[] args) {
		PearsonCorrelationScore pearsonCorrelationScore = new PearsonCorrelationScore();
		System.out.println(pearsonCorrelationScore.sim_pearson("Lisa Rose",
		"Jack Matthews"));
	}
}

将各个测试集的数据反映到二维坐标面中,如下所示:

上述程序求得的值实际上就为该直线的斜率。其斜率的区间在[-1,1]之间,其绝对值的大小反映了两者相似度大小,斜率越大,相似度越大,当相似度为1时,该直线为一条对角线。

总结

以上就是本文关于JAVA实现基于皮尔逊相关系数的相似度详解的全部内容,希望对大家有所帮助。如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • java算法实现红黑树完整代码示例

    红黑树 定义 红黑树(英语:Red–black tree)是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组. 红黑树的另一种定义是含有红黑链接并满足下列条件的二叉查找树: 红链接均为左链接:没有任何一个结点同时和两条红链接相连:该树是完美黑色平衡的,即任意空链接到根结点的路径上的黑链接数量相同. 满足这样定义的红黑树和相应的2-3树是一一对应的. 旋转 旋转又分为左旋和右旋.通常左旋操作用于将一个向右倾斜的红色链接旋转为向左链接.对比操作前后,可以看出,该操作

  • Java实现分解任意输入数的质因数算法示例

    本文实例讲述了Java实现分解任意输入数的质因数算法.分享给大家供大家参考,具体如下: 分解任意输入数的质因数: 质因数概念:任何一个合数都可以写成几个质数相乘的形式.其中每个质数都是这个合数的因数,叫做这个合数的分解质因数.分解质因数只针对合数. 例如:12 = 2x2x3  18 = 2 x 3 x 3等等 下面来讲解一下这个算法的思路:第一:我们首先写一个求素数的函数:第二;我们做一个分解质因数的函数,然后在其中引入素数函数来判断是否为素数: 下面给出代码(仅供参考): package j

  • 多模字符串匹配算法原理及Java实现代码

    多模字符串匹配算法在这里指的是在一个字符串中寻找多个模式字符字串的问题.一般来说,给出一个长字符串和很多短模式字符串,如何最快最省的求出哪些模式字符串出现在长字符串中是我们所要思考的.该算法广泛应用于关键字过滤.入侵检测.病毒检测.分词等等问题中.多模问题一般有Trie树,AC算法,WM算法等等. 背景 在做实际工作中,最简单也最常用的一种自然语言处理方法就是关键词匹配,例如我们要对n条文本进行过滤,那本身是一个过滤词表的,通常进行过滤的代码如下 for (String document : d

  • Java实现的猴子吃桃问题算法示例

    本文实例讲述了Java实现的猴子吃桃问题算法.分享给大家供大家参考,具体如下: 猴子吃桃问题 概述:猴子第一天摘下N个桃子,当时就吃了一半,还不过瘾,就又吃了一个:第二天又将剩下的桃子吃掉了一半,又多吃了一个:以后每天都吃前一天身下的一半零一个,到第n天再想吃的时候就只剩下一个桃子了,求第一天共摘了多少个桃子? 思路及演算步骤(求出共摘多少桃子的函数表达式): 离现在的天数作为变量 f(1) = 1 (剩下桃子的数目) f(2) = f(3) - (吃掉了一些) =   f(3) -(f(3)/

  • Java求10到100000之间的水仙花数算法示例

    本文实例讲述了Java求10到100000之间的水仙花数算法.分享给大家供大家参考,具体如下: 水仙花数: 概念:水仙花数是指一个 n 位数 ( n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身.(例如:1^3 + 5^3+ 3^3 = 153) 算法思路分析:这个算法我们分两个步骤来进行:第一:我们做一个求一个数的位数的函数:第二:我们通过调用此函数来进行10到100000之间素数的计算! 下面给出具体的代码(仅供参考): package javastudy; public class

  • java实现的各种排序算法代码示例

    折半插入排序 折半插入排序是对直接插入排序的简单改进.此处介绍的折半插入,其实就是通过不断地折半来快速确定第i个元素的 插入位置,这实际上是一种查找算法:折半查找.Java的Arrays类里的binarySearch()方法,就是折半查找的实现,用 于从指定数组中查找指定元素,前提是该数组已经处于有序状态.与直接插入排序的效果相同,只是更快了一些,因 为折半插入排序可以更快地确定第i个元素的插入位置 代码: package interview; /** * @author Administrat

  • java编程之递归算法总结

    1.何为递归 个人理解就是自己调用自己,直到满足一个条件结束自己调用自己的过程,这个就是递归.举一个通俗的点的例子: 假设你在一个电影院,你想知道自己坐在哪一排,但是前面人很多,你懒得去数了,于是你问前一排的人「你坐在哪一排?」,这样前面的人 (代号 A) 回答你以后,你就知道自己在哪一排了--只要把 A 的答案加一,就是自己所在的排了,不料 A 比你还懒,他也不想数,于是他也问他前面的人 B「你坐在哪一排?」,这样 A 可以用和你一模一样的步骤知道自己所在的排.然后 B 也如法炮制,直到他们这

  • Java常用加密算法实例总结

    本文实例总结了Java常用加密算法.分享给大家供大家参考,具体如下: 项目中第一次深入地了解到加密算法的使用,现第一阶段结束,将使用到的加密算法和大家分享一下: 首先还是先给大家普及一下常用加密算法的基础知识 基本的单向加密算法 BASE64 严格地说,属于编码格式,而非加密算法 MD5(Message Digest algorithm 5,信息摘要算法) SHA(Secure Hash Algorithm,安全散列算法) 复杂的加密算法 RSA(算法的名字以发明者的名字命名:Ron Rives

  • JAVA实现基于皮尔逊相关系数的相似度详解

    最近在看<集体智慧编程>,相比其他机器学习的书籍,这本书有许多案例,更贴近实际,而且也很适合我们这种准备学习machinelearning的小白. 这本书我觉得不足之处在于,里面没有对算法的公式作讲解,而是直接用代码去实现,所以给想具体了解该算法带来了不便,所以想写几篇文章来做具体的说明.以下是第一篇,对皮尔逊相关系数作讲解,并采用了自己比较熟悉的java语言做实现. 皮尔逊数学公式如下,来自维基百科. 其中,E是数学期望,cov表示协方差,\sigma_X和\sigma_Y是标准差. 化简后

  • 基于java中的PO VO DAO BO POJO(详解)

    一.PO:persistant object 持久对象,可以看成是与数据库中的表相映射的ava对象. 最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合PO中应该不包含任何对数据库的操作. 二.VO:value object值对象.通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已.但应是抽象出的业务对象可以和表对应也可以不这根据业务的需要 三.DAO:data access object 数据访问对象,此对象用于访问数据库.通常和PO结合使用,DAO中包含了各种

  • 基于java Files类和Paths类的用法(详解)

    Java7中文件IO发生了很大的变化,专门引入了很多新的类: import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.

  • JAVA基于Slack实现异常日志报警详解

    目录 一.功能介绍 二.Slack介绍 三.前期准备 slack配置 pom.xml 四.具体实现 1.实现Slack发送消息 SlackUtil 给Slack发消息工具类 向 webhook发起请求通过Urlencode SlackUtil测试 2.重写打印日志类 常见异常打日志处理 重写封装打印日志的方法 测试日志类 五.优化扩展想法 其他代码 一.功能介绍 在我们日常开发中,如果系统在线上环境上,发生异常,开发人员不能及时知晓来修复,可能会造成重大的损失,因此后端服务中加入异常报警的功能是

  • 使用Jacoco获取 Java 程序的代码执行覆盖率的步骤详解

    Jacoco是Java Code Coverage的缩写,顾名思义,它是获取Java代码执行覆盖率的一个工具,通常用它来获取单元测试覆盖率.它通过分析Java字节码来得到代码执行覆盖率,因此它还可以分析任何基于JVM的语言(如Croovy.Kotlin)的覆盖率.本文不讨论如何用Jacoco获取单元测试的代码覆盖率,而是从Jacoco的原理出发,介绍如何通过Jacoco获取SIT或者UAT的测试覆盖率.更准确来讲,是获取一个应用执行过的代码占总代码的比率.包括字节码指令覆盖率,分支覆盖率,圈复杂

  • Java获取用户IP属地模拟抖音详解

    目录 介绍 内置的三种查询算法 ip2region安装 介绍 细心的小伙伴可能会发现,抖音新上线了IP属地的功能,小伙伴在发表动态.发表评论以及聊天的时候,都会显示自己的IP属地信息 下面,我就来讲讲,Java中是如何获取IP属地的,主要分为以下几步 通过 HttpServletRequest 对象,获取用户的IP地址 通过 IP 地址,获取对应的省份.城市 首先需要写一个IP获取的工具类,因为每一次用户的Request请求,都会携带上请求的IP地址放到请求头中. public class Ip

  • 得物基于StarRocks的OLAP需求实践详解

    目录 1. 什么是 StarRocks 2. 系统架构 3. 存储架构 3.1 表的存储 4. 需求背景 案例一: 案例二: 5. 经验分享 6. 未来规划 1. 什么是 StarRocks 新一代极速全场景MPP数据库,可以用 StarRocks 来支持多种数据分析场景的极速分析: 架构简洁,采用了全面向量化引擎,并配备全新设计的 CBO 优化器,查询速度(尤其是多表关联查询): 很好地支持实时数据分析,并能实现对实时更新数据的高效查询, 还支持现代化物化视图,以进一步加速查询: 用户可以灵活

  • java开发主流定时任务解决方案全横评详解

    目录 引言 Crontab 目标定位 使用方式 实现原理 方案分析 Spring Task 目标定位 使用方式 实现原理 方案分析 ElasticJob 目标定位 使用方式 实现原理 方案分析 XXLJob 目标定位 使用方式 实现原理 方案分析 Serverless Job 目标定位 使用方式 实现原理 方案分析 总结 引言 定时任务作为一种按照约定时间执行预期逻辑的通用模式,在企业级开发中承载着丰富的业务场景,诸如后台定时同步数据生成报表,定时清理磁盘日志文件,定时扫描超时订单进行补偿回调等

  • 基于ScheduledExecutorService的两种方法(详解)

    开发中,往往遇到另起线程执行其他代码的情况,用java定时任务接口ScheduledExecutorService来实现. ScheduledExecutorService是基于线程池设计的定时任务类,每个调度任务都会分配到线程池中的一个线程去执行,也就是说,任务是并发执行,互不影响. 注意,只有当调度任务来的时候,ScheduledExecutorService才会真正启动一个线程,其余时间ScheduledExecutorService都是处于轮询任务的状态. 1.scheduleAtFix

  • 基于HashMap遍历和使用方法(详解)

    map的几种遍历方式: Map< String, String> map = new HashMap<>(); map.put("aa", "@sohu.com"); map.put("bb","@163.com"); map.put("cc", "@sina.com"); System.out.println("普通的遍历方法,通过Map.keySet

随机推荐