Java用WEKA进行机器学习数据挖掘Word格式文档下载.docx
《Java用WEKA进行机器学习数据挖掘Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《Java用WEKA进行机器学习数据挖掘Word格式文档下载.docx(12页珍藏版)》请在冰豆网上搜索。
那么它与这二者究竟有何不同呢?
首先,回归只能用于数值输出,这是它与最近邻的最直接的一个不同点。
分类,如我们在前一篇文章的例子中看到的,使用每个数据实例
来创建树,我们需要遍历此树才能找到答案。
而这一点对于某些数据而言会是一个很严重的问题。
举个例子,亚马逊这样的公司常常使用“购买了X的顾客还购买了Y"
特性,如果亚马逊拟创建一个分类树,那么它将需要多少分支和节点?
它的产品多达数十万。
这个树将有多巨大呀?
如此巨大的一个树能有多精确呢?
即便是单个分支,您都将会惊讶地发现它只有三个产品。
亚马逊的页面通常会有12种产品推荐给您。
对于这类数据,分类树是一种极不适合的数据挖掘模型。
而最近邻则可以非常有效地解决所有这些问题,尤其是在上述亚马逊的例子中遇到的这些问题。
它不会受限于数量。
它的伸缩性对于20个顾客的数据库与对于2000万个顾客的数据库没有什么差异,并且您可以定义您想要得到的结果数。
看起来是一个很棒的技术!
它的确很棒—并且可能对于那些正在阅读本文的电子商务店铺的店主最为有用。
让我们先来探究一下最近邻背后的数学理论,以便能更好地理解这个过程并了解此技术的某些限制。
最近邻背后的数学理论
最近邻技术背后的数学理论非常类似于群集技术所涉及到的数学理论。
对于一个未知的数据点,这个未知数据点与每个已知数据点之间的距离需要被计算出来。
如果用电子数据表计算此距离将会非常繁琐,而一个高性能的计算机则可以立即完成这些计算。
最容易也是最为常见的一种距离计算方式是“NormalizedEuclidianDistance”。
它看起来复杂,实则不然。
让我们通过一个例子来弄清楚第5个顾客有可能会购买什么产品?
清单1.最近邻的数学理论
CustomerAgeIncomePurchasedProduct
14546kBook
239100kTV
33538kDVD
469150kCarCover
55851k?
?
Step1:
DetermineDistanceFormula
Distance=SQRT(((58-Age)/(69-35))^2)+((51000-Income)/(150000-38000))^2)
Step2:
CalculatetheScore
CustomerScorePurchasedProduct
1.385Book
2.710TV
3.686DVD
4.941CarCover
50.0?
如果使用最近邻算法回答我们上面遇到的“第5个顾客最有可能购买什么产品”这一问题,答案将是一本书。
这是因为第5个顾客与第1个顾客之间的距离要比第5个顾客与其他任何顾客之间的距离都短(实际上是短很多)。
基于这个模型,可以得出这样的结论:
由最像第5个顾客的顾客可以预测出第5个顾客的行为。
不过,最近邻的好处远不止于此。
最近邻算法可被扩展成不仅仅限于一个最近匹配,而是可以包括任意数量的最近匹配。
可将这些最近匹配称为是“N-最近邻”(比如3-最近邻)。
回到上述的例子,如果我们想要知道第5个顾客最有可能购买的产品,那么这次的结论是书和
DVD。
而对于上述的亚马逊的例子,如果想要知道某个顾客最有可能购买的12个产品,就可以运行一个12-最近邻算法(但亚马逊实际运行的算法要远比一个简单的12-最近邻算法复杂)。
并且,此算法不只限于预测顾客购买哪个产品。
它还可被用来预测一个Yes/No的输出值。
考虑上述例子,如果我们将最后一列改为(从顾客1到顾客4)“Yes,No,Yes,No,”,那么用1-最近邻模型可以预测第5个顾客会说“Yes”,如果用一个2-最近邻算法也会得到预测结果“Yes”(顾客1和3均说“Yes”),若用3-最近邻模型仍会得到“Yes”(顾客1和3说“Yes”,顾客2说“No”,所以它们的平均值是“Yes”)。
我们考虑的最后一个问题是“我们应该在我们的模型中使用多少邻?
”啊哈—并不是每件事都这么简单。
为了确定所需邻的最佳数量,需要进行试验。
并且,如果要预测值为0和1的列的输出,很显然需要选择奇数个邻,以便打破平局。
针对WEKA的数据集
我们将要为我们的最近邻示例使用的数据集应该看起来非常熟悉—这个数据集就与我们在上一篇文章的分类示例中所用的相同。
该示例关于的是一个虚构的BMW经销店及其向老客户销售两年延保的促销活动。
为了回顾这个数据集,如下列出了我在上一篇文章中曾介绍过的一些指标。
延保的以往销售记录中有4,500个数据点。
数据集中的属性有:
收入水平[0=$0-$30k,1=$31k-$40k,2=$41k-$60k,3=$61k-$75k,4=$76k-$100k,5=$101k-$150k,6=$151k-$500k,7=$501k+]、顾客首辆BMW购买的年/月、最近一辆BMW购买的年/月、顾客是否在过去对延保的促销有过响应。
清单2.最近邻WEKA数据
@attributeIncomeBracket{0,1,2,3,4,5,6,7}
@attributeFirstPurchasenumeric
@attributeLastPurchasenumeric
@attributeresponded{1,0}
@data
4,200210,200601,0
5,200301,200601,1
...
WEKA内的最近邻
我们为何要使用与分类例子中相同的数据集呢?
这是因为分类模型得到的结果,只有59%的准确率,而这完全不能接受(比猜想好不到哪去)。
我们将提高准确率并为这个虚构的经销商提供一些有用的信息。
将数据文件bmw-training.arff载入WEKA,步骤与我们之前在Preprocess选项卡中使用的相同。
加载数据后,屏幕应该类似于图1。
图1.WEKA内的BMW最近邻数据
与我们在之前文章的回归和分类模型中所做的类似,我们接下来应该选择Classify选项卡。
在这个选项卡上,我们应该选择
lazy,然后选择
IBk(IB
代表的是Instance-Based,而
k
则允许我们指定要使用的邻的数量)。
图2.BMW最近邻算法
现在,我们就准备好可以在WEKA内创建我们的模型了。
请确保选中
Usetrainingset
以便我们使用刚载入的这个数据集来创建我们的模型。
单击
Start,让WEKA运行。
图3显示了一个屏幕快照,清单3则包含了此模型的输出。
图3.BMW最近邻模型
清单3.IBk计算的输出
===Evaluationontrainingset===
===Summary===
CorrectlyClassifiedInstances266388.7667%
IncorrectlyClassifiedInstances33711.2333%
Kappastatistic0.7748
Meanabsoluteerror0.1326
Rootmeansquarederror0.2573
Relativeabsoluteerror26.522%
Rootrelativesquarederror51.462%
TotalNumberofInstances3000
===DetailedAccuracyByClass===
TPRateFPRatePrecisionRecallF-MeasureROCAreaClass
0.950.1770.8470.950.8960.9721
0.8230.050.9410.8230.8780.9720
WeightedAvg.0.8880.1140.8930.8880.8870.972
===ConfusionMatrix===
ab<
--classifiedas
144976|a=1
2611214|b=0
上述结果与我们用分类创建模型时的结果有何差异呢?
使用最近邻的这个模型的准确率为89%,而分类模型的准确率只有59%,所以这绝对是一个很好的开始。
接近90%的准确率是非常可以接受的。
让我们再进一步来分析这些结果的假正和假负的情况,以便深入了解来自WEKA的这些结果在实际业务中的适用。
此模型的结果显示我们有76个假正(2.5%),有261个假负(8.7%)。
请记住在本例中一个假正意味着我们的模型预测该客户会购买延保而实际上却未购买,而一个假负则意味着我们的模型预测客户不会购买延保而实际却购买了。
让我们估测经销商的宣传单的派发成本是每个传单$3,延保为经销商带来了$400的利润。
这个模型对经销商的成本/收益的预测应为$400-(2.5%*$3)-(8.7%*400)=$365。
所以,从此模型看来,这个经销商相当有利可图。
与之相比,使用分类模型预测的成本/收益只有$400-(17.2%*$3)-(23.7%*$400)=$304,由此可以看出使用正确的模型可以为此经销商提供20%潜在收入的提高。
您可以自己练习着在这个模型中尝试不同数量的最近邻(您可以右键单击下一个“IBk-K1....”,就会看到一列参数)。
可以任意更改"
KNN"
(K-最近邻)。
在本例中您将会看到随着加入更多的邻,模型的准确率实际上却降低了。
此模型的一些不尽人意之处:
当我们谈论像亚马逊这样的数据集时,最近邻的强大威力是显而易见的。
对于有2000万用户的亚马逊,此算法非常准确,因为在亚马逊的数据库中与您有着类似购买习惯的潜在客户很多。
您的最近邻会非常相似。
因而,所创建的模型会十分准确和高效。
相反,如果能比较的数据点相对很少的话,这个模型很快就会损坏,不再准确。
在在线电子商务店铺的初期,比如只有50个顾客,那么产品推荐特性很可能一点都不准确,因为最近邻实际上与您本身相差甚远。
最近邻技术最后的一个挑战是该算法的计算成本有可能会很高。
在亚马逊的例子中,对于它的2000万客户,每个客户都必须针对其他的2000万客户进行计算以便找到最近邻。
首先,如果您的业务也有2000万的客户群,那么这便不成问题,因为您会财源广进。
其次,这种类型的计算非常适合用云来完成,因为它们能够被分散到许多计算机上同时完成,并最终完成比较。
(比如,Google的MapReduce。
)第三,实际上,如果我只是购买了一本书,那么根本不必针对我对比亚马逊数据库内的每个
客户。
只需将我与其他的购书者进行对比来寻找最佳匹配,这样一来,就将潜在的邻缩小到整个数据库的一部分。
请记住:
数据挖掘模型并不只是简单的输入-输出机制—必须先对数据进行检查以决定该选择哪种正确的模型,让输入能够设法减少计算时间,而输出则必须被分析且要确保准确后才能据此做出整体的判断。
进一步的阅读:
如果您有兴趣进一步学习最近邻算法,可以按如下术语搜索相关信息:
distanceweighting、Hammingdistance、Mahalanobisdistance。
在服务器上使用WEKA
有关WEKA最酷的一件事情是它不仅是一个独立的应用程序,而且还是一个完备的
JAR文件,可以将其投入到您服务器的lib文件夹并从您自己的服务器端代码进行调用。
这能为您的应用程序带来很多有趣的、和重要的功能。
您可以添加充分利用了我们到目前所学的全部数据挖掘技术的报告。
您可以为您的电子商务店铺创建一个“产品推荐”小部件,类似于亚马逊站点上的那个(由于根本不可能为每个顾客都按需这么做,因此需要贯彻这个独立的应用程序运行它)。
WEKA独立应用程序本身只调用底层的WEKAJavaAPI,所以您应该已经看到过这个API的运转了。
现在,我们应该看看如何将它集成到您的自己代码中。
实际上,您已经下载了这个WEKAAPIJAR;
它就是您启动WEKAExplorer时调用的那个JAR文件。
为了访问此代码,让您的Java环境在此类路径中包含这个JAR文件。
在您自己的代码中使用第三方JAR文件的步骤如常。
正如您所想,WEKAAPI内的这个中心构建块就是数据。
数据挖掘围绕此数据进行,当然所有我们已经学习过的这些算法也都是围绕此数据的。
那么让我们看看如何将我们的数据转换成WEKAAPI可以使用的格式。
让我们从简单的开始,先来看看本系列有关房子价值的第一篇文章中的那些数据。
注:
我最好提前告诫您WEKAAPI有时很难导航。
首要的是要复核所用的WEKA的版本和API的版本。
此API在不同的发布版间变化会很大,以至于代码可能会完全不同。
而且,即便此API完备,却没有什么非常好的例子可以帮助我们开始(当然了,这也是为什么您在阅读本文的原因)。
我使用的是WEKAV3.6。
清单4显示了如何格式化数据以便为WEKA所用。
清单4.将数据载入WEKA
//Defineeachattribute(orcolumn),andgiveitanumericalcolumnnumber
//Likely,abetterdesignwouldn'
trequirethecolumnnumber,but
//wouldinsteadgetitfromtheindexinthecontainer
Attributea1=newAttribute("
houseSize"
0);
Attributea2=newAttribute("
lotSize"
1);
Attributea3=newAttribute("
bedrooms"
2);
Attributea4=newAttribute("
granite"
3);
Attributea5=newAttribute("
bathroom"
4);
Attributea6=newAttribute("
sellingPrice"
5);
//EachelementmustbeaddedtoaFastVector,acustom
//containerusedinthisversionofWeka.
//LaterversionsofWekacorrectedthismistakebyonly
//usinganArrayList
FastVectorattrs=newFastVector();
attrs.addElement(a1);
attrs.addElement(a2);
attrs.addElement(a3);
attrs.addElement(a4);
attrs.addElement(a5);
attrs.addElement(a6);
//EachdatainstanceneedstocreateanInstanceclass
//Theconstructorrequiresthenumberofcolumnsthat
//willbedefined.Inthiscase,thisisagooddesign,
//sinceyoucanpassinemptyvalueswheretheyexist.
Instancei1=newInstance(6);
i1.setValue(a1,3529);
i1.setValue(a2,9191);
i1.setValue(a3,6);
i1.setValue(a4,0);
i1.setValue(a5,0);
i1.setValue(a6,205000);
....
//EachInstancehastobeaddedtoalargercontainer,the
//Instancesclass.Intheconstructorforthisclass,you
//mustgiveitaname,passalongtheAttributesthat
//areusedinthedataset,andthenumberof
//Instanceobjectstobeadded.Again,probablynotidealdesign
//torequirethenumberofobjectstobeaddedintheconstructor,
//especiallysinceyoucanspecify0here,andthenaddInstance
//objects,anditwillreturnthecorrectvaluelater(soin
//otherwords,youshouldjustpassin'
0'
here)
Instancesdataset=newInstances("
housePrices"
attrs,7);
dataset.add(i1);
dataset.add(i2);
dataset.add(i3);
dataset.add(i4);
dataset.add(i5);
dataset.add(i6);
dataset.add(i7);
//IntheInstancesclass,weneedtosetthecolumnthatis
//theoutput(akathedependentvariable).Youshouldremember
//thatsomedataminingmethodsareusedtopredictanoutput
//variable,andregressionisoneofthem.
dataset.setClassIndex(dataset.numAttributes()-1);
现在我们已经将数据载入了WEKA。
虽然比想象中的要稍微难一点,但您可以看到编写自己的包装器类来快速从数据库提取数据并将其放入一个WEKA实例类还是很简单和有益的。
实际上,我强烈建议如果打算在服务器上使用WEKA,那么就不要怕花时间,因为以这种方式处理数据是很繁琐的。
一旦将数据放入了这个实例对象,您就可以在数据上进行任何您想要的数据挖掘了,所以您想要这个步骤尽可能地简单。
让我们把我们的数据通过回归模型进行处理并确保输出与我们使用WekaExplorer计算得到的输出相匹配。
实际上使用WEKAAPI让数据通过回归模型得到处理非常简单,远简单于实际加载数据。
清单5.在WEKA内创建回归模型
//CreatetheLinearRegressionmodel,whichisthedatamining
//modelwe'
reusinginthisexample
LinearRegressionlinearRegression=newLinearRegression();
//Thismethoddoesthe"
magic"
andwillcomputetheregression
//model.Ittakestheentiredatasetwe'
vedefinedtothispoint
//Whenthismethodcompletes,allour"
datamining"
willbecomplete
//anditisuptoyoutogetinformationfromtheresults
linearRegression.buildClassifier(dataset);
//Wearemostinterestedinthecomputedcoefficientsinourmodel,
//sincethosewillbeusedtocomputetheoutputvaluesfroman
//unknowndatainstance.
double[]coef=linearRegression.coefficients();
//Usingthevaluesfrommyhouse(fromthefirstarticle),we
//plugi