引入:
在数据挖掘中,经常需要对一组定义了格式的数据集合进行分析,从而找到蕴含在其中内部的规律(或者说是公式),经典的,比如“啤酒和饮料"问题,就是拿对多个用户消费行为进行采样,或者比如说,房屋经销商会获得某个地区的商品房信息(面积,房间数,建造年份,总价) ,当他们获取足够多的信息之后,他们就可以对这些数据信息进行数据挖掘从而找出房屋总价和各个自变量的关系。当然了,不是所有的自变量都和目标有关,比如说房屋的颜色也许就是总价没有太大关系,所以我们建立的数学模型,必须能”火眼金睛“的识别出那些自变量会引起应变量改变那些不能。
在JAVA世界中,我们有了weka,这个可以很轻松的对数据挖掘,对于给定的数据集合,来近似模拟出各种数学模型,以及各种模型的概率统计的评估。
本例目的:
(1)演示WEKA控制台用法
(2)演示如何用JAVA的API 来做同样事情
例子:
假设我们有一个需求,是计算信用卡积分,它”也许“取决于若干的信息(比如”月收入“,”每月工作天数“,”当前信用卡额度“,”历史统计的按时还款比例”,“曾经的最大透支额”,“银行贷款的数目”),当然了,这些信息也许会影响信用卡积分,也许不会影响,所以我们的模型必须去除这些弱影响的因素,从而构建我们的模型。
为了让weka进行分析,我们需要先准备原始数据,按照数据挖掘理论,如果要完备的数据集合的话,当然是数据越多越精确,但是至少应该有N^2个数据(其中N是N个可能影响的自变量的数目),我们为了简单起见,就随便创建20条mock数据,为了导入weka工作,我们将其编辑为ARFF格式,参见
http://www.cs.waikato.ac.nz/~ml/weka/arff.html (当然了,也可以用普通文本格式或者CSV来表示数据),还是那句话,数据格式不重要,数据内容最重要。
我们的ARFF文件如下:
@RELATION creditCardScore %%%% %SECTION1:PERSONAL INFO %%%% % %月收入 % @ATTRIBUTE personInfo.monthlySalary NUMERIC %%%% %SECTION2: BUSINESS INFO %%%% % %每月工作天数 % @ATTRIBUTE businessInfo.workingDayPerMonth NUMERIC %%%% %SECTION 3: CREDIT CARD INFO (信用卡信息) %%%% % %当前额度 % @ATTRIBUTE creditCardInfo.currentLimit NUMERIC % %月度正常还款比例 % @ATTRIBUTE creditCardInfo.percentageOfNormalReturn NUMERIC % %曾经最大透支额 % @ATTRIBUTE creditCardInfo.maximumOverpay NUMERIC %%%% %SECTION 4: FINANCIAL INFO (财政信息) %%%% % %贷款数目 % @ATTRIBUTE financialInfo.personalLoan NUMERIC %%%% %RESULT: CREDIT SCORE(积分) %%%% @ATTRIBUTE creditScore NUMERIC @DATA 10000,22,20000,1, 0, 200000,55 15000,20,30000,0.5,14200,20000, 78 20000,18,40000,0.6,50000,200000,87 30000,22,60000,0.2,30000,150000,67 22000,15,30000,0.7,20000,140000,71 13200,21,18000,0.9,40000,500000,43 15500,20,30000,0.4,14200,20000, 59 25000,26,40000,0.5,50000,200000,88 28670,23,40000,0.7,30000,120000,68 22000,15,40000,0.7,20000,140000,72 10000,18,20000,0.6,30000,150000,47 14300,20,29800,0.5,14200,20000, 72 20000,18,40000,0.9,50000,200000,88 34335,22,50000,0.6,30000,150000,74 24555,15,20000,0.9,20000,120000,79 10055,22,80000,1, 0, 200000,76 15000,20,80000,0.9,90200,20000, 86 25440,17,30000,0.7,50000,200000,82 30000,22,70000,0.2,30000,0, 72 22000,30,80000,0.7,20000,140000,71
假定我们采用多元线性回归模型(因为大体上,信用卡积分是多个因素的加权和,所以它应该满足一个线性模型,我们也用这种模型)
演示weka控制台:
当我们打开weka控制台,导入这个arff文件后,可以很轻易的在"Preprocess"看到对于这个ARFF文件格式的定义部分,包括有多少字段,每个字段的取值,平均值等信息。
然后,当我们选择“Classify",再选择"LinearRegression"分析方法,则可以很清楚的看到对于当前数据集的分析结果,并且给出数学公式和一些数据统计结论。
从上可以看出,我们的信用卡积只和(“月收入”,“正常还款比率”,“最大透支额”,“银行贷款数量”)有关系,当然了,我这些测试数据是随便填写的,现实中可能不是这样。然后下面给出了模拟的线性公式,在下面给出了一些数学统计的信息。(因为我们的数据比较乱,所以最终这些结果可能没有精确的收敛,而是有一定的偏差)
演示java weka API来执行线性回归:
我们最终肯定是希望用程序实现,其实还有点小挑战的,因为有些信息(比如公式信息),没有现成的API直接拿来用,我还是通过debug才发现了公式的存在的。
我们定义一个工具类,它有2个工具方法,一个是获取ARFF文件的内容定义,一个是对于给定ARFF文件“智能”的挖掘出公式,并且给出数学统计值。
package com.charles.demo; import java.io.File; import weka.classifiers.Evaluation; import weka.classifiers.functions.LinearRegression; import weka.core.Instances; import weka.core.converters.ArffLoader; import weka.core.converters.ConverterUtils.DataSource; /** * 利用weka对给定数据集做线性回归,给出其蕴含的公式 * @author charles.wang * */ public class LRRegression { private LRRegression(){} /** * 分析ARFF文件,获取其文件中的格式定义信息 * @param filePath 传入的ARFF文件的文件路径,这里暂时不支持http和ftp,只支持本地文件 * @return 封装字符串的文件内容返回对象 * @throws Exception */ public static String parseArffFile(String filePath) throws Exception { // 创建一个arff文件载入器 ArffLoader loader = new ArffLoader(); //载入文件内容,获取其数据集合 loader.setSource(new File(filePath)); Instances data = loader.getDataSet(); //封装字符串的文件内容返回对象 StringBuilder sb = new StringBuilder(); sb.append("被读取的训练文件路径为:" + filePath + "\n\n"); sb.append("训练文件内容定义为:" + new Instances(data, 0)); return sb.toString(); } /** * 对ARFF文件中的数据集合做线性回归,从而挖掘出其中的公式 * @param filePath 传入的ARFF文件的文件路径,这里暂时不支持http和ftp,只支持本地文件 * @return 线性回归运算得到的公式,以及运算结果的评估 * @throws Exception */ public static String doLinearRegression(String filePath) throws Exception { // 读训练数据 DataSource train_data = new DataSource(filePath); // 获取训练数据集 Instances insTrain = train_data.getDataSet(); // 设置训练集中,target的index insTrain.setClassIndex(insTrain.numAttributes() - 1); // 定义分类器的类型 , 我们采用线性回归 LinearRegression lr = new LinearRegression(); // 训练分类器 lr.buildClassifier(insTrain); // 评估线性回归的结果 Evaluation eval = new Evaluation(insTrain); eval.evaluateModel(lr, insTrain);// 评估结果 // 构造结果对象 StringBuilder sb = new StringBuilder(); sb.append("机器学习后产生的线性回归公式:\n" + lr.toString() + "\n\n"); sb.append("评估此结果:" + eval.toSummaryString() + "\n"); return sb.toString(); } }
我们做一个演示,传入文章开始的ARFF文件,然后分别打印出其定义格式,以及挖掘出的数学公式:
public static void main(String[] args) throws Exception { //演示如何获取ARFF文件中样本数据定义格式信息 String arffFileDef = parseArffFile("D:/Framework Study/weka/data/no-linar/creditcard.arff"); System.out.println(arffFileDef); System.out.println(); //演示如何从ARFF文件中挖掘数据联系(公式)以及给出数学概率的评定 String evalResult = doLinearRegression("D:/Framework Study/weka/data/no-linar/creditcard.arff"); System.out.println(evalResult); }
最后结果如下:
我们可以对比和weka控制台给出的结果,显然是一致的。