Constructive Covering Algorithm
来源:互联网 发布:算法工程师的年薪 编辑:程序博客网 时间:2024/06/08 18:39
以前看的一篇paper:A Three-Way Decisions Model Based on Constructive Covering Algorithm,按照自己的理解用java实现了论文的代码。
package ConstructiveCoveringAlgorithm;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class CCA {
public static int num_features=4;//样本属性值
//样本类,存储每个样本的数据
public class Sample
{
private double[] attributes=new double[num_features];//样本属性值
private double[] attr=new double[num_features+1];//升维后的样本属性,即该样本的覆盖中心
private int label;//样本标签
private int prediction;//经过LR得到的决策值
private double radium;//改样本的覆盖半径
Sample(double[] attributes,int label)
{
for(int i=0;i<this.attributes.length;i++)
{
this.attributes[i]=attributes[i];
this.attr[i]=attributes[i];
}
this.label=label;
this.prediction=label;
this.radium=0;
}
public double[] getAttributes()//获得样本的属性
{
return this.attr;
}
public void setAttributes(int i,double value)//设置样本对应的属性值
{
this.attr[i]=value;
}
public int getLabel()//获得样本的标签
{
return this.label;
}
public double getPrediction()//获得样本的决策值
{
return this.prediction;
}
public void setPrediction(int value)//设置样本的决策值
{
this.prediction=value;
}
public double getRadium()//获得样本的覆盖半径
{
return this.radium;
}
public void setRadium(double value)//设置样本的覆盖半径
{
this.radium=value;
}
}
public void load_datas(String path,ArrayList<Sample> sampleSet)
{
String line;//记录从数据集中读取的行数据
String[] s ;//存储从数据集中读出的行数据分割后的样本属性和标签
double[] attributes=new double[num_features];//存储每个样本的属性值
FileReader fr =null;
BufferedReader bufr = null ;
try
{
fr = new FileReader(path);
bufr= new BufferedReader(fr);
//读取训练样本
while((line = bufr.readLine())!=null)
{
s = line.split(",");
for(int i=0;i<num_features;i++)//将获得的样本属性值转为double类型
{
attributes[i]=Double.parseDouble(s[i]);
}
sampleSet.add(new Sample(attributes,Integer.parseInt(s[s.length-1].trim())));
}
}
catch(IOException e){}
finally
{
try
{
if(bufr!=null)
bufr.close();
}
catch(IOException e){
}
}
}
//将原始数据集划分为训练集和测试集
public void divid_dataSet(ArrayList<Sample> sampleSet,ArrayList<Sample> trainSet,ArrayList<Sample> testSet)
{
ArrayList<Sample> posSet = new ArrayList<Sample>();// 正样本集
ArrayList<Sample> negSet = new ArrayList<Sample>();// 负样本集
int pos = 0;// 正样本个数
int neg = 0;// 负样本个数
int train_instances = 0;// 训练样本个数
int train_instances_pos = 0;// 训练集中正 个数
int i=0;
Iterator<Sample> it_sampleSet= sampleSet.iterator();
Collections.shuffle(sampleSet);//打乱原始数据集,重新随机排列
while(it_sampleSet.hasNext())//迭代遍历原始样本集,计算其中正,负样本数目
{
Sample s=it_sampleSet.next();
if(s.getLabel()==1)
{
posSet.add(s);//标签为1的样本加入正样本集
pos++;
}
else
{
negSet.add(s);//标签为0的样本加入负样本集
neg++;
}
}
train_instances =(int)(sampleSet.size()*0.8);//取原始数据集的80%作为训练集
train_instances_pos = (int)(train_instances * ((pos*(1.0)) / (pos + neg)));//采用分层抽样,获取训练集中相应的正样本数
i=0;
Iterator<Sample> it_posSet= posSet.iterator();
while(it_posSet.hasNext())//迭代遍历正样本集
{
Sample s= it_posSet.next();
if (i< train_instances_pos) {// 选择正样本加入训练集
trainSet.add(s);
i++;
}
else// 选择正样本加入测试集
{
testSet.add(s);
}
}
i=0;
Iterator<Sample> it_negSet= negSet.iterator();
while(it_negSet.hasNext())//迭代遍历负样本集
{
Sample s= it_negSet.next();
if (i < train_instances - train_instances_pos) {// 选择负样本加入训练集
trainSet.add(s);
i++;
}
else// 选择负样本加入测试集
{
testSet.add(s);
}
}
}
//计算两个样本的欧式距离
public double distance(double[] attr1,double[] attr2)
{
double distance=0;
for(int i=0;i<attr1.length;i++)
{
distance +=Math.pow(attr1[i]-attr2[i], 2);
}
return Math.pow(distance, 0.5);
}
//对样本的每一个属性进行归一化
public void normalization(ArrayList<Sample> sampleSet)
{
int i;
Sample s;
double[][] max_min=new double[num_features][2];//每一行存储所有样本对应某一属性的最大值和最小值
double max=-999,min=999,temp=0,value=0;
for(i=0;i<num_features;i++)//找出所有样本对应4个属性的最大值和最小值
{
max=-999;
min=999;
temp=0;
Iterator<Sample> it_sampleSet=sampleSet.iterator();
while(it_sampleSet.hasNext())
{
s=it_sampleSet.next();
temp=s.getAttributes()[i];
if(temp>max)
max=temp;
if(temp<min)
min=temp;
}
max_min[i][0]=max;
max_min[i][1]=min;
}
Iterator<Sample> it_sampleSet=sampleSet.iterator();
while(it_sampleSet.hasNext())//归一化处理
{
s=it_sampleSet.next();
for(i=0;i<num_features;i++)
{
value=(s.getAttributes()[i]-max_min[i][1])/(max_min[i][0]-max_min[i][1]);
s.setAttributes(i, value);//设置样本属性归一化后的值
}
}
}
//将n(4)维样本投影到n+1(5)维空间,即升维。
public void projection(ArrayList<Sample> sampleSet)
{
double max=0,sum=0;
Sample s;
Iterator<Sample> it_set=sampleSet.iterator();
while(it_set.hasNext())//找出所有样本中n(4)个属性值平方和得最大值
{
sum=0;
s=it_set.next();
for(int i=0;i<s.getAttributes().length;i++)
{
sum +=Math.pow(s.getAttributes()[i], 2);
}
if(max<sum)
max=sum;
}
Iterator<Sample> it_set1=sampleSet.iterator();
while(it_set1.hasNext())//利用所有样本中4个属性值平方和得最大值减去每个样本的n(4)个属性平方和,得n+1(5)维
{
sum=0;
s=it_set1.next();
for(int i=0;i<s.getAttributes().length;i++)
{
sum +=Math.pow(s.getAttributes()[i], 2);
}
s.attr[4]=Math.pow(Math.pow(max, 2)-Math.pow(sum, 2),0.5);
}
}
//训练数据,形成覆盖
public void train(ArrayList<Sample> trainSet,ArrayList<ArrayList<Sample>> coverings)
{
Sample s1,s2;
double max_radium,min_radium,radium=0,distance=0;
ArrayList<Sample> covering_pos =coverings.get(0);//正样本的覆盖集合
ArrayList<Sample> covering_neg =coverings.get(1);//负样本的覆盖集合
Iterator<Sample> it_trainSet1=trainSet.iterator();
while(it_trainSet1.hasNext())//计算相应样本距离训练集中同类样本的最大距离,异类样本的最小距离,形成覆盖中心
{
s1=it_trainSet1.next();
max_radium=0;//同类样本的最大距离
min_radium=99999;//异类样本的最小距离
Iterator<Sample> it_trainSet2=trainSet.iterator();
while(it_trainSet2.hasNext())
{
s2=it_trainSet2.next();
distance=distance(s1.getAttributes(),s2.getAttributes());
if(s1.getLabel()==s2.getLabel())
{
if(max_radium<distance)
max_radium=distance;
}
else
{
if(min_radium>distance)
min_radium=distance;
}
}
if(min_radium<max_radium)//距离异类样本的最小距离小于距离同类样本的最大距离时
max_radium=min_radium-0.00001;
radium=(max_radium+min_radium)/2.0;//覆盖中心
s1.setRadium(radium);
if(s1.getLabel()==1)
covering_pos.add(s1);
else
covering_neg.add(s1);
}
coverings.set(0, covering_pos);
coverings.set(1, covering_neg);
}
//测试
public double[] test(ArrayList<Sample> testSet,ArrayList<Sample> trainSet,ArrayList<ArrayList<Sample>> coverings) throws IOException
{
double tp=0,fp=0,tn=0,fn=0;//分类结果混淆矩阵的4个值
double[] perform=new double[4];//存储分类结果混淆矩阵的4个值
Sample s,s_pos,s_neg,s_trainSample;
int flag_pos,flag_neg,flag=0,bd_flag=0;
double distance=0,min;
ArrayList<Sample> covering_pos =coverings.get(0);//训练形成的正样本覆盖集合
ArrayList<Sample> covering_neg =coverings.get(1);//训练形成的负样本覆盖集合
BufferedWriter bufw = new BufferedWriter(new FileWriter("./data/ROC.txt"));//将样本的决策值和真实标签写入文件,在matlab中画ROC
Iterator<Sample> it_testSet=testSet.iterator();
while(it_testSet.hasNext())
{
s=it_testSet.next();
flag_pos=0;
flag_neg=0;
Iterator<Sample> it_covering_pos=covering_pos.iterator();
while(it_covering_pos.hasNext())//计算测试样本与正覆盖集合中样本的距离,比较覆盖半径
{
s_pos=it_covering_pos.next();
distance=distance(s.getAttributes(),s_pos.getAttributes());
if(distance<s_pos.getRadium())//测试样本与正覆盖集合中某个样本的距离小于其覆盖半径
{
flag_pos=1;
break;
}
}
Iterator<Sample> it_covering_neg=covering_neg.iterator();
while(it_covering_neg.hasNext())//计算测试样本与负覆盖集合中样本的距离,比较覆盖半径
{
s_neg=it_covering_neg.next();
distance=distance(s.getAttributes(),s_neg.getAttributes());
if(distance<s_neg.getRadium())//测试样本与负覆盖集合中某个样本的距离小于其覆盖半径
{
flag_neg=1;
break;
}
}
if(flag_pos==1&&flag_neg==0)//测试样本与正覆盖集合中某样本的距离小于覆盖半径,并与负覆盖集合中所有样本的距离大于覆盖半径
flag=1;
else if(flag_pos==0&&flag_neg==1)//测试样本与正覆盖集合中所有样本的距离大于覆盖半径,并存在与负覆盖集合中某样本的距离大于覆盖半径
flag=0;
else//处于边界域
flag=2;
if(flag==2)//处于边界域的利用距覆盖中心最近原则进行划分
{
min=999;
Iterator<Sample> it_trainSet=trainSet.iterator();
while(it_trainSet.hasNext())
{
s_trainSample=it_trainSet.next();
distance=distance(s.getAttributes(),s_trainSample.getAttributes());
if(distance<min)
{
min=distance;
bd_flag=s_trainSample.getLabel();
}
}
flag=bd_flag;
}
bufw.write(s.getLabel()+" "+flag);
bufw.newLine();
s.setPrediction(flag);
if(s.getLabel()==1)
{
if(flag==1)
tp++;
else
fn++;
}
if(s.getLabel()==0)
{
if(flag==1)
fp++;
else
tn++;
}
}
bufw.close();
perform[0]=tp;
perform[1]=fp;
perform[2]=tn;
perform[3]=fn;
return perform;
}
public void evaluation( double tp,double fp,double tn,double fn)//算法性能表示
{
double accuracy = (tp + tn) / (tp + tn + fp + fn);
double specificity = tn / (fp + tn);
double precision = tp / (tp + fp);
double recall = tp / (tp + fn);
double sensitivity = tp / (tp + fn);
double mcc = (tp * tn - fp * fn)
/ Math.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn));
double f1 = (2 * precision * recall) / (precision + recall);
System.out
.println("*********************************Result*****************************************");
System.out
.println("TP=" + tp + ",FP=" + fp + ",TN=" + tn + ",FN=" + fn);
System.out.println("Accuracy=" + accuracy + ",Specificity="
+ specificity);
System.out.println("Precision=" + precision + ",Recall=" + recall);
System.out.println("Sensitivity=" + sensitivity + ",MCC=" + mcc);
System.out.println("F1-measure=" + f1);
System.out
.println("********************************************************************************");
}
public static void main(String[] args) throws IOException
{
CCA cca = new CCA();
ArrayList<Sample> sampleSet= new ArrayList<Sample>();//原始样本集
ArrayList<Sample> trainSet= new ArrayList<Sample>();//训练样本集
ArrayList<Sample> testSet= new ArrayList<Sample>();//测试样本集
ArrayList<ArrayList<Sample>> coverings=new ArrayList<ArrayList<Sample>>();
coverings.add(new ArrayList<Sample>());
coverings.add(new ArrayList<Sample>());
cca.load_datas("./data/dataSet.txt",sampleSet);//加载数据集
cca.normalization(sampleSet);//归一化
cca.projection(sampleSet);//投影,升维
cca.divid_dataSet(sampleSet,trainSet,testSet);//将原始数据集划分为训练集和测试集
cca.train(trainSet,coverings);//训练
double[] perform=cca.test(testSet,trainSet,coverings);//测试
cca.evaluation(perform[0],perform[1],perform[2],perform[3]);
}
}
- Constructive Covering Algorithm
- Covering
- sgu-250 Constructive Plan
- HDU6185-Covering
- Covering HDU
- Constructive Solid Geometry with the Stencil Buffer
- sgu250:Constructive Plan(单调性乱搞)
- Algorithm
- Algorithm
- algorithm
- algorithm
- algorithm
- algorithm
- algorithm
- Algorithm
- Algorithm
- algorithm
- Algorithm
- 【Maven+SSM】补充:写一个文件上传的请求
- mysql命令
- 连接数据库出现ORA-12518: TNS: 监听程序无法分发客户机连接错误
- KVstore 笔记【随时增】
- 网狐荣耀版棋牌游戏机器人的添加
- Constructive Covering Algorithm
- python机器学习-交叉验证(cross-vaildation)
- less学习(三)—关于变量
- Git(IV)分支与合并分支
- [ZZ]IT 民工男的 CS 课程记忆
- Matlab之初
- 对于文本溢出处理的方法
- SQL Server中,查询数据库中有多少个表,以及数据库其余类型数据统计查询
- 案例:使用XPath的的爬虫