Java实现 基于密度的局部离群点检测------lof算法

算法概述

算法:基于密度的局部离群点检测(lof算法)

输入:样本集合D,正整数K(用于计算第K距离)

输出:各样本点的局部离群点因子

过程:

  1. 计算每个对象与其他对象的欧几里得距离
  2. 对欧几里得距离进行排序,计算第k距离以及第K领域
  3. 计算每个对象的可达密度
  4. 计算每个对象的局部离群点因子
  5. 对每个点的局部离群点因子进行排序,输出。

算法Java源码

本算法包括两个类文件,一个是:DataNode,另一个是:OutlierNodeDetect

DataNode的源码

package com.bigdata.ml.outlier;

import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author zouzhongfan
 *
 */
public class DataNode {
	private String nodeName; // 样本点名
	private double[] dimensioin; // 样本点的维度
	private double kDistance; // k-距离
	private List<DataNode> kNeighbor = new ArrayList<DataNode>();// k-领域
	private double distance; // 到给定点的欧几里得距离
	private double reachDensity;// 可达密度
	private double reachDis;// 可达距离

	private double lof;// 局部离群因子

	public DataNode() {

	}

	public DataNode(String nodeName, double[] dimensioin) {
		this.nodeName = nodeName;
		this.dimensioin = dimensioin;
	}

	public String getNodeName() {
		return nodeName;
	}

	public void setNodeName(String nodeName) {
		this.nodeName = nodeName;
	}

	public double[] getDimensioin() {
		return dimensioin;
	}

	public void setDimensioin(double[] dimensioin) {
		this.dimensioin = dimensioin;
	}

	public double getkDistance() {
		return kDistance;
	}

	public void setkDistance(double kDistance) {
		this.kDistance = kDistance;
	}

	public List<DataNode> getkNeighbor() {
		return kNeighbor;
	}

	public void setkNeighbor(List<DataNode> kNeighbor) {
		this.kNeighbor = kNeighbor;
	}

	public double getDistance() {
		return distance;
	}

	public void setDistance(double distance) {
		this.distance = distance;
	}

	public double getReachDensity() {
		return reachDensity;
	}

	public void setReachDensity(double reachDensity) {
		this.reachDensity = reachDensity;
	}

	public double getReachDis() {
		return reachDis;
	}

	public void setReachDis(double reachDis) {
		this.reachDis = reachDis;
	}

	public double getLof() {
		return lof;
	}

	public void setLof(double lof) {
		this.lof = lof;
	}

}

OutlierNodeDetect.java的源码如下:

package com.bigdata.ml.outlier;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * 离群点分析
 *
 * @author zouzhongfan
 * 算法:基于密度的局部离群点检测(lof算法)
 * 输入:样本集合D,正整数K(用于计算第K距离)
 * 输出:各样本点的局部离群点因子
 * 过程:
 *  1)计算每个对象与其他对象的欧几里得距离
 *  2)对欧几里得距离进行排序,计算第k距离以及第K领域
 *  3)计算每个对象的可达密度
 *  4)计算每个对象的局部离群点因子
 *  5)对每个点的局部离群点因子进行排序,输出。
 **/
public class OutlierNodeDetect {
	private static int INT_K = 5;//正整数K

	// 1.找到给定点与其他点的欧几里得距离
	// 2.对欧几里得距离进行排序,找到前5位的点,并同时记下k距离
	// 3.计算每个点的可达密度
	// 4.计算每个点的局部离群点因子
	// 5.对每个点的局部离群点因子进行排序,输出。
	public List<DataNode> getOutlierNode(List<DataNode> allNodes) {

		List<DataNode> kdAndKnList = getKDAndKN(allNodes);
		calReachDis(kdAndKnList);
		calReachDensity(kdAndKnList);
		calLof(kdAndKnList);
		//降序排序
		Collections.sort(kdAndKnList, new LofComparator());

		return kdAndKnList;
	}

	/**
	 * 计算每个点的局部离群点因子
	 * @param kdAndKnList
	 */
	private void calLof(List<DataNode> kdAndKnList) {
		for (DataNode node : kdAndKnList) {
			List<DataNode> tempNodes = node.getkNeighbor();
			double sum = 0.0;
			for (DataNode tempNode : tempNodes) {
				double rd = getRD(tempNode.getNodeName(), kdAndKnList);
				sum = rd / node.getReachDensity() + sum;
			}
			sum = sum / (double) INT_K;
			node.setLof(sum);
		}
	}

	/**
	 * 计算每个点的可达距离
	 * @param kdAndKnList
	 */
	private void calReachDensity(List<DataNode> kdAndKnList) {
		for (DataNode node : kdAndKnList) {
			List<DataNode> tempNodes = node.getkNeighbor();
			double sum = 0.0;
			double rd = 0.0;
			for (DataNode tempNode : tempNodes) {
				sum = tempNode.getReachDis() + sum;
			}
			rd = (double) INT_K / sum;
			node.setReachDensity(rd);
		}
	}

	/**
	 * 计算每个点的可达密度,reachdis(p,o)=max{ k-distance(o),d(p,o)}
	 * @param kdAndKnList
	 */
	private void calReachDis(List<DataNode> kdAndKnList) {
		for (DataNode node : kdAndKnList) {
			List<DataNode> tempNodes = node.getkNeighbor();
			for (DataNode tempNode : tempNodes) {
				//获取tempNode点的k-距离
				double kDis = getKDis(tempNode.getNodeName(), kdAndKnList);
				//reachdis(p,o)=max{ k-distance(o),d(p,o)}
				if (kDis < tempNode.getDistance()) {
					tempNode.setReachDis(tempNode.getDistance());
				} else {
					tempNode.setReachDis(kDis);
				}
			}
		}
	}

	/**
	 * 获取某个点的k-距离(kDistance)
	 * @param nodeName
	 * @param nodeList
	 * @return
	 */
	private double getKDis(String nodeName, List<DataNode> nodeList) {
		double kDis = 0;
		for (DataNode node : nodeList) {
			if (nodeName.trim().equals(node.getNodeName().trim())) {
				kDis = node.getkDistance();
				break;
			}
		}
		return kDis;

	}

	/**
	 * 获取某个点的可达距离
	 * @param nodeName
	 * @param nodeList
	 * @return
	 */
	private double getRD(String nodeName, List<DataNode> nodeList) {
		double kDis = 0;
		for (DataNode node : nodeList) {
			if (nodeName.trim().equals(node.getNodeName().trim())) {
				kDis = node.getReachDensity();
				break;
			}
		}
		return kDis;

	}

	/**
	 * 计算给定点NodeA与其他点NodeB的欧几里得距离(distance),并找到NodeA点的前5位NodeB,然后记录到NodeA的k-领域(kNeighbor)变量。
	 * 同时找到NodeA的k距离,然后记录到NodeA的k-距离(kDistance)变量中。
	 * 处理步骤如下:
	 * 1,计算给定点NodeA与其他点NodeB的欧几里得距离,并记录在NodeB点的distance变量中。
	 * 2,对所有NodeB点中的distance进行升序排序。
	 * 3,找到NodeB点的前5位的欧几里得距离点,并记录到到NodeA的kNeighbor变量中。
	 * 4,找到NodeB点的第5位距离,并记录到NodeA点的kDistance变量中。
	 * @param allNodes
	 * @return List<Node>
	 */
	private List<DataNode> getKDAndKN(List<DataNode> allNodes) {
		List<DataNode> kdAndKnList = new ArrayList<DataNode>();
		for (int i = 0; i < allNodes.size(); i++) {
			List<DataNode> tempNodeList = new ArrayList<DataNode>();
			DataNode nodeA = new DataNode(allNodes.get(i).getNodeName(), allNodes
					.get(i).getDimensioin());
			//1,找到给定点NodeA与其他点NodeB的欧几里得距离,并记录在NodeB点的distance变量中。
			for (int j = 0; j < allNodes.size(); j++) {
				DataNode nodeB = new DataNode(allNodes.get(j).getNodeName(), allNodes
						.get(j).getDimensioin());
				//计算NodeA与NodeB的欧几里得距离(distance)
				double tempDis = getDis(nodeA, nodeB);
				nodeB.setDistance(tempDis);
				tempNodeList.add(nodeB);
			}

			//2,对所有NodeB点中的欧几里得距离(distance)进行升序排序。
			Collections.sort(tempNodeList, new DistComparator());
			for (int k = 1; k < INT_K; k++) {
				//3,找到NodeB点的前5位的欧几里得距离点,并记录到到NodeA的kNeighbor变量中。
				nodeA.getkNeighbor().add(tempNodeList.get(k));
				if (k == INT_K - 1) {
					//4,找到NodeB点的第5位距离,并记录到NodeA点的kDistance变量中。
					nodeA.setkDistance(tempNodeList.get(k).getDistance());
				}
			}
			kdAndKnList.add(nodeA);
		}

		return kdAndKnList;
	}

	/**
	 * 计算给定点A与其他点B之间的欧几里得距离。
	 * 欧氏距离的公式:
	 * d=sqrt( ∑(xi1-xi2)^2 ) 这里i=1,2..n
	 * xi1表示第一个点的第i维坐标,xi2表示第二个点的第i维坐标
	 * n维欧氏空间是一个点集,它的每个点可以表示为(x(1),x(2),...x(n)),
	 * 其中x(i)(i=1,2...n)是实数,称为x的第i个坐标,两个点x和y=(y(1),y(2)...y(n))之间的距离d(x,y)定义为上面的公式.
	 * @param A
	 * @param B
	 * @return
	 */
	private double getDis(DataNode A, DataNode B) {
		double dis = 0.0;
		double[] dimA = A.getDimensioin();
		double[] dimB = B.getDimensioin();
		if (dimA.length == dimB.length) {
			for (int i = 0; i < dimA.length; i++) {
				double temp = Math.pow(dimA[i] - dimB[i], 2);
				dis = dis + temp;
			}
			dis = Math.pow(dis, 0.5);
		}
		return dis;
	}

	/**
	 * 升序排序
	 * @author zouzhongfan
	 *
	 */
	class DistComparator implements Comparator<DataNode> {
		public int compare(DataNode A, DataNode B) {
			//return A.getDistance() - B.getDistance() < 0 ? -1 : 1;
			if((A.getDistance()-B.getDistance())<0)
                return -1;
            else if((A.getDistance()-B.getDistance())>0)
                return 1;
            else return 0;
		}
	}

	/**
	 * 降序排序
	 * @author zouzhongfan
	 *
	 */
	class LofComparator implements Comparator<DataNode> {
		public int compare(DataNode A, DataNode B) {
			//return A.getLof() - B.getLof() < 0 ? 1 : -1;
			if((A.getLof()-B.getLof())<0)
                return 1;
            else if((A.getLof()-B.getLof())>0)
                return -1;
            else return 0;
		}
	}

	public static void main(String[] args) {

		java.text.DecimalFormat   df   =new   java.text.DecimalFormat("#.####");  

		ArrayList<DataNode> dpoints = new ArrayList<DataNode>();

		double[] a = { 2, 3 };
		double[] b = { 2, 4 };
		double[] c = { 1, 4 };
		double[] d = { 1, 3 };
		double[] e = { 2, 2 };
		double[] f = { 3, 2 };

		double[] g = { 8, 7 };
		double[] h = { 8, 6 };
		double[] i = { 7, 7 };
		double[] j = { 7, 6 };
		double[] k = { 8, 5 };

		double[] l = { 100, 2 };// 孤立点

		double[] m = { 8, 20 };
		double[] n = { 8, 19 };
		double[] o = { 7, 18 };
		double[] p = { 7, 17 };
		double[] q = { 8, 21 };

		dpoints.add(new DataNode("a", a));
		dpoints.add(new DataNode("b", b));
		dpoints.add(new DataNode("c", c));
		dpoints.add(new DataNode("d", d));
		dpoints.add(new DataNode("e", e));
		dpoints.add(new DataNode("f", f));

		dpoints.add(new DataNode("g", g));
		dpoints.add(new DataNode("h", h));
		dpoints.add(new DataNode("i", i));
		dpoints.add(new DataNode("j", j));
		dpoints.add(new DataNode("k", k));

		dpoints.add(new DataNode("l", l));

		dpoints.add(new DataNode("m", m));
		dpoints.add(new DataNode("n", n));
		dpoints.add(new DataNode("o", o));
		dpoints.add(new DataNode("p", p));
		dpoints.add(new DataNode("q", q));

		OutlierNodeDetect lof = new OutlierNodeDetect();

		List<DataNode> nodeList = lof.getOutlierNode(dpoints);

		for (DataNode node : nodeList) {
			System.out.println(node.getNodeName() + "  " + df.format(node.getLof()));
		}

	}
}

测试

测试结果如下:

l  39.3094
n  0.8867
h  0.8626
j  0.8626
f  0.8589
a  0.8498
d  0.8498
m  0.8176
o  0.8176
g  0.7837
b  0.7694
c  0.7694
i  0.7518
k  0.7518
e  0.7485
p  0.7459
q  0.7459

到此这篇关于Java实现 基于密度的局部离群点检测------lof算法的文章就介绍到这了,更多相关Java实现离群点检测------lof算法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java网络编程TCP实现聊天功能

    网络编程TCP实现聊天的前提还需要掌握IO流,话不多说,直接上代码! 客户端: package com.kuang.lesson02; import java.io.IOException; import java.io.OutputStream; import java.net.InetAddress; import java.net.Socket; //客户端 public class TcpClientDemo01 { public static void main(String[] ar

  • Java实现pdf转图片案例

    工程加入依赖: <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.15</version> </dependency> <dependency> <groupId>org.apache.pdfbox</groupId> <artif

  • Java并发编程必备之Future机制

    前言 Java 5在concurrency包中引入了java.util.concurrent.Callable 接口,它和Runnable接口很相似,但它可以返回一个对象或者抛出一个异常. Callable接口使用泛型去定义它的返回类型.Executors类提供了一些有用的方法在线程池中执行Callable内的任务.由于Callable任务是并行的,我们必须等待它返回的结果.而线程是属于异步计算模型,所以不可能直接从别的线程中得到函数返回值. java.util.concurrent.Futur

  • 详解JavaScript闭包问题

    闭包是纯函数式编程语言的传统特性之一.通过将闭包视为核心语言构件的组成部分,JavaScript语言展示了其与函数式编程语言的紧密联系.由于能够简化复杂的操作,闭包在主流JavaScript库以及高水平产品代码中日益流行起来. 一.变量的作用域 在介绍闭包之前,我们先理解JavaScript的变量作用域.变量的作用域分为两种:全局变量和局部变量. 1.全局变量 var n = 999; //全局变量 function f1() { a = 100; //在这里a也是全局变量 alert(n);

  • 每日六道java新手入门面试题,通往自由的道路--JVM

    目录 1. JVM是如何判断对象是否可回收 2. 你知道有什么垃圾回收的常见算法吗? 3. 你知道有什么垃圾收集器吗? 4. 那你知道什么时候才会触发Full GC 5. JVM中四种引用你有了解过吗? 6. 说说你知道的几种主要的JVM参数 1.堆设置 2.收集器设置 3.并行收集器设置 4.并发收集器设置 5.JVM 调优的参数 总结 1. JVM是如何判断对象是否可回收 垃圾收集器在做垃圾回收的时候,首先需要判断一个对象是存活状态还是死亡状态,死亡的对象将会被标识为垃圾数据并等待收集器进行

  • Java网络编程TCP实现文件上传功能

    本文实例为大家分享了Java网络编程TCP实现文件上传的具体代码,供大家参考,具体内容如下 上一篇博客,用网络编程TCP 实现聊天,这次实现文件上传. 客户端: package com.kuang.lesson02; import java.io.*; import java.net.InetAddress; import java.net.Socket; //客户端 public class TcpClientDemo2 { public static void main(String[] a

  • Java实现 基于密度的局部离群点检测------lof算法

    算法概述 算法:基于密度的局部离群点检测(lof算法) 输入:样本集合D,正整数K(用于计算第K距离) 输出:各样本点的局部离群点因子 过程: 计算每个对象与其他对象的欧几里得距离 对欧几里得距离进行排序,计算第k距离以及第K领域 计算每个对象的可达密度 计算每个对象的局部离群点因子 对每个点的局部离群点因子进行排序,输出. 算法Java源码 本算法包括两个类文件,一个是:DataNode,另一个是:OutlierNodeDetect DataNode的源码 package com.bigdat

  • Java语言基于无向有权图实现克鲁斯卡尔算法代码示例

    所谓有权图,就是图中的每一条边上都会有相应的一个或一组值.通常情况下,这个值只是一个数字 如:在交通运输网中,边上的权值可能表示的是路程,也可能表示的是运输费用(显然二者都是数字).不过,边上的权值也有可能是其它东西,比如说是一个字符串,甚至是一个更加复杂的数据包,里面集合了更多的数据 克鲁斯卡尔算法的核心思想是:在带权连通图中,不断地在边集合中找到最小的边,如果该边满足得到最小生成树的条件,就将其构造,直到最后得到一颗最小生成树. 克鲁斯卡尔算法的执行步骤: 第一步:在带权连通图中,将边的权值

  • PHP局部异常因子算法-Local Outlier Factor(LOF)算法的具体实现解析

    这两天在完善自己系统的过程中要实现一个查找异常的功能,于是在朋友的指点下学习并实现了异常点查找的一个基本算法"局部异常因子算法-Local Outlier Factor(LOF)算法". 首先,找相关说明看看这是个什么东西吧. 我参考了这一篇文章: 异常点/离群点检测算法--LOF 大致明白了lof算法是在讲什么,我的理解还有很多不完善的地方,不过还是作为一个初学者写出来供大家批评指正. 根据我的理解大致描述如下: 1. k-distance,点p的第k距离就是距离点p第k远的那个点的

  • Java应用服务器之tomcat会话复制集群配置的示例详解

    会话是识别用户,跟踪用户访问行为的一个手段,通过cookie(存在客户端)或session(存在服务端)来判断本次请求是那个客户端发送过来:常用的会话保持有绑定会话,就是前边我们聊的在代理上通过算法或通过给客户端响应首部加cookie这种方式来保持同一cookie或同一ip地址的请求始终发送到同一后端server进行响应:但是这样的会话绑定的方式存在一个问题,就是当后端某一server宕机,那么之前上面的所有会话信息将消失,那么后续的客户端来请求,代理是否要把请求调度到后端宕机的server呢?

  • 基于Docker部署Tomcat集群、 Nginx负载均衡的问题小结

    写在前面 看完Dokcer相关的书籍,正好有个项目要这样搞,所以自己练习一下. 当作一百世一样.这里的道理很明白:我思故我在,既然我存在,就不能装作不存在.无论如何,我要为自己负起责任.--王小波<三十而立> 结构图: 这里仅作为一种学习,一般这种负载的话,Nginx是放到主机侧的, JavaWeb(Tomcat)应用放到容器里. 效果 新建文件夹. D=uag;mkdir $D;cd $D;mkdir uag_nginx uag_tomcat8; ls uag_nginx uag_tomca

  • java实现基于SMTP发送邮件的方法

    本文实例讲述了java实现基于SMTP发送邮件的方法.分享给大家供大家参考.具体实现方法如下: import java.util.Date; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Tra

  • Java中基于maven实现zxing二维码功能

    maven所需jar <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.0.0</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifac

  • Java Web基于Session的登录实现方法

    本文实例讲述了Java Web基于Session的登录实现方法.分享给大家供大家参考,具体如下: package cn.com.login; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpSer

  • 基于BootStrap实现局部刷新分页实例代码

    在之前的工作中我用的分页有很多,一直不牢固,所以自己用起来也不是很顺手,这是一个局部刷新的分页,我试了很多,本想用mvcPager来做局部刷新,但是考虑到成本太高,放弃了,先来总结一下基于bootstrap的分页吧,便于自己以后使用 开源地址 https://github.com/lyonlai/bootstrap-paginator 首先引用 Jquery bootstrap.min.js bootstrap-paginator.min.js 控制器代码 [AuthorizationCodeA

  • java实现基于SGIP协议开发联通短信的方法

    本文实例讲述了java实现基于SGIP协议开发联通短信的方法.分享给大家供大家参考.具体如下: 近段时间,由于公司的业务需要,开发出了联通短信.此文章的编写也是根据网上的一些示例来完成的.闲话少说,下面来看代码:(运行此程序的时候需要导入华为的开发包,此包可以到网上下载) 下行: public class Mt { private static String SPNumber = "**********"; //接入号码 private static String ChargeNumb

随机推荐