用 WEKA 进行数据挖掘,第 3 部分: 最近邻和服务器端库
from:http://www.ibm.com/developerworks/cn/opensource/os-weka3/index.html
簡介
在這個 “用 WEKA 進行數據挖掘” 系列之前的兩篇文章中,我介紹了數據挖掘的概念。如果您還未曾閱讀過?用 WEKA 進行數據挖掘,第 1 部分:簡介和回歸?和?用 WEKA 進行數據挖掘,第 2 部分:分類和群集,那么請先閱讀這兩個部分,因為二者涵蓋了一些在繼續之前必須了解的關鍵概念。而且更重要的是,在這兩個部分中我談及了數據挖掘中常用的三種技術,它們可以將難以理解的無用數據轉變為有意義的規則和趨勢。第一種技術是回歸,用來基于其他的示例數據預測一個數值輸出(比如房屋價值)。第二種技術是分類(即分類樹或決策樹),用來創建一個實際的分支樹來預測某個未知數據點的輸出值。(在我們的例子中,我們預測的是對 BMW 促銷活動的反應。)我介紹的第三種技術是群集,可用它來創建數據組(群集)并從中識別出趨勢和其他規則(在我們的例子中,即 BMW 的銷售)。三者的相似點在于它們都能將數據轉換成有用信息,但它們各自的實現方法以及使用的數據各不相同,而這正是數據挖掘最為重要的一點:正確的模型必須用于正確的數據。
本文將討論四種常用的數據挖掘技術中的最后一種:最近鄰。您將看到它更像是分類與群集的組合,并為我們消滅數據誤導的使命提供了另一種有用的武器。
在我們之前的文章中,我們將 WEKA 用作一種獨立的應用程序。那么它在實際中能多有用呢?很顯然,它并不完美。由于 WEKA 是一種基于 Java 的應用程序,它有一個可被用在我們自己的服務器端代碼中的 Java 庫。對于大多數人而言,這可能是最為常見的用法,因為您可以編寫代碼來不斷地分析您的數據并動態地做出調整,而不必依賴他人提取數據、將其轉換成 WEKA 格式,然后再在 WEKA Explorer 內運行它。
回頁首
最近鄰
最近鄰(也即 Collaborative Filtering 或 Instance-based Learning)是一種非常有用的數據挖掘技術,可用來用輸出值已知的以前的數據實例來預測一個新數據實例的未知輸出值。從目前的這種描述看來,最近鄰非常類似于回歸和分類。那么它與這二者究竟有何不同呢?首先,回歸只能用于數值輸出,這是它與最近鄰的最直接的一個不同點。分類,如我們在前一篇文章的例子中看到的,使用每個數據實例?來創建樹,我們需要遍歷此樹才能找到答案。而這一點對于某些數據而言會是一個很嚴重的問題。舉個例子,亞馬遜這樣的公司常常使用 “購買了 X 的顧客還購買了 Y" 特性,如果亞馬遜擬創建一個分類樹,那么它將需要多少分支和節點?它的產品多達數十萬。這個樹將有多巨大呀?如此巨大的一個樹能有多精確呢?即便是單個分支,您都將會驚訝地發現它只有三個產品。亞馬遜的頁面通常會有 12 種產品推薦給您。對于這類數據,分類樹是一種極不適合的數據挖掘模型。
而最近鄰則可以非常有效地解決所有這些問題,尤其是在上述亞馬遜的例子中遇到的這些問題。它不會受限于數量。它的伸縮性對于 20 個顧客的數據庫與對于 2000 萬個顧客的數據庫沒有什么差異,并且您可以定義您想要得到的結果數。看起來是一個很棒的技術!它的確很棒 — 并且可能對于那些正在閱讀本文的電子商務店鋪的店主最為有用。
讓我們先來探究一下最近鄰背后的數學理論,以便能更好地理解這個過程并了解此技術的某些限制。
最近鄰背后的數學理論
最近鄰技術背后的數學理論非常類似于群集技術所涉及到的數學理論。對于一個未知的數據點,這個未知數據點與每個已知數據點之間的距離需要被計算出來。如果用電子數據表計算此距離將會非常繁瑣,而一個高性能的計算機則可以立即完成這些計算。最容易也是最為常見的一種距離計算方式是 “Normalized Euclidian Distance”。它看起來復雜,實則不然。讓我們通過一個例子來弄清楚第 5 個顧客有可能會購買什么產品?
清單 1. 最近鄰的數學理論
Customer Age Income Purchased Product 1 45 46k Book 2 39 100k TV 3 35 38k DVD 4 69 150k Car Cover 5 58 51k ???Step 1: Determine Distance Formula Distance = SQRT( ((58 - Age)/(69-35))^2) + ((51000 - Income)/(150000-38000))^2 )Step 2: Calculate the Score Customer Score Purchased Product 1 .385 Book 2 .710 TV 3 .686 DVD 4 .941 Car Cover 5 0.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 數據
@attribute IncomeBracket {0,1,2,3,4,5,6,7} @attribute FirstPurchase numeric @attribute LastPurchase numeric @attribute responded {1,0}@data4,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 內創建我們的模型了。請確保選中?Use training set?以便我們使用剛載入的這個數據集來創建我們的模型。 單擊?Start,讓 WEKA 運行。圖 3 顯示了一個屏幕快照,清單 3 則包含了此模型的輸出。
圖 3. BMW 最近鄰模型
清單 3. IBk 計算的輸出
=== Evaluation on training set === === Summary ===Correctly Classified Instances 2663 88.7667 % Incorrectly Classified Instances 337 11.2333 % Kappa statistic 0.7748 Mean absolute error 0.1326 Root mean squared error 0.2573 Relative absolute error 26.522 % Root relative squared error 51.462 % Total Number of Instances 3000 === Detailed Accuracy By Class ===TP Rate FP Rate Precision Recall F-Measure ROC Area Class0.95 0.177 0.847 0.95 0.896 0.972 10.823 0.05 0.941 0.823 0.878 0.972 0 Weighted Avg. 0.888 0.114 0.893 0.888 0.887 0.972=== Confusion Matrix ===a b <-- classified as1449 76 | a = 1261 1214 | 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
// Define each attribute (or column), and give it a numerical column number // Likely, a better design wouldn't require the column number, but // would instead get it from the index in the container Attribute a1 = new Attribute("houseSize", 0); Attribute a2 = new Attribute("lotSize", 1); Attribute a3 = new Attribute("bedrooms", 2); Attribute a4 = new Attribute("granite", 3); Attribute a5 = new Attribute("bathroom", 4); Attribute a6 = new Attribute("sellingPrice", 5);// Each element must be added to a FastVector, a custom // container used in this version of Weka. // Later versions of Weka corrected this mistake by only // using an ArrayList FastVector attrs = new FastVector(); attrs.addElement(a1); attrs.addElement(a2); attrs.addElement(a3); attrs.addElement(a4); attrs.addElement(a5); attrs.addElement(a6);// Each data instance needs to create an Instance class // The constructor requires the number of columns that // will be defined. In this case, this is a good design, // since you can pass in empty values where they exist. Instance i1 = new Instance(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);....// Each Instance has to be added to a larger container, the // Instances class. In the constructor for this class, you // must give it a name, pass along the Attributes that // are used in the data set, and the number of // Instance objects to be added. Again, probably not ideal design // to require the number of objects to be added in the constructor, // especially since you can specify 0 here, and then add Instance // objects, and it will return the correct value later (so in // other words, you should just pass in '0' here) Instances dataset = new Instances("housePrices", attrs, 7); dataset.add(i1); dataset.add(i2); dataset.add(i3); dataset.add(i4); dataset.add(i5); dataset.add(i6); dataset.add(i7);// In the Instances class, we need to set the column that is // the output (aka the dependent variable). You should remember // that some data mining methods are used to predict an output // variable, and regression is one of them. dataset.setClassIndex(dataset.numAttributes() - 1);現在我們已經將數據載入了 WEKA。雖然比想象中的要稍微難一點,但您可以看到編寫自己的包裝器類來快速從數據庫提取數據并將其放入一個 WEKA 實例類還是很簡單和有益的。實際上,我強烈建議如果打算在服務器上使用 WEKA,那么就不要怕花時間,因為以這種方式處理數據是很繁瑣的。一旦將數據放入了這個實例對象,您就可以在數據上進行任何您想要的數據挖掘了,所以您想要這個步驟盡可能地簡單。
讓我們把我們的數據通過回歸模型進行處理并確保輸出與我們使用 Weka Explorer 計算得到的輸出相匹配。實際上使用 WEKA API 讓數據通過回歸模型得到處理非常簡單,遠簡單于實際加載數據。
清單 5. 在 WEKA 內創建回歸模型
// Create the LinearRegression model, which is the data mining // model we're using in this example LinearRegression linearRegression = new LinearRegression();// This method does the "magic", and will compute the regression // model. It takes the entire dataset we've defined to this point // When this method completes, all our "data mining" will be complete // and it is up to you to get information from the results linearRegression.buildClassifier(dataset);// We are most interested in the computed coefficients in our model, // since those will be used to compute the output values from an // unknown data instance. double[] coef = linearRegression.coefficients();// Using the values from my house (from the first article), we // plug in the values and multiply them by the coefficients // that the regression model created. Note that we skipped // coefficient[5] as that is 0, because it was the output // variable from our training data double myHouseValue = (coef[0] * 3198) +(coef[1] * 9669) +(coef[2] * 5) +(coef[3] * 3) +(coef[4] * 1) +coef[6];System.out.println(myHouseValue); // outputs 219328.35717359098 // which matches the output from the earlier article大功告成!運行分類、群集或最近鄰都不如回歸模型簡單,但它們也沒有那么困難。運行數據挖掘模型要比將數據載入模型簡單得多。
我們希望這一小節能夠讓您產生將 WEKA 集成到您自己的服務器端代碼的興趣。不管您是運營一個電子商務的店鋪并想為客戶提供更好的產品推薦,還是您有一個禮券促銷活動需要加以改善,抑或是您想要優化您的 AdWords 活動,又或者是您想要優化您的著陸頁,這些數據挖掘技術都能幫助您在這些領域改善您的結果。比如,借助于 WEKA API 的內置特性,您就可以編寫服務器端代碼來輪換您的著陸頁并使用數據挖掘不斷地分析結果以找到最為有效的著陸頁。通過在 AdWords 上綜合它與數據挖掘分析,您就可以快速找到最佳的途徑來將客戶吸引到您的站點并將客戶的到訪變為銷售。
回頁首
結束語
本文是由三篇文章組成的系列文章的終結篇,該系列向您介紹了數據挖掘的概念尤其是 WEKA 軟件。正如您所見,WEKA 可以完成很多在商業軟件包中才能完成的數據挖掘任務。WEKA 功能強大且 100 % 免費。像這樣的好事絕無僅有,因為您可以迅速啟動 WEKA 并即刻就開始處理您的數據。
本文探究了第四種常見的數據挖掘算法,“最近鄰”。這種算法非常適合于尋找接近于一個未知數據點的那些數據點并使用來自這些值的已知輸出來預測未知輸出。我向您展示了這種數據挖掘為何對在線購物網站上的推薦產品功能非常理想。通過一些數據挖掘,像亞馬遜這樣的站點可以快速(對于這類站點是最起碼的,因為有數千臺計算機)告訴您與您類似的其他顧客購買的東西。
本文的最后一節顯示了您不應該將自己限制于只使用 WEKA 與 Explorer 窗口作為一個獨立的應用程序。WEKA 還能被用作一個獨立的 Java 庫,您可以將其放入到您服務器端的環境內并像其他 Java 庫那樣調用它的 API。我向您展示了您如何能將數據載入此 WEKA API(并且建議您花些時間圍繞您的數據庫編寫一個漂亮的包裝程序以便讓這個過于復雜的過程簡單一些)。最后,我向您展示了創建一個回歸模型并從獲自此獨立應用程序的這個 API 獲得相同的結果是多么地容易。
我對使用此 API 的最后一點建議是通讀相關文檔并花些時間來閱讀所提供的全部可用函數。我發現這個 API 多少有點難以使用,所以如果事先仔細地研讀就能順利地使用它,而不至于最終將它扔入回收站。
希望,在閱讀完本系列后,您能躍躍欲試地下載 WEKA 并嘗試從您自己的數據中找到模式和規則。
回頁首
下載
| os-weka3-Examples.zip | 17KB |
參考資料
學習
- WEKA 要求所有關于它的出版物都必須提及這篇題為 “The WEKA Data Mining Software: An Update” (作者 Mark Hall、Eibe Frank、Geoffrey Holmes、Bernhard Pfahringer Peter Reutemann 和 Ian H. Witten)的論文。
- 查閱?WEKA Web 站點?獲得此軟件的所有文檔和一個 FAQ。
- 查閱?WEKA Java API。
- 閱讀有關?ARFF?的詳細信息,以便您可以將數據載入 WEKA。
- IBM 有自己的數據挖掘軟件, “?將 InfoSphere Warehouse 數據挖掘與 IBM Cognos 報告集成,第 1 部分: InfoSphere Warehouse 與 Cognos 集成架構概述” 提供了一個很好的起點。
- 要收聽面向軟件開發人員的有趣訪談和討論,請訪問?developerWorks 播客。
- 隨時關注 developerWorks?技術活動和網絡廣播。
- 查閱最近將在全球舉辦的面向 IBM 開放源碼開發人員的研討會、交易展覽、網絡廣播和其他活動。
- 訪問 developerWorks?Open source 專區獲得豐富的 how-to 信息、工具和項目更新以及最受歡迎的文章和教程,幫助您用開放源碼技術進行開發,并將它們與 IBM 產品結合使用。
- developerWorks 社區?是流行社區的一個成功典范,包含廣泛的主題。
- 查看免費的?developerWorks 演示中心,觀看并了解 IBM 及開源技術和產品功能。
獲得產品和技術
- 下載 WEKA?并在您自己的系統上運行它。
- 使用?IBM 產品評估試用版軟件?改進您的下一個開源開發項目,這些軟件可以通過下載獲得。
- 下載?IBM 產品評估試用版軟件?或?IBM SOA Sandbox for People?并使用來自 DB2?、Lotus?、Rational?、Tivoli? 和 WebSphere? 的應用程序開發工具和中間件產品。
討論
- 此外,請查閱 My developerWorks 上的這個新的?Data Mining?組。
- 參與?developerWorks 博客?并加入 developerWorks 社區。
總結
以上是生活随笔為你收集整理的用 WEKA 进行数据挖掘,第 3 部分: 最近邻和服务器端库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用 WEKA 进行数据挖掘,第 2 部分
- 下一篇: 文本深度表示模型Word2Vec