據(jù)挖掘?qū)崙?zhàn):從CSV到ARFF的完整預(yù)處理與避坑指南)
簡介這份文檔面向數(shù)據(jù)挖掘與機(jī)器學(xué)習(xí)初學(xué)者系統(tǒng)講解WEKA這一公開數(shù)據(jù)挖掘工作平臺的操作入門知識幫助讀者快速理解平臺的數(shù)據(jù)組織方式與核心功能。內(nèi)容圍繞WEKA的數(shù)據(jù)格式與術(shù)語展開涵蓋實(shí)例、屬性、關(guān)系等基本概念并詳細(xì)說明ARFF文件的頭信息與數(shù)據(jù)信息結(jié)構(gòu)包括關(guān)系聲明、屬性聲明及numeric、nominal、string、date四種數(shù)據(jù)類型同時(shí)介紹從CSV、Excel、Matlab等格式準(zhǔn)備數(shù)據(jù)的思路。資源包為1個(gè)doc文檔大小約172KB便于下載后離線閱讀與查閱。WEKA集合了數(shù)據(jù)預(yù)處理、分類、回歸、聚類、關(guān)聯(lián)規(guī)則與可視化等算法接口開放可集成自定義算法或借鑒其方法實(shí)現(xiàn)可視化工具曾獲ACM SIGKDD數(shù)據(jù)挖掘與知識探索最高服務(wù)獎(jiǎng)。目前已有791人學(xué)習(xí)適合希望以WEKA為工具入門數(shù)據(jù)挖掘?qū)嵺`、需要一份簡明操作指引的讀者參考。1. 從一份 weather.arff 說起WEKA 到底能幫你把數(shù)據(jù)挖到什么程度很多人第一次打開 WEKA看到那個(gè)鳥標(biāo)和一堆按鈕心里是發(fā)懵的。我當(dāng)年也是手里攥著一份 CSV想跑個(gè)分類看看效果結(jié)果卡在“數(shù)據(jù)怎么進(jìn)去”這一步整整一個(gè)下午。WEKA 的全稱是懷卡托智能分析環(huán)境Waikato Environment for Knowledge Analysis由新西蘭懷卡托大學(xué)開發(fā)2005 年在第 11 屆 ACM SIGKDD 國際會議上拿了數(shù)據(jù)挖掘和知識探索領(lǐng)域的最高服務(wù)獎(jiǎng)算下來發(fā)展歷史已經(jīng)超過二十年。它把分類、回歸、聚類、關(guān)聯(lián)規(guī)則、數(shù)據(jù)預(yù)處理和可視化全部塞進(jìn)一個(gè)圖形界面里而且接口開放你能看它的接口文檔也能把自己的算法集成進(jìn)去。這篇文章不講空泛的“數(shù)據(jù)挖掘概論”只講一件事拿到一份 CSV 或 Excel怎么一步步變成 WEKA 能吃的 ARFF怎么在 Explorer 里做預(yù)處理怎么避開那些讓人想砸鍵盤的坑。適合手里有數(shù)據(jù)、想快速驗(yàn)證想法、又不想一上來就寫幾百行 Python 的從業(yè)者。2. ARFF 文件結(jié)構(gòu)拆解從 relation 到 data 的每一行2.1 頭信息與數(shù)據(jù)信息的分界線WEKA 處理的數(shù)據(jù)集在邏輯上就是一張二維表格一行叫一個(gè)實(shí)例Instance一列叫一個(gè)屬性Attribute整張表呈現(xiàn)的關(guān)系叫 Relation。它存儲數(shù)據(jù)的格式是 ARFFAttribute-Relation File Format本質(zhì)是一個(gè) ASCII 文本文件。以 WEKA 安裝目錄data子目錄下的weather.arff為例去掉以%開頭的注釋行之后整個(gè)文件被data標(biāo)記切成兩半上半部分是頭信息Head information負(fù)責(zé)聲明關(guān)系名稱和屬性定義下半部分是數(shù)據(jù)信息Data information就是逗號分隔的實(shí)際數(shù)值。關(guān)系聲明必須是第一個(gè)有效行格式是relation relation-name。如果名稱里帶空格必須用英文單引號或雙引號包起來否則 WEKA 解析直接報(bào)錯(cuò)。屬性聲明用attribute開頭每個(gè)屬性一行順序極其重要——它決定了數(shù)據(jù)部分每一列對應(yīng)哪個(gè)屬性。比如humidity是第三個(gè)被聲明的屬性那數(shù)據(jù)部分每行用逗號切開后的第三個(gè)數(shù)就是 humidity 的值。最后一個(gè)聲明的屬性默認(rèn)被當(dāng)作 class 屬性在分類或回歸任務(wù)里就是目標(biāo)變量。2.2 四種數(shù)據(jù)類型與日期格式的寫法WEKA 支持的屬性類型有四種numeric數(shù)值型、nominal-specification分類型用花括號列出所有可能取值、string字符串型、date [date-format]日期時(shí)間型。分類型的寫法是attribute outlook {sunny, overcast, rainy}花括號里的值區(qū)分大小寫。日期型稍微特殊格式是attribute name date [date-format]默認(rèn)格式是 ISO-8601 的yyyy-MM-ddTHH:mm:ss。如果你數(shù)據(jù)里的日期是2024/01/15這種斜杠分隔的寫法就必須在聲明里顯式指定date yyyy/MM/dd否則 WEKA 會把它當(dāng)成字符串或者直接解析失敗。下面是一個(gè)最小可用的 ARFF 模板你可以直接抄去改relation my_dataset attribute age numeric attribute income numeric attribute student {yes, no} attribute credit_rating {fair, excellent} attribute buys_computer {yes, no} data 25,50000,yes,fair,no 30,80000,no,excellent,yes 35,60000,yes,fair,yes這段聲明里age和income是數(shù)值型student、credit_rating、buys_computer是分類型。buys_computer放在最后自動成為目標(biāo)變量。數(shù)據(jù)部分每行五個(gè)值順序必須和屬性聲明完全一致少一個(gè)逗號或者多一個(gè)空格都可能讓 WEKA 讀出一堆問號。注意ARFF 文件里不要用中文標(biāo)點(diǎn)逗號必須是英文逗號花括號和引號也必須是英文半角。我見過有人從 Word 里復(fù)制屬性名結(jié)果引號是彎的WEKA 直接報(bào)Unable to determine structure as arff。3. 把 CSV 和 Excel 喂給 WEKA轉(zhuǎn)換命令與 Explorer 預(yù)處理實(shí)操3.1 CSV 轉(zhuǎn) ARFF 的兩條路WEKA 原生支持 CSV但有個(gè)硬性要求CSV 第一行必須是屬性名。很多從 Matlab 導(dǎo)出的 CSV 沒有表頭Excel 另存為 CSV 時(shí)也可能丟掉表頭這時(shí)候直接丟給 WEKA它會把第一行數(shù)據(jù)當(dāng)成變量名后面全亂套。常見做法是先用 UltraEdit 或 VS Code 打開 CSV手工補(bǔ)一行屬性名屬性個(gè)數(shù)必須和數(shù)據(jù)列數(shù)一致用英文逗號隔開。補(bǔ)好表頭之后轉(zhuǎn)換最快的方式是走 WEKA 的 Simple CLI。啟動 WEKA 主程序點(diǎn)下方Simple CLI按鈕在窗口最下方的輸入框里敲java weka.core.converters.CSVLoader bank-data.csv bank-data.arff這條命令調(diào)用CSVLoader類讀取bank-data.csv把標(biāo)準(zhǔn)輸出重定向到bank-data.arff。注意路徑問題如果 CSV 不在 WEKA 當(dāng)前工作目錄下要么寫絕對路徑要么先cd過去。轉(zhuǎn)換完成后用文本編輯器打開 ARFF 檢查一下重點(diǎn)看attribute的類型是不是合理——WEKA 會自動推斷數(shù)值列給numeric文本列給nominal但有時(shí)候會把本該是分類的列推斷成string那就需要手動改。另一條路是在 Explorer 里操作打開 WEKA進(jìn)Explorer點(diǎn)Open file選 CSVWEKA 會彈窗問你是否轉(zhuǎn)換確認(rèn)后直接加載。然后點(diǎn)Save按鈕在保存類型里選.arff就能存成 ARFF。這條路適合不習(xí)慣命令行的新手但批量轉(zhuǎn)換時(shí)還是 CLI 更省事。3.2 Explorer 界面八個(gè)區(qū)域的分工Explorer 是 WEKA 用得最多的模塊界面可以分成八個(gè)區(qū)域來理解。區(qū)域 1 是頂部選項(xiàng)卡切換 Preprocess、Classify、Cluster、Associate、Select attributes、Visualize 等不同任務(wù)面板。區(qū)域 2 是常用按鈕包括打開數(shù)據(jù)、保存、編輯、Undo。區(qū)域 3 是 Filter 選擇區(qū)點(diǎn)Choose會彈出一棵 Filter 樹數(shù)據(jù)預(yù)處理主要靠它。區(qū)域 4 顯示數(shù)據(jù)集的基本情況比如實(shí)例數(shù)、屬性數(shù)。區(qū)域 5 列出所有屬性勾選后點(diǎn)Remove可以刪列刪錯(cuò)了用區(qū)域 2 的Undo找回。區(qū)域 6 顯示選中屬性的摘要數(shù)值屬性和分類屬性的摘要形式不一樣。區(qū)域 7 是直方圖如果最后一個(gè)屬性是分類變量直方圖會按類別比例分色。區(qū)域 8 是狀態(tài)欄右邊的 WEKA 鳥在動說明正在執(zhí)行任務(wù)右鍵狀態(tài)欄可以觸發(fā) Java 內(nèi)存垃圾回收。以bank-data.csv為例這個(gè)數(shù)據(jù)集有 id、age、sex、region、income、married、children、car、save_acct、current_acct、mortgage、pep 這些列。id 是唯一標(biāo)識對挖掘任務(wù)沒用在區(qū)域 5 勾選id然后點(diǎn)Remove刪掉。刪完后保存一次用文本編輯器打開 ARFF你會看到 WEKA 已經(jīng)為每個(gè)屬性自動選好了類型。3.3 數(shù)值屬性離散化Discretize Filter 的參數(shù)怎么設(shè)有些算法只能處理分類型屬性比如 Apriori 關(guān)聯(lián)規(guī)則。bank-data里有三個(gè)數(shù)值型變量age、income、children。其中children只有 0、1、2、3 四個(gè)取值直接在 ARFF 文件里把a(bǔ)ttribute children numeric改成attribute children {0,1,2,3}就行改完在 Explorer 里重新打開選中children看區(qū)域 6 的 Type 是不是變成了Nominal。age和income的離散化用DiscretizeFilter。在區(qū)域 3 點(diǎn)Choose逐級找到weka.filters.unsupervised.attribute.Discretize點(diǎn)擊后 Choose 旁邊的文本框會顯示Discretize -B 10 -M -0.1 -R first-last。點(diǎn)這個(gè)文本框彈出參數(shù)窗口把a(bǔ)ttributeIndices改成1,4對應(yīng) age 和 income 在屬性列表里的位置把bins改成3其他不動點(diǎn) OK 回到 Explorer再點(diǎn)Apply。區(qū)域 5 里 age 和 income 就變成分類屬性了取值形如(-inf-34.333333]。如果嫌這種區(qū)間標(biāo)識太晦澀保存 ARFF 后用文本編輯器把所有(-inf-34.333333]替換成0_34其他區(qū)間類似處理。替換時(shí)注意引號ARFF 里帶特殊字符的 nominal 值需要用單引號包起來。attribute age {0_34,34_50,50_inf} attribute income {0_30k,30k_60k,60k_inf}這樣改完可讀性提升一大截后續(xù)看規(guī)則輸出也舒服得多。提示Discretize 的-M參數(shù)是useEqualFrequency默認(rèn)-M -0.1表示不啟用等頻分箱。如果你希望每個(gè)區(qū)間樣本數(shù)盡量均勻把-M勾上-0.1改成-1。4. 避坑與排查ARFF 讀取失敗、類型推斷錯(cuò)誤和內(nèi)存溢出4.1 現(xiàn)象打開 ARFF 報(bào) “Unable to determine structure as arff”原因通常有三個(gè)文件里有中文標(biāo)點(diǎn)或不可見字符屬性聲明順序和數(shù)據(jù)列數(shù)對不上data后面有空行或者行尾有多余逗號。解決方法是先用文本編輯器的“顯示不可見字符”功能檢查一遍確保所有分隔符都是英文半角。然后數(shù)一下attribute的行數(shù)和數(shù)據(jù)部分每行的逗號數(shù)屬性數(shù)應(yīng)該等于逗號數(shù)加一。如果數(shù)據(jù)行末尾多了一個(gè)逗號WEKA 會認(rèn)為多了一列直接報(bào)錯(cuò)。4.2 現(xiàn)象CSV 轉(zhuǎn)換后第一行變成了屬性名數(shù)據(jù)少了一行原因就是 CSV 沒有表頭WEKA 把第一行數(shù)據(jù)當(dāng)成了屬性名。解決方法是手工補(bǔ)一行屬性名或者在轉(zhuǎn)換時(shí)用-H參數(shù)指定不把第一行當(dāng)表頭但這樣屬性名會變成att1、att2這種默認(rèn)名后續(xù)還得改。我一般直接補(bǔ)表頭雖然多一步但屬性名可控。4.3 現(xiàn)象數(shù)值列被推斷成 nominal或者 nominal 列被推斷成 stringWEKA 的自動推斷基于采樣數(shù)據(jù)量小或者取值特殊時(shí)容易翻車。比如income列如果前幾行都是整數(shù)WEKA 給numeric但如果中間混了一個(gè)N/A就可能變成string。解決方法是轉(zhuǎn)換后打開 ARFF 手動改attribute的類型聲明。改完保存在 Explorer 里重新加載驗(yàn)證。4.4 現(xiàn)象Explorer 跑算法時(shí)卡死狀態(tài)欄的鳥一直動但不出結(jié)果大概率是 Java 堆內(nèi)存不夠。WEKA 默認(rèn)堆內(nèi)存可能只有 512MB數(shù)據(jù)量稍大就撐不住。解決辦法是啟動 WEKA 時(shí)加-Xmx參數(shù)比如java -Xmx4g -jar weka.jar把最大堆內(nèi)存調(diào)到 4GB。Windows 下可以改RunWeka.ini里的maxheap值。另外右鍵狀態(tài)欄觸發(fā)垃圾回收只能臨時(shí)緩解根治還是得加內(nèi)存。4.5 現(xiàn)象Discretize 之后屬性值變成All或者只有一個(gè)區(qū)間原因通常是attributeIndices設(shè)錯(cuò)了或者選中的屬性本身就是 nominal 類型。Discretize 只對 numeric 屬性生效如果屬性已經(jīng)是 nominalFilter 會把它所有值歸到一個(gè)區(qū)間。解決方法是先確認(rèn)屬性類型只對 numeric 列做離散化并且attributeIndices用屬性在列表里的序號不是屬性名。5. 進(jìn)階技巧用 UltraEdit 批量改 ARFF 與交叉驗(yàn)證的實(shí)操細(xì)節(jié)5.1 批量替換 nominal 區(qū)間標(biāo)識的腳本化思路手工替換幾十個(gè)區(qū)間標(biāo)識很痛苦我一般用 UltraEdit 的“在文件中替換”功能或者寫個(gè)簡單的 Python 腳本處理。思路是讀入 ARFF 文件用正則匹配\(-inf-([\d.])\]這種模式替換成可讀的區(qū)間名。下面是一個(gè)示例腳本import re def simplify_arff_intervals(filepath): with open(filepath, r, encodingutf-8) as f: content f.read() # 匹配形如 (-inf-34.333333] 的區(qū)間標(biāo)識 pattern r\(-inf-([\d.])\] def repl(match): upper float(match.group(1)) return f0_{int(upper)} content re.sub(pattern, repl, content) # 匹配形如 (34.333333-50] 的中間區(qū)間 pattern2 r\(([\d.])-([\d.])\] def repl2(match): lower int(float(match.group(1))) upper int(float(match.group(2))) return f{lower}_{upper} content re.sub(pattern2, repl2, content) with open(filepath, w, encodingutf-8) as f: f.write(content) simplify_arff_intervals(bank-data.arff)這段代碼先處理(-inf-上限]形式的下界無窮區(qū)間再處理(下限-上限]形式的中間區(qū)間。替換后的值不帶引號因?yàn)?_34這種字符串不包含特殊字符ARFF 解析器能直接識別。注意替換前備份原文件正則匹配不到的情況要人工檢查。5.2 在 Explorer 里跑交叉驗(yàn)證與查看規(guī)則輸出預(yù)處理完的數(shù)據(jù)可以直接在 Explorer 的 Classify 面板跑分類。選一個(gè)算法比如trees.J48Test options 里選Cross-validationFolds 設(shè) 10點(diǎn)Start。右側(cè) Classifier output 會顯示準(zhǔn)確率、混淆矩陣和決策樹。如果跑的是 Associate 面板的 Apriori輸出的是關(guān)聯(lián)規(guī)則這時(shí)候之前離散化并簡化過的區(qū)間名就派上用場了規(guī)則像age0_34 income0_30k buys_computerno這樣讀起來一目了然。我自己的習(xí)慣是每次拿到新數(shù)據(jù)先補(bǔ)表頭轉(zhuǎn) ARFF再刪 ID 列然后對數(shù)值列做 Discretize最后用腳本簡化區(qū)間名。這套流程走完再跑算法基本不會在數(shù)據(jù)格式上翻車。從那以后我每次處理新數(shù)據(jù)集都強(qiáng)制走一遍這個(gè)檢查清單省下來的調(diào)試時(shí)間夠跑好幾輪實(shí)驗(yàn)了。希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取