在WEKA中,過濾器用來進行數據預處理。他們能夠在weka.filters包中找到。各過濾器可歸爲如下兩類別之一: 數據結構
• 有監督 -過濾器須要設置一個類屬性。 app
• 無監督 - 類的屬性能夠不存在。 測試
而且可歸爲兩個子類之一: ui
• 基於屬性 -處理列,例如,添加或刪除列。 spa
• 基於實例 -處理行,例如,添加或刪除行。 orm
這些類別代表了Weka中兩個 離散化 過濾器之間的區別。有監督的 過濾器須要考慮數據集中類的屬性及其分佈,以肯定最佳的容器的數量和規模,而 無監督的 過濾器依賴於用戶指定容器的數量。 ci
除了這種分類,過濾器也可分爲基於數據流或基於批處理。流 過濾器能夠立刻處理數據,使其當即能夠再次收集。另外一方面,批量 過濾器,須要一個批次的數據,來設置它們的內部數據結構。Add 過濾器(過濾器能夠發如今 weka.filters.unsupervised.attribute 包)是流過濾器的一個例子。添加一個只包含缺失值的新屬性,不須要任何複雜的設置。然而,ReplaceMissingValues 過濾器(與 Add 過濾器 相似的包 )須要一個批次的數據,以肯定每一個屬性的平均值和模式。不然,過濾器將沒法用有意義的值來代替缺失值。但只要批量過濾器已用第一批數據初始化,它也能夠一行一行地處理數據,就像一個流過濾器。 rem
基於實例的 過濾器在處理數據上有點特別。正如前面提到的,首批數據處理完後, 全部 過濾器均可以一行一行地處理數據。固然,若是過濾器是從一批數據中添加或刪除行,當它工做於單行處理模式下這將再也不有效。這是有道理的,若是你想到一個涉及 FilteredClassifier 元分類器的場景:訓練階段(第一批數據)完後,分類器將從測試集獲得評估,一次一個實例。如今,若是過濾器移除惟一的實例,或添加一些實例,它將再也不被正確評估,由於評估過程指望只獲得一個惟一的返回結果。這就是爲何 基於實例的 過濾器只傳遞任何後續批次的數據,不做任何處理的緣由。例如,Resample 過濾器就是這樣的。 字符串
能夠在WEKA Example 集合的 wekaexamples.filters 包中找到過濾器的示例類 it
下面的示例使用 Remove 過濾器(過濾器位於 weka.filters.unsupervised.attribute包中)刪除數據集中的第一個屬性。設置選項, 傳遞setOptions(字符串[]) 方法。
import weka.core.Instances;
import weka.filters.Filter;
import weka.filters.unsupervised.attribute.Remove;
…
String[] options = new String[2];
options[0] = "-R"; // "range"
options[1] = "1"; // first attribute
Remove remove = new Remove(); // new instance of filter
remove.setOptions(options); // set options
remove.setInputFormat(data); // inform filter about dataset
// **AFTER** setting options
Instances newData = Filter.useFilter(data, remove); // apply filter
一個常見的陷阱是, setInputFormat(Instances) 被調用後才設置選項。因爲這個方法(一般狀況下)用於肯定輸出的數據格式,全部選項必需調用前設置。不然,全部以後設置的選項將被忽略。
若是若是兩個或兩個以上的數據集須要根據相同的過濾器初始化進行處理,批量過濾是必要的,若是不使用批量過濾,例如,當使 StringToWordVector 過濾器( weka.filters.unsupervised.attribute包)一個訓練集和一個測試集,那麼這兩個過濾器的運行是徹底獨立的,並會帶來兩個極可能不兼容的數據集。在兩個不一樣的數據集上運行 StringToWordVector ,這將產生兩個不一樣的詞典,所以產生不一樣的屬性。
下面的代碼示例顯示瞭如何使用Standardize 過濾器(weka.filters.unsupervised.attribute包)規範化(即把全部數值屬性轉化成具備零均值和單位方差)訓練集和測試集:
Instances train = ... // from somewhere Instances test = ... // from somewhere
Standardize filter = new Standardize(); // initializing the filter once with training set
filter.setInputFormat(train);
// configures the Filter based on train instances and returns
/ /過濾實例
Instances newTrain = Filter.useFilter(train, filter);
/ /建立一個新的測試集
Instances newTest = Filter.useFilter(test, filter);
即便使用API爲咱們提供了一個完整控制數據的方式,使得在同一時間處理幾個數據集變得方便,運行中(on-the-fly)過濾數據將使咱們的工做更方便。這個方便的功能是能夠經過WEKA的元方案(meta schemes)實現,如FilteredClassifier(package weka.classifiers.meta),FilteredClusterer (package weka.clusterers),FilteredAssociator(package weka.associations) and FilteredAttributeEval/FilteredSubsetEval(in weka.attributeSelection). 相比於事先 過濾數據 , 咱們只要設置一個元方案,讓它去過濾。
下面的例子使用 FilteredClassifier 和 Remove 過濾器,一塊兒刪除數據集的第一個屬性(這剛好是一個ID屬性), 其中使用J48(J48是WEKA的C4.5的實現,包 weka.classifiers.trees)做爲基分類器。首先,用一個訓練集建立分類器,而後用獨立的測試集測試分類器。實際和預測的類值打印到控制檯上。關於分類的更多信息,請參閱第16.6章。
import weka.classifiers.meta.FilteredClassifier;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import weka.filters.unsupervised.attribute.Remove;
...
Instances train = ... // from somewhere
Instances test = ... // from somewhere
// filter
Remove rm = new Remove();
rm.setAttributeIndices("1"); // remove 1st attribute
// classifier
J48 j48 = new J48();
j48.setUnpruned(true); // using an unpruned J48
// meta-classifier
FilteredClassifier fc = new FilteredClassifier();
fc.setFilter(rm);
fc.setClassifier(j48);
// train and output model
fc.buildClassifier(train);
System.out.println(fc);
for (int i = 0; i < test.numInstances(); i++)
{ double pred = fc.classifyInstance(test.instance(i));
double actual = test.instance(i).classValue();
System.out.print("ID: "
+ test.instance(i).value(0));
System.out.print(", actual: "
+ test.classAttribute().value((int) actual));
System.out.println(", predicted: "
+ test.classAttribute().value((int)pred)); }