上篇博客主要讲解了Weka静态数据文件格式ARFF,本博客讲解以下Weka运行时数据的存储对象Instances和Instance。
Instances对象实例化后,就存储了所有数据,同时也附带了很多数据属性,简单来说,你可以认为Instances就像一个电子表格,存储了你所加载的数据。
Instances实例化有很多方式,在这里我介绍三种方式:
①通过文件直接加载数据
Instances(java.io.Reader reader)
Reads an ARFF file from a reader, and assigns a weight of one to each instance.
Instances(java.io.Reader reader, int capacity)
Deprecated. instead of using this method in conjunction with the readInstance(Reader) method, one should use the ArffLoader or DataSource class instead.
可以看Weka API中Instances的两种构造方法,直接传入一个Java Reader 对象即可,当然,这里文件类型可以不是ARFF,weka内部会做转换。
import weka.core.Instances;
import java.io.BufferedReader;
import java.io.FileReader;
...
Instances data = new Instances( new BufferedReader(
new FileReader("/Path/data.arff")));
②使用DataSource从文件中加载数据
最新的API提供了一种新的方式加载数据,即DataSource类
import weka.core.converters.ConverterUtils.DataSource;
...
DataSource source = new DataSource("/some/where/data.arff");
Instances data = source.getDataSet();
通过使用DataSource类,我们就可以直接从文件名直接创建Instances对象,而不用再使用Java IO类。
③从数据库实例化Instances对象
从数据库加载数据比较复杂,首先应该进行合适的数据库配置,具体的过程资料很多,不在赘述,直接贴出来代码:
import weka.core.Instances;
import weka.experiment.InstanceQuery;
...
InstanceQuery query = new InstanceQuery();
query.setUsername("root");
query.setPassword("123456");
query.setQuery("select * from mydatabase");
Instances data = query.retrieveInstances();
④创建一个空的Instances对象
以上方式讲的都是创建非空Instances,如果想创建一个空白的Instances怎么办呢?
最简单的方法就是从另外一个非空Instances生成,当然这样会继承非空Instances中的所有数据属性,示例如下:
DataSource source = new DataSource("/some/where/data.arff");
Instances A = source.getDataSet();
Instances blank = new Instances(A,0)
这里的参数0指的是新的Instances容量初始化为0,自然就创建了一个空白的Instances。
还有一种方法是直接创建空白的Instances,由于Instances中有成员变量Attribute,即数据集每列的属性信息,因此必须要先创建Attribute才可以初始化一个Instances对象,大家可以看Instances的构造方法:
Instances(java.lang.String name, java.util.ArrayList attInfo, int capacity)
Creates an empty set of instances.
第二个参数就是传入的Instances属性的数组。由于Attribute还没有讲解,下次博客会剖析Attribute
ArrayList atts = new ArrayList();
for(count = 0; count<10; count++){
atts.add(new Attribute(String.valueOf(count + 1)));
}
Instances df = new Instances("Data", atts, 0);
df.setClassIndex(df.numAttributes() - 1);
Instances创建完毕后,还需要进行一些其他设置,一个最常见的设置就是指定CLASS列的编号,由于一般类别都是标号在最后一列,你可以使用下列代码来标注class:
data.setClassIndex(data.numAttributes() - 1);
- Instance剖析
讲解完了Instances后,下面讲解下Instance,很明显这两个对象关系很大,其实Instance就是相当于Instances中的一条数据,就内部实现上来说,Instance其实就是借助Instances实现的。
那么我们怎么样创建一条Instance呢?
首先看官方API上的举例:
/ Create empty instance with three attribute values
Instance inst = new DenseInstance(3);
// Set instance's values for the attributes "length", "weight", and "position"
inst.setValue(length, 5.3);
inst.setValue(weight, 300);
inst.setValue(position, "first");
// Set instance's dataset to be the dataset "race"
inst.setDataset(race);
其实思路比较简单,就是要先创建一个指定容量的Instance,然后为其指定属性,最后非常关键的是,inst.setDataset(race); ,没有这一句会报错!!!
具体在实现上,Instance必须依附于某个Instances存在,这可能也困扰了很多人。
在程序中,我的实现如下:
再上面生成空Instances的基础上,再实现Instance创建。
ArrayList atts = new ArrayList();
for(count = 0; count<10; count++){
atts.add(new Attribute(String.valueOf(count + 1)));
}
Instances df = new Instances("Data", atts, 0);
Instances df = new Instances("predictData", atts, 0);
df.setClassIndex(df.numAttributes() - 1);
Instance sample = new DenseInstance(1.0, temp);
sample.setDataset(df);
以上代码针对Weka API 的3.7版本,3.7版本以下并没有DenseInstance类。