1. 程式人生 > >使用Weka進行資料探勘(Weka教程六)Weka取樣Filter/Resample/SMOTE

使用Weka進行資料探勘(Weka教程六)Weka取樣Filter/Resample/SMOTE

資料預處理中,有一個原理很簡單但是非常重要的部分:取樣。良好的取樣可以讓資料集變得平衡,會大大的提高預測和分類的效果。
取樣是很複雜的一個領域,背後涉及到資料的分佈/資料的性質等很多內容。常見的取樣有:
Simple Random Sampling(簡單隨機取樣),
OfflineSampling(離線等可能K取樣),
Online Sampling(線上等可能K取樣),
Ratio-based Sampling(等比例隨機取樣),
Acceptance-RejectionSampling(接受-拒絕取樣),
Importance Sampling(重要性取樣),
MCMC(MarkovChain Monte Carlo 馬爾科夫蒙特卡羅取樣演算法)。

  • 簡單有放回隨機取樣

Filter支援多種取樣方式,其中有監督的取樣比較複雜,因此主要講解有監督學習取樣方法。Filter中的Resample取樣就是簡單的有放回抽樣。
其引數有下面幾個:

 -S <num>
  Specify the random number seed (default 1)
  指定隨機數種子,隨機數種子相同,則取樣結果相同。
 -Z <num>
  The size of the output dataset, as a percentage of
  the input dataset (default 100)
  指定取樣資料佔整個資料的比例。
 -B <num
> Bias factor towards uniform class distribution. 0 = distribution in input data -- 1 = uniform distribution. (default 0) 是否按照原來資料類別的分佈分層抽樣。 -no-replacement Disables replacement of instances (default: with replacement) -V Inverts the selection - only available with '-no-replacement'
.

由以上引數可以看出,Weka支援的比例好像最小為1%,其實並不是,你可以使用小數實現更低的取樣比。此外,你可以將取樣比例設定成大於100%,如果你這樣做了,那麼你的結果資料集將會出現重複的資料。這樣是沒有意義的。

使用Resample進行取樣是比較簡單的,下面是一個例子:

 public static Instances BoostrapSample(Instances data) {
        String[] options = {"-S",1};
        Resample convert = new Resample();
        try {
            convert.setOptions(options);
            convert.setInputFormat(data);
            data = Filter.useFilter(data, convert);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return data;
    }
  • SMOTE取樣
    隨機取樣比較簡單,其實Weka還支援一種附加的取樣方法,在Weka3.6版本以下,這個功能嵌入在Weka包裡,Weka3.7版本開始,這個功能需要額外的第三方包的支援,這種取樣就是SMOTE取樣。
    SMOTE演算法的思想是合成新的少數類樣本,合成的策略是對每個少數類樣本a,從它的最近鄰中隨機選一個樣本b,然後在a、b之間的連線上隨機選一點作為新合成的少數類樣本。 這是一種過取樣方法,通過製造更多模擬的少數類樣本來實現各個樣本之間的平衡。
    下圖是其主要思想的形式化表示:
    這裡寫圖片描述
    在Weka3.7版本,你必須先新增第三方包,最簡單的方法就是新增一個新的maven依賴:
<dependency>
    <groupId>nz.ac.waikato.cms.weka</groupId>
    <artifactId>SMOTE</artifactId>
    <version>1.0.3</version>
</dependency>

SMOTE取樣實現程式碼如下:

public static Instances SMOTESample(Instances data,int normalElemFlag) {
        SMOTE convert = new SMOTE();
        int seed = (int) (Math.random() * 10);
        String[] options = {"-S", String.valueOf(seed), "-P", "100.0", "-K", "5"};
        Instances SmoteInstances = null;
        try {
            convert.setOptions(options);
            convert.setInputFormat(data);
            SmoteInstances = Filter.useFilter(data, convert);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return SmoteInstances;
    }

需要注意的是,在執行完畢SMOTE取樣之後,多數類樣本並不會隨之減少,因此,如果你想讓多數類和少數類樣本平衡,就必須再使用簡單取樣丟棄多餘的多數類樣本。