基于距离的离群点检测算法

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

基于距离的离群点检测算法

08计算机二班侯宇铭张国勇易小倩一、概述:

这个算法是一个基于距离的异常点检测算法,算法以欧式距离为衡量标准,整个算法分三个部分。第四部分的改进是用了类似密度检测的思想,比较了之前步骤选出的怀疑离群点的三近邻,经过C++语言的实现,效果还不错。但是程序稍有漏洞,因此没有在这里体现。但是第四阶段算法的思想已经附在算法描述后面。

本文档附上测试的数据集的arff格式,excel格式,以及txt供程序使用的格式。三种格式的数据都是一样的。数据分布如下:

附上算法涉及的变量名称对应表:

二、算法描述:

(这里以数据集为两个相对集中的数据簇和若干离群点为例进行说明)

第一部分:找出两个质心

Step1: 遍历数据,将数据存入数组dot中该数据设为二维数据,有x,y两个属性。

Step2:设定遍历时的第一个和第二个数据为初始质心。设定两个变量longest_distance分别记录两个初始簇的最长的距离,设置dotcore1变量记录第一个簇的质心,dotcore2变量记录第二个簇的质心。

Step3:循环:当一个新的点p进入程序时,首先比较点p分别到点dotcore1的距离和到dotcore2的距离,选择距离较小的质心(这里假设选择了dotcore1),记该距离为distancep。比较distancep和第一个簇(因为选择了dotcore1)的longest_distance。若distanceplongest_distance,则使点p成为新的质心coredot1。这样循环下去,就可以找到两个簇的最终质心。

算法流程图:

进入阶段2

图.1 阶段1

第二部分:将所有的点归簇,并筛选一部分点

Step4: 开始第二次点的扫描:当一个新的点p进入程序时,首先比较点p分别到点dotcore1的距离和到dotcore2的距离,选择距离较小的质心。设置点数分簇记录:簇1的点数记录在变量dot_Dispatch1中,簇2的点数记录在变量dot_Dispatch0中。(假设选择了点dotcore1)则点p的序号记录在簇1的数组中。表示点p属于这个簇。若选择了dotcore2,以此类推。同时计算两个簇各个点分别到质心的距离的和。

Step5:在完成了分簇之后,我们对比各个点到质心的距离,若该点的距离大于当前的平均距离,那么将该点分别存入Suspt1和Suspt0数组中,以备以后的过程使用。

第三部分:将怀疑点到质心距离与距离均值的差,再与均值的方差作比较。

Step6: 分别求出两个簇的标准差variance1和variance0。

Step7: 将Suspt1中的各个点的距离减去距离的均值(先以怀疑点p1为例,其他点的处理办法一样),将p1与距离的差值与variance1*1.67(取置信区间为90%)相比较。若p1计算的差值大于variance1*1.67,则将其归入Suspt21和Suspt20数组中,以备以后过程进一步使用。

第一阶段

进入第三阶段

图.2 第二阶段

图.3 第三阶段

(改进设想)第四部分:将Suspt21和Suspt20中的点比较其三近邻,做最终的筛选

Step8: 将Suspt21和Suspt20中的点,(以p1点为例)p1计算与所有的点的距离,取距离值最小的三个,将这三个距离取平均值,得到均值p1avg。求p1avg与所属簇的平均距离的差值,再用这个差值与该簇的标准差*1.67相比,若大于,则确认为离群点。

三、程序实现代码(C++语言)

一、第一阶段:

//录入数据集

//第一步开始:

ifstream ifile ("test1.txt");

if (! ifile)

{ cout << "Error opening file";return 1; }

int i=0;

while(!ifile.eof())

{

ifile>>buffer[dotnum];

// cout<

dotnum++;

}

ifile.close();

int l=0;

for(int j=0;j

{

for(int k=0;k<2;k++)

{

dot[j][k%2]=buffer[l++];

if(j<=1)

dot_Core[j][k%2]=dot[j][k%2]; //把数据第一第二个点设为原始质心 }

}

/* for (int j=0;j

for (int k=0;k<=1;k++)

cout<

}*/

文件需是txt格式且坐标xy间用制表符分割;经过这一步录入后dot[j][0]为j点的x坐标,dot[j][0]为j点的Y坐标。

计算出质心:

//第一次正序扫描

for(int j=0;j

if(distance(j,0)

if(distance(j,0)>distance_Longest[0]){

distance_Longest[0]=distance(j,0);

dot_Core[0][0]=dot[j][0];

};

}

else{

if(distance(j,1)>distance_Longest[1]){

distance_Longest[1]=distance(j,1);

dot_Core[1][0]=dot[j][0];

dot_Core[1][1]=dot[j][1];

};

}

if(j==dotnum/6)

{

dot_Core2[0][0]=dot_Core[0][0];

dot_Core2[0][1]=dot_Core[0][1];

dot_Core2[1][0]=dot_Core[1][0];

dot_Core2[1][1]=dot_Core[1][1];

}

if(j==dotnum/3)

{

dot_Core4[0][0]=dot_Core[0][0];

dot_Core4[0][1]=dot_Core[0][1];

dot_Core4[1][0]=dot_Core[1][0];

dot_Core4[1][1]=dot_Core[1][1];

}

}

dot_Core[0][0]=((dot_Core[0][0]+dot_Core2[0][0])/2+dot_Core4[0][0])/2; dot_Core[0][1]=((dot_Core[0][1]+dot_Core2[0][1])/2+dot_Core4[0][1])/2; dot_Core[1][0]=((dot_Core[1][0]+dot_Core2[1][0])/2+dot_Core4[1][0])/2; dot_Core[1][1]=((dot_Core[1][1]+dot_Core2[1][1])/2+dot_Core4[1][1])/2; //第二次倒序扫描

for(int j=dotnum/2-1;j>=0;j--){

if(distance(j,0)

if(distance(j,0)>distance_Longest2[0]){

distance_Longest2[0]=distance(j,0);

dot_Core3[0][0]=dot[j][0];

dot_Core3[0][1]=dot[j][1];

};

}

else{

if(distance(j,1)>distance_Longest2[1]){

distance_Longest2[1]=distance(j,1);

相关文档
最新文档