关于weka中Instances的属性删除

最近这些天一直在用weka实现一个算法,也是从这次开始接触weka,刚上手难免有些磕磕绊绊,这次实现也是遇到了各种各样的问题,其中的一个就
和weka中的Instances有关,刚刚把程序跑起来了,因为数据比较多,没有个一天两天估计是跑不完了,趁这个空闲时间,把我遇到的问题及解决方法
记录下来,一是这样可能会帮助到其他人,还有就是也方便我自己以后查阅,毕竟俗话说得好,烂笔头胜过好记性。

首先,weka是从事数据挖掘相关研究的人一定会接触到的一个软件,这个软件由新西兰waikato大学编写,里面实现了种类繁多的算法,这里就不一一介绍,相信用过weka的人都知道我在说什么。

这篇随笔将会从三个具体的和属性选择相关的实际问题出发,给出具体的解决办法及代码。在讨论实际问题之前,先来说说为什么需要属性删除,也就是需求的问题。

一、为什么需要属性删除

我们知道,在做交叉验证的时候,在训练集上做过什么处理,这些处理必须原封不动地施加到测试集上,这样分类得到的结果才是可信的。

大 数据时代已经来临,我们经常会遇到那种实例多,维度高(属性多)的大数据,处理这样的数据时,从效果和效率两方面来考虑,我们都需要先对数据进行预处理,
最常见的一种预处理的方式就是属性选择,也就是我现在一直在做的东西,所谓属性选择,从字面上理解,就是从高维的数据中选择出一部分的属性,用这部分属性
代替属性总体,这样一来,很显然能够减少数据处理的时间,另外,如果算法选择得当,我们能得到更好的结果,比如说,分类的精度更高。

如果我 们用属性选择后的训练集构建了一个分类器,我们怎么测试这个分类器的好坏呢,还是要靠实验说话,在测试集上测试这个分类器的精度,前面说过,在分类的时候
在训练集上的处理必须原封不动的施加到测试集上,训练集上属性选择了,测试集也要属性选择,并且选出来的属性必须和训练集上选出来的属性完全一致,为了得
到属性选择后的测试集,显然,除了训练集上选择出来的属性,测试集上的其他属性都要删除。

二、三个具体的问题

为了更好的描述这几个问题,我们定义一些变量,这些变量在三个问题中通用。

train:训练集   test:测试集
trainInstance:在训练集上属性选择之后返回的训练集 testInstances:依据trainInstances在test上删除相应的属性返回的测试集
trainIndex:在训练集上属性选择之后返回的训练集的下标数组

1.属性选择算法返回的是trainInstances,这个时候,为了得到testInstances,可以使用下面这段代码


public static Instances delAttr(Instances model, Instances origin){
boolean flag = false;
ArrayList<Integer> al = new ArrayList<Integer>();
for(int q = 0; q < origin.numAttributes() - 1; q++){
String temp2 = origin.attribute(q).name();
for(int x = 0; x < model.numAttributes() - 1; x++){
String temp1 = model.attribute(x).name();
if(temp1.equals(temp2)){
flag = true;
break;
}
}
if(flag)
{
flag = false;
continue;
}
else
// dataCopy.deleteAttributeAt(q); //you can not do like this
al.add(new Integer(q));
}

for(int q = 0; q < al.size(); q++){
int deltemp = al.get(q) - q; // pay attention to this line
origin.deleteAttributeAt(deltemp);
}

return origin;
}

model相当于trainInstances,origin相当于test,返回的origin相当于testInstances.

上面这段代码的思想无非就是通过属性的名字把需要删除的属性的下标全部存放在一个ArrayList的数据结构中,然后根据这个ArrayList删除对应的属性,返回新构造的Instances.

注意上面我写的两行注释,因为你删除一条属性之后,排在这条属性之后的所有属性的index都是会变化的(-1),这就相当于你从String删除一个字符一样,知道这一点,你就知道为什么第二条注释对应的删除方法可以正常工作了。

注意:如果你用的数据集中有两个或多个属性的名字完全一样,这种方法会把拥有这个名字的所有属性都保留,但是,有可能你真正需要的只是其中一个。

2.直接使用1返回的结果交给分类器,往往会报错,其中的原因有点微妙,解释如下:

假 设train有四个属性,分别是{attr1,attr2,attr3,attr4},attr4是类标签,test也是这样
在train上属性选择,返回trainInstances{attr3,attr2,attr4},把trainInstances和test交给1,
返回的是testInstances{attr2,attr3,attr4},把testInstances交给分类器,报错,报错的原因是
trainInstances和testInstances的属性错位了.

这种情况下,我们需要交换两个属性的位置,下面这段代码解决了这个问题


public static Instances sort(Instances model, Instances process){
Attribute attr;
for(int i = 0; i < model.numAttributes()-1; i++){
for(int j = 0; j < process.numAttributes()-1; j++){
if(process.attribute(j).name().equals(model.attribute(i).name())){
if(j!=i){
attr = process.attribute(j);
process.insertAttributeAt(attr, i);
for(int k = 0; k < process.numInstances(); k++){
process.instance(k).setValue(i, process.instance(k).stringValue(j+1)); //pay attention to j+1
}
break;
}
}
}
}
for(int i = process.numAttributes() - 2; i > model.numAttributes()-2; i--){
process.deleteAttributeAt(i);;
}
return process;
}

model相当于trainInstances,process相当于1中返回的testInstances,2中返回的process就是能和trainInstances的每个属性对应起来的testInstances。

这段代码的思想是找到
process中每个属性在model中的对应位置,然后再process的对应位置插入这个属性,插入属性的时候需要把属性值复制过去。

注意因为我用到的数据都是nominal类型的,所以在复制属性值的时候选的是stringValue这个方法,如果是numeric或者其他的类型需要选择对应的方法,这个在weka的Instance类中可以找到。

3.属性选择算法返回的是下标数组trainIndex

3和1的不同之处在于省去了自己用属性名去匹配的这个步骤,也因此,即使数据集中有多个属性的名字完全一致,也没有影响,因为返回的是下标。

这种情况可以用下面的代码:


public static Instances delAttr(ArrayList<Integer> al, Instances inst){
for(int i = inst.numAttributes() - 1; i > -1; i--){ //delete from back to forward
if(!al.contains(i))
inst.deleteAttributeAt(i);
}

return inst;
}

注意:这段代码我是从后往前删的,这种删除方法不会出现问题,因为每次删除的都是需要删除的属性的最后一个,对前面需要删除的属性的下标不会有任何影响。

注意:拿到属性下标之后,先看看是不是排序过,没有排序的话,最好先排序一下,按从小到大的顺序排,这样虽然需要花费一点额外的时间,有时却能避免意想不到的错误,具体原因我说不清楚,但是我遇到过。

三、总结

很显然,第三种情况最简单,代码清晰,花费的时间也相对较少,所以在属性选择之后能够直接拿到下标数组最好,否则将拿到的结果转化成下标数组也可以。

关于weka中Instances的属性删除

时间: 2024-10-13 00:01:08

关于weka中Instances的属性删除的相关文章

jquary根据td中按钮的元素属性删除tr行(删选出想删除的行)

删除没有蓝色按钮的行. <html> <tr> <td>凉山彝族自治州分行</td> <td>管理网</td> <td>离行式ATM</td> <td class="text-center">MSTP</td> <td>西昌市西客站航天阳光</td> <td class="text-center">建设中<

删除一个Javascript对象中的一个属性

一个Javascript对象如下 var myObject = { "ircEvent": "PRIVMSG", "method": "newURI", "regex": "^http://.*" }; 想要达到的目的如下 var myObject = { "ircEvent": "PRIVMSG", "method": &qu

机器学习:weka中添加自己的分类和聚类算法

不管是实验室研究机器学习算法或是公司研发,都有需要自己改进算法的时候,下面就说说怎么在weka里增加改进的机器学习算法. 一 添加分类算法的流程 1 编写的分类器必须继承 Classifier或是Classifier的子类:下面用比较简单的zeroR举例说明: 2 复写接口 buildClassifier,其是主要的方法之一,功能是构造分类器,训练模型: 3 复写接口 classifyInstance,功能是预测一个标签的概率:或实现distributeForInstance,功能是对得到所有的

WEKA中的数据预处理

数据预处理包括数据的缺失值处理.标准化.规范化和离散化处理. 数据的缺失值处理:weka.filters.unsupervised.attribute.ReplaceMissingValues. 对于数值属性,用平均值代替缺失值,对于nominal属性,用它的mode(出现最多的值)来代替缺失值. 标准化(standardize):类weka.filters.unsupervised.attribute.Standardize.标准化给定数据集中所有数值属性的值到一个0均值和单位方差的正态分布.

Hibernate中的inverse属性

Inverse属性 一.Inverse是hibernate双向关系中的基本概念.inverse的真正作用就是指定由哪一方来维护之间的关联关系.当一方中指定了“inverse=false”(默认),那么那一方就有责任负责之间的关联关系,说白了就是hibernate如何生成Sql来维护关联的记录! Hibernate仅仅按照主控方对象的状态的变化来同步更新数据库.按照原来的映射文件,people.getAddresses().add(address),即主控方对象的状态发生了改变,因此数据库会跟着对

Andriod React Native 样式表中可用样式属性

写了这么多篇Android React Native的博文,基本上把复杂的东西都搞定了,接下来来看看一些轻松的东西,和布局有关,就是css样式,那么一个View可以设置哪些css样式呢,是和web中的css样式完全一样呢,还是有所不同呢?其实你只要在样式表中书写一个不存在的样式,就会报一大堆错,提示你该样式不存在,然后提供所有可用的样式给你,如图 下面的样式就是样式表中所有可用的属性. "alignItems", "alignSelf", "backfac

C#中gridView常用属性和技巧介绍

1.隐藏最上面的GroupPanel gridView1.OptionsView.ShowGroupPanel=false; 2.得到当前选定记录某字段的值 sValue=Table.Rows[gridView1.FocusedRowHandle][FieldName].ToString(); 3.数据只读 gridView1.OptionsBehavior.Editable=false; 4.不显示MasterDetailView gridView1.OptionsDetail.EnableM

Meta标签中的apple-mobile-web-app属性及含义

一.Meta标签中的apple-mobile-web-app-capable属性及含义 这meta的作用就是删除默认的苹果工具栏和菜单栏. content有两个值”yes”和”no”,当我们需要显示工具栏和菜单栏时,这个行meta就不用加了,默认就是显示. 二.Meta标签中的apple-mobile-web-app-status-bar-style属性及含义 “apple-mobile-web-app-status-bar-style”作用是控制状态栏显示样式 (默认样) 具体效果如下: st

js中的内部属性与delete操作符

本文正式地址:http://www.xiabingbao.com/javascript/2015/08/03/javascript-delete-configurable 在讲解Configurable之前,我们首先来看一道面试题: a = 1; console.log( window.a ); // 1 console.log( delete window.a ); // false console.log( window.a ); // 1 var b = 2; console.log( w