学堂 学堂 学堂公众号手机端

数据挖掘技术中的最近邻和服务器端库怎么理解

lewis 1年前 (2024-04-15) 阅读数 11 #技术

这篇文章跟大家分析一下“数据挖掘技术中的最近邻和服务器端库怎么理解”。内容详细易懂,对“数据挖掘技术中的最近邻和服务器端库怎么理解”感兴趣的朋友可以跟着小编的思路慢慢深入来阅读一下,希望阅读后能够对大家有所帮助。下面跟着小编一起深入学习“数据挖掘技术中的最近邻和服务器端库怎么理解”的知识吧。

在我们之前的文章中,我们将 WEKA 用作一种独立的应用程序。那么它在实际中能多有用呢?很显然,它并不完美。由于 WEKA 是一种基于 Java 的应用程序,它有一个可被用在我们自己的服务器端代码中的 Java 库。对于大多数人而言,这可能是最为常见的用法,因为您可以编写代码来不断地分析您的数据并动态地做出调整,而不必依赖他人提取数据、将其转换成 WEKA 格式,然后再在 WEKA Explorer 内运行它。

回页首


最近邻

最近邻(也即 Collaborative Filtering 或 Instance-based Learning)是一种非常有用的数据挖掘技术,可用来用输出值已知的以前的数据实例来预测一个新数据实例的未知输出值。从目前的这种描述看来,最近邻非常类似于回归和分类。那么它与这二者究竟有何不同呢?首先,回归只能用于数值输出,这是它与最近邻的最直接的一个不同点。分类,如我们在前一篇文章的例子中看到的,使用每个数据实例来创建树,我们需要遍历此树才能找到答案。而这一点对于某些数据而言会是一个很严重的问题。举个例子,亚马逊这样的公司常常使用 “购买了 X 的顾客还购买了 Y" 特性,如果亚马逊拟创建一个分类树,那么它将需要多少分支和节点?它的产品多达数十万。这个树将有多巨大呀?如此巨大的一个树能有多精确呢?即便是单个分支,您都将会惊讶地发现它只有三个产品。亚马逊的页面通常会有 12 种产品推荐给您。对于这类数据,分类树是一种极不适合的数据挖掘模型。

而最近邻则可以非常有效地解决所有这些问题,尤其是在上述亚马逊的例子中遇到的这些问题。它不会受限于数量。它的伸缩性对于 20 个顾客的数据库与对于 2000 万个顾客的数据库没有什么差异,并且您可以定义您想要得到的结果数。看起来是一个很棒的技术!它的确很棒 — 并且可能对于那些正在阅读本文的电子商务店铺的店主最为有用。

让我们先来探究一下最近邻背后的数学理论,以便能更好地理解这个过程并了解此技术的某些限制。

最近邻背后的数学理论

最近邻技术背后的数学理论非常类似于群集技术所涉及到的数学理论。对于一个未知的数据点,这个未知数据点与每个已知数据点之间的距离需要被计算出来。如果用电子数据表计算此距离将会非常繁琐,而一个高性能的计算机则可以立即完成这些计算。最容易也是最为常见的一种距离计算方式是 “Normalized Euclidian Distance”。它看起来复杂,实则不然。让我们通过一个例子来弄清楚第 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,然后选择IBkIB代表的是 Instance-Based,而k则允许我们指定要使用的邻的数量)。

图 2. BMW 最近邻算法

现在,我们就准备好可以在 WEKA 内创建我们的模型了。请确保选中Use training set以便我们使用刚载入的这个数据集来创建我们的模型。 单击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 -K 1....”,就会看到一列参数)。可以任意更改 "KNN"(K-最近邻)。在本例中您将会看到随着加入更多的邻,模型的准确率实际上却降低了。

此模型的一些不尽人意之处:当我们谈论像亚马逊这样的数据集时,最近邻的强大威力是显而易见的。对于有 2000 万用户的亚马逊,此算法非常准确,因为在亚马逊的数据库中与您有着类似购买习惯的潜在客户很多。您的最近邻会非常相似。因而,所创建的模型会十分准确和高效。相反,如果能比较的数据点相对很少的话,这个模型很快就会损坏,不再准确。在在线电子商务店铺的初期,比如只有 50 个顾客,那么产品推荐特性很可能一点都不准确,因为最近邻实际上与您本身相差甚远。

最近邻技术最后的一个挑战是该算法的计算成本有可能会很高。在亚马逊的例子中,对于它的 2000 万客户,每个客户都必须针对其他的 2000 万客户进行计算以便找到最近邻。首先,如果您的业务也有 2000 万的客户群,那么这便不成问题,因为您会财源广进。其次,这种类型的计算非常适合用云来完成,因为它们能够被分散到许多计算机上同时完成,并最终完成比较。(比如,Google 的 MapReduce。)第三,实际上,如果我只是购买了一本书,那么根本不必针对我对比亚马逊数据库内的每个客户。只需将我与其他的购书者进行对比来寻找最佳匹配,这样一来,就将潜在的邻缩小到整个数据库的一部分。

请记住:数据挖掘模型并不只是简单的输入-输出机制 — 必须先对数据进行检查以决定该选择哪种正确的模型,让输入能够设法减少计算时间,而输出则必须被分析且要确保准确后才能据此做出整体的判断。

进一步的阅读:如果您有兴趣进一步学习最近邻算法,可以按如下术语搜索相关信息:distance weighting、Hamming distance、Mahalanobis distance。

回页首

在服务器上使用 WEKA

有关 WEKA 最酷的一件事情是它不仅是一个独立的应用程序,而且还是一个完备的 Java JAR 文件,可以将其投入到您服务器的 lib 文件夹并从您自己的服务器端代码进行调用。这能为您的应用程序带来很多有趣的、和重要的功能。您可以添加充分利用了我们到目前所学的全部数据挖掘技术的报告。您可以为您的电子商务店铺创建一个“产品推荐”小部件,类似于亚马逊站点上的那个(由于根本不可能为每个顾客都按需这么做,因此需要贯彻这个独立的应用程序运行它)。WEKA 独立应用程序本身只调用底层的 WEKA Java API,所以您应该已经看到过这个 API 的运转了。现在,我们应该看看如何将它集成到您的自己代码中。

实际上,您已经下载了这个 WEKA API JAR;它就是您启动 WEKA Explorer 时调用的那个 JAR 文件。为了访问此代码,让您的 Java 环境在此类路径中包含这个 JAR 文件。在您自己的代码中使用第三方 JAR 文件的步骤如常。

正如您所想,WEKA API 内的这个中心构建块就是数据。数据挖掘围绕此数据进行,当然所有我们已经学习过的这些算法也都是围绕此数据的。那么让我们看看如何将我们的数据转换成 WEKA API 可以使用的格式。让我们从简单的开始,先来看看本系列有关房子价值的第一篇文章中的那些数据。

: 我最好提前告诫您 WEKA API 有时很难导航。首要的是要复核所用的 WEKA 的版本和 API 的版本。此 API 在不同的发布版间变化会很大,以至于代码可能会完全不同。而且,即便此 API 完备,却没有什么非常好的例子可以帮助我们开始(当然了,这也是为什么您在阅读本文的原因)。我使用的是 WEKA V3.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,那么就不要怕花时间,因为以这种方式处理数据是很繁琐的。一旦将数据放入了这个实例对象,您就可以在数据上进行任何您想要的数据挖掘了,所以您想要这个步骤尽可能地简单。

让我们把我们的数据通过回归模型进行处理并确保输出与我们使用 Weka Explorer 计算得到的输出相匹配。实际上使用 WEKA API 让数据通过回归模型得到处理非常简单,远简单于实际加载数据。

清单 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
//pluginthevaluesandmultiplythembythecoefficients
//thattheregressionmodelcreated.Notethatweskipped
//coefficient[5]asthatis0,becauseitwastheoutput
//variablefromourtrainingdata
doublemyHouseValue=(coef[0]*3198)+
(coef[1]*9669)+
(coef[2]*5)+
(coef[3]*3)+
(coef[4]*1)+
coef[6];

System.out.println(myHouseValue);
//outputs219328.35717359098
//whichmatchestheoutputfromtheearlierarticle

大功告成!运行分类、群集或最近邻都不如回归模型简单,但它们也没有那么困难。运行数据挖掘模型要比将数据载入模型简单得多。

我们希望这一小节能够让您产生将 WEKA 集成到您自己的服务器端代码的兴趣。不管您是运营一个电子商务的店铺并想为客户提供更好的产品推荐,还是您有一个礼券促销活动需要加以改善,抑或是您想要优化您的 AdWords 活动,又或者是您想要优化您的着陆页,这些数据挖掘技术都能帮助您在这些领域改善您的结果。比如,借助于 WEKA API 的内置特性,您就可以编写服务器端代码来轮换您的着陆页并使用数据挖掘不断地分析结果以找到最为有效的着陆页。通过在 AdWords 上综合它与数据挖掘分析,您就可以快速找到最佳的途径来将客户吸引到您的站点并将客户的到访变为销售。

关于数据挖掘技术中的最近邻和服务器端库怎么理解就分享到这里啦,希望上述内容能够让大家有所提升。如果想要学习更多知识,请大家多多留意小编的更新。谢谢大家关注一下博信网站!

版权声明

本文仅代表作者观点,不代表博信信息网立场。

热门