在用Java使用weka时,我们需要weka支持的数据格式,weka官网上给出的大多是从arff文件中导入数据。从数据库中生成对系统环境要求也较高。因此本文介绍了如何通过普通的Java对象生成weka支持的Instance对象,并保存到arff文件中。
首先创建一个Instances对象,为Instances对象设置属性(@Attribute),然后从对象创建Instance加入到Instances中,如果需要保存,可以直接将Instances对象保存为arff格式的文件。
在介绍attribute之前首先简述一下arff的文件格式。官网上示例如下:
% 1. Title: Iris Plants Database
%
% 2. Sources:
% (a) Creator: R.A. Fisher
% (b) Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov)
% (c) Date: July, 1988
%
@RELATION iris
@ATTRIBUTE sepallength NUMERIC
@ATTRIBUTE sepalwidth NUMERIC
@ATTRIBUTE petallength NUMERIC
@ATTRIBUTE petalwidth NUMERIC
@ATTRIBUTE class {Iris-setosa,Iris-versicolor,Iris-virginica}
@DATA
5.1,3.5,1.4,0.2,Iris-setosa
4.9,3.0,1.4,0.2,Iris-setosa
4.7,3.2,1.3,0.2,Iris-setosa
4.6,3.1,1.5,0.2,Iris-setosa
5.0,3.6,1.4,0.2,Iris-setosa
5.4,3.9,1.7,0.4,Iris-setosa
4.6,3.4,1.4,0.3,Iris-setosa
5.0,3.4,1.5,0.2,Iris-setosa
4.4,2.9,1.4,0.2,Iris-setosa
4.9,3.1,1.5,0.1,Iris-setosa
因为arff文件和Instances是对应的,在创建Instances对象之前我们需要指定Instances的属性,对应到Java中,@ATTRIBUTE对应的是weka.core.Attribute对象。
Instance是一条数据,类似于数据库中的一行。在新版的weka(>3.5)中,Instance只是一个接口,在本文中以DenseInstance为例创建Instance,其他Instance可以在weka官方api中查到。
private Instances generatePopularInstance(List entities) {
//set attributes
ArrayList attributes = new ArrayList<>();
attributes.add(new Attribute("fork"));
attributes.add(new Attribute("size"));
attributes.add(new Attribute("sum"));
attributes.add(new Attribute("avg"));
attributes.add(new Attribute("weight"));
//set instances
Instances instances = new Instances("repo_popular",attributes,0);
instances.setClassIndex(instances.numAttributes() - 1);
//add instance
for (SecRepoEntity secRepoEntity: entities) {
Instance instance = new DenseInstance(attributes.size());
instance.setValue(0,secRepoEntity.getForkCount());
instance.setValue(1,secRepoEntity.getSize());
instance.setValue(2,secRepoEntity.getSumFollower());
instance.setValue(3,secRepoEntity.getAvgFollower());
instance.setValue(4,secRepoEntity.getWeightFollower());
instances.add(instance);
}
return instances;
}
/**
* generate weka dataSource file
* @param instances weka Instances
*/
public void generateArffFile(Instances instances, String path) {
ArffSaver saver = new ArffSaver();
saver.setInstances(instances);
try {
saver.setFile(new File(path));
saver.writeBatch();
} catch (IOException e) {
e.printStackTrace();
}
}
weka官网有详细的说明,这里摘录新版的方法。(使用DataSource)
import weka.core.converters.ConverterUtils.DataSource;
...
DataSource source = new DataSource("/some/where/data.arff");
Instances data = source.getDataSet();
// setting class attribute if the data format does not provide this information
// For example, the XRFF format saves the class attribute information as well
if (data.classIndex() == -1)
data.setClassIndex(data.numAttributes() - 1);