
Weka系列寫到第五篇前四篇我們一直在Explorer里打轉(zhuǎn)。Explorer是真好用選數(shù)據(jù)、選算法、點一下Start就出結果但用上幾輪你一定會遇到兩個問題一是這些操作過程沒有地方保存想復現(xiàn)某次實驗結果只能靠截圖、靠筆記、靠記憶二是數(shù)據(jù)量稍微大一點Explorer加載起來就像拖著一塊鐵板頁面轉(zhuǎn)圈轉(zhuǎn)到讓人懷疑人生。今天要聊的KnowledgeFlow就是專門解決這兩類問題而存在的。它把從讀數(shù)據(jù)、洗數(shù)據(jù)、跑算法到看結果整條鏈路搬到一張畫布上用節(jié)點和連線把流程搭出來執(zhí)行一次就能把整條實驗路徑完整固化下來換數(shù)據(jù)、改參數(shù)、換算法都可以直接在流程上改。這篇文章適合剛把Explorer摸熟、想往正經(jīng)實驗管理方向走的人也適合每天要反復跑模型、需要批量處理數(shù)據(jù)的人。1. Explorer很好用但這兩個場景它確實頂不住1.1 你只能記住“你點過什么”記不住“你為什么要這樣點”Explorer界面的操作邏輯是一次性的打開某個數(shù)據(jù)集、選某個過濾器、換某個分類器、點Start、看結果全部過程中產(chǎn)生的操作路徑只有你自己知道。一旦你關掉Weka下次再想用同樣的參數(shù)組合只能重新在界面里一步一步點。更麻煩的是當你要做對照實驗——同一個數(shù)據(jù)集跑J48和NaiveBayes或者對比歸一化前后效果你得手動切換、重新加載、重新點Start稍不留神就忘了某個參數(shù)改過沒有。KnowledgeFlow的思路完全不同。它把所有環(huán)節(jié)畫成一張流程圖讀數(shù)據(jù)的節(jié)點、做清洗的節(jié)點、跑分類的節(jié)點、看結果的節(jié)點一目了然。你搭好一次流程后以后每次打開布局文件就是把上一次的實驗環(huán)境原封不動恢復出來。連數(shù)據(jù)路徑、算法參數(shù)、評估方式都在里面。對需要寫實驗報告、做復盤、跑周期性模型的人來說這種可復現(xiàn)的流程記錄價值相當大。1.2 數(shù)據(jù)太大Explorer會直接卡給你看Explorer打開數(shù)據(jù)集的邏輯是全量載入內(nèi)存數(shù)據(jù)一多等待時間就會很難受。而且很多時候你只是想快速驗證一條處理鏈路并不想反復把同一份大數(shù)據(jù)文件讀進內(nèi)存。KnowledgeFlow明顯更輕盈它對流程中每個節(jié)點做了更靈活的調(diào)度你可以只讓數(shù)據(jù)流經(jīng)某條分支也可以在需要時才觸發(fā)某些節(jié)點執(zhí)行。如果你面對的是幾十MB甚至GB級別的數(shù)據(jù)Explorer幾乎是一種折磨而KnowledgeFlow至少給了你一個結構化的思路一次讀取多個下游節(jié)點復用同一份數(shù)據(jù)也可以配合Weka支持的增量學習能力對超大數(shù)據(jù)集做流式處理。這一點后面我會專門展開講。2. KnowledgeFlow的界面和五個核心概念2.1 左側(cè)的節(jié)點庫先認識八類節(jié)點在GUI Chooser里啟動KnowledgeFlow會看到一個空白畫布左側(cè)是一棵可展開的樹里面把節(jié)點按功能分類。第一次打開的人容易被密密麻麻的節(jié)點嚇到其實核心就八類節(jié)點分類作用常見節(jié)點DataSources讀取數(shù)據(jù)作為流程起點ArffLoader、CsvLoader、DatabaseLoaderDataSinks把數(shù)據(jù)或結果寫出ArffSaver、CsvSaverFilters數(shù)據(jù)預處理Normalize、Standardize、Remove、ReplaceMissingValuesClassifiers分類模型J48、NaiveBayes、ZeroRClusterers聚類模型SimpleKMeans、EMEvaluators評估模型效果ClassifierPerformanceEvaluator、CrossValidationEvaluatorVisualization可視化數(shù)據(jù)與結果DataVisualizer、ScatterPlot、TextViewer、AttributeSummarizerTools輔助工具數(shù)據(jù)轉(zhuǎn)換節(jié)點、訓練測試集切分節(jié)點等我的建議是先從DataSources、Classifiers、Evaluators、Visualization這四類入手搭通一條最簡單的流程后再慢慢加Filters和Tools。KnowledgeFlow里的節(jié)點很多但絕大多數(shù)是同一個思想在不同場景下的變體核心邏輯是一樣的。2.2 連線不只是“連上去”還得分清連接類型知識流和普通畫圖軟件最大的不同在于連接線是有語義的。你把一個節(jié)點的輸出拖到另一個節(jié)點的輸入時Weka會彈窗讓你選擇“這個連接到底在傳什么類型的數(shù)據(jù)”。比如ArffLoader輸出的是DataSet而J48需要的是TrainingSet和TestSet。數(shù)據(jù)源節(jié)點到J48的連線實際上是在往它的某個輸入端口灌數(shù)據(jù)。所以這條規(guī)則要記牢連線的價值不只是畫一條線而是明確“上游輸出什么、下游接收什么”。常見的連接類型包括DataSet、TrainingSet、TestSet、BatchClassifier、Performance成set等。如果兩個端口之間的類型不匹配連線根本拉不上去或者連接后下游節(jié)點不執(zhí)行。很多新手卡在“為什么我連了線還是不出結果”八成就是端口類型沒選對。2.3 執(zhí)行控制與狀態(tài)展示Restart、Play、StepKnowledgeFlow頂部工具欄提供了Restart、Stop、Play、Step這幾個執(zhí)行控制按鈕它們的邏輯和播放器有點像Restart把整條流程重置到初始狀態(tài)所有節(jié)點的歷史執(zhí)行結果清空數(shù)據(jù)源會重新讀取。改動了流程結構或參數(shù)后建議都先Restart再Play避免下游節(jié)點拿舊數(shù)據(jù)做新計算。Play從當前狀態(tài)開始執(zhí)行所有沒有正確結果的節(jié)點。正常情況下點一次Play整條鏈路會陸續(xù)跑完。Step一步一步執(zhí)行。每一步會只執(zhí)行一個節(jié)點適合排查某個具體環(huán)節(jié)的問題。Stop終止當前正在執(zhí)行的節(jié)點。界面上并不總是能明顯看出某個節(jié)點跑沒跑完最直觀的判斷方式是看右下角日志面板。每條日志會寫明哪個節(jié)點開始執(zhí)行、耗時多少、有沒有報錯。我后來幾乎不看圖標顏色只看日志因為不同Weka版本里節(jié)點狀態(tài)的樣式不完全一樣日志才是統(tǒng)一可靠的依據(jù)。3. 搭一條最簡單的分類流水線Iris全流程走查3.1 需要的節(jié)點清單和為什么這么選紙上談兵沒有意義我們直接動手搭一條最經(jīng)典的分類流水線。我用的是Weka自帶的iris數(shù)據(jù)集它小、干凈、類別少適合驗證流程。需要拖進畫布的節(jié)點如下兩個ArffLoader一個讀訓練集一個讀測試集。實際使用中你可以把同一個arff文件分別指給兩個Loader也可以一個用train.arff一個用test.arff。一個J48分類器決策樹算法參數(shù)少跑得快用來驗證KnowledgeFlow的連線邏輯非常合適。一個ClassifierPerformanceEvaluator負責把分類器的預測結果做成評估報告。一個TextViewer展示評估報告文本。一個DataVisualizer可視化訓練集的數(shù)據(jù)結構幫助我們驗證數(shù)據(jù)有沒有被正確讀取。這套組合是最小可用配置兩個數(shù)據(jù)源負責喂數(shù)據(jù)分類器負責建模評估器負責算指標兩個顯示節(jié)點負責把結果攤開看。3.2 一條條連線怎么連訓練集、測試集、batchClassifier節(jié)點拖進來之后連線才是重點。下面按實際連接順序走一遍首先把第一個ArffLoader的輸出端口DataSet拖到J48的輸入端口上此時會彈出選擇連接類型的對話框。這里要選TrainingSet意思是“這份數(shù)據(jù)作為訓練數(shù)據(jù)”。同樣第二個ArffLoader的輸出端口拖到J48的另一個輸入端口選擇TestSet。這里特別提醒J48如果只連了TrainingSet沒有連TestSet運行后只會得到在訓練集上評估的結果不能用來衡量真實泛化能力。很多人第一次跑通后看到準確率接近100%還特別高興其實就是把TestSet漏了。然后把J48的輸出端口拖到ClassifierPerformanceEvaluator的輸入端口連接類型選擇BatchClassifier或?qū)姆诸惼鬏敵鲱愋?。J48作為基分類器執(zhí)行完會輸出一個寫好的模型對象給評估器。最后把ClassifierPerformanceEvaluator的輸出端口Text拖到TextViewer的輸入端口Text并讓第一個或第二個ArffLoader的輸出端口直接拖到DataVisualizer的輸入端口用于展示數(shù)據(jù)分布。DataVisualizer是可以直接接收DataSet的連接時選對應端口即可。注意這個可視化分支和訓練測試分支是并行的互不影響。3.3 運行與驗證TextViewer里看到的結果長什么樣連線完畢先點Restart再點Play等待右下角日志不再滾動。然后右鍵點擊TextViewer選擇“Show”打開窗口。正常情況下你能看到分類器信息J48構建出的決策樹結構。評估摘要Correctly Classified Instances的數(shù)目和百分比?;煜仃嚸總€類別哪些樣本被分對、哪些被分錯。我一般先做三件事確認流程正確第一看評估摘要里的實例條數(shù)是不是和測試集大小一致第二看決策樹是否生成第三看DataVisualizer里的點是否明顯分簇。如果這三項都對說明整條流水線已經(jīng)通了后面往里面加處理步驟就只是習慣問題。DataVisualizer的使用也很簡單打開后點右上角一欄下拉框選擇兩個屬性作為橫縱坐標再點更新就能看到數(shù)據(jù)點的分布。還有一個實用的選項是“Colour”下拉框選擇類屬性后不同類別的點會用不同顏色顯示分簇效果一目了然。做完這個實驗你就會明白為什么iris數(shù)據(jù)集是機器學習入門必備也明白KnowledgeFlow比Explorer好在哪所有環(huán)節(jié)都能同時放在眼前。3.4 參數(shù)改動的“熱折騰”改了J48參數(shù)要不要重來場景你跑通之后想改J48的參數(shù)比如從默認置信度改為更保守的置信度。在KnowledgeFlow里修改J48的參數(shù)后并不是只重跑J48就行所有下游節(jié)點其實都依賴它的輸出最穩(wěn)妥的做法是先Restart把整條流程置為初始狀態(tài)再Play。為什么不能只重跑J48因為ClassifierPerformanceEvaluator和TextViewer可能仍保留上一次執(zhí)行的輸出結果界面顯示的會舊數(shù)據(jù)。KnowledgeFlow不像Explorer那樣每次點Start都是一次全新計算它的節(jié)點有“當前結果”的概念舊結果不會自動清掉。所以我在實踐里養(yǎng)成了一個習慣任何一次參數(shù)修改后都只使用“Restart Play”這一組組合不做局部執(zhí)行。這樣可以避免把舊結果當新結果看。4. 過濾器、分支和增量學習讓流水線干更復雜的活4.1 過濾器節(jié)點把Normalize單獨拉出來接在數(shù)據(jù)源后面Explorer里使用過濾器是在預處理面板里操作的而在KnowledgeFlow中過濾器就是一個獨立節(jié)點。它接收DataSet輸出處理后的DataSet完全符合“數(shù)據(jù)流”的思想。舉個例子你想比較iris數(shù)據(jù)不做歸一化和做歸一化后的J48準確率。那么大致的畫布結構是ArffLoader1 → J48的TrainingSetArffLoader1 → Normalize → J48的TrainingSet等等這里有個容易犯糊涂的地方一個J48節(jié)點只有兩個輸入端口TrainingSet和TestSet不能同時接收兩份不同的訓練數(shù)據(jù)并自動做對比。正確做法是再拖一個J48實例一個接原始數(shù)據(jù)一個接歸一化后的數(shù)據(jù)。也就是說一份ArffLoader輸出可以分成兩支一支直接去J48一支先經(jīng)過Normalize再去另一個J48。這恰恰是KnowledgeFlow的優(yōu)勢原始數(shù)據(jù)可以被多個下游節(jié)點復用你不需要為每個實驗重新加載文件。畫布上可以看到數(shù)據(jù)源出來了多條線分而治之互不干擾。4.2 一個數(shù)據(jù)源拖出多個分支同時看多種結果在實際項目中很多人會把同一個數(shù)據(jù)源同時接到分類器、評估器、可視化器和保存節(jié)點上構成一個多路輸出的并行結構。KnowledgeFlow對這類結構支持得相當好因為每個節(jié)點的輸出端口可以同時拉出多根連線數(shù)據(jù)并不會被“復制消耗”。舉個例子ArffLoader1 → J48 → ClassifierPerformanceEvaluator → TextViewerArffLoader1 → DataVisualizerArffLoader1 → ArffSaver同樣是讀取一份數(shù)據(jù)既可以訓練模型、查看評估報告又可以可視化數(shù)據(jù)分布還可以把原始數(shù)據(jù)保存到另一個文件。整個流程只讀一次數(shù)據(jù)非常節(jié)省時間。這里補充一個實用技巧如果畫布上節(jié)點太多太亂可以按住鼠標左鍵框選多個節(jié)點拖動調(diào)整位置。連線會跟著節(jié)點走不會斷掉。如果數(shù)據(jù)源輸出連了很多條了后續(xù)還想要一條新分支直接從源節(jié)點的輸出端口再拉一根線出去就行不用從頭再來。4.3 超大數(shù)據(jù)集與增量評估NaiveBayesUpdateable使用場景回到文章開頭提到的痛點數(shù)據(jù)太大Explorer卡死。KnowledgeFlow對這個問題的解法之一是增量學習。所謂增量學習就是算法不用一次性看到全部數(shù)據(jù)而是來一條學一條邊讀邊更新模型。Weka里有一批帶“Updateable”后綴的分類器比如NaiveBayesUpdateable。用KnowledgeFlow跑增量學習的流程和普通分類流程有區(qū)別關鍵點在于要使用IncrementalClassifierEvaluator來評估。它和普通評估器的差別是普通評估器要拿到整個測試集才能算指標增量評估器則是接收一個實例實例、更新一個模型不斷累計指標。連接方式稍復雜但基本思路是一樣的數(shù)據(jù)源不斷產(chǎn)生實例分類器不斷學習評估器持續(xù)跟蹤效果。這種情況對大數(shù)據(jù)集特別有價值。你不再需要一個超大文件一次性在內(nèi)存里展開數(shù)據(jù)源可以逐條喂給算法。當然要真正處理超出內(nèi)存的數(shù)據(jù)量仍需配合硬件和JVM內(nèi)存設置。Weka的啟動方式里可以在啟動腳本中為JVM分配更多堆內(nèi)存。例如java -Xmx4g -jar weka.jar這個命令會以4GB堆內(nèi)存啟動Weka界面。如果數(shù)據(jù)達到幾十GB那已經(jīng)超出Weka單機處理的舒適區(qū)應該考慮抽樣或者分布式方案不能用Weka硬扛。KnowledgeFlow的增量機制可以緩解內(nèi)存壓力但不是萬能的。5. 我在實際項目里踩過的KnowledgeFlow坑5.1 連線沒連對節(jié)點就是不執(zhí)行trainingSet和dataset的區(qū)別我第一次跑通KnowledgeFlow用了很久卡的最狠的一次是J48節(jié)點接到了ArffLoader的輸出畫布上連線清清楚楚但點擊Play之后J48毫無反應。后來才明白我把連接類型選成了Dataset而不是TrainingSet。J48作為一個分類器在啟動訓練前必須拿到TrainingSet如果只拿到一個普通Dataset它不知道應該用這份數(shù)據(jù)做什么。這個坑在官方文檔里提過但新手第一次接觸端口類型時很容易忽略。每當節(jié)點不執(zhí)行先右鍵點開節(jié)點查看輸入端口是否都滿足再檢查連接類型。這是排查KnowledgeFlow問題時的第一反應而不是去懷疑軟件出了bug。5.2 保存布局后數(shù)據(jù)路徑失效.kf文件只記路徑不搬數(shù)據(jù)KnowledgeFlow的布局文件后綴是.kf里面保存了節(jié)點的位置、參數(shù)和連接關系以及數(shù)據(jù)源的讀取路徑。問題在于如果你把.kf文件拷貝到另一臺電腦或者把arff文件挪了位置打開布局后ArffLoader往往找不到數(shù)據(jù)。解決辦法很樸素把布局文件和所有使用的arff數(shù)據(jù)集放到同一個目錄里并保持相對路徑一致。舉例來說如果布局文件名叫“實驗1.kf”和“train.arff”“test.arff”放在一個文件夾打開布局后通常能正常加載。如果打開后發(fā)現(xiàn)讀取節(jié)點報錯優(yōu)先打開ArffLoader的屬性窗口重新選擇數(shù)據(jù)文件路徑再Restart執(zhí)行。另一個相關的坑如果你在團隊里共享布局文件同事那邊的Weka版本不一致某些節(jié)點的默認參數(shù)可能有差異導致結果不完全一致。所以做嚴肅實驗記錄時除了保存.kf布局最好把每個關鍵節(jié)點的參數(shù)用截圖或文字記錄下來避免只依賴布局文件。5.3 過濾一遍等于只改這一路分支上的數(shù)據(jù)不是全局生效很多新手以為在流程里接了一個Normalize節(jié)點就相當于“全局把數(shù)據(jù)清洗了”后面所有節(jié)點都會自動應用歸一化。但KnowledgeFlow沒有這種全局狀態(tài)它的數(shù)據(jù)是嚴格沿著連線流動的。你從ArffLoader拉出一根線接到Normalize那只有沿著Normalize繼續(xù)走的分支會拿到歸一化數(shù)據(jù)你如果另有分支直接從ArffLoader接到某個分類器那條路的數(shù)據(jù)仍然是原始數(shù)據(jù)。這個設計初看讓人不太習慣但它非常符合真實數(shù)據(jù)管道的思想每個環(huán)節(jié)的數(shù)據(jù)是否被處理過看的是它的上游鏈路而不是整個流程里有沒有某個過濾器節(jié)點。我在實際項目里就遇到過這種問題以為所有節(jié)點都統(tǒng)一用了歸一化數(shù)據(jù)結果后來發(fā)現(xiàn)只有一個分支做了歸一化另一個分支用的是原始數(shù)據(jù)模型對比結論完全偏離了。所以在復雜流程里要針對每個模型節(jié)點自問一句它連的到底是原始分支還是處理后的分支5.4 日志和狀態(tài)顏色判斷“卡住”還是“正在跑”KnowledgeFlow執(zhí)行的時候如果數(shù)據(jù)量很大某些節(jié)點會持續(xù)一段時間。新手容易把正在執(zhí)行的流程誤判為卡死不停點Stop或者關閉界面。我一般這么判斷看右下角日志面板如果每隔一小段時間就有新日志滾動出來說明流程還在跑如果長時間沒有新日志并且沒有任何節(jié)點處于執(zhí)行中的狀態(tài)才有可能真的卡住了。還有一個小經(jīng)驗在跑大數(shù)據(jù)集或復雜參數(shù)時先把Weka的日志級別調(diào)高讓日志面板輸出更多執(zhí)行信息排查起來省力很多。日志里出現(xiàn)報錯信息時不要只看最后的報錯往上翻幾行找到是哪個節(jié)點先出錯通常問題就出在那個節(jié)點的上游。5.5 實驗管理的小習慣執(zhí)行完立刻另存布局最后分享一個我在實際工作中養(yǎng)成的習慣每次跑完一通流程確定結果正確后立刻將布局“另存為”一個帶日期和實驗目的的.kf文件。文件名起得像實驗記錄一樣比如“iris-對比歸一化-0503.kf”。這樣即使過了幾個月也能快速知道這個布局是為了驗證什么跑的、用的什么數(shù)據(jù)、連接結構是什么。我見過不少人在Explorer里隨機點了一堆操作后因為沒保存跑了很久的實驗結果只能拿截圖交差。KnowledgeFlow的本質(zhì)優(yōu)勢就是讓實驗流程變得可以固化、可以復現(xiàn)、可以交接。如果只是把Explorer的操作習慣搬到KnowledgeFlow上那反而浪費了這個工具的設計初衷。如果你的實驗越來越復雜下一步可以嘗試把流程里重復出現(xiàn)的分支封裝成子流程或者用Weka的KnowledgeFlow配合命令行批量執(zhí)行再做進一步的自動化。到那個時候你已經(jīng)不是在“用工具”而是在“搭實驗系統(tǒng)”了。