数据挖掘与机器学习:Weka Java 编程接口 API
文章目录
- 1 环境配置
- 2 数据模型
- 2.1 Instances:数据集
- 2.2 Instance:数据实例
- 2.3 Attribute:属性类
- 3 DataSource
- 4 DataSink
- 5 数据集处理
- 5.1 创建数据集
- 5.2 添加数据
- 6 过滤
- 7 分类
- 8 聚类
1 环境配置
在 Idea 上创建 Maven Java 项目,并添加依赖:
<dependency><groupId>nz.ac.waikato.cms.weka</groupId><artifactId>weka-stable</artifactId><version>3.8.6</version></dependency><!-- 下面是 weka 测试代码程序包 --><dependency><groupId>nz.ac.waikato.cms.weka</groupId><artifactId>weka-stable</artifactId><version>3.8.6</version><classifier>tests</classifier></dependency>
2 数据模型
Instances 是数据集类,可类似理解为数据表,Attribute 类描述了数据集中的属性定义,Instance 表示数据集中的一个数据实例,可类比理解为数据表中的一行数据。
2.1 Instances:数据集
Instances 类用来存储一个完整的数据集信息,其内部是基于行的数据结构,可以通过调用 instance(int) 方法来获取一行的数据,可以通过 attribute(int) 方法获取一列数据。
import weka.core.converters.ConverterUtils.DataSource;// Read all the instances in the file (ARFF, CSV, XRFF, ...)
DataSource source = new DataSource(filename);
Instances instances = source.getDataSet();// Make the last attribute be the class
instances.setClassIndex(instances.numAttributes() - 1);// Print header and instances.
System.out.println("\nDataset:\n");
System.out.println(instances);
2.2 Instance:数据实例
该类表示数据集中的一行,基本上是一个原始 double 数组的包装类。该类中不包含列的类型信息,可以通过访问关联的 Instances 数据集对象,来获取想要的信息。
AbstractInstance 类直接派生 weka.core.DenseInstance 类和 weka.core.SparseInstance 类,这两个类提供了实例的基本功能。前者处理实例速度较快,是更为优雅的面向对象方法;后者只存储非零值,因而节省一些存储空间。在后文的示例中,大部分都使用DenseInstance类,很少使用SparseInstance类,但两者的处理非常相似。
稠密数据在 arff 文件中如下:
@data 0, X, 0, Y, "class A" 0, 0, W, 0, "class B"
用稀疏格式表达的话,如下:
@data {1 X, 3 Y, 4 "class A"} {2 W, 4 "class B"}
每个实例用花括号括起来。实例中每一个非0的属性值用<index> <空格> <value>表示。<index>是属性的序号,从0开始计;<value>是属性值。属性值之间仍用逗号隔开。这里每个实例的数值必须按属性的顺序来写,如 {1 X, 3 Y, 4 "class A"} ,不能写成 {3 Y, 1 X, 4 "class A"}。注意在稀疏格式中没有注明的属性值不是缺失值,而是 0 值。若要表示缺失值必须显式的用问号表示出来。
实例中的所有值(数字、日期、标称值、字符串或关系型)都以浮点数的形式在内部存储,如果属性是标称(或字符串或关系),则存储的值是属性定义中相应标称(或字符串或关系)值的索引。这种实现方式在进行数据处理时,更优雅和高效。
// 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);// Print the instance
System.out.println("The instance: " + inst);
当添加字符串属性值时,实际上添加到数据数组中的是字符串属性的索引,具体过程如下列代码所示:
// 添加字符串属性值;
public final void setValue(int attIndex, String value) {int valIndex;if (m_Dataset == null) { // m_Dataset 是该数据实例所在数据集的引用throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");}// 判断该属性的类型,是否为字符串型if (!attribute(attIndex).isNominal() && !attribute(attIndex).isString()) {throw new IllegalArgumentException("Attribute neither nominal nor string!");}// 判断值为 value 的属性是否已存在?valIndex = attribute(attIndex).indexOfValue(value);if (valIndex == -1) {if (attribute(attIndex).isNominal()) {throw new IllegalArgumentException("Value not defined for given nominal attribute!");} else {attribute(attIndex).forceAddValue(value); // 新建属性valIndex = attribute(attIndex).indexOfValue(value);}}setValue(attIndex, valIndex); // 实际添加的是属性值的索引!}
2.3 Attribute:属性类
该类保存数据集中的属性的元信息,如属性的类型,以及标称型属性的标签、字符串属性的全部值,以及关系属性的数据集。
支持以下数据类型:
- numeric : 数值型,表示一个浮点数据;
- nominal : 标称型,可以理解为枚举型;
- string:字符串;
- date:日期型,实际保存的是其相应的浮点型时间戳值;
- relational:关系型,保存的是其他实例的引用。
示例:
// Create numeric attributes "length" and "weight"
Attribute length = new Attribute("length");
Attribute weight = new Attribute("weight");// Create list to hold nominal values "first", "second", "third"
List my_nominal_values = new ArrayList(3);
my_nominal_values.add("first");
my_nominal_values.add("second");
my_nominal_values.add("third");// Create nominal attribute "position"
Attribute position = new Attribute("position", my_nominal_values);
3 DataSource
Weka 支持多种格式的数据文件,比如 arff,csf,xrff 等,加载文件数据时,weka 会通过文件扩展名来推断文件内容的数据格式,然后选择合适的加载类。
可用的文件数据加载器放在 weka.core.converters 包中:
ConverterUtils 是一个工具类,其中定义了两个重要的内部类:DataSource, DataSink;DataSource 用于从文件中读取数据,DataSink 用于保存数据到文件。
Instances data1 = DataSource.read("/some/where/dataset.arff");Instances data2 = DataSource.read("/some/where/dataset.csv");Instances data3 = DataSource.read("/some/where/dataset.xrff");// 也可以通过指定加载器的方式来加载文件:此时的文件扩展名,不受约束。CSVLoader loader = new CSVLoader();loader.setSource(new File("/some/where/some.data"));Instances data = loader.getDataSet();
DataSource 是用于从文件和URL加载数据的帮助类。通过 ConverterUtils 类,它决定使用哪个转换器将数据加载到内存中。如果选择的转换器是增量转换器,则数据将以增量方式加载,否则将以批处理方式加载。在这两种情况下,将使用相同的接口(hasMoreElements,nextElement)。在再次读取数据之前,必须调用重置方法。
4 DataSink
所有的保存器(saver)都位于 weka.core.converters 包中,保存数据既可以让 Weka 选择合适的转换器,也可以指定显示转换器。
// 要保存的数据结构Instances data = DataSource.read("/some/where/dataset.arff");// 保存为ARFFDataSink.write("/some/where/data.arff", data);// 保存为CSVDataSink.write("/some/where/data.csv", data);// 保存为CSVCSVSaver saver = new CSVSaver();saver.setInstances(data);saver.setFile(new File("/some/where/data.csv"));saver.writeBatch();
5 数据集处理
5.1 创建数据集
创建数据集是指在内存中生成 Instances 对象,这个一个两阶段的过程:1, 通过设置属性定义数据格式;2,添加数据记录。其中数据定义可以理解为数据库操作中的 create table 操作,添加数据记录,可以理解为 insert 操作。
Weka目前有以下五种不同的属性类型。
- numeric(数值型):连续变量。
- date(日期型):日期变量。
- nominal(标称型):预定义的标签。
- string(字符串型):文本数据。
- relational(关系型):包含其他关系。例如,多个实例数据组成的包(bags)。
// 1. 数值型
Attribute numeric = new Attribute("numeric_test");// 2. 日期型
Attribute date = new Attribute("date_test ", "yyyy-MM-dd");// 3. 标称型
ArrayList<String> labels = new ArrayList<String>();labels.add ("label_a");labels.add ("label_b");labels.add ("label_c");labels.add ("label_d");
Attribute nominal = new Attribute("nominal_test", labels);/*** 4. 字符串型* * 与标称属性不同,字符串类型不需要存放预定义的标签列表。通常用于存储文本数据,即文本分类的文档内容。* 字符串型使用与标称属性相同的构造函数,但需要提供一个null值,而非java.util.ArrayList<String>的实例。
*/
Attribute string = new Attribute("attribute_name", (ArrayList<String>)null);
5.2 添加数据
用户可以使用 DenseInstance 类的两种构造函数来实例化一个数据行,两种构造函数的功能如下。
- DenseInstance(double weight, double[] attValues):
该构造函数生成一个指定权重及给定 double 数组的 DenseInstance 对象。在 Weka 内部,全部五种属性类型都使用 double 格式。double格式表示数值型和日期型肯定没有问题,在Java内部,日期型也是用数值来表示的。对于标称型、字符串型和关系型属性,仅仅需要存放存储值的索引。
- DenseInstance(int numAttributes):
该构造函数生成一个新的、权重为1.0,全部值都缺失的DenseInstance对象。
double[] values = new double[data.numAttributes()]; // 创建示例数据// 添加属性值;
values[0] = 1.23;
values[1] = data.attribute(1).parseDate("2013-05-11");
values[2] = data.attribute(2).indexOf("label_b");
values[3] = data.attribute(3).addStringValue("A string");Instances dataRel = new Instances(data.attribute(4).relation(), 0); // 创建数据集
valuesRel = new double[dataRel.numAttributes()];
valuesRel[0] = 2.34;
valuesRel[1] = dataRel.attribute(1).indexOf("val_C");
dataRel.add(new DenseInstance(1.0, valuesRel));
values[4] = data.attribute(4).addRelation(dataRel);Instance inst = new DenseInstance(1.0, values); // 创建数据实例
data.add(inst); // 将实例添加到数据集
创建 Instances 的完整示例:
private Instances relationInstances() {ArrayList<Attribute> attrRelation = new ArrayList<>();// -- 关系属性 1:数值型attrRelation.add(new Attribute("att5.1"));// -- 关系属性 2:标称型ArrayList<String> attValsRel = new ArrayList<>();for (int i = 0; i < 5; i++){attValsRel.add("val5." + (i + 1));}attrRelation.add(new Attribute("att5.2", attValsRel));return new Instances("att5", attrRelation, 0);}@Testpublic void printInstancesTest() throws Throwable {// 属性定义ArrayList<Attribute> attributes = new ArrayList<>();// - 属性1:数值型attributes.add(new Attribute("att1"));// - 属性2:标称型ArrayList<String> attrTags = new ArrayList<>(); // 为标称值创建标签for (int i = 0; i < 5; i++){attrTags.add("val" + (i + 1));}attributes.add(new Attribute("att2", attrTags));// - 属性3:字符串型attributes.add(new Attribute("att3", (ArrayList<String>) null));// - 属性4:日期型attributes.add(new Attribute("att4", "yyyy-MM-dd"));// - 属性5:关系型attributes.add(new Attribute("att5", relationInstances(), 0));Instances data = new Instances("MyRelation", attributes, 0);// 3. 添加数据// 第一个实例Instances dataRel = new Instances(data.attribute(4).relation(), 0);// -- 第一个实例dataRel.add(new DenseInstance(1.0, new double[]{Math.PI + 1,dataRel.attribute(1).indexOfValue("val5.3")}));// -- 第二个实例dataRel.add(new DenseInstance(1.0, new double[]{Math.PI + 2,dataRel.attribute(1).indexOfValue("val5.2")}));// 添加实例1// 2. 创建Instances对象data.add(new DenseInstance(1.0, new double[]{Math.PI, // - 数值型attrTags.indexOf("val3"), // - 标称型data.attribute(2).addStringValue("A string."), // - 字符串型data.attribute(3).parseDate("2013-04-05"), // - 日期型data.attribute(4).addRelation(dataRel) // 关系型}));// 4. 输出数据System.out.println(data);}
输出的数据集:
@relation MyRelation@attribute att1 numeric
@attribute att2 {val1,val2,val3,val4,val5}
@attribute att3 string
@attribute att4 date yyyy-MM-dd
@attribute att5 relational
@attribute att5.1 numeric
@attribute att5.2 {val5.1,val5.2,val5.3,val5.4,val5.5}
@end att5@data
3.141593,val3,'A string.',2013-04-05,'4.141593,val5.3\n5.141593,val5.2'
6 过滤
在 Weka 中,使用过滤器进行数据预处理。
在 weka.filters 包下可以找到这些过滤器,过滤器分为有监督过滤器和无监督过滤器两类。前者需要设置一个类别属性,后者不需要;过滤器还可以分为基于属性和基于实例两个子类,前者针对列的处理,例如,添加或删除列;后者针对行的处理,例如,添加或删除行。
除此之外,过滤器还可以分为流式过滤器或批处理过滤器。
String[] options = new String[2];options[0] = "-R"; // 范围options[1] = "1"; // 第一个属性Remove remove = new Remove(); // 构建过滤器实例remove.setOptions(options); // 设置选项remove.setInputFormat(data); // 设置输入格式,一定要在 setOptions 后面;Instances newData = Filter.useFilter(data, remove); // 应用过滤器
批量过滤器可以同时处理多个数据集。
7 分类
在 Weka 中,分类和回归算法都称为“分类器”,位于 weka.classifier 包下。
所有的 Weka 分类器都设计为可批量训练的,即分类器对整个数据集一次就能训练好;还有一些算法可以随时随机地更新自己的内部模型,称为增量分类器。
批量分类器的构建非常简单:
- 设置选项;
- 进行训练;
import weka.classifiers.trees.J48;import weka.core.Instances;import weka.core.converters.ArffLoader;import java.io.File;/*** 批量方式构建J48分类器,并输出决策树模型*/public class BatchClassifier {public static void main(String[] args) throws Exception {// 加载数据ArffLoader loader = new ArffLoader();loader.setFile(new File("C:/Weka-3-7/data/weather.nominal.arff"));Instances data = loader.getDataSet();data.setClassIndex(data.numAttributes() - 1);// 训练J48分类器String[] options = new String[1];options[0] = "-U"; // 未裁剪树选项J48 tree = new J48(); // J48分类器对象tree.setOptions(options); // 设置选项tree.buildClassifier(data); // 构建分类器// 输出生成模型System.out.println(tree);}}
Evaluation 分类评估器,用于评估分类的性能,Weka 支持两种类型的评估,1,交叉验证,2,专用测试集验证。
Evaluation 中的常见方法:
方法名 | 说明 |
---|---|
toSummaryString() | 以摘要的形式输出性能统计数据,第一个参数为摘要标题,第二个参数为是否打印复杂的性能统计数据; |
toMatrixString() | 输出混淆矩阵; |
toClassDetailsString() | 输出TP / FP率、查准率、查全率、F-度量、AUC(每个类别); |
toCumulativeMarginDistributionString() | 输出累计边距分布; |
correct() | 正确分类的实例数量,不正确分类的实例数量可调用 incorrect() 方法得到; |
pctCorrect() | 正确分类的实例的百分比(查准率)。pctIncorrect() 返回错误分类的实例的百分比; |
areaUnderROC(int) | 指定的类别标签索引(基于0的索引)的AUC; |
correlationCoefficient() | 相关系数 |
meanAbsoluteError() | 平均绝对误差 |
rootMeanSquaredError() | 均方根误差 |
numInstances() | 类别值的实例数量 |
unclassified() | 未分类的实例数量 |
pctUnclassified() | 未分类的实例的百分比 |
8 聚类
聚类是一种在数据中发现模式的无监督机器学习技术,也就是说,这些算法没有类别属性,这与分类不同,分类算法需要有一个类别属性,是有监督的机器学习算法。
执行聚类算法的步骤:
- 构建聚类器;
- 评估:对构建的聚类器进行评估;
- 执行聚类:对未知的实例进行聚类;
Instances train = DataSource.read("C:/Weka-3-7/data/segment-challenge.arff");Instances test = DataSource.read("C:/Weka-3-7/data/segment-test.arff");String[] options = new String[2];options[0] = "-I"; // 最大迭代次数options[1] = "100";EM clusterer = new EM(); // 聚类器的新实例clusterer.setOptions(options); // 设置选项clusterer.buildClusterer(train); // 构建聚类器// 评估ClusterEvaluation eval = new ClusterEvaluation();eval.setClusterer(cl);eval.evaluateClusterer(new Instances(train));System.out.println(eval.clusterResultsToString());// 执行聚类for (int i = 0; i < test.numInstances(); i++) {int cluster = clusterer.clusterInstance(test.instance(i));double[] dist = clusterer.distributionForInstance(test.instance(i));System.out.print((i + 1));System.out.print(" - ");System.out.print(cluster);System.out.print(" - ");System.out.print(Utils.arrayToString(dist));System.out.println();}
聚类器评估不像分类器评估那样容易做得很全面,由于聚类是无监督的,因此很难确定一个模型的性能到底有多好。 Weka 用于评估聚类算法的是 weka.clusters 包的 ClusterEvaluation 类。
数据挖掘与机器学习:Weka Java 编程接口 API相关推荐
- [转载]Z-stack 应用程序编程接口(API)-网络层
原文地址:Z-stack 应用程序编程接口(API)-网络层作者:vexation NWK 层为更高层提供了如下功能:· · 网络管理 · 地址管理 · 网络参数与功能函数 除了管理功能,NW ...
- USB联机线编程接口(API)
USB联机线编程接口(API) 2013-10-19 本页面的文字允许在知识共享 署名-相同方式共享 3.0协议和GNU自由文档许可证下修改和再使用. 关键字:USB隔离线.USB点对点通讯.USB通 ...
- USB数据共享、联机线、联网线编程接口(API)
本页面的文字允许在知识共享 署名-相同方式共享 3.0协议和GNU自由文档许可证下修改和再使用. USB联机线编程接口(API) 2017-11-26 一.概述 USB2.0理论传输速率最高为480M ...
- java api接口报500_应用程序编程接口API,我们来聊一聊这个熟悉的名词
API,全称叫做Application Programming interface,也就是应用程序接口,API是一些预先定义的函数,我是学Java的,当我要使用这些函数的时候,便可以直接调用Java ...
- FTK应用程序编程接口(API)手册-1
框架函数 框架函数支撑FTK的主体,它负责初始化应用程序,启动主循环和退出主循环.它对任何一个FTK应用程序都是不可缺少的,即使应用程序没有使用任何控件(当然这也没有什么意义),所以我们先介绍这些函数 ...
- FTK应用程序编程接口(API)手册-2
全局对象存取函数 FTK中有一些单实例的对象,这些对象是以全局变量的形式存在的,为了有效的控制对这些对象的访问,我们提供了相应的存/取函数.这些对象都是在FTK初始化时创建的,所以开发人员无需要再调用 ...
- api有哪些 javasocket_基于java的socket编程及API解析
一.socket通讯过程 1.socket与socket编程简介: socket 被翻译为"套接字",它是计算机之间进行通信的一种约定或一种方式.通过 socket 这种约定,一台 ...
- java扫描接口_一种扫描接口并生成可调用API接口文档的方法与流程
本发明属于JavaWeb开发技术领域,涉及一种API接口文档的生成方法,尤其是一种扫描接口并生成可调用API接口文档的方法. 背景技术: API(Application Programming Int ...
- Java接口调用的安全性_java编程接口调用安全性都有哪些要求
接口调用是我们在使用java编程开发语言的时候会经常使用到的一个功能,而今天我们就通过案例分析来了解一下,java编程接口调用安全性都有哪些要求. 1.调用接口的先决条件-token 获取token一 ...
最新文章
- 我一个普通程序员,光靠GitHub打赏就年入70万,要不你也试试
- HDU 1008 Elevator
- 弹出提示框 自动消失
- C#中简单的正则表达式(也经常会用到的)
- JavaScript二叉搜索树
- Python应用实战-LUX在pandas中智能可视化分析
- 解决RabbitMQ service is already present - only up...
- 好大夫王航:长尾开发者应尽快接入百度轻应用
- 通过文件锁 Lockfile/flock 让脚本单实例运行
- SQOOP --hive-import 错误(Sqoop Hive exited with status 1)及解决
- 力扣-面试题 10.05 稀疏数组搜索
- 机器字长 存储字长 指令字长 机器字长
- 正方形面积圆形面积Java
- 马哥教育42期第二周作业
- 虚无世界java路_[AoA3]虚无世界3 (Advent of Ascension 3)
- 【软件介绍】IGV软件的安装和基本介绍
- 副连长是什么级别_军改后连长工资有多少?军改后军队各级别工资待遇标准
- 解决Failed to introspect Class KafkaMetricsAutoConfiguration
- 移动端meta设置大全(持续收集中。。。。)
- 第一啪,第一啪电影网,第一啪电影网用的哪里的模板diyipa.cc
热门文章
- sqlite3.OperationalError: near “(“: syntax error
- kingmax超棒启动制作
- 一款典型的智慧电力物联网关的技术要求
- 华为OD机试真题 Python 实现【工单调度策略】【2023 Q1 | 100分】
- IT、CS、IS, 计算专业傻傻分不清楚? 这有何难
- 记两个国外CTF的弱pwn
- 【基础练习】【模拟】Uva489 - Hangman Judge题解
- BJDctf2020 Ezphp
- 隐函数及参数方程求导——“高等数学”
- Laravel 5.0 框架查看执行过的SQL语句